Skip to content

Commit

Permalink
- Add touch to XL
Browse files Browse the repository at this point in the history
- Add RGB sidebars
- Cleanup sim neopixel
  • Loading branch information
vintagepc committed Apr 30, 2023
1 parent 8cfd919 commit 68ac9bd
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 23 deletions.
6 changes: 6 additions & 0 deletions hw/arm/prusa/parts/spi_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,12 @@ static void spi_display_cursor(void *opaque, int n, int level)
static void spi_display_led(void *opaque, int n, int level)
{
SPIDisplayState *s = SPI_DISPLAY(opaque);
if (n==3)
{
// backlight LED
uint8_t r = level >> 16;
level = r << 16 | r << 8 | r;
}
s->leds[n] = level;
for (int row = s->dpy_info->rows; row< s->dpy_info->rows + LED_HT; row++) {
for (int col = n*LED_W; col< ((n+1)*LED_W); col++) {
Expand Down
43 changes: 31 additions & 12 deletions hw/arm/prusa/parts/spi_rgb.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@
#include "../utility/macros.h"
#include "../utility/p404scriptable.h"
#include "../utility/ScriptHost_C.h"
#include "spi_rgb.h"

#define B1_10M5Hz 0b1111111000000
#define B0_10M5Hz 0b111000000000
#define ALT_B1_10M5Hz 0b1110000000
#define ALT_B0_10M5Hz 0b1111111000
#define RST_10M5Hz 535U
#define ALT_RST_10M5Hz 12U


typedef union {
Expand Down Expand Up @@ -66,12 +70,12 @@ struct RGBLedState {
colour_t set_colour;

bool passthrough;
bool is_ws2811;
qemu_irq dout;
qemu_irq reset;
qemu_irq colour;


qemu_irq rgb_out[3];
uint8_t led_type;
uint8_t flags;
};

#define TYPE_RGB_LED "spi_rgb"
Expand All @@ -90,19 +94,22 @@ static void rgb_led_din(void* opaque, int n, int level) {
s->set_colour.raw = level;
s->passthrough = true;
uint32_t rgb;
if (s->is_ws2811)
if (s->led_type == SPI_RGB_WS2811)
{
// HACK alert, this is just to compensate for the fact this chip only uses the green channel for a white backlight
// on the Prusa MK4.
rgb = (s->set_colour.ws8211.r << 16) | (s->set_colour.ws8211.r << 8) | s->set_colour.ws8211.r;

rgb = (s->set_colour.ws8211.r << 16) | (s->set_colour.ws8211.g << 8) | s->set_colour.ws8211.b;
}
else
{
rgb = (s->set_colour.ws8212.r << 16) | (s->set_colour.ws8212.g << 8) | s->set_colour.ws8212.b;
}
if (s->flags & SPI_RGB_FLAG_INVERTED)
{
rgb = 0xFFFFFF - rgb;
}
qemu_set_irq(s->colour,rgb);
// printf("Colour received (rgb): %02x %02x %02x\n",s->set_colour.ws8212.r,s->set_colour.ws8212.g,s->set_colour.ws8212.b);
qemu_set_irq(s->rgb_out[0], rgb >> 16);
qemu_set_irq(s->rgb_out[1], (rgb >> 8) & 0xFF);
qemu_set_irq(s->rgb_out[2], rgb & 0xFF);
}
}

Expand All @@ -120,7 +127,6 @@ static void rgb_led_reset(void* opaque, int n, int level) {
static uint32_t rgb_led_transfer(SSIPeripheral *dev, uint32_t data)
{
RGBLedState *s = RGB_LED(dev);
// printf("LED data: %"PRIx32"\n", data);
for (int i=7; i>=0; i--) {
s->chunks_in <<=1;
bool new_bit = ((data & (1U<<i))>0);
Expand All @@ -136,19 +142,29 @@ static uint32_t rgb_led_transfer(SSIPeripheral *dev, uint32_t data)
switch (s->chunks_in) {
case B1_10M5Hz:
case B0_10M5Hz:
if (s->flags & SPI_RGB_FLAG_ALT_TIMINGS) continue;
s->current_colour.raw <<=1U;
s->current_colour.raw |= (s->chunks_in == B1_10M5Hz);
s->bit_count++;
s->chunks_in = 0;
break;
case ALT_B0_10M5Hz:
case ALT_B1_10M5Hz:
if (!(s->flags & SPI_RGB_FLAG_ALT_TIMINGS)) continue;
s->current_colour.raw <<=1U;
s->current_colour.raw |= (s->chunks_in == ALT_B1_10M5Hz);
s->bit_count++;
s->chunks_in = 0;
break;
}
if (s->bit_count == 24)
{
// if (s->no_cs) printf("LED data: %"PRIx32"\n", s->current_colour.raw);
// Reached the RGB length.
rgb_led_din(s, 0,s->current_colour.raw);
s->bit_count = 0;
}
if (s->zero_count == RST_10M5Hz) {
if (s->zero_count == (s->flags & SPI_RGB_FLAG_ALT_TIMINGS ? ALT_RST_10M5Hz : RST_10M5Hz)) {
rgb_led_reset(s, 0,0);
}
}
Expand Down Expand Up @@ -177,6 +193,7 @@ static void rgb_led_realize(SSIPeripheral *d, Error **errp)
{
DeviceState *dev = DEVICE(d);
RGBLedState *s = RGB_LED(d);
if (s->flags & SPI_RGB_FLAG_NO_CS) d->cs = true;

rgb_led_reset(s, 0,0);

Expand All @@ -186,11 +203,13 @@ static void rgb_led_realize(SSIPeripheral *d, Error **errp)
qdev_init_gpio_in_named(dev, rgb_led_reset, "reset",1);
qdev_init_gpio_out_named(dev, &s->reset, "reset-out", 1);
qdev_init_gpio_out_named(dev, &s->colour, "colour", 1);
qdev_init_gpio_out_named(dev, s->rgb_out, "rgb-out", 3);

}

static Property rgb_led_properties[] = {
DEFINE_PROP_BOOL("is_ws2811",RGBLedState, is_ws2811, false),
DEFINE_PROP_UINT8("led-type",RGBLedState, led_type, (uint64_t)SPI_RGB_WS2812),
DEFINE_PROP_UINT8("flags",RGBLedState, flags, SPI_RGB_FLAG_NONE),
DEFINE_PROP_END_OF_LIST(),
};

Expand Down
13 changes: 13 additions & 0 deletions hw/arm/prusa/parts/spi_rgb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Helper for SPI_RGB types:

enum {
SPI_RGB_WS2812 = 0,
SPI_RGB_WS2811,
};

enum SPI_RGB_FLAG {
SPI_RGB_FLAG_NONE,
SPI_RGB_FLAG_INVERTED = 1,
SPI_RGB_FLAG_ALT_TIMINGS = 2,
SPI_RGB_FLAG_NO_CS = 4,
};
3 changes: 2 additions & 1 deletion hw/arm/prusa/prusa-mk4.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "parts/dashboard_types.h"
#include "stm32_common/stm32_common.h"
#include "hw/arm/armv7m.h"
#include "parts/spi_rgb.h"

#define BOOTLOADER_IMAGE "Prusa_Mk4_Boot.bin"
#define XFLASH_FN "Prusa_Mk4_xflash.bin"
Expand Down Expand Up @@ -258,7 +259,7 @@ static void mk4_init(MachineState *machine, mk4_cfg_t cfg)
for (int i=0; i<4; i++) {
npixel[i] = qdev_new("spi_rgb");
if (i==3) {
qdev_prop_set_bit(npixel[i],"is_ws2811",true);
qdev_prop_set_uint8(npixel[i],"led-type",SPI_RGB_WS2811);
}
ssi_realize_and_unref(npixel[i], bus, &error_fatal);
if (i>0)
Expand Down
69 changes: 59 additions & 10 deletions hw/arm/prusa/prusa-xl.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "parts/xl_bridge.h"
#include "stm32_common/stm32_common.h"
#include "hw/arm/armv7m.h"
#include "parts/spi_rgb.h"

#define BOOTLOADER_IMAGE "Prusa_XL_Boot.bin"
#define XFLASH_FN "Prusa_XL_xflash.bin"
Expand Down Expand Up @@ -221,18 +222,19 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg)

/* Wire up display */
void *bus;
DeviceState* npixel[6];
DeviceState* lcd_dev;
{
bus = qdev_get_child_bus(
stm32_soc_get_periph(dev_soc, cfg.lcd_spi),
"ssi");

DeviceState *lcd_dev = ssi_create_peripheral(bus, "ili9488");
lcd_dev = ssi_create_peripheral(bus, "ili9488");

DeviceState *npixel[4];
for (int i=0; i<4; i++) {
npixel[i] = qdev_new("spi_rgb");
if (i==3) {
qdev_prop_set_bit(npixel[i],"is_ws2811",true);
qdev_prop_set_uint8(npixel[i],"led-type",SPI_RGB_WS2811);
}
ssi_realize_and_unref(npixel[i], bus, &error_fatal);
if (i>0)
Expand All @@ -244,6 +246,25 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg)
qdev_get_gpio_in_named(lcd_dev,"leds",i)
);
}
npixel[5] = qdev_new("spi_rgb");
qdev_prop_set_uint8(npixel[5],"led-type",SPI_RGB_WS2811);
qdev_prop_set_uint8(npixel[5],"flags",SPI_RGB_FLAG_ALT_TIMINGS | SPI_RGB_FLAG_INVERTED);
ssi_realize_and_unref(npixel[5],
(SSIBus*) qdev_get_child_bus(
stm32_soc_get_periph(dev_soc, STM32_P_SPI4),
"ssi"),
&error_fatal);
npixel[4] = qdev_new("spi_rgb");
qdev_prop_set_uint8(npixel[4],"led-type",SPI_RGB_WS2811);
qdev_prop_set_uint8(npixel[4],"flags", SPI_RGB_FLAG_ALT_TIMINGS | SPI_RGB_FLAG_INVERTED | SPI_RGB_FLAG_NO_CS);
ssi_realize_and_unref(npixel[4],
(SSIBus*) qdev_get_child_bus(
stm32_soc_get_periph(dev_soc, STM32_P_SPI4),
"ssi"),
&error_fatal);
qdev_connect_gpio_out(npixel[4], 0, qdev_get_gpio_in(npixel[5], 0));
qdev_connect_gpio_out_named(npixel[4], "reset-out", 0, qdev_get_gpio_in_named(npixel[5], "reset", 0));

qemu_irq lcd_cs = qdev_get_gpio_in_named(lcd_dev, SSI_GPIO_CS, 0);
if (cfg.lcd_cs_invert) {
lcd_cs = qemu_irq_invert(lcd_cs);
Expand All @@ -256,7 +277,6 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg)
qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, BANK(cfg.lcd_cd)),PIN(cfg.lcd_cd), lcd_cd);

qemu_irq led_cs = qemu_irq_split(lcd_cs, qdev_get_gpio_in_named(npixel[0], SSI_GPIO_CS, 0));

qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, BANK(cfg.lcd_cs)),PIN(cfg.lcd_cs),led_cs);
}

