diff --git a/Core/Inc/eeprom.h b/Core/Inc/eeprom.h index 5f364c5..c4daf48 100644 --- a/Core/Inc/eeprom.h +++ b/Core/Inc/eeprom.h @@ -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------------------------------------------- diff --git a/Core/Inc/keyboard.h b/Core/Inc/keyboard.h index 3b8db07..20567c8 100644 --- a/Core/Inc/keyboard.h +++ b/Core/Inc/keyboard.h @@ -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); diff --git a/Core/Inc/regs.h b/Core/Inc/regs.h index 07095f6..b400fd3 100644 --- a/Core/Inc/regs.h +++ b/Core/Inc/regs.h @@ -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 diff --git a/Core/Src/keyboard.c b/Core/Src/keyboard.c index ab39b66..4cbcc3d 100644 --- a/Core/Src/keyboard.c +++ b/Core/Src/keyboard.c @@ -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 diff --git a/Core/Src/main.c b/Core/Src/main.c index 0161951..42e69f6 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -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 diff --git a/Core/Src/regs.c b/Core/Src/regs.c index 4484906..4dacf6f 100644 --- a/Core/Src/regs.c +++ b/Core/Src/regs.c @@ -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); diff --git a/Makefile b/Makefile index 3fd66a9..3816b93 100644 --- a/Makefile +++ b/Makefile @@ -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 = diff --git a/README.md b/README.md index 8df2724..8a744ec 100644 --- a/README.md +++ b/README.md @@ -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)