Registers tweaks
Prepare for new registers structure used in v1
This commit is contained in:
parent
e1a77fc1ca
commit
cdee81d3ff
@ -145,6 +145,7 @@ extern volatile uint32_t systicks_counter;
|
|||||||
extern volatile uint8_t pmu_irq;
|
extern volatile uint8_t pmu_irq;
|
||||||
extern volatile uint8_t stop_mode_active;
|
extern volatile uint8_t stop_mode_active;
|
||||||
|
|
||||||
|
extern volatile uint8_t rtc_reg_xor_events;
|
||||||
extern volatile RTC_TimeTypeDef_u rtc_alarm_time;
|
extern volatile RTC_TimeTypeDef_u rtc_alarm_time;
|
||||||
extern volatile RTC_DateTypeDef_u rtc_alarm_date;
|
extern volatile RTC_DateTypeDef_u rtc_alarm_date;
|
||||||
|
|
||||||
|
20
Core/Inc/i2cs.h
Normal file
20
Core/Inc/i2cs.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "stm32f1xx_hal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef I2CS_H_
|
||||||
|
#define I2CS_H_
|
||||||
|
|
||||||
|
#define I2CS_REARM_TIMEOUT 500
|
||||||
|
|
||||||
|
|
||||||
|
enum i2cs_state {
|
||||||
|
//I2CS_STATE_HALT,
|
||||||
|
I2CS_STATE_IDLE,
|
||||||
|
I2CS_STATE_REG_REQUEST,
|
||||||
|
I2CS_STATE_REG_ANSWER
|
||||||
|
};
|
||||||
|
|
||||||
|
extern enum i2cs_state i2cs_state;
|
||||||
|
extern uint32_t i2cs_rearm_counter;
|
||||||
|
|
||||||
|
#endif /* I2CS_H_ */
|
@ -8,7 +8,7 @@ enum reg_id {
|
|||||||
REG_ID_TYP = 0x00, //!< firmware type (0=official, others=custom)
|
REG_ID_TYP = 0x00, //!< firmware type (0=official, others=custom)
|
||||||
REG_ID_VER = 0x01, //!< fw version (7:4=Major, 3:0=Minor)
|
REG_ID_VER = 0x01, //!< fw version (7:4=Major, 3:0=Minor)
|
||||||
#ifdef I2C_REGS_COMPAT
|
#ifdef I2C_REGS_COMPAT
|
||||||
REG_ID_CFG = 0x02, // config
|
REG_ID_SYS_CFG = 0x02, // config
|
||||||
REG_ID_INT = 0x03, // interrupt status
|
REG_ID_INT = 0x03, // interrupt status
|
||||||
REG_ID_KEY = 0x04, // key status
|
REG_ID_KEY = 0x04, // key status
|
||||||
REG_ID_BKL = 0x05, // backlight steps (0-9)
|
REG_ID_BKL = 0x05, // backlight steps (0-9)
|
||||||
@ -27,31 +27,54 @@ enum reg_id {
|
|||||||
REG_ID_RTC_ALARM_DATE = 0x12, // RTC alarm date
|
REG_ID_RTC_ALARM_DATE = 0x12, // RTC alarm date
|
||||||
REG_ID_RTC_ALARM_TIME = 0x13, // RTC alarm time
|
REG_ID_RTC_ALARM_TIME = 0x13, // RTC alarm time
|
||||||
#else
|
#else
|
||||||
REG_ID_CFG = 0x02, //!< config
|
// TODO: REG_ID_CFG_0 - 32b (RW)
|
||||||
|
REG_ID_SYS_CFG = 0x02, //!< config
|
||||||
REG_ID_INT_CFG = 0x03, //!< IRQ config
|
REG_ID_INT_CFG = 0x03, //!< IRQ config
|
||||||
REG_ID_INT = 0x04, //!< interrupt status
|
REG_ID_PWR_CTRL = 0x04, //!< Power control (0: idle, 1: pico reset, 2: system reset, 3: reserved, 4: sleep, 5: full-shutdown)
|
||||||
REG_ID_BKL = 0x05, //!< backlight steps (0-9)
|
REG_ID_RTC_CFG = 0x05, //!< RTC general config
|
||||||
REG_ID_BK2 = 0x06, //!< keyboard backlight (0-9)
|
|
||||||
REG_ID_DEB = 0x07, //!< debounce cfg (time in ms)
|
|
||||||
REG_ID_FRQ = 0x08, //!< poll freq cfg (time in ms)
|
|
||||||
REG_ID_PWR_CTRL = 0x09, //!< Power control (0: idle, 1: pico reset, 2: system reset, 3: reserved, 4: sleep, 5: full-shutdown)
|
|
||||||
|
|
||||||
REG_ID_RTC_CFG = 0x0A, //!< RTC general config
|
// TODO: REG_ID_CFG_1 - 32b (RW)
|
||||||
REG_ID_RTC_DATE = 0x0B, //!< RTC date
|
REG_ID_DEB = 0x06, //!< debounce cfg (time in ms)
|
||||||
REG_ID_RTC_TIME = 0x0C, //!< RTC time
|
REG_ID_FRQ = 0x07, //!< poll freq cfg (time in ms)
|
||||||
REG_ID_RTC_ALARM_DATE = 0x0D, //!< RTC alarm date
|
REG_ID_BKL = 0x08, //!< backlight steps (0-9)
|
||||||
REG_ID_RTC_ALARM_TIME = 0x0E, //!< RTC alarm time
|
REG_ID_BK2 = 0x09, //!< keyboard backlight (0-9)
|
||||||
|
|
||||||
REG_ID_KEY = 0x10, //!< key status
|
// TODO: REG_ID_RTC_DATE - 32b (RW)
|
||||||
REG_ID_FIF = 0x11, //!< fifo
|
REG_ID_RTC_DATE = 0x0A, //!< RTC date
|
||||||
REG_ID_C64_MTX = 0x12, //!< read c64 matrix
|
// TODO: REG_ID_RTC_TIME - 32b (RW)
|
||||||
REG_ID_C64_JS = 0x13, //!< joystick io bits
|
REG_ID_RTC_TIME = 0x0B, //!< RTC time
|
||||||
|
// TODO: REG_ID_RTC_ALARM_DATE - 32b (RW)
|
||||||
|
REG_ID_RTC_ALARM_DATE = 0x0C, //!< RTC alarm date
|
||||||
|
// TODO: REG_ID_RTC_ALARM_TIME - 32b (RW)
|
||||||
|
REG_ID_RTC_ALARM_TIME = 0x0D, //!< RTC alarm time
|
||||||
|
|
||||||
REG_ID_BAT = 0x30, //!< battery
|
// TODO: REG_ID_INT - 32b (RO)
|
||||||
|
REG_ID_INT = 0x10, //!< interrupt flags status
|
||||||
|
|
||||||
|
// TODO: REG_ID_KBD - 32b (RO)
|
||||||
|
REG_ID_KEY = 0x14, //!< key status - 8b
|
||||||
|
REG_ID_C64_JS = 0x15, //!< joystick io bits - 8b
|
||||||
|
REG_ID_FIF = 0x16, //!< fifo - 16b
|
||||||
|
|
||||||
|
// TODO: REG_ID_BAT - 32b (RO)
|
||||||
|
REG_ID_BAT = 0x18, //!< battery percentage - 16b
|
||||||
|
//REG_ID_BAT_RAW //!< battery voltage value in mV - 16b
|
||||||
|
|
||||||
|
// TODO: REG_ID_C64_MTX_0 - 32b (RO)
|
||||||
|
REG_ID_C64_MTX = 0x1A, //!< read c64 matrix
|
||||||
|
// TODO: REG_ID_C64_MTX_1 - 32b (RO)
|
||||||
|
// TODO: REG_ID_C64_MTX_2 - 32b (RO)
|
||||||
#endif
|
#endif
|
||||||
REG_ID_LAST
|
REG_ID_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define REGS_GLOBAL_ENTRY()
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const uint8_t addr;
|
||||||
|
uint8_t* value[];
|
||||||
|
} REGS_GLOBAL_ENTRY;
|
||||||
|
|
||||||
#define CFG_OVERFLOW_ON (1 << 0) //When a FIFO overflow happens, should the new entry still be pushed, overwriting the oldest one. If 0 then new entry is lost.
|
#define CFG_OVERFLOW_ON (1 << 0) //When a FIFO overflow happens, should the new entry still be pushed, overwriting the oldest one. If 0 then new entry is lost.
|
||||||
#define CFG_REPORT_MODS (1 << 6) // Should Alt, Sym and Shifts be reported as well
|
#define CFG_REPORT_MODS (1 << 6) // Should Alt, Sym and Shifts be reported as well
|
||||||
#define CFG_USE_MODS (1 << 7) // Should Alt, Sym and Shifts modify the keys reported
|
#define CFG_USE_MODS (1 << 7) // Should Alt, Sym and Shifts modify the keys reported
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
#define VERSION_H_
|
#define VERSION_H_
|
||||||
|
|
||||||
#define VERSION_MAJOR (0)
|
#define VERSION_MAJOR (0)
|
||||||
#define VERSION_MINOR (5)
|
#define VERSION_MINOR (6)
|
||||||
|
|
||||||
#endif /* VERSION_H_ */
|
#endif /* VERSION_H_ */
|
||||||
|
@ -37,6 +37,7 @@ UART_HandleTypeDef huart1;
|
|||||||
UART_HandleTypeDef huart3;
|
UART_HandleTypeDef huart3;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
volatile uint8_t rtc_reg_xor_events = 0;
|
||||||
volatile RTC_TimeTypeDef_u rtc_alarm_time = {.raw = 0x00000000};
|
volatile RTC_TimeTypeDef_u rtc_alarm_time = {.raw = 0x00000000};
|
||||||
volatile RTC_DateTypeDef_u rtc_alarm_date = {.raw = 0x00010101};
|
volatile RTC_DateTypeDef_u rtc_alarm_date = {.raw = 0x00010101};
|
||||||
|
|
||||||
|
221
Core/Src/i2cs.c
Normal file
221
Core/Src/i2cs.c
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#include "i2cs.h"
|
||||||
|
|
||||||
|
#include "hal_interface.h"
|
||||||
|
#include "backlight.h"
|
||||||
|
#include "fifo.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
#include "regs.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern I2C_HandleTypeDef hi2c1;
|
||||||
|
extern I2C_HandleTypeDef hi2c2;
|
||||||
|
|
||||||
|
extern RTC_HandleTypeDef hrtc;
|
||||||
|
|
||||||
|
static uint8_t i2cs_r_buff[5];
|
||||||
|
static volatile uint8_t i2cs_r_idx = 0;
|
||||||
|
static uint8_t i2cs_w_buff[10];
|
||||||
|
static volatile uint8_t i2cs_w_idx = 0;
|
||||||
|
static volatile uint8_t i2cs_w_len = 0;
|
||||||
|
|
||||||
|
enum i2cs_state i2cs_state = I2CS_STATE_IDLE;
|
||||||
|
uint32_t i2cs_rearm_counter = 0;
|
||||||
|
|
||||||
|
|
||||||
|
extern void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) {
|
||||||
|
if (hi2c == &hi2c1) {
|
||||||
|
// I2C slave addr match error detection
|
||||||
|
if (AddrMatchCode != 0x3E) // 0x1F << 1
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TransferDirection == I2C_DIRECTION_TRANSMIT) {
|
||||||
|
if (i2cs_state == I2CS_STATE_IDLE) {
|
||||||
|
i2cs_state = I2CS_STATE_REG_REQUEST;
|
||||||
|
|
||||||
|
i2cs_r_idx = 0;
|
||||||
|
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, i2cs_r_buff, 1, I2C_FIRST_FRAME); // This write the first received byte to i2cs_r_buff[0]
|
||||||
|
|
||||||
|
i2cs_rearm_counter = uptime_ms();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TransferDirection == I2C_DIRECTION_RECEIVE) {
|
||||||
|
if (i2cs_state == I2CS_STATE_REG_REQUEST) {
|
||||||
|
const uint8_t is_write = (uint8_t)(i2cs_r_buff[0] & (1 << 7));
|
||||||
|
const uint8_t reg = (uint8_t)(i2cs_r_buff[0] & ~(1 << 7));
|
||||||
|
|
||||||
|
i2cs_w_buff[0] = reg;
|
||||||
|
i2cs_w_len = 2;
|
||||||
|
|
||||||
|
if (reg == REG_ID_BKL) { // We wait an another byte for these registers
|
||||||
|
if (is_write)
|
||||||
|
lcd_backlight_update(i2cs_r_buff[1]);
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_BKL);
|
||||||
|
} else if (reg == REG_ID_BK2) {
|
||||||
|
if (is_write)
|
||||||
|
kbd_backlight_update(i2cs_r_buff[1]);
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_BK2);
|
||||||
|
} else if (reg == REG_ID_SYS_CFG) {
|
||||||
|
if (is_write)
|
||||||
|
reg_set_value(REG_ID_SYS_CFG, i2cs_r_buff[1]);
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_SYS_CFG);
|
||||||
|
} else if (reg == REG_ID_INT_CFG) {
|
||||||
|
if (is_write)
|
||||||
|
reg_set_value(REG_ID_INT_CFG, i2cs_r_buff[1]);
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_INT_CFG);
|
||||||
|
} else if (reg == REG_ID_DEB) {
|
||||||
|
if (is_write) {
|
||||||
|
keyboard_set_hold_period(*((uint16_t*)&i2cs_r_buff[1]));
|
||||||
|
reg_set_value(REG_ID_DEB, 0); // Trig async flag for EEPROM saving
|
||||||
|
}
|
||||||
|
*((uint16_t*)&i2cs_w_buff[1]) = keyboard_get_hold_period();
|
||||||
|
|
||||||
|
i2cs_w_len = 3;
|
||||||
|
} else if (reg == REG_ID_FRQ) {
|
||||||
|
if (is_write)
|
||||||
|
reg_set_value(REG_ID_FRQ, i2cs_r_buff[1]);
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_FRQ);
|
||||||
|
} else if (reg == REG_ID_FIF) {
|
||||||
|
struct fifo_item item = {0};
|
||||||
|
fifo_dequeue(&item);
|
||||||
|
i2cs_w_buff[0] = item.state;
|
||||||
|
i2cs_w_buff[1] = item.key;
|
||||||
|
} else if (reg == REG_ID_INT) {
|
||||||
|
if (is_write)
|
||||||
|
reg_set_value(REG_ID_INT, 0);
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_INT);
|
||||||
|
LL_GPIO_SetOutputPin(PICO_IRQ_GPIO_Port, PICO_IRQ_Pin); // De-assert the IRQ signal
|
||||||
|
} else if (reg == REG_ID_VER) {
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_VER);
|
||||||
|
} else if (reg == REG_ID_TYP) {
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_TYP);
|
||||||
|
} else if (reg == REG_ID_BAT) {
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_BAT);
|
||||||
|
} else if (reg == REG_ID_RTC_CFG) {
|
||||||
|
if (is_write) {
|
||||||
|
rtc_reg_xor_events |= reg_get_value(REG_ID_RTC_CFG) ^ i2cs_r_buff[1]; // Using a "OR" set style to avoid loosing change before processing it
|
||||||
|
reg_set_value(REG_ID_RTC_CFG, i2cs_r_buff[1]);
|
||||||
|
}
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_RTC_CFG);
|
||||||
|
} else if (reg == REG_ID_RTC_DATE) {
|
||||||
|
RTC_DateTypeDef date_s = {0};
|
||||||
|
if (is_write) {
|
||||||
|
i2cs_RTC_date_from_buffer(&date_s, &i2cs_r_buff[1]);
|
||||||
|
|
||||||
|
HAL_RTC_SetDate(&hrtc, &date_s, RTC_FORMAT_BIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
HAL_RTC_GetDate(&hrtc, &date_s, RTC_FORMAT_BIN);
|
||||||
|
i2cs_fill_buffer_RTC_date(&i2cs_w_buff[1], &date_s);
|
||||||
|
|
||||||
|
i2cs_w_len = 5;
|
||||||
|
} else if (reg == REG_ID_RTC_TIME) {
|
||||||
|
RTC_TimeTypeDef time_s = {0};
|
||||||
|
if (is_write) {
|
||||||
|
i2cs_RTC_time_from_buffer(&time_s, &i2cs_r_buff[1]);
|
||||||
|
|
||||||
|
HAL_RTC_SetTime(&hrtc, &time_s, RTC_FORMAT_BIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
HAL_RTC_GetTime(&hrtc, &time_s, RTC_FORMAT_BIN);
|
||||||
|
i2cs_fill_buffer_RTC_time(&i2cs_w_buff[1], &time_s);
|
||||||
|
|
||||||
|
i2cs_w_len = 4;
|
||||||
|
} else if (reg == REG_ID_RTC_ALARM_DATE) {
|
||||||
|
if (is_write)
|
||||||
|
i2cs_RTC_date_from_buffer(&rtc_alarm_date._s, &i2cs_r_buff[1]);
|
||||||
|
|
||||||
|
i2cs_fill_buffer_RTC_date(&i2cs_w_buff[1], &rtc_alarm_date._s);
|
||||||
|
|
||||||
|
i2cs_w_len = 5;
|
||||||
|
} else if (reg == REG_ID_RTC_ALARM_TIME) {
|
||||||
|
if (is_write)
|
||||||
|
i2cs_RTC_time_from_buffer(&rtc_alarm_time._s, &i2cs_r_buff[1]);
|
||||||
|
|
||||||
|
i2cs_fill_buffer_RTC_time(&i2cs_w_buff[1], &rtc_alarm_time._s);
|
||||||
|
|
||||||
|
i2cs_w_len = 4;
|
||||||
|
} else if (reg == REG_ID_KEY) {
|
||||||
|
i2cs_w_buff[0] = fifo_count();
|
||||||
|
i2cs_w_buff[0] |= keyboard_get_numlock() ? KEY_NUMLOCK : 0x00;
|
||||||
|
i2cs_w_buff[0] |= keyboard_get_capslock() ? KEY_CAPSLOCK : 0x00;
|
||||||
|
} else if (reg == REG_ID_C64_MTX) {
|
||||||
|
//memcpy(write_buffer + 1, io_matrix, sizeof(io_matrix));
|
||||||
|
*((uint32_t*)(&i2cs_w_buff[1]) + 0) = *((uint32_t*)(io_matrix) + 0);
|
||||||
|
*((uint32_t*)(&i2cs_w_buff[1]) + 1) = *((uint32_t*)(io_matrix) + 1);
|
||||||
|
i2cs_w_buff[9] = io_matrix[8];
|
||||||
|
|
||||||
|
i2cs_w_len = 10;
|
||||||
|
} else if (reg == REG_ID_C64_JS) {
|
||||||
|
i2cs_w_buff[1] = js_bits;
|
||||||
|
} else if (reg == REG_ID_PWR_CTRL) {
|
||||||
|
if (is_write)
|
||||||
|
reg_set_value(REG_ID_PWR_CTRL, i2cs_r_buff[1]);
|
||||||
|
i2cs_w_buff[1] = reg_get_value(REG_ID_PWR_CTRL);
|
||||||
|
} else {
|
||||||
|
i2cs_w_buff[0] = 0;
|
||||||
|
i2cs_w_buff[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2cs_state = I2CS_STATE_REG_ANSWER;
|
||||||
|
i2cs_w_idx = 0;
|
||||||
|
|
||||||
|
HAL_I2C_Slave_Sequential_Transmit_IT(hi2c, i2cs_w_buff, i2cs_w_len, I2C_FIRST_AND_LAST_FRAME);
|
||||||
|
|
||||||
|
i2cs_rearm_counter = uptime_ms();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
|
||||||
|
if (hi2c == &hi2c1) {
|
||||||
|
i2cs_r_idx++;
|
||||||
|
|
||||||
|
if (i2cs_state == I2CS_STATE_REG_REQUEST) {
|
||||||
|
const uint8_t is_write = (uint8_t)(i2cs_r_buff[0] & (1 << 7));
|
||||||
|
const uint8_t reg = (uint8_t)(i2cs_r_buff[0] & ~(1 << 7));
|
||||||
|
uint8_t bytes_needed = 0;
|
||||||
|
|
||||||
|
// Check for another mandatories bytes depending on register requested
|
||||||
|
if (reg == REG_ID_BKL ||
|
||||||
|
reg == REG_ID_BK2 ||
|
||||||
|
reg == REG_ID_SYS_CFG ||
|
||||||
|
reg == REG_ID_INT_CFG ||
|
||||||
|
reg == REG_ID_FRQ) {
|
||||||
|
if (is_write)
|
||||||
|
bytes_needed = 1;
|
||||||
|
} else if (reg == REG_ID_DEB) {
|
||||||
|
if (is_write)
|
||||||
|
bytes_needed = 2;
|
||||||
|
} else if (reg == REG_ID_RTC_DATE ||
|
||||||
|
reg == REG_ID_RTC_ALARM_DATE ||
|
||||||
|
reg == REG_ID_RTC_TIME ||
|
||||||
|
reg == REG_ID_RTC_ALARM_TIME) {
|
||||||
|
if (is_write)
|
||||||
|
bytes_needed = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_needed > 0)
|
||||||
|
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, i2cs_r_buff + i2cs_r_idx, bytes_needed, I2C_NEXT_FRAME); // This write the second or more received byte to i2cs_r_buff[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void HAL_I2C_ListenCpltCallback (I2C_HandleTypeDef *hi2c) {
|
||||||
|
if (hi2c == &hi2c1) {
|
||||||
|
if (i2cs_state == I2CS_STATE_REG_ANSWER)
|
||||||
|
i2cs_state = I2CS_STATE_IDLE;
|
||||||
|
|
||||||
|
HAL_I2C_EnableListen_IT(hi2c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) {
|
||||||
|
if (hi2c == &hi2c1)
|
||||||
|
if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF) {
|
||||||
|
//Error_Handler();
|
||||||
|
// Actually this will trigger the watchdog and restart the system... That can ruin the day of the user.
|
||||||
|
NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
}
|
@ -152,27 +152,27 @@ static void transition_to(struct list_item * const p_item, const enum key_state
|
|||||||
|
|
||||||
switch (p_entry->mod) {
|
switch (p_entry->mod) {
|
||||||
case MOD_ALT:
|
case MOD_ALT:
|
||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_REPORT_MODS))
|
if (reg_is_bit_set(REG_ID_SYS_CFG, CFG_REPORT_MODS))
|
||||||
chr = KEY_MOD_ALT;
|
chr = KEY_MOD_ALT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_SHL:
|
case MOD_SHL:
|
||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_REPORT_MODS))
|
if (reg_is_bit_set(REG_ID_SYS_CFG, CFG_REPORT_MODS))
|
||||||
chr = KEY_MOD_SHL;
|
chr = KEY_MOD_SHL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_SHR:
|
case MOD_SHR:
|
||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_REPORT_MODS))
|
if (reg_is_bit_set(REG_ID_SYS_CFG, CFG_REPORT_MODS))
|
||||||
chr = KEY_MOD_SHR;
|
chr = KEY_MOD_SHR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_SYM:
|
case MOD_SYM:
|
||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_REPORT_MODS))
|
if (reg_is_bit_set(REG_ID_SYS_CFG, CFG_REPORT_MODS))
|
||||||
chr = KEY_MOD_SYM;
|
chr = KEY_MOD_SYM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_CTRL:
|
case MOD_CTRL:
|
||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_REPORT_MODS))
|
if (reg_is_bit_set(REG_ID_SYS_CFG, CFG_REPORT_MODS))
|
||||||
chr = KEY_MOD_CTRL;
|
chr = KEY_MOD_CTRL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ static void transition_to(struct list_item * const p_item, const enum key_state
|
|||||||
capslock_changed = 1;
|
capslock_changed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_USE_MODS)) {
|
if (reg_is_bit_set(REG_ID_SYS_CFG, CFG_USE_MODS)) {
|
||||||
const uint8_t shift = (mods[MOD_SHL] || mods[MOD_SHR]);
|
const uint8_t shift = (mods[MOD_SHL] || mods[MOD_SHR]);
|
||||||
const uint8_t alt = mods[MOD_ALT] | numlock;
|
const uint8_t alt = mods[MOD_ALT] | numlock;
|
||||||
//const uint8_t ctrl = mods[MOD_CTRL];
|
//const uint8_t ctrl = mods[MOD_CTRL];
|
||||||
|
218
Core/Src/main.c
218
Core/Src/main.c
@ -27,6 +27,7 @@
|
|||||||
#include "eeprom.h"
|
#include "eeprom.h"
|
||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
#include "i2cs.h"
|
||||||
#include "regs.h"
|
#include "regs.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
|
|
||||||
@ -40,9 +41,6 @@
|
|||||||
#define DEFAULT_KBD_DEB (KEY_HOLD_TIME)
|
#define DEFAULT_KBD_DEB (KEY_HOLD_TIME)
|
||||||
#define DEFAULT_RCT_CFG (0x00)
|
#define DEFAULT_RCT_CFG (0x00)
|
||||||
|
|
||||||
#define I2CS_REARM_TIMEOUT 500
|
|
||||||
#define I2CS_W_BUFF_LEN 31+1 // The last one must be only a 0 value, TODO: another cleaner way?
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define DEBUG_UART_MSG(msg) HAL_UART_Transmit(&huart1, (uint8_t*)msg, sizeof(msg)-1, 1000)
|
#define DEBUG_UART_MSG(msg) HAL_UART_Transmit(&huart1, (uint8_t*)msg, sizeof(msg)-1, 1000)
|
||||||
//#define DEBUG_UART_MSG2(d,s) HAL_UART_Transmit(&huart1, (uint8_t*)d, s, 200)
|
//#define DEBUG_UART_MSG2(d,s) HAL_UART_Transmit(&huart1, (uint8_t*)d, s, 200)
|
||||||
@ -51,12 +49,6 @@
|
|||||||
|
|
||||||
|
|
||||||
// Private typedef -----------------------------------------------------------
|
// Private typedef -----------------------------------------------------------
|
||||||
enum i2cs_state {
|
|
||||||
//I2CS_STATE_HALT,
|
|
||||||
I2CS_STATE_IDLE,
|
|
||||||
I2CS_STATE_REG_REQUEST,
|
|
||||||
I2CS_STATE_REG_ANSWER
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Private variables ---------------------------------------------------------
|
// Private variables ---------------------------------------------------------
|
||||||
@ -79,20 +71,10 @@ extern UART_HandleTypeDef huart3;
|
|||||||
|
|
||||||
volatile uint32_t systicks_counter = 0; // 1 MHz systick counter
|
volatile uint32_t systicks_counter = 0; // 1 MHz systick counter
|
||||||
static uint32_t pmu_check_counter = 0;
|
static uint32_t pmu_check_counter = 0;
|
||||||
static uint32_t i2cs_rearm_counter = 0;
|
|
||||||
|
|
||||||
static uint8_t i2cs_r_buff[5];
|
|
||||||
static volatile uint8_t i2cs_r_idx = 0;
|
|
||||||
static uint8_t i2cs_w_buff[I2CS_W_BUFF_LEN];
|
|
||||||
static volatile uint8_t i2cs_w_idx = 0;
|
|
||||||
static volatile uint8_t i2cs_w_len = 0;
|
|
||||||
static enum i2cs_state i2cs_state = I2CS_STATE_IDLE;
|
|
||||||
|
|
||||||
static uint8_t keycb_start = 0;
|
static uint8_t keycb_start = 0;
|
||||||
static uint32_t head_phone_status = 0; // TODO: Combine status registers
|
static uint32_t head_phone_status = 0; // TODO: Combine status registers
|
||||||
|
|
||||||
static volatile uint8_t rtc_reg_xor_events = 0;
|
|
||||||
|
|
||||||
volatile uint8_t stop_mode_active = 0;
|
volatile uint8_t stop_mode_active = 0;
|
||||||
|
|
||||||
volatile uint8_t pmu_irq = 0;
|
volatile uint8_t pmu_irq = 0;
|
||||||
@ -117,202 +99,6 @@ extern void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) {
|
|
||||||
if (hi2c == &hi2c1) {
|
|
||||||
// I2C slave addr match error detection
|
|
||||||
if (AddrMatchCode != 0x3E) // 0x1F << 1
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (TransferDirection == I2C_DIRECTION_TRANSMIT) {
|
|
||||||
if (i2cs_state == I2CS_STATE_IDLE) {
|
|
||||||
i2cs_state = I2CS_STATE_REG_REQUEST;
|
|
||||||
|
|
||||||
i2cs_r_idx = 0;
|
|
||||||
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, i2cs_r_buff, 1, I2C_FIRST_FRAME); // This write the first received byte to i2cs_r_buff[0]
|
|
||||||
|
|
||||||
i2cs_rearm_counter = uptime_ms();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TransferDirection == I2C_DIRECTION_RECEIVE) {
|
|
||||||
if (i2cs_state == I2CS_STATE_REG_REQUEST) {
|
|
||||||
const uint8_t is_write = (uint8_t)(i2cs_r_buff[0] & (1 << 7));
|
|
||||||
const uint8_t reg = (uint8_t)(i2cs_r_buff[0] & ~(1 << 7));
|
|
||||||
|
|
||||||
i2cs_w_buff[0] = reg;
|
|
||||||
i2cs_w_len = 2;
|
|
||||||
|
|
||||||
if (reg == REG_ID_BKL) { // We wait an another byte for these registers
|
|
||||||
if (is_write)
|
|
||||||
lcd_backlight_update(i2cs_r_buff[1]);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_BKL);
|
|
||||||
} else if (reg == REG_ID_BK2) {
|
|
||||||
if (is_write)
|
|
||||||
kbd_backlight_update(i2cs_r_buff[1]);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_BK2);
|
|
||||||
} else if (reg == REG_ID_CFG) {
|
|
||||||
if (is_write)
|
|
||||||
reg_set_value(REG_ID_CFG, i2cs_r_buff[1]);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_CFG);
|
|
||||||
} else if (reg == REG_ID_INT_CFG) {
|
|
||||||
if (is_write)
|
|
||||||
reg_set_value(REG_ID_INT_CFG, i2cs_r_buff[1]);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_INT_CFG);
|
|
||||||
} else if (reg == REG_ID_DEB) {
|
|
||||||
if (is_write) {
|
|
||||||
keyboard_set_hold_period(*((uint16_t*)&i2cs_r_buff[1]));
|
|
||||||
reg_set_value(REG_ID_DEB, 0); // Trig async flag for EEPROM saving
|
|
||||||
}
|
|
||||||
*((uint16_t*)&i2cs_w_buff[1]) = keyboard_get_hold_period();
|
|
||||||
|
|
||||||
i2cs_w_len = 3;
|
|
||||||
} else if (reg == REG_ID_FRQ) {
|
|
||||||
if (is_write)
|
|
||||||
reg_set_value(REG_ID_FRQ, i2cs_r_buff[1]);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_FRQ);
|
|
||||||
} else if (reg == REG_ID_FIF) {
|
|
||||||
struct fifo_item item = {0};
|
|
||||||
fifo_dequeue(&item);
|
|
||||||
i2cs_w_buff[0] = item.state;
|
|
||||||
i2cs_w_buff[1] = item.key;
|
|
||||||
} else if (reg == REG_ID_INT) {
|
|
||||||
if (is_write)
|
|
||||||
reg_set_value(REG_ID_INT, 0);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_INT);
|
|
||||||
LL_GPIO_SetOutputPin(PICO_IRQ_GPIO_Port, PICO_IRQ_Pin); // De-assert the IRQ signal
|
|
||||||
} else if (reg == REG_ID_VER) {
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_VER);
|
|
||||||
} else if (reg == REG_ID_TYP) {
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_TYP);
|
|
||||||
} else if (reg == REG_ID_BAT) {
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_BAT);
|
|
||||||
} else if (reg == REG_ID_RTC_CFG) {
|
|
||||||
if (is_write) {
|
|
||||||
rtc_reg_xor_events |= reg_get_value(REG_ID_RTC_CFG) ^ i2cs_r_buff[1]; // Using a "OR" set style to avoid loosing change before processing it
|
|
||||||
reg_set_value(REG_ID_RTC_CFG, i2cs_r_buff[1]);
|
|
||||||
}
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_RTC_CFG);
|
|
||||||
} else if (reg == REG_ID_RTC_DATE) {
|
|
||||||
RTC_DateTypeDef date_s = {0};
|
|
||||||
if (is_write) {
|
|
||||||
i2cs_RTC_date_from_buffer(&date_s, &i2cs_r_buff[1]);
|
|
||||||
|
|
||||||
HAL_RTC_SetDate(&hrtc, &date_s, RTC_FORMAT_BIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
HAL_RTC_GetDate(&hrtc, &date_s, RTC_FORMAT_BIN);
|
|
||||||
i2cs_fill_buffer_RTC_date(&i2cs_w_buff[1], &date_s);
|
|
||||||
|
|
||||||
i2cs_w_len = 5;
|
|
||||||
} else if (reg == REG_ID_RTC_TIME) {
|
|
||||||
RTC_TimeTypeDef time_s = {0};
|
|
||||||
if (is_write) {
|
|
||||||
i2cs_RTC_time_from_buffer(&time_s, &i2cs_r_buff[1]);
|
|
||||||
|
|
||||||
HAL_RTC_SetTime(&hrtc, &time_s, RTC_FORMAT_BIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
HAL_RTC_GetTime(&hrtc, &time_s, RTC_FORMAT_BIN);
|
|
||||||
i2cs_fill_buffer_RTC_time(&i2cs_w_buff[1], &time_s);
|
|
||||||
|
|
||||||
i2cs_w_len = 4;
|
|
||||||
} else if (reg == REG_ID_RTC_ALARM_DATE) {
|
|
||||||
if (is_write)
|
|
||||||
i2cs_RTC_date_from_buffer(&rtc_alarm_date._s, &i2cs_r_buff[1]);
|
|
||||||
|
|
||||||
i2cs_fill_buffer_RTC_date(&i2cs_w_buff[1], &rtc_alarm_date._s);
|
|
||||||
|
|
||||||
i2cs_w_len = 5;
|
|
||||||
} else if (reg == REG_ID_RTC_ALARM_TIME) {
|
|
||||||
if (is_write)
|
|
||||||
i2cs_RTC_time_from_buffer(&rtc_alarm_time._s, &i2cs_r_buff[1]);
|
|
||||||
|
|
||||||
i2cs_fill_buffer_RTC_time(&i2cs_w_buff[1], &rtc_alarm_time._s);
|
|
||||||
|
|
||||||
i2cs_w_len = 4;
|
|
||||||
} else if (reg == REG_ID_KEY) {
|
|
||||||
i2cs_w_buff[0] = fifo_count();
|
|
||||||
i2cs_w_buff[0] |= keyboard_get_numlock() ? KEY_NUMLOCK : 0x00;
|
|
||||||
i2cs_w_buff[0] |= keyboard_get_capslock() ? KEY_CAPSLOCK : 0x00;
|
|
||||||
} else if (reg == REG_ID_C64_MTX) {
|
|
||||||
//memcpy(write_buffer + 1, io_matrix, sizeof(io_matrix));
|
|
||||||
*((uint32_t*)(&i2cs_w_buff[1]) + 0) = *((uint32_t*)(io_matrix) + 0);
|
|
||||||
*((uint32_t*)(&i2cs_w_buff[1]) + 1) = *((uint32_t*)(io_matrix) + 1);
|
|
||||||
i2cs_w_buff[9] = io_matrix[8];
|
|
||||||
|
|
||||||
i2cs_w_len = 10;
|
|
||||||
} else if (reg == REG_ID_C64_JS) {
|
|
||||||
i2cs_w_buff[1] = js_bits;
|
|
||||||
} else if (reg == REG_ID_PWR_CTRL) {
|
|
||||||
if (is_write)
|
|
||||||
reg_set_value(REG_ID_PWR_CTRL, i2cs_r_buff[1]);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_PWR_CTRL);
|
|
||||||
} else {
|
|
||||||
i2cs_w_buff[0] = 0;
|
|
||||||
i2cs_w_buff[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2cs_state = I2CS_STATE_REG_ANSWER;
|
|
||||||
i2cs_w_idx = 0;
|
|
||||||
|
|
||||||
HAL_I2C_Slave_Sequential_Transmit_IT(hi2c, i2cs_w_buff, i2cs_w_len, I2C_FIRST_AND_LAST_FRAME);
|
|
||||||
|
|
||||||
i2cs_rearm_counter = uptime_ms();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
|
|
||||||
if (hi2c == &hi2c1) {
|
|
||||||
i2cs_r_idx++;
|
|
||||||
|
|
||||||
if (i2cs_state == I2CS_STATE_REG_REQUEST) {
|
|
||||||
const uint8_t is_write = (uint8_t)(i2cs_r_buff[0] & (1 << 7));
|
|
||||||
const uint8_t reg = (uint8_t)(i2cs_r_buff[0] & ~(1 << 7));
|
|
||||||
uint8_t bytes_needed = 0;
|
|
||||||
|
|
||||||
// Check for another mandatories bytes depending on register requested
|
|
||||||
if (reg == REG_ID_BKL ||
|
|
||||||
reg == REG_ID_BK2 ||
|
|
||||||
reg == REG_ID_CFG ||
|
|
||||||
reg == REG_ID_INT_CFG ||
|
|
||||||
reg == REG_ID_FRQ) {
|
|
||||||
if (is_write)
|
|
||||||
bytes_needed = 1;
|
|
||||||
} else if (reg == REG_ID_DEB) {
|
|
||||||
if (is_write)
|
|
||||||
bytes_needed = 2;
|
|
||||||
} else if (reg == REG_ID_RTC_DATE ||
|
|
||||||
reg == REG_ID_RTC_ALARM_DATE ||
|
|
||||||
reg == REG_ID_RTC_TIME ||
|
|
||||||
reg == REG_ID_RTC_ALARM_TIME) {
|
|
||||||
if (is_write)
|
|
||||||
bytes_needed = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_needed > 0)
|
|
||||||
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, i2cs_r_buff + i2cs_r_idx, bytes_needed, I2C_NEXT_FRAME); // This write the second or more received byte to i2cs_r_buff[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void HAL_I2C_ListenCpltCallback (I2C_HandleTypeDef *hi2c) {
|
|
||||||
if (hi2c == &hi2c1) {
|
|
||||||
if (i2cs_state == I2CS_STATE_REG_ANSWER)
|
|
||||||
i2cs_state = I2CS_STATE_IDLE;
|
|
||||||
|
|
||||||
HAL_I2C_EnableListen_IT(hi2c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) {
|
|
||||||
if (hi2c == &hi2c1)
|
|
||||||
if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF)
|
|
||||||
Error_Handler();
|
|
||||||
// Actually this will trigger the watchdog and restart the system... That can ruin the day of the user.
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void uart_rawdata_write(uint32_t c, size_t s, uint8_t swap) {
|
void uart_rawdata_write(uint32_t c, size_t s, uint8_t swap) {
|
||||||
uint8_t r[4];
|
uint8_t r[4];
|
||||||
@ -626,7 +412,7 @@ static void key_cb(char key, enum key_state state) {
|
|||||||
int_trig = 1;
|
int_trig = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg_is_bit_set(REG_ID_CFG, CFG_OVERFLOW_ON)) fifo_enqueue_force(item);
|
if (reg_is_bit_set(REG_ID_SYS_CFG, CFG_OVERFLOW_ON)) fifo_enqueue_force(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef UART_PICO_INTERFACE
|
#ifndef UART_PICO_INTERFACE
|
||||||
|
@ -9,9 +9,13 @@
|
|||||||
extern RTC_HandleTypeDef hrtc;
|
extern RTC_HandleTypeDef hrtc;
|
||||||
|
|
||||||
static uint8_t regs[REG_ID_LAST] = {0};
|
static uint8_t regs[REG_ID_LAST] = {0};
|
||||||
static uint8_t regs_unsync[REG_ID_LAST] = {0};
|
|
||||||
static uint32_t eeprom_refresh_counter;
|
static uint32_t eeprom_refresh_counter;
|
||||||
|
|
||||||
|
static uint32_t regs_unsync[(REG_ID_LAST / 32) + 1] = {0};
|
||||||
|
#define REGS_UNSYNC_SET(x) regs_unsync[(x / 32)] |= (uint32_t)(1U << (x % 32))
|
||||||
|
#define REGS_UNSYNC_UNSET(x) regs_unsync[(x / 32)] &= ~((uint32_t)(1U << (x % 32)))
|
||||||
|
#define REGS_UNSYNC_GET(x) ((regs_unsync[(x / 32)] >> (x % 32)) & (uint32_t)0x1)
|
||||||
|
|
||||||
inline uint8_t reg_get_value(enum reg_id reg) {
|
inline uint8_t reg_get_value(enum reg_id reg) {
|
||||||
if (reg >= REG_ID_LAST)
|
if (reg >= REG_ID_LAST)
|
||||||
return 0;
|
return 0;
|
||||||
@ -28,7 +32,7 @@ inline void reg_set_value(enum reg_id reg, uint8_t value) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
regs[reg] = value;
|
regs[reg] = value;
|
||||||
regs_unsync[reg] = 1;
|
REGS_UNSYNC_SET(reg);
|
||||||
eeprom_refresh_counter = uptime_ms();
|
eeprom_refresh_counter = uptime_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,29 +48,30 @@ inline void reg_set_bit(enum reg_id reg, uint8_t bit) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
regs[reg] |= bit;
|
regs[reg] |= bit;
|
||||||
regs_unsync[reg] = 1;
|
REGS_UNSYNC_SET(reg);
|
||||||
eeprom_refresh_counter = uptime_ms();
|
eeprom_refresh_counter = uptime_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* | Bit | Name | Description |
|
* | Bit | Name | Description |
|
||||||
| ------ |:----------------:| ------------------------------------------------------------------:|
|
* | ------ |:----------------:| ------------------------------------------------------------------:|
|
||||||
| 7 | CFG_USE_MODS | Should Alt, Sym and the Shift keys modify the keys being reported. |
|
* | 7 | CFG_USE_MODS | Should Alt, Sym and the Shift keys modify the keys being reported. |
|
||||||
| 6 | CFG_REPORT_MODS | Should Alt, Sym and the Shift keys be reported as well. |
|
* | 6 | CFG_REPORT_MODS | Should Alt, Sym and the Shift keys be reported as well. |
|
||||||
| 5 | CFG_PANIC_INT | Currently not implemented. |
|
* | 5 | CFG_PANIC_INT | Currently not implemented. |
|
||||||
| 4 | CFG_KEY_INT | Should an interrupt be generated when a key is pressed. |
|
* | 4 | CFG_KEY_INT | Should an interrupt be generated when a key is pressed. |
|
||||||
| 3 | CFG_NUMLOCK_INT | Should an interrupt be generated when Num Lock is toggled. |
|
* | 3 | CFG_NUMLOCK_INT | Should an interrupt be generated when Num Lock is toggled. |
|
||||||
| 2 | CFG_CAPSLOCK_INT | Should an interrupt be generated when Caps Lock is toggled. |
|
* | 2 | CFG_CAPSLOCK_INT | Should an interrupt be generated when Caps Lock is toggled. |
|
||||||
| 1 | CFG_OVERFLOW_INT | Should an interrupt be generated when a FIFO overflow happens. |
|
* | 1 | CFG_OVERFLOW_INT | Should an interrupt be generated when a FIFO overflow happens. |
|
||||||
| 0 | CFG_OVERFLOW_ON | When a FIFO overflow happens, should the new entry still be pushed, overwriting the oldest one. If 0 then new entry is lost. |
|
* | 0 | CFG_OVERFLOW_ON | When a FIFO overflow happens, should the new entry still be pushed,|
|
||||||
|
* | | | overwriting the oldest one. If 0 then new entry is lost. |
|
||||||
*/
|
*/
|
||||||
void reg_init(void) {
|
void reg_init(void) {
|
||||||
uint32_t buff;
|
uint32_t buff;
|
||||||
|
|
||||||
regs[REG_ID_VER] = (uint8_t)((VERSION_MAJOR << 4) | VERSION_MINOR); // 1.2 => (0x1 << 4) | 0x2
|
regs[REG_ID_VER] = (uint8_t)((VERSION_MAJOR << 4) | VERSION_MINOR); // 1.2 => (0x1 << 4) | 0x2
|
||||||
|
|
||||||
EEPROM_ReadVariable(EEPROM_VAR_CFG, (EEPROM_Value*)&buff);
|
EEPROM_ReadVariable(REG_ID_SYS_CFG, (EEPROM_Value*)&buff);
|
||||||
regs[REG_ID_CFG] = (uint8_t)((buff >> 8) & 0xFF);
|
regs[REG_ID_SYS_CFG] = (uint8_t)((buff >> 8) & 0xFF);
|
||||||
regs[REG_ID_INT_CFG] = (uint8_t)(buff & 0xFF);
|
regs[REG_ID_INT_CFG] = (uint8_t)(buff & 0xFF);
|
||||||
|
|
||||||
EEPROM_ReadVariable(EEPROM_VAR_KBD, (EEPROM_Value*)&buff);
|
EEPROM_ReadVariable(EEPROM_VAR_KBD, (EEPROM_Value*)&buff);
|
||||||
@ -100,33 +105,33 @@ uint32_t reg_check_and_save_eeprom(void) {
|
|||||||
uint8_t need_save = 0;
|
uint8_t need_save = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < REG_ID_LAST; i++)
|
for (size_t i = 0; i < REG_ID_LAST; i++)
|
||||||
if (regs_unsync[i] == 1) {
|
if (REGS_UNSYNC_GET(i) == 1) {
|
||||||
need_save = 1;
|
need_save = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_save == 1) {
|
if (need_save == 1) {
|
||||||
if (regs_unsync[REG_ID_CFG] == 1)
|
if (REGS_UNSYNC_GET(REG_ID_SYS_CFG) == 1)
|
||||||
result |= EEPROM_WriteVariable(EEPROM_VAR_CFG, (EEPROM_Value)(uint16_t)((regs[REG_ID_CFG] << 8) | regs[REG_ID_INT_CFG]), EEPROM_SIZE16);
|
result |= EEPROM_WriteVariable(EEPROM_VAR_CFG, (EEPROM_Value)(uint16_t)((regs[REG_ID_SYS_CFG] << 8) | regs[REG_ID_INT_CFG]), EEPROM_SIZE16);
|
||||||
|
|
||||||
if (regs_unsync[REG_ID_DEB] == 1 || regs_unsync[REG_ID_FRQ] == 1)
|
if (REGS_UNSYNC_GET(REG_ID_DEB) == 1 || REGS_UNSYNC_GET(REG_ID_FRQ) == 1)
|
||||||
result |= EEPROM_WriteVariable(EEPROM_VAR_KBD, (EEPROM_Value)(uint32_t)((keyboard_get_hold_period() << 16) | regs[REG_ID_FRQ]), EEPROM_SIZE32);
|
result |= EEPROM_WriteVariable(EEPROM_VAR_KBD, (EEPROM_Value)(uint32_t)((keyboard_get_hold_period() << 16) | regs[REG_ID_FRQ]), EEPROM_SIZE32);
|
||||||
|
|
||||||
if (regs_unsync[REG_ID_BKL] == 1 || regs_unsync[REG_ID_BK2] == 1)
|
if (REGS_UNSYNC_GET(REG_ID_BKL) == 1 || REGS_UNSYNC_GET(REG_ID_BK2) == 1)
|
||||||
result |= EEPROM_WriteVariable(EEPROM_VAR_BCKL, (EEPROM_Value)(uint16_t)((regs[REG_ID_BKL] << 8) | regs[REG_ID_BK2]), EEPROM_SIZE16);
|
result |= EEPROM_WriteVariable(EEPROM_VAR_BCKL, (EEPROM_Value)(uint16_t)((regs[REG_ID_BKL] << 8) | regs[REG_ID_BK2]), EEPROM_SIZE16);
|
||||||
|
|
||||||
if (regs_unsync[REG_ID_RTC_ALARM_TIME] == 1 || regs_unsync[REG_ID_RTC_CFG] == 1) {
|
if (REGS_UNSYNC_GET(REG_ID_RTC_ALARM_TIME) == 1 || REGS_UNSYNC_GET(REG_ID_RTC_CFG) == 1) {
|
||||||
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, ((rtc_alarm_time.raw & 0xFF) << 8) | regs[REG_ID_RTC_CFG]);
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, ((rtc_alarm_time.raw & 0xFF) << 8) | regs[REG_ID_RTC_CFG]);
|
||||||
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, rtc_alarm_time.raw >> 16);
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, rtc_alarm_time.raw >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regs_unsync[REG_ID_RTC_ALARM_DATE] == 1) {
|
if (REGS_UNSYNC_GET(REG_ID_RTC_ALARM_DATE) == 1) {
|
||||||
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, rtc_alarm_date.raw & 0xFFFF);
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, rtc_alarm_date.raw & 0xFFFF);
|
||||||
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, rtc_alarm_date.raw >> 16);
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, rtc_alarm_date.raw >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < REG_ID_LAST; i++)
|
for (size_t i = 0; i < REG_ID_LAST; i++)
|
||||||
regs_unsync[i] = 0;
|
REGS_UNSYNC_UNSET(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
18
README.md
18
README.md
@ -9,11 +9,12 @@ The main differences with the original firmware are the followings:
|
|||||||
- drastic reduction in the STM32's electricity consumption when running (~3.5 mA),
|
- drastic reduction in the STM32's electricity consumption when running (~3.5 mA),
|
||||||
- clean up (by removing stm32duino dependencies, use STM32HAL instead, maybe I'll switch to libopencm3 someday...) to reduce binary size (~25 KB) and allow more features to be implemented,
|
- clean up (by removing stm32duino dependencies, use STM32HAL instead, maybe I'll switch to libopencm3 someday...) to reduce binary size (~25 KB) and allow more features to be implemented,
|
||||||
- added configuration saving solution (using internal flash, including backlight option),
|
- added configuration saving solution (using internal flash, including backlight option),
|
||||||
- new I2C registers and structure (keeping compatible access to REG_ID_TYP and REG_ID_VER registers to check how to handle comm from pico board side),
|
- new I2C registers memory allocation and structure (keeping compatible access to REG_ID_TYP and REG_ID_VER registers to check how to handle comm from pico board side)(WIP),
|
||||||
- interrupt event output to pico board can be configured during runtime (for keyboard event or RTC alarm),
|
- interrupt event output to pico board can be configured during runtime (for keyboard event or RTC alarm),
|
||||||
- rewriten or added some debug UART interface message,
|
- rewriten or added some debug UART interface message (only when compiled in DEBUG release type),
|
||||||
- internal RTC access through dedicated I2C registers (WIP),
|
- internal RTC access through dedicated I2C registers,
|
||||||
- lighten AXP2101 PMIC driver.
|
- auto wake-up using RTC (WIP),
|
||||||
|
- lighten AXP2101 PMIC driver (based on X-PowersLib).
|
||||||
|
|
||||||
## Compile
|
## Compile
|
||||||
This source code can be compiled using ARM gcc toolchain (using v13) in path and using make program.
|
This source code can be compiled using ARM gcc toolchain (using v13) in path and using make program.
|
||||||
@ -23,9 +24,18 @@ But this makes them incompatible with official firmware. (More details to come a
|
|||||||
|
|
||||||
If you plan using pico official firmware (PicoMite, etc.), you should set I2C_REGS_COMPAT = 1 in the Makefile.
|
If you plan using pico official firmware (PicoMite, etc.), you should set I2C_REGS_COMPAT = 1 in the Makefile.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- Registers memory structure/allocation rewrite
|
||||||
|
- Auto wake-up
|
||||||
|
- IRQ to Pico management (register exist but does nothing)
|
||||||
|
- Add a Pico test program for registers/features implemented
|
||||||
|
- add few wiki page to detail the I2C protocol, added features, etc.
|
||||||
|
|
||||||
## Important notes
|
## Important notes
|
||||||
The current implementation of this firmware is subject to change until the v1 release.
|
The current implementation of this firmware is subject to change until the v1 release.
|
||||||
|
|
||||||
|
Some features can be unstable or buggy and are marked as pre-release. A test program will be developped soon to provide some regression testing.
|
||||||
|
|
||||||
The permanent settings (EEPROM) save can be broken between 0.x version, it is recommanded to make a full flash erase before updating, as
|
The permanent settings (EEPROM) save can be broken between 0.x version, it is recommanded to make a full flash erase before updating, as
|
||||||
EEPROM configuration survives update.
|
EEPROM configuration survives update.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user