Expand Down Expand Up @@ -321,7 +341,7 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg)
static const char* links[4] = {"motor[0]","motor[1]","motor[4]"};
qdev_prop_set_uint8(db2, "fans", 0);
qdev_prop_set_uint8(db2, "thermistors", 0);
qdev_prop_set_string(db2, "indicators", "ZF");
qdev_prop_set_string(db2, "indicators", "ZFRWC");

{
static int32_t stepsize[4] = { 80*16, 80*16, 800*16, 400*16 };
Expand Down Expand Up @@ -441,6 +461,20 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg)

sysbus_realize(SYS_BUS_DEVICE(db2), &error_fatal);

// Sidebar RGB
qdev_connect_gpio_out_named(npixel[4],"colour",0,
qdev_get_gpio_in_named(db2,"led-rgb",2)
);
// Sidebar W
qdev_connect_gpio_out_named(npixel[5],"rgb-out",0,
qdev_get_gpio_in_named(db2,"led-w",3)
);
// Cheese LED
qdev_connect_gpio_out_named(npixel[5],"rgb-out",1,
qdev_get_gpio_in_named(db2,"led-w",4)
);


uint16_t startvals[] = {18,20, 25, 512, 20};
uint8_t channels[] = {10,4,3,5,6};
int tables[] = {cfg.e_table_index, 1, 2000,0,5};
Expand Down Expand Up @@ -567,11 +601,26 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg)
#endif
}

