From 3babe3f1ef26748ac0e3ff64b88d5ff17fdc57c5 Mon Sep 17 00:00:00 2001 From: kazu Date: Sun, 3 Jan 2021 16:21:20 +0100 Subject: [PATCH] some refactoring, minor code changes added a small class for SNESController reading --- Platforms.h | 8 ++- ext/ctrl/SNESController.h | 122 ++++++++++++++++++++++++++++++++++++++ ext/lcd/ST7735.h | 22 ++++++- ext/sens/INA219.h | 20 +++---- io/GPIO.h | 20 ++++++- io/HardSPI.h | 5 +- io/I2S.h | 11 ++-- io/SoftSPI.h | 2 +- 8 files changed, 188 insertions(+), 22 deletions(-) create mode 100644 ext/ctrl/SNESController.h diff --git a/Platforms.h b/Platforms.h index c71b96b..3951083 100644 --- a/Platforms.h +++ b/Platforms.h @@ -9,9 +9,11 @@ #define WROOM32_DEVKIT 32 #define TTGO 33 +#define TEENSY_41 41 #define ESP8266 (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU) #define ESP32 (PLATFORM == WROOM32_DEVKIT) || (PLATFORM == TTGO) +#define TEENSY (PLATFORM == TEENSY_41) #ifndef PLATFORM #error "PLATFORM compile time variable not defined" @@ -29,9 +31,13 @@ #define DELAY_US(us) os_delay_us(us) #define IN_FLASH ICACHE_FLASH_ATTR +#elif (TEENSY) + + #pragma message "Using Teensy" + #else - #error "unsupported platform"; + #error "Platforms.h: unsupported platform"; #endif diff --git a/ext/ctrl/SNESController.h b/ext/ctrl/SNESController.h new file mode 100644 index 0000000..65bab03 --- /dev/null +++ b/ext/ctrl/SNESController.h @@ -0,0 +1,122 @@ +#ifndef SNES_CONTROLLER_H +#define SNES_CONTROLLER_H + +#include "../../io/GPIO.h" + + +/** https://fpgalover.com/images/manuals/SNES/time.JPG */ +template class SNESController { + +public: + + union State { + + uint16_t raw; + + State() : raw(0) {} + + State(uint16_t raw) : raw(raw) {} + + struct { + + uint8_t dummy1 : 1; + uint8_t dummy2 : 1; + uint8_t dummy3 : 1; + uint8_t dummy4 : 1; + uint8_t r : 1; + uint8_t l : 1; + uint8_t x : 1; + uint8_t a : 1; + + uint8_t right : 1; + uint8_t left : 1; + uint8_t down : 1; + uint8_t up : 1; + uint8_t start : 1; + uint8_t select : 1; + uint8_t y : 1; + uint8_t b : 1; + + }; + + bool operator != (const State o) const {return raw != o.raw;} + + /** write current state into the given 12+1 char* */ + void toString(char* dst) { + dst[ 0] = !r ? 'R' : ' '; + dst[ 1] = !l ? 'L' : ' '; + dst[ 2] = !x ? 'X' : ' '; + dst[ 3] = !a ? 'A' : ' '; + dst[ 4] = !right ? 'r' : ' '; + dst[ 5] = !left ? 'l' : ' '; + dst[ 6] = !down ? 'd' : ' '; + dst[ 7] = !up ? 'u' : ' '; + dst[ 8] = !start ? 'S' : ' '; + dst[ 9] = !select ? 's' : ' '; + dst[10] = !y ? 'Y' : ' '; + dst[11] = !b ? 'B' : ' '; + dst[12] = 0; + } + + + }; + +public: + + /** ctor */ + SNESController() { + MyGPIO::setInput(PIN_DATA); + MyGPIO::setOutput(PIN_LATCH); + MyGPIO::setOutput(PIN_CLK); + } + + + /** read the current state from the controller */ + State read() { + + // latch the current data (remember state) + latch(); + + // read all 16 data bits + uint16_t res = 0; + for (uint8_t i = 0; i < 16; ++i) { + res <<= 1; + res |= readBit(); + } + + // wrap + return State(res); + + } + +private: + + void latch() { + + // ensure CLK is HIGH + MyGPIO::set(PIN_CLK); + + // send latch impulse + MyGPIO::set(PIN_LATCH); + wait(); + MyGPIO::clear(PIN_LATCH); + wait(); + + } + + uint8_t readBit() { + MyGPIO::set(PIN_CLK); + wait(); + MyGPIO::clear(PIN_CLK); + uint8_t res = MyGPIO::get(PIN_DATA); + wait(); + return res; + } + + void wait() { + for (uint8_t i = 0; i < 128; ++i) {asm("nop");} + } + +}; + +#endif diff --git a/ext/lcd/ST7735.h b/ext/lcd/ST7735.h index 9e8a525..6762f1b 100644 --- a/ext/lcd/ST7735.h +++ b/ext/lcd/ST7735.h @@ -230,8 +230,8 @@ private: public: - void flush(const uint16_t* data) { - + void startWrite() { + select(); sendCommand(ST7735_CASET); // Column addr set @@ -249,6 +249,22 @@ public: sendCommand(ST7735_RAMWR); modeData(); + + } + + void writePixel(const uint16_t rgb) { + spi.writeByte(rgb >> 0); + spi.writeByte(rgb >> 8); + } + + void stopWrite() { + deselect(); + } + + void flush(const uint16_t* data) { + + startWrite(); + /* for (int i = 0; i < (V*H); ++i) { const uint16_t color = data[i]; @@ -262,7 +278,7 @@ public: spi.write((const uint8_t*)data, V*H*sizeof(uint16_t)); - deselect(); + stopWrite(); } diff --git a/ext/sens/INA219.h b/ext/sens/INA219.h index 3a30adb..ae0ceb6 100644 --- a/ext/sens/INA219.h +++ b/ext/sens/INA219.h @@ -19,7 +19,7 @@ public: struct Voltages { - int vShunt; // in uV * 10(!!!) + int16_t vShunt; // in uV * 10(!!!) int16_t vBus; // in mV int getMilliAmps(int shunt_milliOhm) const { @@ -68,24 +68,24 @@ public: const uint8_t pg = (cfg & 0b01100000000000) >> 11; const uint8_t brng = (cfg & 0b10000000000000) >> 13; printf("INA219\n"); - printf("- Mode: %d", mode); - printf("- SADC: %d", sadc); - printf("- BADC: %d", badc); - printf("PG (shunt divider) %d", (1<> 3) * 4; // lower 3 bits are status indicators -> remove, the LSB equals 4 mV -> * 4 + return (int16_t)((getU16(buf) >> 3) * 4); // lower 3 bits are status indicators -> remove, the LSB equals 4 mV -> * 4 } /** convert to bytes into a uV reading */ - int getShuntVoltage(const uint8_t* buf) { - return ((int)((int16_t)getU16(buf))); // NOTE: LSB = 10 uV + int16_t getShuntVoltage(const uint8_t* buf) { + return (int16_t)getU16(buf); // NOTE: LSB = 10 uV } uint16_t getU16(const uint8_t* buf) { diff --git a/io/GPIO.h b/io/GPIO.h index d6ea87f..78313b1 100644 --- a/io/GPIO.h +++ b/io/GPIO.h @@ -177,10 +177,28 @@ } }; + +#elif TEENSY + + struct MyGPIO { + + public: + + static void setOutput(uint8_t pin) {pinMode(pin, OUTPUT);} + + static void setInput(uint8_t pin) {pinMode(pin, INPUT);} + + static void clear(uint8_t pin) {digitalWriteFast(pin, 0);} + + static void set(uint8_t pin) {digitalWriteFast(pin, 1);} + + static uint8_t get(uint8_t pin) {return digitalReadFast(pin);} + + }; #else - #error "unsupported platform"; + #error "GPIO: unsupported platform"; #endif diff --git a/io/HardSPI.h b/io/HardSPI.h index f2b18fe..3ef0ff4 100644 --- a/io/HardSPI.h +++ b/io/HardSPI.h @@ -17,7 +17,7 @@ template class HardSPI { //class HardSPI { - static constexpr int MAX_LEN = 4000; + static constexpr int MAX_LEN = 8192; spi_device_handle_t spi; @@ -57,7 +57,7 @@ private: // DEVICE specific options memset(&devcfg, 0, sizeof(devcfg)); - devcfg.clock_speed_hz = 10 * 1000 * 1000; + devcfg.clock_speed_hz = 20 * 1000 * 1000; // IMPORTANT! devcfg.mode = 0; devcfg.spics_io_num = -1;//PIN_NUM_CS; // currently not used devcfg.queue_size = 2; @@ -104,6 +104,7 @@ public: } + void read(uint8_t* dst, size_t len) { // sanity check diff --git a/io/I2S.h b/io/I2S.h index e71bd97..329ed1c 100644 --- a/io/I2S.h +++ b/io/I2S.h @@ -28,13 +28,16 @@ public: cfg.mode = static_cast(I2S_MODE_MASTER | I2S_MODE_TX); #endif - cfg.dma_buf_count = 6; + // cfg.dma_buf_count = 6; + // cfg.dma_buf_len = 128; + + cfg.dma_buf_count = 16; cfg.dma_buf_len = 128; cfg.sample_rate = 44100; cfg.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT; cfg.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; //2-channels - cfg.communication_format = I2S_COMM_FORMAT_I2S_MSB; + cfg.communication_format = I2S_COMM_FORMAT_STAND_I2S;//I2S_COMM_FORMAT_I2S_MSB; cfg.intr_alloc_flags = 0; //Default interrupt priority @@ -72,9 +75,9 @@ public: } /** add the given samples for playback. returns the number of added samples, which might be less in case of timeouts */ - size_t add(const uint8_t* data, const size_t len) { + size_t add(const uint8_t* data, const size_t len_bytes) { size_t written; - i2s_write(port, data, len, &written, portMAX_DELAY); + i2s_write(port, data, len_bytes, &written, portMAX_DELAY); return written; } diff --git a/io/SoftSPI.h b/io/SoftSPI.h index a79bbaa..9eeb723 100644 --- a/io/SoftSPI.h +++ b/io/SoftSPI.h @@ -88,7 +88,7 @@ public: writeByte((word>>0)&0xFF); } - void IRAM_ATTR writeByte(uint8_t byte) { + inline void IRAM_ATTR writeByte(uint8_t byte) { writeBit(byte & BIT( 7)); writeBit(byte & BIT( 6)); writeBit(byte & BIT( 5));