Upgraded I2C receive handler

This commit is contained in:
JackCarterSmith 2025-05-08 18:42:43 +02:00
parent c8351f0124
commit 4f003168c4
Signed by: JackCarterSmith
GPG Key ID: 832E52F4E23F8F24
8 changed files with 83 additions and 22 deletions

View File

@ -9,10 +9,10 @@
//---------------------------------------------Datas registration--------------------------------------------
#define EEPROM_VAR_ID (0) // 16b: Init ID: 0xCA1C
#define EEPROM_VAR_CFG (1) // 16b: CFG + INT_CFG reg
#define EEPROM_VAR_KBD (2) // 16b: DEB + FRQ regs
#define EEPROM_VAR_BCKL (3) // 16b: LCD + KBD backlight step indice
#define EEPROM_VAR_ID (0) // 16b: Init ID: 0xCA1C
#define EEPROM_VAR_CFG (1) // 16b: CFG(15:8) + INT_CFG(7:0) reg
#define EEPROM_VAR_KBD (2) // 32b: DEB(15:0) + 0x00 + FRQ(7:0) regs
#define EEPROM_VAR_BCKL (3) // 16b: LCD(15:8) + KBD(7:0) backlight step indice
//-------------------------------------------library configuration-------------------------------------------

View File

@ -83,6 +83,8 @@ void keyboard_set_key_callback(key_callback callback);
void keyboard_set_lock_callback(lock_callback callback);
uint8_t keyboard_get_capslock(void);
uint8_t keyboard_get_numlock(void);
uint16_t keyboard_get_hold_period(void);
void keyboard_set_hold_period(uint16_t);
void keyboard_process(void);

View File