dev = qdev_new("encoder-input");
sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
qdev_connect_gpio_out_named(dev, "encoder-button", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_btn)), PIN(cfg.enc_btn)));
qdev_connect_gpio_out_named(dev, "encoder-a", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_a)), PIN(cfg.enc_a)));
qdev_connect_gpio_out_named(dev, "encoder-b", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_b)), PIN(cfg.enc_b)));
DeviceState* encoder = qdev_new("encoder-input");
sysbus_realize(SYS_BUS_DEVICE(encoder), &error_fatal);
qdev_connect_gpio_out_named(encoder, "encoder-button", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_btn)), PIN(cfg.enc_btn)));
qdev_connect_gpio_out_named(encoder, "encoder-a", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_a)), PIN(cfg.enc_a)));
qdev_connect_gpio_out_named(encoder, "encoder-b", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_b)), PIN(cfg.enc_b)));

bus = qdev_get_child_bus(
stm32_soc_get_periph(dev_soc, STM32_P_I2C3),
"i2c");
dev = qdev_new("gt911");
qdev_prop_set_uint8(dev, "address", 0x5D);
qdev_realize(dev, bus, &error_fatal);
qdev_connect_gpio_out(dev,0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOC),8));

qemu_irq x_split = qemu_irq_split(qdev_get_gpio_in_named(lcd_dev, "cursor", 0), qdev_get_gpio_in_named(dev, "x_y_touch", 0));
qemu_irq y_split = qemu_irq_split(qdev_get_gpio_in_named(lcd_dev, "cursor", 1), qdev_get_gpio_in_named(dev, "x_y_touch", 1));
qemu_irq t_split = qemu_irq_split(qdev_get_gpio_in_named(lcd_dev, "cursor", 2), qdev_get_gpio_in_named(dev, "x_y_touch", 2));
qdev_connect_gpio_out_named(encoder, "cursor_xy", 0, x_split);
qdev_connect_gpio_out_named(encoder, "cursor_xy", 1, y_split);
qdev_connect_gpio_out_named(encoder, "touch", 0, t_split);

// Needs to come last because it has the scripting engine setup.
dev = qdev_new("p404-scriptcon");
Expand Down

0 comments on commit 68ac9bd

Please sign in to comment.