-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
9,118 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#pragma once | ||
|
||
#include <hal/gpio_hal.h> | ||
#include <input/keypad.h> | ||
|
||
#define HAS_OUTPUT_GU312 | ||
#define HAS_KEYPAD | ||
|
||
// Plasma Information System OS (not DOS, there's no disk in it!) | ||
#define PRODUCT_NAME "LongPIS-OS" | ||
#define PRODUCT_VERSION "5.3" | ||
|
||
// ---- Connection to beeper ---- | ||
const gpio_num_t HWCONF_BEEPER_GPIO = GPIO_NUM_33; | ||
const uint8_t HWCONF_BEEPER_PWM_CHANNEL = 0; | ||
|
||
// ---- Connection to display ---- | ||
const gpio_num_t HWCONF_GU312_DATABUS_GPIOS[] = { | ||
GPIO_NUM_5, | ||
GPIO_NUM_0, | ||
GPIO_NUM_23, | ||
GPIO_NUM_2, | ||
GPIO_NUM_22, | ||
GPIO_NUM_15, | ||
GPIO_NUM_4, | ||
GPIO_NUM_21 | ||
}; | ||
const gpio_num_t HWCONF_GU312_CD_GPIO = GPIO_NUM_19; | ||
const gpio_num_t HWCONF_GU312_WR_GPIO = GPIO_NUM_18; | ||
|
||
#define HWCONF_DISPLAY_WIDTH_PX 192 | ||
#define HWCONF_DISPLAY_HEIGHT_PX 16 | ||
|
||
// ---- Connection of buttons ---- | ||
const keypad_definition_t HWCONF_KEYPAD = { | ||
{GPIO_NUM_14, KEY_RIGHT}, | ||
{GPIO_NUM_32, KEY_LEFT}, | ||
{GPIO_NUM_34, KEY_UP}, | ||
{GPIO_NUM_27, KEY_DOWN}, | ||
{GPIO_NUM_35, KEY_HEADPAT}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#pragma once | ||
#include <graphics/display_driver.h> | ||
#include <device_config.h> | ||
|
||
#if HAS(OUTPUT_GU312) | ||
class NoritakeGu312Driver: public DisplayDriver { | ||
public: | ||
/// @brief Initialize the interface. Configures the GPIO and prepares the outputs for use, also disables the output and high voltage supply. | ||
/// @note Connect the CS to LOW | ||
/// @param databus 8 pins connected to the display controller's data bus, DB0 to DB7 | ||
/// @param cd Pin connected to the display controller's C/D pin | ||
/// @param wr Pin connected to the display controller's WR pin | ||
/// @param blank Pin connected to the display controller's blanking pin | ||
NoritakeGu312Driver( | ||
const gpio_num_t databus[8], | ||
const gpio_num_t cd, | ||
const gpio_num_t wr | ||
// const gpio_num_t blank | ||
); | ||
|
||
void initialize(); | ||
/// @brief Reset the display controller | ||
void reset(); | ||
void clear(); | ||
|
||
/// @brief Enable or disable the high voltage supply | ||
void set_power(bool on); | ||
|
||
/// @brief Enable or disable dimming | ||
void set_bright(bool bright); | ||
|
||
/// @brief Send an array of half-columns to the display controller | ||
void write_fanta(const uint8_t * strides, size_t count); | ||
|
||
private: | ||
gpio_num_t databus_gpios[8]; | ||
gpio_num_t cd_gpio; | ||
gpio_num_t wr_gpio; | ||
|
||
void send_command(uint8_t cmd); | ||
inline void set_databus(uint8_t data); | ||
inline void set_is_command(bool); | ||
inline void pulse_clock(); | ||
void write_string(const char *); | ||
|
||
bool power_state; | ||
void _set_pmu_internal(); | ||
}; | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
#include <device_config.h> | ||
|
||
// This is a result of reverse engineering a bus display that uses a half meter long GU192x16-321. | ||
// Mostly similar to the old noritake protocol but there are some undocumented states. | ||
// The pinout is also undocumented so here goes | ||
// 1 2 | ||
// +______+ | ||
// D7>| . . | GND | ||
// D6 | . . | GND | ||
// D5 | . . | GND | ||
// D4 | . . | GND | ||
// D3 | . . | GND | ||
// D2 | . . | GND | ||
// D1 | . . | GND | ||
// D0 | . . | GND | ||
// ~WR | . . GND | ||
// A0 | . . | GND | ||
// ~RD | . . | GND | ||
// A1 | . . | ??? | ||
// FEP | . . | ~BL <-- note: FEP is Vsync out FROM the display!. ~BL=0 turns display off. | ||
// GND | . . | GND | ||
//~RST | . . | GND | ||
// A2 | . . | GND | ||
// ~CS | . . | GND | ||
// +------+ | ||
// 33 34 | ||
|
||
|
||
|
||
|
||
|
||
#if HAS(OUTPUT_GU312) | ||
#include "display/gu312.h" | ||
#include <esp32-hal-log.h> | ||
#include <esp32-hal-gpio.h> | ||
#include <esp_err.h> | ||
|
||
static char LOG_TAG[] = "Gu312"; | ||
static portMUX_TYPE _spinlock = portMUX_INITIALIZER_UNLOCKED; | ||
|
||
NoritakeGu312Driver::NoritakeGu312Driver( | ||
const gpio_num_t databus[8], | ||
const gpio_num_t cd, | ||
const gpio_num_t wr | ||
) { | ||
for(int i = 0; i < 8; i++) { | ||
databus_gpios[i] = databus[i]; | ||
} | ||
cd_gpio = cd; | ||
wr_gpio = wr; | ||
power_state = false; | ||
} | ||
|
||
void NoritakeGu312Driver::initialize() { | ||
ESP_LOGI(LOG_TAG, "Initializing Noritake Itron GU312 with data bus: %i %i %i %i %i %i %i %i, cd=%i, wr=%i", databus_gpios[0], databus_gpios[1], databus_gpios[2], databus_gpios[3], databus_gpios[4], databus_gpios[5], databus_gpios[6], databus_gpios[7], cd_gpio, wr_gpio); | ||
|
||
gpio_config_t io_conf = { | ||
.mode = GPIO_MODE_OUTPUT, | ||
.pull_up_en = gpio_pullup_t::GPIO_PULLUP_ENABLE, | ||
}; | ||
|
||
for(int i = 0; i < sizeof(databus_gpios) / sizeof(databus_gpios[0]); i++) { | ||
io_conf.pin_bit_mask |= 1ULL << databus_gpios[i]; | ||
} | ||
|
||
io_conf.pin_bit_mask |= 1ULL << cd_gpio; | ||
io_conf.pin_bit_mask |= 1ULL << wr_gpio; | ||
|
||
ESP_ERROR_CHECK(gpio_config(&io_conf)); | ||
|
||
gpio_set_level(wr_gpio, 1); | ||
gpio_set_level(cd_gpio, 0); | ||
|
||
delay(500); | ||
} | ||
|
||
void NoritakeGu312Driver::set_databus(uint8_t data) { | ||
uint8_t local_sts = data; | ||
for(int i = 0; i < 8; i++) { | ||
uint8_t cur_state = (local_sts & 1); | ||
gpio_set_level(databus_gpios[i], cur_state); | ||
local_sts >>= 1; | ||
} | ||
} | ||
|
||
void NoritakeGu312Driver::pulse_clock() { | ||
gpio_set_level(wr_gpio, 0); | ||
delayMicroseconds(2); | ||
gpio_set_level(wr_gpio, 1); | ||
delayMicroseconds(2); | ||
} | ||
|
||
void NoritakeGu312Driver::set_is_command(bool rs) { | ||
// H: COMMAND, L: Data | ||
gpio_set_level(cd_gpio, rs ? 1 : 0); | ||
delayMicroseconds(3); | ||
} | ||
|
||
void NoritakeGu312Driver::write_string(const char * s) { | ||
set_is_command(false); | ||
int len = strlen(s); | ||
for(int i = 0; i < len; i++) { | ||
set_databus(s[i]); | ||
pulse_clock(); | ||
delayMicroseconds(100); | ||
} | ||
} | ||
|
||
void NoritakeGu312Driver::send_command(uint8_t cmd) { | ||
set_is_command(true); | ||
set_databus(cmd); | ||
pulse_clock(); | ||
set_is_command(false); | ||
} | ||
|
||
void NoritakeGu312Driver::reset() { | ||
ESP_LOGI(LOG_TAG, "Resetting"); | ||
taskENTER_CRITICAL(&_spinlock); | ||
|
||
send_command(0b11000); // brightness max | ||
send_command(0b00010); // SCR2 on | ||
send_command(0b00111); // SCR2 graphic | ||
send_command(0b00100); // cursor auto increment | ||
|
||
send_command(0b01010); // set read pos SCR#1 Low | ||
set_databus(0x80); pulse_clock(); | ||
send_command(0b01011); // set read pos SCR#1 High | ||
set_databus(0x1); pulse_clock(); | ||
|
||
send_command(0b01100); // set read pos SCR#2 Low | ||
set_databus(0x0); pulse_clock(); | ||
send_command(0b01101); // set read pos SCR#2 High | ||
set_databus(0xc); pulse_clock(); | ||
|
||
// put all 0 in SCR1 | ||
send_command(0b01110); // set write pos Low | ||
set_databus(0x0); pulse_clock(); | ||
send_command(0b01111); // set write pos High | ||
set_databus(0xc); pulse_clock(); | ||
send_command(0b01000); // WRITE mode | ||
|
||
for(int i = 0; i < 192 * 8; i++) { | ||
set_databus(0xAA); | ||
pulse_clock(); | ||
} | ||
|
||
ESP_LOGI(LOG_TAG, "Reset complete"); | ||
|
||
taskEXIT_CRITICAL(&_spinlock); | ||
// while(true) vTaskDelay(portMAX_DELAY); | ||
} | ||
|
||
void NoritakeGu312Driver::set_power(bool power) { | ||
power_state = power; | ||
_set_pmu_internal(); | ||
} | ||
|
||
void NoritakeGu312Driver::clear() { | ||
taskENTER_CRITICAL(&_spinlock); | ||
|
||
taskEXIT_CRITICAL(&_spinlock); | ||
} | ||
|
||
inline uint8_t flipByte(uint8_t c){ | ||
char r=0; | ||
for(uint8_t i = 0; i < 8; i++){ | ||
r <<= 1; | ||
r |= c & 1; | ||
c >>= 1; | ||
} | ||
return r; | ||
} | ||
|
||
void NoritakeGu312Driver::write_fanta(const uint8_t * strides, size_t count) { | ||
taskENTER_CRITICAL(&_spinlock); | ||
send_command(0b01110); // set write pos Low | ||
set_databus(0); pulse_clock(); | ||
send_command(0b01111); // set write pos High | ||
set_databus(0xc); pulse_clock(); | ||
send_command(0b01000); // WRITE mode | ||
for(int i = 0; i < count; i++) { | ||
set_databus(flipByte(strides[i])); | ||
pulse_clock(); | ||
if(i % 2 != 0) { | ||
set_databus(0); | ||
for(int i = 0; i < 6; i++) pulse_clock(); | ||
} | ||
} | ||
send_command(0b00010); | ||
taskEXIT_CRITICAL(&_spinlock); | ||
} | ||
|
||
void NoritakeGu312Driver::set_bright(bool bright) { | ||
taskENTER_CRITICAL(&_spinlock); | ||
send_command(bright ? 0b11001 : 0b11011); | ||
// undocumented: can go from 11000 (100%) to as low as 11111 (undocumented) | ||
taskEXIT_CRITICAL(&_spinlock); | ||
} | ||
|
||
void NoritakeGu312Driver::_set_pmu_internal() { | ||
taskENTER_CRITICAL(&_spinlock); | ||
|
||
taskEXIT_CRITICAL(&_spinlock); | ||
} | ||
|
||
#endif |
Oops, something went wrong.