@ -29,8 +29,8 @@ enum reg_id {
REG_ID_INT = 0x04, //!< interrupt status
REG_ID_BKL = 0x05, //!< backlight steps (0-9)
REG_ID_BK2 = 0x06, //!< keyboard backlight (0-9)
REG_ID_DEB = 0x07, //!< debounce cfg
REG_ID_FRQ = 0x08, //!< poll freq cfg
REG_ID_DEB = 0x07, //!< debounce cfg (time in ms)
REG_ID_FRQ = 0x08, //!< poll freq cfg (time in ms)
REG_ID_KEY = 0x10, //!< key status
REG_ID_FIF = 0x11, //!< fifo

View File

@ -109,6 +109,7 @@ static uint8_t capslock_changed = 0;
static uint8_t capslock = 0;
static uint8_t numlock_changed = 0;
static uint8_t numlock = 0;
static uint16_t hold_period = KEY_HOLD_TIME;
uint8_t io_matrix[9] = {0}; //for IO matrix,last byte is the restore key(c64 only)
uint8_t js_bits = 0xFF; // c64 joystick bits
@ -130,6 +131,14 @@ inline uint8_t keyboard_get_numlock(void) {
return numlock & 0x1;
}
inline uint16_t keyboard_get_hold_period(void) {
return hold_period;
}
inline void keyboard_set_hold_period(uint16_t value) {
hold_period = value;
}
static void transition_to(struct list_item * const p_item, const enum key_state next_state) {
uint8_t output = 1;
const struct entry * const p_entry = p_item->p_entry;
@ -272,7 +281,7 @@ static void next_item_state(struct list_item* const p_item, const uint8_t presse
break;
case KEY_STATE_PRESSED:
if (uptime_ms() > p_item->hold_start_time + KEY_HOLD_TIME) {
if (uptime_ms() > p_item->hold_start_time + hold_period) {
transition_to(p_item, KEY_STATE_HOLD);
p_item->last_repeat_time = uptime_ms();
} else if (!pressed)
@ -283,7 +292,7 @@ static void next_item_state(struct list_item* const p_item, const uint8_t presse
if (!pressed)
transition_to(p_item, KEY_STATE_RELEASED);
else {
if (uptime_ms() > p_item->hold_start_time + KEY_HOLD_TIME) {
if (uptime_ms() > p_item->hold_start_time + hold_period) {
if(uptime_ms() > p_item->last_repeat_time + KEY_REPEAT_TIME) {
transition_to(p_item, KEY_STATE_HOLD);
p_item->last_repeat_time = uptime_ms();
@ -305,7 +314,7 @@ static void next_item_state(struct list_item* const p_item, const uint8_t presse
void keyboard_process(void) {
js_bits = 0xFF;
if (uptime_ms() <= (last_process_time + KEY_POLL_TIME))
if (uptime_ms() <= (last_process_time + reg_get_value(REG_ID_FRQ)))
return;
// Scan for columns

View File

@ -26,8 +26,10 @@
// Private define ------------------------------------------------------------
//#define DEFAULT_LCD_BL (205) // ~40% PWM@7.81kHz (9 bits resolution)
//#define DEFAULT_KBD_BL (20) // ~4% PWM@7.81kHz (9 bits resolution)
#define DEFAULT_LCD_BL (3) //step-4 (~50%)
#define DEFAULT_KBD_BL (0) //step-1 (0%)
#define DEFAULT_LCD_BL (3) //step-4 (~50%)
#define DEFAULT_KBD_BL (0) //step-1 (0%)
#define DEFAULT_KBD_FREQ (KEY_POLL_TIME)
#define DEFAULT_KBD_DEB (KEY_HOLD_TIME)
#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?
@ -68,7 +70,7 @@ volatile uint32_t systicks_counter = 0; // 1 MHz systick counter - TODO: implem
volatile uint32_t pmu_check_counter = 0;
volatile uint32_t i2cs_rearm_counter = 0;
static uint8_t i2cs_r_buff[2];
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;
@ -129,6 +131,25 @@ extern void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirect
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);
@ -188,14 +209,24 @@ extern void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
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;
// We wait an another byte for these registers
// Check for another mandatories bytes depending on register requested
if (reg == REG_ID_BKL ||
reg == REG_ID_BK2) {
if (is_write) {
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, i2cs_r_buff + i2cs_r_idx, 1, I2C_NEXT_FRAME); // This write the second received byte to i2cs_r_buff[1]
}
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;
}
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]
}
}
}
@ -261,7 +292,7 @@ int main(void) {
EEPROM_ReadVariable(EEPROM_VAR_ID, (EEPROM_Value*)&result);
if ((uint16_t)result != 0xCA1C) {
EEPROM_WriteVariable(EEPROM_VAR_BCKL, (EEPROM_Value)(uint16_t)((DEFAULT_LCD_BL << 8) | DEFAULT_KBD_BL), EEPROM_SIZE16);
EEPROM_WriteVariable(EEPROM_VAR_KBD, (EEPROM_Value)(uint16_t)((10 << 8) | 5), EEPROM_SIZE16);
EEPROM_WriteVariable(EEPROM_VAR_KBD, (EEPROM_Value)(uint32_t)((DEFAULT_KBD_DEB << 16) | DEFAULT_KBD_FREQ), EEPROM_SIZE32);
EEPROM_WriteVariable(EEPROM_VAR_CFG, (EEPROM_Value)(uint16_t)(((CFG_USE_MODS | CFG_REPORT_MODS) << 8) | (INT_OVERFLOW | INT_KEY)), EEPROM_SIZE16);
EEPROM_WriteVariable(EEPROM_VAR_ID, (EEPROM_Value)(uint16_t)0xCA1C, EEPROM_SIZE16);
#ifdef DEBUG

View File

@ -67,7 +67,7 @@ void reg_init(void) {
regs[REG_ID_INT_CFG] = (uint8_t)(buff & 0xFF);
EEPROM_ReadVariable(EEPROM_VAR_KBD, (EEPROM_Value*)&buff);
regs[REG_ID_DEB] = (uint8_t)((buff >> 8) & 0xFF);
//regs[REG_ID_DEB] = (uint8_t)((buff >> 8) & 0xFF);
regs[REG_ID_FRQ] = (uint8_t)(buff & 0xFF);
EEPROM_ReadVariable(EEPROM_VAR_BCKL, (EEPROM_Value*)&buff);
@ -96,7 +96,7 @@ uint32_t reg_check_and_save_eeprom(void) {
result |= EEPROM_WriteVariable(EEPROM_VAR_CFG, (EEPROM_Value)(uint16_t)((regs[REG_ID_CFG] << 8) | regs[REG_ID_INT_CFG]), EEPROM_SIZE16);
if (regs_unsync[REG_ID_DEB] == 1 || regs_unsync[REG_ID_FRQ] == 1)
result |= EEPROM_WriteVariable(EEPROM_VAR_KBD, (EEPROM_Value)(uint16_t)((regs[REG_ID_DEB] << 8) | regs[REG_ID_FRQ]), EEPROM_SIZE16);
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)
result |= EEPROM_WriteVariable(EEPROM_VAR_BCKL, (EEPROM_Value)(uint16_t)((regs[REG_ID_BKL] << 8) | regs[REG_ID_BK2]), EEPROM_SIZE16);

View File

@ -20,6 +20,8 @@ TARGET = picocalc_BIOS_jcs
DEBUG = 0
# optimization
OPT = -O3
# use old I2C registers structure
I2C_REGS_COMPAT = 0
#######################################
@ -122,6 +124,10 @@ ifeq ($(DEBUG), 1)
C_DEFS += -DDEBUG
endif
ifeq ($(I2C_REGS_COMPAT), 1)
C_DEFS += -DI2C_REGS_COMPAT
endif
# AS includes
AS_INCLUDES =

View File

@ -7,15 +7,28 @@ PicoCalc STM32F103R8T6 firmware.
The main differences with the original firmware are the followings:
- drastic reduction in the STM32's electricity consumption when running (~3.5 mA),
- clean up (in progress) to reduce binary size (~25 KB) and allow more features to be implemented,
- removed stm32duino dependencies (use STM32HAL instead, maybe I'll switch to libopencm3 someday...),
- 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),
- 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),
- 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,
- internal RTC access through dedicated I2C registers (WIP),
- lighten AXP2101 PMIC driver.
## Compile
This source code can be compiled using ARM gcc toolchain (using v13) in path and using make program.
CAUTION: By default, I2C registers use a new, exploded structure that is more flexible!
But this makes them incompatible with official firmware. (More details to come about I2C registers structure in the wiki...)
If you plan using pico official firmware (PicoMite, etc.), you should set I2C_REGS_COMPAT = 1 in the Makefile.
## Important notes
The current implementation of this firmware is subject to change until the v1 release.
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.
## Credits
- STM32-HAL: [link](https://github.com/STMicroelectronics/stm32f1xx-hal-driver)
- STM32-CMSIS: [link](https://github.com/STMicroelectronics/cmsis-device-f1)