Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
akasaka committed Nov 27, 2024
2 parents ad4568e + c956bdd commit 6308f0b
Show file tree
Hide file tree
Showing 16 changed files with 39,893 additions and 51 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ More photos in [the gallery](https://pis-os.genjit.su/index.html#photos)
* [Kosaki Satoru - Haruhi no Omoi](https://www.youtube.com/watch?v=KMKoyHKYSNk): [MIDI](helper/chimes/haruhi_no_omoi.mid)
* [WAVE and DRAX - When Present Is Past](https://modarchive.org/index.php?request=view_by_moduleid&query=140039): [MIDI](helper/chimes/when_present_is_past.mid)
* [Kawada Mami - Hishoku no Sora](https://www.youtube.com/watch?v=FNl1ud7KxtI): [MIDI](helper/chimes/hishoku.mid)
* [? - Like The Wind (TMMS)](https://www.youtube.com/watch?v=uYpkri8Kv2E): [MIDI](helper/chimes/like_the_wind.mid)
* [FEX — Subways Of Your Mind (Like The Wind / The Most Mysterious Song On The Internet)](https://www.youtube.com/watch?v=uYpkri8Kv2E): [MIDI](helper/chimes/like_the_wind.mid)
* [NightRadio - Waiting Freqs](https://www.youtube.com/watch?v=_0MBreuq94Y): [MIDI](helper/chimes/waiting_freqs.mid)
* [NightRadio - The Way](https://nightradio.bandcamp.com/track/the-way): [MIDI](helper/chimes/the_way.mid)
* [Dougal & Gammer — Guitar Hero](https://youtu.be/ID4pO9epHPA?t=89): [MIDI](helper/chimes/gtrhero.mid), [MP3 Recording](docs/rec/guitarhero.mp3)
Expand Down Expand Up @@ -202,7 +202,8 @@ An ESP32-WROVER is required, because the firmware takes up 99.8% of an OTA parti
* Morio Denki 16101DS (see [below](#morio-denki-plasma-display-info), [driver](src/display/md_plasma.cpp), feature flag `HAS_OUTPUT_MD_PLASMA`)
* Winstar (sometimes sold as Vishay) WEG010016A in 8-bit parallel mode ([driver](src/display/ws0010.cpp), feature flag `HAS_OUTPUT_WS0010`). Includes BFI (Black Frame Insertion) for smoother operation and dimming. Datasheet backup: [Controller](docs/reference/datasheet/winstar/WS0010.pdf), [display](docs/reference/datasheet/winstar/WEG010016ALPP5N00000.pdf)
* Noritake ITRON GU-NNNx16-7000 series graphic VFDs in 8-bit parallel mode ([driver](src/display/gu7000.cpp), feature flag `HAS_OUTPUT_GU7000`). Datasheet backup before the bundled CDR got completely rotten: [140x16-7000](docs/reference/datasheet/noritake_itron/s-gu140x16g-7000_j04.pdf), [140x16-7100](docs/reference/datasheet/noritake_itron/s-gu140x16g-7100_j00.pdf), [112x16](docs/reference/datasheet/noritake_itron/s-gu112x16g-7000_j04.pdf)
* *Experimental:* [Akizuki Denshi K-875](https://akizukidenshi.com/img/contents/kairo/%E3%83%87%E3%83%BC%E3%82%BF/%E8%A1%A8%E7%A4%BA%E8%A3%85%E7%BD%AE/LED%E9%9B%BB%E5%85%89%E6%8E%B2%E7%A4%BA.pdf) ×4 for a 128x16 display (I couldn't resist not scooping some up in the Outlet Sale for 200 yen apiece). Known issues: small luma jitter sometimes, driver code is cursed. [Driver](src/display/akizuki_k875.cpp), feature flag `HAS_OUTPUT_AKIZUKI_K875`. [Datasheet backup](docs/reference/datasheet/akizuki/LED電光掲示.pdf)
* [Akizuki Denshi K-875](https://akizukidenshi.com/img/contents/kairo/%E3%83%87%E3%83%BC%E3%82%BF/%E8%A1%A8%E7%A4%BA%E8%A3%85%E7%BD%AE/LED%E9%9B%BB%E5%85%89%E6%8E%B2%E7%A4%BA.pdf) ×4 for a 128x16 display (I couldn't resist not scooping some up in the Outlet Sale for 200 yen apiece). Known issues: small luma jitter sometimes, driver code is cursed. [Driver](src/display/akizuki_k875.cpp), feature flag `HAS_OUTPUT_AKIZUKI_K875`. [Datasheet backup](docs/reference/datasheet/akizuki/LED電光掲示.pdf)
* *Experimental* Noritake ITRON GU-NNNx16-312. Mine is 192px wide, taken out of an old bus display panel (labeled GU-192x16-505), no datasheet, no other technical info aside from that written in the [driver](src/display/gu312.cpp)'s comments. Autoincrement is weird so there is a lot of write amplification in the driver. Supports Vsync/FEP (untested). No software heater power-off. Feature flag `HAS_OUTPUT_GU312`.

### Speaker (at least one required)

Expand Down Expand Up @@ -237,6 +238,7 @@ An ESP32-WROVER is required, because the firmware takes up 99.8% of an OTA parti

* Keypad/D-Pad. Set feature flag `HAS_KEYPAD` and define `const keypad_definition_t HWCONF_KEYPAD` in the device definition. [Driver](src/input/keypad.cpp)
* Touch plane. E.g. a faceplate with touch sensitive arrow keys to work in place of a D-pad. Set feature flag `HAS_TOUCH_PLANE` and define `const touch_plane_definition_t HWCONF_TOUCH_PLANE` in the device definition. [Driver](src/input/touch_plane.cpp)
* *Experimental/Untested* IR Remote. Set feature flag `HAS_IR_RECEIVER` and define `const infrared_definition_t HWCONF_IR_BUTTONS` in the device definition. [Driver](src/input/infrared.cpp)

### Others

Expand Down
26 changes: 23 additions & 3 deletions include/devices/big_noritake.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

#include <hal/gpio_hal.h>
#include <input/keypad.h>
#include <input/infrared.h>

#define HAS_OUTPUT_GU312
#define HAS_KEYPAD
#define HAS_VARYING_BRIGHTNESS
#define HAS_MOTION_SENSOR
#define HAS_IR_RECEIVER

// Plasma Information System OS (not DOS, there's no disk in it!)
#define PRODUCT_NAME "LongPIS-OS"
Expand All @@ -14,6 +18,11 @@
const gpio_num_t HWCONF_BEEPER_GPIO = GPIO_NUM_33;
const uint8_t HWCONF_BEEPER_PWM_CHANNEL = 0;

// ---- Connection to light sensors ----
const gpio_num_t HWCONF_MOTION_GPIO = GPIO_NUM_39;
const gpio_num_t HWCONF_LIGHTSENSE_GPIO = GPIO_NUM_36;
const gpio_num_t HWCONF_IR_RECV_GPIO = GPIO_NUM_14;

// ---- Connection to display ----
const gpio_num_t HWCONF_GU312_DATABUS_GPIOS[] = {
GPIO_NUM_5,
Expand All @@ -27,15 +36,26 @@ const gpio_num_t HWCONF_GU312_DATABUS_GPIOS[] = {
};
const gpio_num_t HWCONF_GU312_CD_GPIO = GPIO_NUM_19;
const gpio_num_t HWCONF_GU312_WR_GPIO = GPIO_NUM_18;
const gpio_num_t HWCONF_GU312_BLANKING_GPIO = GPIO_NUM_12;
const gpio_num_t HWCONF_GU312_FEP_GPIO = GPIO_NUM_13; //<- optional, can be GPIO_NUM_NC

#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_27, KEY_RIGHT},
{GPIO_NUM_32, KEY_LEFT},
{GPIO_NUM_34, KEY_UP},
{GPIO_NUM_27, KEY_DOWN},
{GPIO_NUM_35, KEY_HEADPAT},
{GPIO_NUM_35, KEY_DOWN},
};

const infrared_definition_t HWCONF_IR_BUTTONS = {
{
{
.protocol = IRPROTO_RC5,
.value = 0 // dummy for test
},
KEY_UP
}
};
4 changes: 3 additions & 1 deletion include/display/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ static AkizukiK875Driver display_driver(
static NoritakeGu312Driver display_driver(
HWCONF_GU312_DATABUS_GPIOS,
HWCONF_GU312_CD_GPIO,
HWCONF_GU312_WR_GPIO
HWCONF_GU312_WR_GPIO,
HWCONF_GU312_BLANKING_GPIO,
HWCONF_GU312_FEP_GPIO
);
#else
#error Display module type not selected
Expand Down
12 changes: 6 additions & 6 deletions include/display/gu312.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ class NoritakeGu312Driver: public DisplayDriver {
/// @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
/// @param vsync Pin connected to the display controller's FEP pin (optional)
NoritakeGu312Driver(
const gpio_num_t databus[8],
const gpio_num_t cd,
const gpio_num_t wr
// const gpio_num_t blank
const gpio_num_t wr,
const gpio_num_t blank,
const gpio_num_t vsync = gpio_num_t::GPIO_NUM_NC
);

void initialize();
Expand All @@ -36,14 +38,12 @@ class NoritakeGu312Driver: public DisplayDriver {
gpio_num_t databus_gpios[8];
gpio_num_t cd_gpio;
gpio_num_t wr_gpio;
gpio_num_t blank_gpio;
gpio_num_t fep_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
21 changes: 21 additions & 0 deletions include/input/infrared.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include "keys.h"
#include <vector>

// @warning must match definitions of IRRecv library
typedef enum infrared_protocol {
IRPROTO_RC5 = 1,
IRPROTO_RC6 = 2,
IRPROTO_NEC = 3,
IRPROTO_SONY = 4
} infrared_protocol_t;

typedef struct infrared_identifier {
infrared_protocol_t protocol;
uint64_t value;
uint32_t address;
uint32_t command;
} infrared_identifier_t;

typedef std::vector<std::pair<const infrared_identifier_t, const key_id_t>> infrared_definition_t;
void infrared_start();
2 changes: 1 addition & 1 deletion include/service/owm/weather.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define FORECAST_WEATHER_HOURS 36

typedef enum weather_condition_code {
UNKNOWN = 0,
UNKNOWN_CONDITIONS = 0,

THUNDERSTORM = 200,

Expand Down
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
; https://docs.platformio.org/page/projectconf.html

[common]
build_flags = -DCORE_DEBUG_LEVEL=3 -DPDFB_PERF_LOGS -DPDFB_PERF_LOG_INTERVAL=1200 -DGP_NO_OTA -DGP_NO_DNS -DGP_NO_MDNS
build_flags = -DCORE_DEBUG_LEVEL=3 -DPDFB_PERF_LOGS -DPDFB_PERF_LOG_INTERVAL=1200 -DGP_NO_OTA -DGP_NO_DNS -DGP_NO_MDNS -D_IR_ENABLE_DEFAULT_=false -DDECODE_NEC=true -DDECODE_RC5=true -DDECODE_RC6=true -DDECODE_SONY=true

[env]
platform = [email protected]
Expand All @@ -22,6 +22,7 @@ lib_deps =
gyverlibs/GyverPortal@^3.6.6
h2zero/NimBLE-Arduino@^1.4.2
fortyseveneffects/MIDI Library@^5.0.2
crankyoldgit/IRremoteESP8266@^2.8.6
extra_scripts =
pre:helper/env-extra.py
pre:helper/aquestalk-detect.py
Expand Down
2 changes: 1 addition & 1 deletion src/app/idle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ void weather_overlay_update() {
case SCATTERED_CLOUDS:
case BROKEN_CLOUDS:
case OVERCAST:
case UNKNOWN:
case UNKNOWN_CONDITIONS:
default:
// No rain, no snow, nothing
rain->set_intensity(0);
Expand Down
54 changes: 26 additions & 28 deletions src/display/gu312.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
// +------+
// 33 34





#if HAS(OUTPUT_GU312)
#include "display/gu312.h"
#include <esp32-hal-log.h>
Expand All @@ -41,18 +37,21 @@ 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
const gpio_num_t wr,
const gpio_num_t blank,
const gpio_num_t vsync
) {
for(int i = 0; i < 8; i++) {
databus_gpios[i] = databus[i];
}
cd_gpio = cd;
wr_gpio = wr;
power_state = false;
blank_gpio = blank;
fep_gpio = vsync;
}

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);
ESP_LOGI(LOG_TAG, "Initializing Noritake Itron GU312 with data bus: %i %i %i %i %i %i %i %i, cd=%i, wr=%i, bl=%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, blank_gpio);

gpio_config_t io_conf = {
.mode = GPIO_MODE_OUTPUT,
Expand All @@ -65,12 +64,24 @@ void NoritakeGu312Driver::initialize() {

io_conf.pin_bit_mask |= 1ULL << cd_gpio;
io_conf.pin_bit_mask |= 1ULL << wr_gpio;
io_conf.pin_bit_mask |= 1ULL << blank_gpio;

ESP_ERROR_CHECK(gpio_config(&io_conf));

gpio_set_level(blank_gpio, 1);
gpio_set_level(wr_gpio, 1);
gpio_set_level(cd_gpio, 0);

if(fep_gpio != GPIO_NUM_NC) {
gpio_config_t fep_conf = {
.pin_bit_mask = 1ULL << fep_gpio,
.mode = GPIO_MODE_INPUT,
.pull_up_en = gpio_pullup_t::GPIO_PULLUP_DISABLE,
.pull_down_en = gpio_pulldown_t::GPIO_PULLDOWN_DISABLE,
};
ESP_ERROR_CHECK(gpio_config(&io_conf));
}

delay(500);
}

Expand All @@ -96,16 +107,6 @@ void NoritakeGu312Driver::set_is_command(bool rs) {
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);
Expand Down Expand Up @@ -151,14 +152,11 @@ void NoritakeGu312Driver::reset() {
}

void NoritakeGu312Driver::set_power(bool power) {
power_state = power;
_set_pmu_internal();
gpio_set_level(blank_gpio, power ? 1 : 0);
}

void NoritakeGu312Driver::clear() {
taskENTER_CRITICAL(&_spinlock);

taskEXIT_CRITICAL(&_spinlock);
ESP_LOGW(LOG_TAG, "Not supported!");
}

inline uint8_t flipByte(uint8_t c){
Expand All @@ -173,6 +171,12 @@ inline uint8_t flipByte(uint8_t c){

void NoritakeGu312Driver::write_fanta(const uint8_t * strides, size_t count) {
taskENTER_CRITICAL(&_spinlock);
if(fep_gpio != GPIO_NUM_NC) {
// wait for frame pulse
while(!gpio_get_level(fep_gpio));
while(gpio_get_level(fep_gpio));
}

send_command(0b01110); // set write pos Low
set_databus(0); pulse_clock();
send_command(0b01111); // set write pos High
Expand All @@ -197,10 +201,4 @@ void NoritakeGu312Driver::set_bright(bool bright) {
taskEXIT_CRITICAL(&_spinlock);
}

void NoritakeGu312Driver::_set_pmu_internal() {
taskENTER_CRITICAL(&_spinlock);

taskEXIT_CRITICAL(&_spinlock);
}

#endif
69 changes: 69 additions & 0 deletions src/input/infrared.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "input/infrared.h"
#include <device_config.h>
#include <esp32-hal-log.h>
#include <map>
#include <os_config.h>

#if HAS(IR_RECEIVER)
// NB: disable all the stuff of no use in the platformio.ini file!
#include <IRrecv.h>
#endif

static char LOG_TAG[] = "IRRC";

static TaskHandle_t hTask;

static key_id_t last_pressed = KEY_MAX_INVALID;

#if HAS(IR_RECEIVER)
static IRrecv receiver(HWCONF_IR_RECV_GPIO);

static void ir_task(void*) {
static decode_results results;
while(1) {
if(receiver.decode(&results)) {
ESP_LOGI(LOG_TAG, "IR code TYPE=%i, VALUE=%i, ADDRESS=%i, COMMAND=%i", results.decode_type, results.value, results.address, results.command);

for(auto &mapping: HWCONF_IR_BUTTONS) {
const infrared_identifier_t * id = &mapping.first;
if(id->protocol == results.decode_type &&
id->address == results.address &&
id->command == results.command &&
id->value == results.value) {

if(last_pressed != KEY_MAX_INVALID) {
if(last_pressed == mapping.second)
break;
hid_set_key_state(last_pressed, false);
}

last_pressed = mapping.second;
hid_set_key_state(mapping.second, true);
}
}
} else {
if(last_pressed != KEY_MAX_INVALID) {
hid_set_key_state(last_pressed, false);
last_pressed = KEY_MAX_INVALID;
}
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
#endif

void infrared_start() {
#if HAS(IR_RECEIVER)
receiver.enableIRIn(true);

ESP_LOGI(LOG_TAG, "Creating task");
xTaskCreate(
ir_task,
"IRRC",
4096,
nullptr,
pisosTASK_PRIORITY_KEYPAD,
&hTask
);
#endif
}
6 changes: 4 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#include <graphics/font.h>
#include <console.h>
#include <sensor/sensors.h>
#include <input/touch_plane.h>
#include <input/keypad.h>
#include <sound/yukkuri.h>
#include <sound/melodies.h>
#include <network/netmgr.h>
Expand Down Expand Up @@ -204,6 +202,10 @@ void bringup_hid() {
#if HAS(KEYPAD)
keypad_start();
ESP_LOGI(LOG_TAG, "Keypad ready");
#endif
#if HAS(IR_RECEIVER)
infrared_start();
ESP_LOGI(LOG_TAG, "Infrared ready");
#endif
if(prefs_get_bool(PREFS_KEY_BUTTON_BEEP)) {
hid_set_key_beeper(beepola);
Expand Down
Loading

0 comments on commit 6308f0b

Please sign in to comment.