Skip to content

Commit

Permalink
WIP - support for t-deck
Browse files Browse the repository at this point in the history
  • Loading branch information
cgreening committed Dec 6, 2024
1 parent d51d32f commit 1456f8f
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 60 deletions.
Binary file added firmware/data/manic.z80
Binary file not shown.
46 changes: 46 additions & 0 deletions firmware/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,49 @@ build_flags =
-DSD_CARD_MOSI=GPIO_NUM_23
-DSD_CARD_CLK=GPIO_NUM_18
-DSD_CARD_CS=GPIO_NUM_5


[env:lilygo-t-keyboard]
extends = esp32_common
board = esp32-s3-devkitc-1
board_build.arduino.memory_type = qio_opi
build_unflags =
${common.build_unflags}
build_flags =
${common.build_flags}
-DBOARD_HAS_PSRAM
-DLILYGO_T_KEYBOARD
; TFT setup
-DTFT_ST7789
-DBOARD_POWERON=GPIO_NUM_10
-DTFT_SPI_FREQUENCY=SPI_MASTER_FREQ_40M
-DTFT_RGB_ORDER=TFT_BGR
-DTFT_WIDTH=320
-DTFT_HEIGHT=240
-DTFT_SCLK=GPIO_NUM_40
-DTFT_MISO=GPIO_NUM_38
-DTFT_MOSI=GPIO_NUM_41
-DTFT_RST=GPIO_NUM_NC
-DTFT_DC=GPIO_NUM_11
-DTFT_CS=GPIO_NUM_12
-DTFT_BL=GPIO_NUM_42
; audio settings
; SD card
; TODO
; -DUSE_SDCARD
; -DSD_CARD_CS=GPIO_NUM_39
; audio settings
-DI2S_SPEAKER_SERIAL_CLOCK=GPIO_NUM_7
-DI2S_SPEAKER_LEFT_RIGHT_CLOCK=GPIO_NUM_5
-DI2S_SPEAKER_SERIAL_DATA=GPIO_NUM_6
; nunchuck
; -DNUNCHUK_CLOCK=GPIO_NUM_43
; -DNUNCHUK_DATA=GPIO_NUM_44
; Adafruit Seesaw
; -DSEESAW_CLOCK=GPIO_NUM_43
; -DSEESAW_DATA=GPIO_NUM_44
; enable mounting the SD Card on USB
; -DENABLE_MSC
-DARDUINO_USB_MODE
-DARDUINO_USB_CDC_ON_BOOT
; -DNO_GLOBAL_SERIAL
30 changes: 1 addition & 29 deletions firmware/src/AudioOutput/I2SBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,6 @@ void I2SBase::stop()
i2s_driver_uninstall(m_i2s_port);
}

