diff --git a/include/devices/mid_clock.h b/include/devices/mid_clock.h index d7230bc..c4abf29 100644 --- a/include/devices/mid_clock.h +++ b/include/devices/mid_clock.h @@ -10,7 +10,9 @@ #define HAS_OUTPUT_WS0010 #define HAS_TEMP_SENSOR #define HAS_KEYPAD -#define HAS_SERIAL_MIDI +#define HAS_VARYING_BRIGHTNESS +#define HAS_LIGHT_SENSOR +#define HAS_MOTION_SENSOR // Plasma Information System OS (not DOS, there's no disk in it!) #define PRODUCT_NAME "uPIS-OS" @@ -38,6 +40,10 @@ const gpio_num_t HWCONF_WS0010_DATABUS_GPIOS[] = { const gpio_num_t HWCONF_WS0010_RS_GPIO = GPIO_NUM_19; const gpio_num_t HWCONF_WS0010_EN_GPIO = GPIO_NUM_18; +// ---- Connection to light sensors ---- +const gpio_num_t HWCONF_MOTION_GPIO = GPIO_NUM_39; +const gpio_num_t HWCONF_LIGHTSENSE_GPIO = GPIO_NUM_36; + #define HWCONF_DISPLAY_WIDTH_PX 100 #define HWCONF_DISPLAY_HEIGHT_PX 16 diff --git a/include/display/ws0010.h b/include/display/ws0010.h index 7f0c6f4..b665bb2 100644 --- a/include/display/ws0010.h +++ b/include/display/ws0010.h @@ -38,8 +38,6 @@ class Ws0010OledDriver: public DisplayDriver { gpio_num_t rs_gpio; gpio_num_t en_gpio; bool is_writing_ddram; - bool show_state; - bool is_dim = false; uint8_t ddram_ptr; inline void set_databus(uint8_t data); @@ -47,5 +45,10 @@ class Ws0010OledDriver: public DisplayDriver { inline void pulse_clock(); void write_string(const char *); void write_stride(uint8_t stride); + + bool show_state; + bool bright_state; + bool power_state; + void _set_pmu_internal(); }; #endif \ No newline at end of file diff --git a/src/display/ws0010.cpp b/src/display/ws0010.cpp index 86a5924..efdeec1 100644 --- a/src/display/ws0010.cpp +++ b/src/display/ws0010.cpp @@ -6,6 +6,8 @@ #include #include +#define WS0010_NO_BFI + #ifndef WS0010_BFI_DIMMER_DURATION_US #define WS0010_BFI_DIMMER_DURATION_US 6600 //<- experimentally found value for roughly 50% brightness @ 5v supply #endif @@ -24,7 +26,9 @@ Ws0010OledDriver::Ws0010OledDriver( rs_gpio = rs; en_gpio = en; is_writing_ddram = false; - is_dim = false; + show_state = false; + bright_state = false; + power_state = false; ddram_ptr = 0; } @@ -117,29 +121,20 @@ void Ws0010OledDriver::reset() { delayMicroseconds(400); delay(200); - write_string("uPIS-OS init"); + write_string("uPIS-OS WS0010 init"); delay(500); taskEXIT_CRITICAL(&_spinlock); } void Ws0010OledDriver::set_show(bool show) { - taskENTER_CRITICAL(&_spinlock); show_state = show; - set_is_command(true); - set_databus(0b00001000 | (show ? 0b111 : 0)); // cursor and blink always off - pulse_clock(); - delayMicroseconds(5); - taskEXIT_CRITICAL(&_spinlock); + _set_pmu_internal(); } void Ws0010OledDriver::set_power(bool power) { - taskENTER_CRITICAL(&_spinlock); - set_is_command(true); - set_databus(0b00011000 | (power ? 0b111 : 0b011)); // G/C always set to GRAPHIC - pulse_clock(); - delayMicroseconds(400); - taskEXIT_CRITICAL(&_spinlock); + power_state = power; + _set_pmu_internal(); } void Ws0010OledDriver::clear() { @@ -168,8 +163,11 @@ void Ws0010OledDriver::write_stride(uint8_t stride) { void Ws0010OledDriver::write_fanta(const uint8_t * strides, size_t count) { taskENTER_CRITICAL(&_spinlock); #ifndef WS0010_NO_BFI - bool show_backup = show_state; - set_show(false); + if(power_state && show_state) { + set_is_command(true); + set_databus(0b00001000 | 0b000); // cursor and blink always off + pulse_clock(); + } #endif // First write even (top row), then odd (bottom row) for(int i = 0; i < count - 1; i += 2) { @@ -181,17 +179,38 @@ void Ws0010OledDriver::write_fanta(const uint8_t * strides, size_t count) { write_stride(strides[i]); } #ifndef WS0010_NO_BFI - if(is_dim) { - delayMicroseconds(WS0010_BFI_DIMMER_DURATION_US); + if(power_state && show_state) { + set_is_command(true); + set_databus(0b00001000 | 0b111); // cursor and blink always off + pulse_clock(); } - set_show(show_backup); #endif taskEXIT_CRITICAL(&_spinlock); } void Ws0010OledDriver::set_bright(bool bright) { - ESP_LOGI(LOG_TAG, "BFI dimming is now %s", bright ? "OFF":"ON"); - is_dim = !bright; + bright_state = bright; + _set_pmu_internal(); +} + +// The power management of the WS0010 running at 5V is somewhat wacky, so the set_bright and set_show and set_power commands don't really match up with +// the real stuff that the controller does +void Ws0010OledDriver::_set_pmu_internal() { + taskENTER_CRITICAL(&_spinlock); + bool actual_bright = bright_state; + bool actual_show = (show_state && power_state); + + set_is_command(true); + set_databus(0b00011000 | (actual_bright ? 0b111 : 0b011)); // G/C always set to GRAPHIC + pulse_clock(); + delayMicroseconds(10); + + set_is_command(true); + set_databus(0b00001000 | (actual_show ? 0b111 : 0b000)); // cursor and blink always off + pulse_clock(); + delayMicroseconds(5); + + taskEXIT_CRITICAL(&_spinlock); } #endif \ No newline at end of file