forked from Aircoookie/WLED
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First working Elekstube IPS and RTC mod
- Loading branch information
1 parent
371c4e0
commit 2d58640
Showing
23 changed files
with
762 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -473,3 +473,37 @@ platform_packages = ${common.platform_packages} | |
board_build.ldscript = ${common.ldscript_4m1m} | ||
build_unflags = ${common.build_unflags} | ||
build_flags = ${common.build_flags_esp8266} | ||
|
||
# ------------------------------------------------------------------------------ | ||
# EleksTube-IPS | ||
# ------------------------------------------------------------------------------ | ||
[env:elekstube_ips] | ||
board = esp32dev | ||
platform = [email protected] | ||
upload_speed = 921600 | ||
lib_deps = ${env.lib_deps} | ||
TFT_eSPI | ||
build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED | ||
-D USERMOD_RTC | ||
-D USERMOD_ELEKSTUBE_IPS | ||
-D LEDPIN=12 | ||
-D RLYPIN=27 | ||
-D BTNPIN=34 | ||
-D WLED_DISABLE_INFRARED | ||
-D DEFAULT_LED_COUNT=6 | ||
# Display config | ||
-D ST7789_DRIVER | ||
-D TFT_WIDTH=135 | ||
-D TFT_HEIGHT=240 | ||
-D CGRAM_OFFSET | ||
-D TFT_SDA_READ | ||
-D TFT_MOSI=23 | ||
-D TFT_SCLK=18 | ||
-D TFT_DC=25 | ||
-D TFT_RST=26 | ||
-D SPI_FREQUENCY=40000000 | ||
-D USER_SETUP_LOADED | ||
monitor_filters = esp32_exception_decoder | ||
lib_ignore = | ||
ESPAsyncTCP | ||
ESPAsyncUDP |
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,70 @@ | ||
#ifndef CHIP_SELECT_H | ||
#define CHIP_SELECT_H | ||
|
||
#include "Hardware.h" | ||
|
||
/* | ||
* `digit`s are as defined in Hardware.h, 0 == seconds ones, 5 == hours tens. | ||
*/ | ||
|
||
class ChipSelect { | ||
private: | ||
uint8_t digits_map; | ||
const uint8_t all_on = 0x3F; | ||
const uint8_t all_off = 0x00; | ||
public: | ||
ChipSelect() : digits_map(all_off) {} | ||
|
||
void update() { | ||
// Documented in README.md. Q7 and Q6 are unused. Q5 is Seconds Ones, Q0 is Hours Tens. | ||
// Q7 is the first bit written, Q0 is the last. So we push two dummy bits, then start with | ||
// Seconds Ones and end with Hours Tens. | ||
// CS is Active Low, but digits_map is 1 for enable, 0 for disable. So we bit-wise NOT first. | ||
|
||
uint8_t to_shift = (~digits_map) << 2; | ||
|
||
digitalWrite(CSSR_LATCH_PIN, LOW); | ||
shiftOut(CSSR_DATA_PIN, CSSR_CLOCK_PIN, LSBFIRST, to_shift); | ||
digitalWrite(CSSR_LATCH_PIN, HIGH); | ||
} | ||
|
||
void begin() | ||
{ | ||
pinMode(CSSR_LATCH_PIN, OUTPUT); | ||
pinMode(CSSR_DATA_PIN, OUTPUT); | ||
pinMode(CSSR_CLOCK_PIN, OUTPUT); | ||
|
||
digitalWrite(CSSR_DATA_PIN, LOW); | ||
digitalWrite(CSSR_CLOCK_PIN, LOW); | ||
digitalWrite(CSSR_LATCH_PIN, LOW); | ||
update(); | ||
} | ||
|
||
// These speak the indexes defined in Hardware.h. | ||
// So 0 is disabled, 1 is enabled (even though CS is active low, this gets mapped.) | ||
// So bit 0 (LSB), is index 0, is SECONDS_ONES | ||
// Translation to what the 74HC595 uses is done in update() | ||
void setDigitMap(uint8_t map, bool update_=true) { digits_map = map; if (update_) update(); } | ||
uint8_t getDigitMap() { return digits_map; } | ||
|
||
// Helper functions | ||
// Sets just the one digit by digit number | ||
void setDigit(uint8_t digit, bool update_=true) { setDigitMap(0x01 << digit, update_); } | ||
void setAll(bool update_=true) { setDigitMap(all_on, update_); } | ||
void clear(bool update_=true) { setDigitMap(all_off, update_); } | ||
void setSecondsOnes() { setDigit(SECONDS_ONES); } | ||
void setSecondsTens() { setDigit(SECONDS_TENS); } | ||
void setMinutesOnes() { setDigit(MINUTES_ONES); } | ||
void setMinutesTens() { setDigit(MINUTES_TENS); } | ||
void setHoursOnes() { setDigit(HOURS_ONES); } | ||
void setHoursTens() { setDigit(HOURS_TENS); } | ||
bool isSecondsOnes() { return (digits_map&SECONDS_ONES_MAP > 0); } | ||
bool isSecondsTens() { return (digits_map&SECONDS_TENS_MAP > 0); } | ||
bool isMinutesOnes() { return (digits_map&MINUTES_ONES_MAP > 0); } | ||
bool isMinutesTens() { return (digits_map&MINUTES_TENS_MAP > 0); } | ||
bool isHoursOnes() { return (digits_map&HOURS_ONES_MAP > 0); } | ||
bool isHoursTens() { return (digits_map&HOURS_TENS_MAP > 0); } | ||
}; | ||
|
||
|
||
#endif // CHIP_SELECT_H |
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,52 @@ | ||
/* | ||
* Define the hardware for the EleksTube IPS clock. Mostly pin definitions | ||
*/ | ||
#ifndef ELEKSTUBEHAX_HARDWARE_H | ||
#define ELEKSTUBEHAX_HARDWARE_H | ||
|
||
#include <stdint.h> | ||
#include <Arduino.h> // for HIGH and LOW | ||
|
||
// Common indexing scheme, used to identify the digit | ||
#define SECONDS_ONES (0) | ||
#define SECONDS_TENS (1) | ||
#define MINUTES_ONES (2) | ||
#define MINUTES_TENS (3) | ||
#define HOURS_ONES (4) | ||
#define HOURS_TENS (5) | ||
#define NUM_DIGITS (6) | ||
|
||
#define SECONDS_ONES_MAP (0x01 << SECONDS_ONES) | ||
#define SECONDS_TENS_MAP (0x01 << SECONDS_TENS) | ||
#define MINUTES_ONES_MAP (0x01 << MINUTES_ONES) | ||
#define MINUTES_TENS_MAP (0x01 << MINUTES_TENS) | ||
#define HOURS_ONES_MAP (0x01 << HOURS_ONES) | ||
#define HOURS_TENS_MAP (0x01 << HOURS_TENS) | ||
|
||
// WS2812 (or compatible) LEDs on the back of the display modules. | ||
#define BACKLIGHTS_PIN (12) | ||
|
||
// Buttons, active low, externally pulled up (with actual resistors!) | ||
#define BUTTON_LEFT_PIN (33) | ||
#define BUTTON_MODE_PIN (32) | ||
#define BUTTON_RIGHT_PIN (35) | ||
#define BUTTON_POWER_PIN (34) | ||
|
||
// I2C to DS3231 RTC. | ||
#define RTC_SCL_PIN (22) | ||
#define RTC_SDA_PIN (21) | ||
|
||
// Chip Select shift register, to select the display | ||
#define CSSR_DATA_PIN (14) | ||
#define CSSR_CLOCK_PIN (16) | ||
#define CSSR_LATCH_PIN (17) | ||
|
||
// SPI to displays | ||
// DEFINED IN User_Setup.h | ||
// Look for: TFT_MOSI, TFT_SCLK, TFT_CS, TFT_DC, and TFT_RST | ||
|
||
// Power for all TFT displays are grounded through a MOSFET so they can all be turned off. | ||
// Active HIGH. | ||
#define TFT_ENABLE_PIN (27) | ||
|
||
#endif // ELEKSTUBEHAX_HARDWARE_H |
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,169 @@ | ||
#ifndef TFTS_H | ||
#define TFTS_H | ||
|
||
#include <FS.h> | ||
|
||
#include <TFT_eSPI.h> | ||
#include "Hardware.h" | ||
#include "ChipSelect.h" | ||
|
||
class TFTs : public TFT_eSPI { | ||
private: | ||
uint8_t digits[NUM_DIGITS]; | ||
|
||
// These read 16- and 32-bit types from the SD card file. | ||
// BMP data is stored little-endian, Arduino is little-endian too. | ||
// May need to reverse subscript order if porting elsewhere. | ||
|
||
uint16_t read16(fs::File &f) { | ||
uint16_t result; | ||
((uint8_t *)&result)[0] = f.read(); // LSB | ||
((uint8_t *)&result)[1] = f.read(); // MSB | ||
return result; | ||
} | ||
|
||
uint32_t read32(fs::File &f) { | ||
uint32_t result; | ||
((uint8_t *)&result)[0] = f.read(); // LSB | ||
((uint8_t *)&result)[1] = f.read(); | ||
((uint8_t *)&result)[2] = f.read(); | ||
((uint8_t *)&result)[3] = f.read(); // MSB | ||
return result; | ||
} | ||
|
||
uint16_t output_buffer[TFT_HEIGHT][TFT_WIDTH]; | ||
|
||
// These BMP functions are stolen directly from the TFT_SPIFFS_BMP example in the TFT_eSPI library. | ||
// Unfortunately, they aren't part of the library itself, so I had to copy them. | ||
// I've modified drawBmp to buffer the whole image at once instead of doing it line-by-line. | ||
|
||
//// BEGIN STOLEN CODE | ||
|
||
bool drawBmp(const char *filename, int16_t x, int16_t y) { | ||
// Nothing to do. | ||
if ((x >= width()) || (y >= height())) return(true); | ||
|
||
fs::File bmpFS; | ||
|
||
// Open requested file on SD card | ||
bmpFS = WLED_FS.open(filename, "r"); | ||
|
||
if (!bmpFS) | ||
{ | ||
Serial.println(F("File not found")); | ||
return(false); | ||
} | ||
|
||
uint32_t seekOffset; | ||
int16_t w, h, row; | ||
uint8_t r, g, b; | ||
|
||
uint16_t magic = read16(bmpFS); | ||
if (magic == 0xFFFF) { | ||
Serial.println(F("BMP not found!")); | ||
bmpFS.close(); | ||
return(false); | ||
} | ||
|
||
if (magic != 0x4D42) { | ||
Serial.print(F("File not a BMP. Magic: ")); | ||
Serial.println(magic); | ||
bmpFS.close(); | ||
return(false); | ||
} | ||
|
||
read32(bmpFS); | ||
read32(bmpFS); | ||
seekOffset = read32(bmpFS); | ||
read32(bmpFS); | ||
w = read32(bmpFS); | ||
h = read32(bmpFS); | ||
|
||
if ((read16(bmpFS) != 1) || (read16(bmpFS) != 24) || (read32(bmpFS) != 0)) { | ||
Serial.println(F("BMP format not recognized.")); | ||
bmpFS.close(); | ||
return(false); | ||
} | ||
|
||
bool oldSwapBytes = getSwapBytes(); | ||
setSwapBytes(true); | ||
bmpFS.seek(seekOffset); | ||
|
||
uint16_t padding = (4 - ((w * 3) & 3)) & 3; | ||
uint8_t lineBuffer[w * 3 + padding]; | ||
|
||
// row is decremented as the BMP image is drawn bottom up | ||
for (row = h-1; row >= 0; row--) { | ||
if (row & 0b00000111 == 7) strip.service(); //still refresh backlight to mitigate stutter every few rows | ||
bmpFS.read(lineBuffer, sizeof(lineBuffer)); | ||
uint8_t* bptr = lineBuffer; | ||
|
||
// Convert 24 to 16 bit colours while copying to output buffer. | ||
for (uint16_t col = 0; col < w; col++) | ||
{ | ||
b = *bptr++; | ||
g = *bptr++; | ||
r = *bptr++; | ||
output_buffer[row][col] = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); | ||
} | ||
} | ||
|
||
pushImage(x, y, w, h, (uint16_t *)output_buffer); | ||
setSwapBytes(oldSwapBytes); | ||
|
||
bmpFS.close(); | ||
return(true); | ||
} | ||
|
||
public: | ||
TFTs() : TFT_eSPI(), chip_select() | ||
{ for (uint8_t digit=0; digit < NUM_DIGITS; digit++) digits[digit] = 0; } | ||
|
||
// no == Do not send to TFT. yes == Send to TFT if changed. force == Send to TFT. | ||
enum show_t { no, yes, force }; | ||
// A digit of 0xFF means blank the screen. | ||
const static uint8_t blanked = 255; | ||
|
||
void begin() { | ||
pinMode(TFT_ENABLE_PIN, OUTPUT); | ||
digitalWrite(TFT_ENABLE_PIN, HIGH); //enable displays on boot | ||
|
||
// Start with all displays selected. | ||
chip_select.begin(); | ||
chip_select.setAll(); | ||
|
||
// Initialize the super class. | ||
init(); | ||
} | ||
|
||
void showDigit(uint8_t digit) { | ||
chip_select.setDigit(digit); | ||
|
||
if (digits[digit] == blanked) { | ||
fillScreen(TFT_BLACK); | ||
} | ||
else { | ||
// Filenames are no bigger than "255.bmp\0" | ||
char file_name[10]; | ||
sprintf(file_name, "/%d.bmp", digits[digit]); | ||
drawBmp(file_name, 0, 0); | ||
} | ||
} | ||
|
||
void setDigit(uint8_t digit, uint8_t value, show_t show=yes) { | ||
uint8_t old_value = digits[digit]; | ||
digits[digit] = value; | ||
|
||
if (show != no && (old_value != value || show == force)) { | ||
showDigit(digit); | ||
} | ||
} | ||
uint8_t getDigit(uint8_t digit) { return digits[digit]; } | ||
|
||
void showAllDigits() { for (uint8_t digit=0; digit < NUM_DIGITS; digit++) showDigit(digit); } | ||
|
||
// Making chip_select public so we don't have to proxy all methods, and the caller can just use it directly. | ||
ChipSelect chip_select; | ||
}; | ||
|
||
#endif // TFTS_H |
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,47 @@ | ||
/* | ||
* This is intended to over-ride `User_Setup.h` that comes with the TFT_eSPI library. | ||
* I hate having to modify the library code. | ||
*/ | ||
|
||
// ST7789 135 x 240 display with no chip select line | ||
|
||
#define ST7789_DRIVER // Configure all registers | ||
|
||
#define TFT_WIDTH 135 | ||
#define TFT_HEIGHT 240 | ||
|
||
#define CGRAM_OFFSET // Library will add offsets required | ||
|
||
//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue | ||
//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red | ||
|
||
//#define TFT_INVERSION_ON | ||
//#define TFT_INVERSION_OFF | ||
|
||
// EleksTube IPS | ||
#define TFT_SDA_READ // Read and write on the MOSI/SDA pin, no separate MISO pin | ||
#define TFT_MOSI 23 | ||
#define TFT_SCLK 18 | ||
//#define TFT_CS -1 // Not connected | ||
#define TFT_DC 25 // Data Command, aka Register Select or RS | ||
#define TFT_RST 26 // Connect reset to ensure display initialises | ||
|
||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH | ||
//#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters | ||
//#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters | ||
//#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm | ||
//#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. | ||
//#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. | ||
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT | ||
//#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts | ||
|
||
//#define SMOOTH_FONT | ||
|
||
|
||
//#define SPI_FREQUENCY 27000000 | ||
#define SPI_FREQUENCY 40000000 | ||
|
||
/* | ||
* To make the Library not over-write all this: | ||
*/ | ||
#define USER_SETUP_LOADED |
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.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.