// high pass filter to remove any DC offset
typedef float REAL;
#define NBQ 4
REAL biquada[]={0.9998380079498859,-1.9996254961162483,0.9987226842352888,-1.998510171954402,0.9915562184741177,-1.9913436697006053,-0.9854172919732774};
REAL biquadb[]={0.9999999999999998,-1.9997906555550162,0.9999999999999999,-1.9998054508889258,1,-1.9998831022849304,-1};
REAL gain=1.0123741492041554;
REAL xyv[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

REAL applyfilter(REAL v)
{
int i,b,xp=0,yp=3,bqp=0;
REAL out=v/gain;
for (i=14; i>0; i--) {xyv[i]=xyv[i-1];}
for (b=0; b<NBQ; b++)
{
int len=(b==NBQ-1)?1:2;
xyv[xp]=out;
for(i=0; i<len; i++) { out+=xyv[xp+len-i]*biquadb[bqp+i]-xyv[yp+len-i]*biquada[bqp+i]; }
bqp+=len;
xyv[yp]=out;
xp=yp; yp+=len+1;
}
return out;
}

void I2SBase::write(const uint8_t *samples, int count)
{
int sample_index = 0;
Expand All @@ -55,11 +30,8 @@ void I2SBase::write(const uint8_t *samples, int count)
for (int i = 0; i < NUM_FRAMES_TO_SEND && sample_index < count; i++)
{
float sample = samples[i]/255.0f;
sample = applyfilter(sample);
// soft clipping
sample = tanh(sample);
// scale up to 16 bits
sample = sample * 32767.0f;
sample = sample * 5000.0f;
// volume adjustment
sample = sample * mVolume / 10;
int16_t sample16 = process_sample(sample);
Expand Down
68 changes: 68 additions & 0 deletions firmware/src/Emulator/keyboard_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,72 @@ const std::unordered_map<SpecKeys, char> specKeyToLetter = {
{ SPECKEY_X, 'X' },
{ SPECKEY_Y, 'Y' },
{ SPECKEY_Z, 'Z' },
};

// map letters to the SpecKeys enum
const std::unordered_map<char, SpecKeys> letterToSpecKey = {
{ '0', SPECKEY_0 },
{ '1', SPECKEY_1 },
{ '2', SPECKEY_2 },
{ '3', SPECKEY_3 },
{ '4', SPECKEY_4 },
{ '5', SPECKEY_5 },
{ '6', SPECKEY_6 },
{ '7', SPECKEY_7 },
{ '8', SPECKEY_8 },
{ '9', SPECKEY_9 },
{ 'A', SPECKEY_A },
{ 'B', SPECKEY_B },
{ 'C', SPECKEY_C },
{ 'D', SPECKEY_D },
{ 'E', SPECKEY_E },
{ 'F', SPECKEY_F },
{ 'G', SPECKEY_G },
{ 'H', SPECKEY_H },
{ 'I', SPECKEY_I },
{ 'J', SPECKEY_J },
{ 'K', SPECKEY_K },
{ 'L', SPECKEY_L },
{ 'M', SPECKEY_M },
{ 'N', SPECKEY_N },
{ 'O', SPECKEY_O },
{ 'P', SPECKEY_P },
{ 'Q', SPECKEY_Q },
{ 'R', SPECKEY_R },
{ 'S', SPECKEY_S },
{ 'T', SPECKEY_T },
{ 'U', SPECKEY_U },
{ 'V', SPECKEY_V },
{ 'W', SPECKEY_W },
{ 'X', SPECKEY_X },
{ 'Y', SPECKEY_Y },
{ 'Z', SPECKEY_Z },
{ 'a', SPECKEY_A },
{ 'b', SPECKEY_B },
{ 'c', SPECKEY_C },
{ 'd', SPECKEY_D },
{ 'e', SPECKEY_E },
{ 'f', SPECKEY_F },
{ 'g', SPECKEY_G },
{ 'h', SPECKEY_H },
{ 'i', SPECKEY_I },
{ 'j', SPECKEY_J },
{ 'k', SPECKEY_K },
{ 'l', SPECKEY_L },
{ 'm', SPECKEY_M },
{ 'n', SPECKEY_N },
{ 'o', SPECKEY_O },
{ 'p', SPECKEY_P },
{ 'q', SPECKEY_Q },
{ 'r', SPECKEY_R },
{ 's', SPECKEY_S },
{ 't', SPECKEY_T },
{ 'u', SPECKEY_U },
{ 'v', SPECKEY_V },
{ 'w', SPECKEY_W },
{ 'x', SPECKEY_X },
{ 'y', SPECKEY_Y },
{ 'z', SPECKEY_Z },
{ ' ', SPECKEY_SPACE },
{ 0x0d, SPECKEY_ENTER },
};
2 changes: 1 addition & 1 deletion firmware/src/Files/Files.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ class FilesImplementation: public IFiles

for (DirectoryIterator it(full_path, prefix, extensions); it != DirectoryIterator(); ++it)
{
files.push_back(FileInfoPtr(new FileInfo(StringUtils::upcase(it->d_name), full_path + "/" + it->d_name)));
files.push_back(FileInfoPtr(new FileInfo(StringUtils::upcase(it->d_name), full_path + it->d_name)));
}
// sort the files - is this needed? Maybe they are already alphabetically sorted
std::sort(files.begin(), files.end(), [](FileInfoPtr a, FileInfoPtr b)
Expand Down
1 change: 1 addition & 0 deletions firmware/src/Files/Flash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

Flash::Flash(const char *mountPoint)
{
m_mountPoint = mountPoint;
if (SPIFFS.begin(true, mountPoint))
{
_isMounted = true;
Expand Down
4 changes: 2 additions & 2 deletions firmware/src/Files/Flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ class Flash
{
private:
bool _isMounted;
const char *_mountPoint;
std::string m_mountPoint;
public:
Flash(const char *mountPoint);
~Flash();
bool isMounted() {
return _isMounted;
}
const char *mountPoint() {
return _mountPoint;
return m_mountPoint.c_str();
}
};
47 changes: 47 additions & 0 deletions firmware/src/Files/SDCard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,53 @@ SDCard::SDCard(const char *mountPoint, gpio_num_t clk, gpio_num_t cmd, gpio_num_
#endif
}

SDCard::SDCard(const char *mountPoint, gpio_num_t cs) {
m_mountPoint = mountPoint;
m_host.max_freq_khz = SDMMC_FREQ_52M;
esp_err_t ret;
// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 5,
.allocation_unit_size = 16 * 1024};

Serial.println("Initializing SD card");

// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = cs;
slot_config.host_id = spi_host_device_t(m_host.slot);

ret = esp_vfs_fat_sdspi_mount(mountPoint, &m_host, &slot_config, &mount_config, &m_card);
if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
Serial.println("Failed to mount filesystem. "
"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
}
else
{
Serial.printf("Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.\n",
esp_err_to_name(ret));
}
return;
}
Serial.printf("SDCard mounted at: %s\n", mountPoint);
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, m_card);
_isMounted = true;

m_sector_count = m_card->csd.capacity;
m_sector_size = m_card->csd.sector_size;

m_mutex = xSemaphoreCreateMutex();
}

SDCard::SDCard(const char *mountPoint, gpio_num_t miso, gpio_num_t mosi, gpio_num_t clk, gpio_num_t cs)
{
m_mountPoint = mountPoint;
Expand Down
1 change: 1 addition & 0 deletions firmware/src/Files/SDCard.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class SDCard
return m_mountPoint.c_str();
}
SDCard(const char *mountPoint, gpio_num_t miso, gpio_num_t mosi, gpio_num_t clk, gpio_num_t cs);
SDCard(const char *mountPoint, gpio_num_t cs);
SDCard(const char *mountPoint, gpio_num_t clk, gpio_num_t cmd, gpio_num_t d0, gpio_num_t d1, gpio_num_t d2, gpio_num_t d3);
bool writeSectors(uint8_t *src, size_t start_sector, size_t sector_count);
bool readSectors(uint8_t *dst, size_t start_sector, size_t sector_count);
Expand Down
53 changes: 53 additions & 0 deletions firmware/src/Input/TDeckKeyboard.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "Wire.h"
#include "../Serial.h"
#include "TDeckKeyboard.h"

TDeckKeyboard::TDeckKeyboard(KeyEventType keyEvent, KeyPressedEventType keyPressedEvent) : m_keyEvent(keyEvent), m_keyPressedEvent(keyPressedEvent)
{
}

bool TDeckKeyboard::start() {
Wire.begin(GPIO_NUM_18, GPIO_NUM_8);
Wire.requestFrom(0x55, 1);
if (Wire.read() == -1) {
Serial.println("LILYGO Keyboad not online .");
return false;
}
// kick off a task to read the keyboard
xTaskCreate(readKeyboardTask, "readKeyboardTask", 4096, this, 5, NULL);
return true;
}

void TDeckKeyboard::readKeyboardTask(void *pvParameters) {
TDeckKeyboard *self = (TDeckKeyboard *)pvParameters;
self->readKeyboard();
}

void TDeckKeyboard::readKeyboard() {
SpecKeys lastKey = SpecKeys::SPECKEY_NONE;
unsigned long lastKeyPress = 0;
while(true) {
char keyValue = 0;
Wire.requestFrom(0x55, 1);
while (Wire.available() > 0) {
keyValue = Wire.read();
if (keyValue != (char)0x00) {
// is it a valid spec key?
// convert to uppercase
if (letterToSpecKey.find(keyValue) != letterToSpecKey.end()) {
SpecKeys key = letterToSpecKey.at(keyValue);
m_keyPressedEvent(key);
m_keyEvent(key, true);
lastKey = key;
lastKeyPress = millis();
}
}
// release any pressed keys
if (lastKey != SpecKeys::SPECKEY_NONE && millis() - lastKeyPress > 100) {
m_keyEvent(lastKey, false);
lastKey = SpecKeys::SPECKEY_NONE;
}
}
vTaskDelay(10);
}
}
19 changes: 19 additions & 0 deletions firmware/src/Input/TDeckKeyboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include <functional>
#include "../Emulator/keyboard_defs.h"

class TDeckKeyboard
{
private:
// this is used for key down and key up events
using KeyEventType = std::function<void(SpecKeys keyCode, bool isPressed)>;
KeyEventType m_keyEvent;
// this is used for key pressed evens and supports repeating keys
using KeyPressedEventType = std::function<void(SpecKeys keyCode)>;
KeyPressedEventType m_keyPressedEvent;
public:
TDeckKeyboard(KeyEventType keyEvent, KeyPressedEventType keyPressedEvent);
bool start();
static void readKeyboardTask(void *pvParameters);
void readKeyboard();
};
17 changes: 13 additions & 4 deletions firmware/src/TFT/ST7789.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,21 @@
ST7789::ST7789(gpio_num_t cs, gpio_num_t dc, gpio_num_t rst, gpio_num_t bl, int width, int height)
: TFTDisplay(cs, dc, rst, bl, width, height)
{
pinMode(rst, OUTPUT);
if (bl != GPIO_NUM_NC) {
pinMode(bl, OUTPUT);
digitalWrite(bl, 0);
delay(3);
digitalWrite(bl, 1);
}
// Reset the display
digitalWrite(rst, LOW);
// gpio_set_level(rst, 0);
if (rst != GPIO_NUM_NC) {
digitalWrite(rst, LOW);
}
vTaskDelay(pdMS_TO_TICKS(100));
digitalWrite(rst, HIGH);
// gpio_set_level(rst, 1);
if (rst != GPIO_NUM_NC) {
digitalWrite(rst, HIGH);
}
vTaskDelay(pdMS_TO_TICKS(100));

SEND_CMD_DATA(ST7789_SLPOUT); // Sleep out
Expand Down
Loading

0 comments on commit 1456f8f

Please sign in to comment.