some refactoring,
minor code changes added a small class for SNESController reading
This commit is contained in:
@@ -9,9 +9,11 @@
|
|||||||
#define WROOM32_DEVKIT 32
|
#define WROOM32_DEVKIT 32
|
||||||
#define TTGO 33
|
#define TTGO 33
|
||||||
|
|
||||||
|
#define TEENSY_41 41
|
||||||
|
|
||||||
#define ESP8266 (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU)
|
#define ESP8266 (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU)
|
||||||
#define ESP32 (PLATFORM == WROOM32_DEVKIT) || (PLATFORM == TTGO)
|
#define ESP32 (PLATFORM == WROOM32_DEVKIT) || (PLATFORM == TTGO)
|
||||||
|
#define TEENSY (PLATFORM == TEENSY_41)
|
||||||
|
|
||||||
#ifndef PLATFORM
|
#ifndef PLATFORM
|
||||||
#error "PLATFORM compile time variable not defined"
|
#error "PLATFORM compile time variable not defined"
|
||||||
@@ -29,9 +31,13 @@
|
|||||||
#define DELAY_US(us) os_delay_us(us)
|
#define DELAY_US(us) os_delay_us(us)
|
||||||
#define IN_FLASH ICACHE_FLASH_ATTR
|
#define IN_FLASH ICACHE_FLASH_ATTR
|
||||||
|
|
||||||
|
#elif (TEENSY)
|
||||||
|
|
||||||
|
#pragma message "Using Teensy"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#error "unsupported platform";
|
#error "Platforms.h: unsupported platform";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
122
ext/ctrl/SNESController.h
Normal file
122
ext/ctrl/SNESController.h
Normal file
@@ -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 <int PIN_LATCH, int PIN_DATA, int PIN_CLK> 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
|
||||||
@@ -230,7 +230,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void flush(const uint16_t* data) {
|
void startWrite() {
|
||||||
|
|
||||||
select();
|
select();
|
||||||
|
|
||||||
@@ -249,6 +249,22 @@ public:
|
|||||||
sendCommand(ST7735_RAMWR);
|
sendCommand(ST7735_RAMWR);
|
||||||
|
|
||||||
modeData();
|
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) {
|
for (int i = 0; i < (V*H); ++i) {
|
||||||
const uint16_t color = data[i];
|
const uint16_t color = data[i];
|
||||||
@@ -262,7 +278,7 @@ public:
|
|||||||
spi.write((const uint8_t*)data, V*H*sizeof(uint16_t));
|
spi.write((const uint8_t*)data, V*H*sizeof(uint16_t));
|
||||||
|
|
||||||
|
|
||||||
deselect();
|
stopWrite();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public:
|
|||||||
|
|
||||||
struct Voltages {
|
struct Voltages {
|
||||||
|
|
||||||
int vShunt; // in uV * 10(!!!)
|
int16_t vShunt; // in uV * 10(!!!)
|
||||||
int16_t vBus; // in mV
|
int16_t vBus; // in mV
|
||||||
|
|
||||||
int getMilliAmps(int shunt_milliOhm) const {
|
int getMilliAmps(int shunt_milliOhm) const {
|
||||||
@@ -68,24 +68,24 @@ public:
|
|||||||
const uint8_t pg = (cfg & 0b01100000000000) >> 11;
|
const uint8_t pg = (cfg & 0b01100000000000) >> 11;
|
||||||
const uint8_t brng = (cfg & 0b10000000000000) >> 13;
|
const uint8_t brng = (cfg & 0b10000000000000) >> 13;
|
||||||
printf("INA219\n");
|
printf("INA219\n");
|
||||||
printf("- Mode: %d", mode);
|
printf("- Mode: %d\n", mode);
|
||||||
printf("- SADC: %d", sadc);
|
printf("- SADC: %d\n", sadc);
|
||||||
printf("- BADC: %d", badc);
|
printf("- BADC: %d\n", badc);
|
||||||
printf("PG (shunt divider) %d", (1<<pg));
|
printf("PG (shunt divider) %d\n", (1<<pg));
|
||||||
if (brng) {printf("- bus voltage range [0:16]");}
|
if (brng) {printf("- bus voltage range [0:16]\n");}
|
||||||
else {printf("- bus voltage range [0:32]");}
|
else {printf("- bus voltage range [0:32]\n");}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** convert to bytes into a mV reading */
|
/** convert to bytes into a mV reading */
|
||||||
int16_t getBusVoltage(const uint8_t* buf) {
|
int16_t getBusVoltage(const uint8_t* buf) {
|
||||||
return (getU16(buf) >> 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 */
|
/** convert to bytes into a uV reading */
|
||||||
int getShuntVoltage(const uint8_t* buf) {
|
int16_t getShuntVoltage(const uint8_t* buf) {
|
||||||
return ((int)((int16_t)getU16(buf))); // NOTE: LSB = 10 uV
|
return (int16_t)getU16(buf); // NOTE: LSB = 10 uV
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getU16(const uint8_t* buf) {
|
uint16_t getU16(const uint8_t* buf) {
|
||||||
|
|||||||
20
io/GPIO.h
20
io/GPIO.h
@@ -178,9 +178,27 @@
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#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
|
#else
|
||||||
|
|
||||||
#error "unsupported platform";
|
#error "GPIO: unsupported platform";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
template <int PIN_NUM_MISO, int PIN_NUM_MOSI, int PIN_NUM_CLK> class HardSPI {
|
template <int PIN_NUM_MISO, int PIN_NUM_MOSI, int PIN_NUM_CLK> class HardSPI {
|
||||||
//class HardSPI {
|
//class HardSPI {
|
||||||
|
|
||||||
static constexpr int MAX_LEN = 4000;
|
static constexpr int MAX_LEN = 8192;
|
||||||
|
|
||||||
spi_device_handle_t spi;
|
spi_device_handle_t spi;
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ private:
|
|||||||
|
|
||||||
// DEVICE specific options
|
// DEVICE specific options
|
||||||
memset(&devcfg, 0, sizeof(devcfg));
|
memset(&devcfg, 0, sizeof(devcfg));
|
||||||
devcfg.clock_speed_hz = 10 * 1000 * 1000;
|
devcfg.clock_speed_hz = 20 * 1000 * 1000; // IMPORTANT!
|
||||||
devcfg.mode = 0;
|
devcfg.mode = 0;
|
||||||
devcfg.spics_io_num = -1;//PIN_NUM_CS; // currently not used
|
devcfg.spics_io_num = -1;//PIN_NUM_CS; // currently not used
|
||||||
devcfg.queue_size = 2;
|
devcfg.queue_size = 2;
|
||||||
@@ -104,6 +104,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void read(uint8_t* dst, size_t len) {
|
void read(uint8_t* dst, size_t len) {
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
|
|||||||
11
io/I2S.h
11
io/I2S.h
@@ -28,13 +28,16 @@ public:
|
|||||||
cfg.mode = static_cast<i2s_mode_t>(I2S_MODE_MASTER | I2S_MODE_TX);
|
cfg.mode = static_cast<i2s_mode_t>(I2S_MODE_MASTER | I2S_MODE_TX);
|
||||||
#endif
|
#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.dma_buf_len = 128;
|
||||||
|
|
||||||
cfg.sample_rate = 44100;
|
cfg.sample_rate = 44100;
|
||||||
cfg.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
|
cfg.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
|
||||||
cfg.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; //2-channels
|
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
|
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 */
|
/** 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;
|
size_t written;
|
||||||
i2s_write(port, data, len, &written, portMAX_DELAY);
|
i2s_write(port, data, len_bytes, &written, portMAX_DELAY);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public:
|
|||||||
writeByte((word>>0)&0xFF);
|
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( 7));
|
||||||
writeBit(byte & BIT( 6));
|
writeBit(byte & BIT( 6));
|
||||||
writeBit(byte & BIT( 5));
|
writeBit(byte & BIT( 5));
|
||||||
|
|||||||
Reference in New Issue
Block a user