Improvements and fixes

This commit is contained in:
ookami125 2025-05-28 05:09:03 +00:00
parent b6ac19a54d
commit d27a2378b0
3 changed files with 126 additions and 11 deletions

View file

@ -109,6 +109,46 @@ esp_err_t epd7in5_v3_init(epd7in5_v3_t *epd)
return ESP_OK;
}
esp_err_t epd7in5_v3_init_fast(epd7in5_v3_t *epd)
{
spi_device_interface_config_t devcfg = {
.clock_speed_hz = 20 * 1000 * 1000, // 2 MHz
.mode = 0, // SPI mode 0
.spics_io_num = epd->pin_cs,
.queue_size = 1,
.flags = SPI_DEVICE_HALFDUPLEX // use .flags |= SPI_DEVICE_3WIRE if necessary
};
ESP_RETURN_ON_ERROR(spi_bus_add_device(epd->spi_host, &devcfg, &epd->spi), "add device", ret);
gpio_set_level(epd->pin_rst, 1);
vTaskDelay(pdMS_TO_TICKS(20));
gpio_set_level(epd->pin_rst, 0);
vTaskDelay(pdMS_TO_TICKS(4));
gpio_set_level(epd->pin_rst, 1);
vTaskDelay(pdMS_TO_TICKS(20));
epd7in5_v3_send_command(epd, 0x50);
epd7in5_v3_send_data(epd, 0x10);
epd7in5_v3_send_data(epd, 0x07);
epd7in5_v3_send_command(epd, 0x04);
vTaskDelay(pdMS_TO_TICKS(100));
epd7in5_v3_busy_wait(epd);
epd7in5_v3_send_command(epd, 0x06);
epd7in5_v3_send_data(epd, 0x27);
epd7in5_v3_send_data(epd, 0x27);
epd7in5_v3_send_data(epd, 0x18);
epd7in5_v3_send_data(epd, 0x17);
epd7in5_v3_send_command(epd, 0xE0);
epd7in5_v3_send_data(epd, 0x02);
epd7in5_v3_send_command(epd, 0xE5);
epd7in5_v3_send_data(epd, 0x5A);
return ESP_OK;
}
esp_err_t epd7in5_v3_send_command(epd7in5_v3_t *epd, uint8_t cmd)
{
esp_err_t ret;

View file

@ -78,6 +78,13 @@ esp_err_t epd7in5_v3_create(epd7in5_v3_t *epd, spi_host_device_t host);
*/
esp_err_t epd7in5_v3_init(epd7in5_v3_t *epd);
/**
* @brief Initialize the EPD panel with fast settings (no full refresh).
* @param epd Pointer to an epd7in5_v3_t struct (must be allocated by caller).
* @return ESP_OK on success, or an error code.
*/
esp_err_t epd7in5_v3_init_fast(epd7in5_v3_t *epd);
/**
* @brief Send a blocking command byte.
*/

View file

@ -52,22 +52,61 @@ QueueHandle_t timerEinkQueue;
QueueHandle_t timerAlarmQueue;
QueueHandle_t alarmQueue;
void copybits(uint8_t *dest,
int dst_bit_offset,
const uint8_t *src,
int src_bit_offset,
int bit_length)
{
for (int i = 0; i < bit_length; i++) {
// --- Read a single bit from src ---
int bit_idx_src = src_bit_offset + i;
int byte_idx_src = bit_idx_src / 8;
int bit_in_src = bit_idx_src % 8;
// extract MSB-first
uint8_t bit = (src[byte_idx_src] >> (7 - bit_in_src)) & 1;
// --- Write that bit into dest ---
int bit_idx_dst = dst_bit_offset + i;
int byte_idx_dst = bit_idx_dst / 8;
int bit_in_dst = bit_idx_dst % 8;
uint8_t mask = 1u << (7 - bit_in_dst);
// clear the destination bit and OR in our new bit
dest[byte_idx_dst] = (dest[byte_idx_dst] & ~mask)
| (bit << (7 - bit_in_dst));
}
}
void draw_char(uint8_t *image, int x, int y, char c) {
uint32_t char_offset = (c - '0') * 16 * 176;
uint32_t char_offset = (c - '0') * 2816;
for(int i=0; i<176; ++i) {
memcpy(&image[x + (y+i)*EPD_WIDTH/8], &OverpassMono_Bitmaps[i*16+char_offset], 16);
int length = 128;
int dst_offset = x;
int src_offset = 0;
if(dst_offset < 0) {
length += dst_offset;
src_offset = -dst_offset;
dst_offset = 0;
}
if(dst_offset + length > EPD_WIDTH) {
length = EPD_WIDTH - dst_offset;
}
if(length < 0) continue;
copybits(&image[(y+i)*EPD_WIDTH/8], dst_offset, &OverpassMono_Bitmaps[char_offset+i*16], src_offset, length);
}
}
void draw_text(uint8_t *image, int x, int y, const char *text, int length)
{
//89x130
for(int i=0; i<length; ++i) {
if(text[i] < '0' || text[i] > '9') {
ESP_LOGE(TAG, "Invalid character '%c' in text: %s", text[i], text);
return;
}
draw_char(image, x + i * 17, y, text[i]);
draw_char(image, x + i*136, y, text[i]);
}
}
@ -79,22 +118,43 @@ void eink_task(void *pvParameter)
epd7in5_v3_t epd;
epd7in5_v3_create(&epd, SPI2_HOST);
while(true) {
int x = 0;
int max_x = EPD_WIDTH - 536;
int y = 0;
int max_y = EPD_HEIGHT - 176;
// Wait for time update from timerQueue
int move_x = 10;
int move_y = 10;
while(true) {
TimerEvent event;
if (xQueueReceive(timerEinkQueue, &event, portMAX_DELAY) != pdTRUE) {
ESP_LOGE(TAG, "Failed to receive timer event from queue");
continue;
}
x += move_x;
y += move_y;
if (x <= 0 || x >= max_x - 1) {
move_x = -move_x;
x = (x < 0) ? 0 : max_x - 1;
}
if (y <= 0 || y >= max_y - 1) {
move_y = -move_y;
y = (y < 0) ? 0 : max_y - 1;
}
char buffer[5] = {0};
memcpy(buffer, &event.time, sizeof(event.time));
memset(image, 0x00, sizeof(image));
if (buffer[3] == '0') {
epd7in5_v3_init(&epd);
draw_text(image, 0, 0, buffer, 4);
} else {
epd7in5_v3_init_fast(&epd);
}
draw_text(image, x, y, buffer, 4);
epd7in5_v3_busy_wait(&epd);
epd7in5_v3_display(&epd, image);
epd7in5_v3_busy_wait(&epd);
@ -121,6 +181,8 @@ void radio_task(void *pvParameter)
{
bool radioActive = false;
int volume = 25;
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, NULL));
@ -171,6 +233,12 @@ void radio_task(void *pvParameter)
AlarmEvent event;
while(true) {
if(!radioActive) {
//write 0
memset(samples, 0, BUFFER_SAMPLES * sizeof(int16_t));
size_t bytes_to_write = BUFFER_SAMPLES * sizeof(int16_t);
size_t bytes_written = 0;
ESP_ERROR_CHECK(i2s_channel_write(tx_handle, samples, bytes_to_write, &bytes_written, portMAX_DELAY));
if(xQueueReceive(alarmQueue, &event, portMAX_DELAY) && event.event_id == 1) {
ESP_LOGI(TAG, "Alarm activated, starting radio");
radioActive = true;
@ -184,7 +252,7 @@ void radio_task(void *pvParameter)
//Do radio shit
for (int i = 0; i < BUFFER_SAMPLES; ++i) {
int16_t sample = level_up[(i+offset) % level_up_size];
samples[i] = sample / 4;
samples[i] = (uint16_t)(((uint32_t)sample) * volume / 100);
}
size_t bytes_to_write = BUFFER_SAMPLES * sizeof(int16_t);
@ -203,8 +271,8 @@ void alarm_task(void *pvParameter)
{
bool alarmActive = false;
int alarmStart = 830; // 20:55 in HHMM format
int alarmEnd = 900; // 20:56 in HHMM format
int alarmStart = 830;
int alarmEnd = 900;
TimerEvent event;
while(true) {