Compare commits

...

2 Commits

Author SHA1 Message Date
f9cc1a72a6
Upgraded I2C receive handler 2025-05-08 19:32:20 +02:00
c8351f0124
New I2C registers IRQ mechanism
Compatibility mode added
2025-05-08 19:32:18 +02:00
10 changed files with 148 additions and 50 deletions

View File

@ -1,3 +1,4 @@
#include "stm32f1xx_hal.h"
//EEPROM emulation library for STM32F1XX with HAL-Driver //EEPROM emulation library for STM32F1XX with HAL-Driver
//V2.0 //V2.0
@ -6,15 +7,12 @@
#ifndef __EEPROM_H #ifndef __EEPROM_H
#define __EEPROM_H #define __EEPROM_H
//includes
#include "stm32f1xx_hal.h"
//---------------------------------------------Datas registration-------------------------------------------- //---------------------------------------------Datas registration--------------------------------------------
#define EEPROM_VAR_ID (0) // 16b: Init ID: 0xCA1C #define EEPROM_VAR_ID (0) // 16b: Init ID: 0xCA1C
#define EEPROM_VAR_CFG (1) // 16b: 0x00 + CFG reg #define EEPROM_VAR_CFG (1) // 16b: CFG(15:8) + INT_CFG(7:0) reg
#define EEPROM_VAR_KBD (2) // 16b: DEB + FRQ regs #define EEPROM_VAR_KBD (2) // 32b: DEB(15:0) + 0x00 + FRQ(7:0) regs
#define EEPROM_VAR_BCKL (3) // 16b: LCD + KBD backlight step indice #define EEPROM_VAR_BCKL (3) // 16b: LCD(15:8) + KBD(7:0) backlight step indice
//-------------------------------------------library configuration------------------------------------------- //-------------------------------------------library configuration-------------------------------------------

View File

@ -103,10 +103,15 @@ extern "C" {
#define PICO_EN_GPIO_Port GPIOA #define PICO_EN_GPIO_Port GPIOA
#define SP_AMP_EN_Pin LL_GPIO_PIN_14 #define SP_AMP_EN_Pin LL_GPIO_PIN_14
#define SP_AMP_EN_GPIO_Port GPIOA #define SP_AMP_EN_GPIO_Port GPIOA
#ifdef UART_PICO_INTERFACE
#define PICO_UART_TX_Pin LL_GPIO_PIN_10 #define PICO_UART_TX_Pin LL_GPIO_PIN_10
#define PICO_UART_TX_GPIO_Port GPIOC #define PICO_UART_TX_GPIO_Port GPIOC
#define PICO_UART_RX_Pin LL_GPIO_PIN_11 #define PICO_UART_RX_Pin LL_GPIO_PIN_11
#define PICO_UART_RX_GPIO_Port GPIOC #define PICO_UART_RX_GPIO_Port GPIOC
#else
#define PICO_IRQ_Pin LL_GPIO_PIN_10
#define PICO_IRQ_GPIO_Port GPIOC
#endif
#define HP_DET_Pin LL_GPIO_PIN_12 #define HP_DET_Pin LL_GPIO_PIN_12
#define HP_DET_GPIO_Port GPIOC #define HP_DET_GPIO_Port GPIOC
#define KEY_4_Pin LL_GPIO_PIN_3 #define KEY_4_Pin LL_GPIO_PIN_3

View File

@ -83,6 +83,8 @@ void keyboard_set_key_callback(key_callback callback);
void keyboard_set_lock_callback(lock_callback callback); void keyboard_set_lock_callback(lock_callback callback);
uint8_t keyboard_get_capslock(void); uint8_t keyboard_get_capslock(void);
uint8_t keyboard_get_numlock(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); void keyboard_process(void);

View File

@ -4,9 +4,10 @@
#ifndef REGS_H_ #ifndef REGS_H_
#define REGS_H_ #define REGS_H_
enum reg_id enum reg_id {
{ 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
REG_ID_CFG = 0x02, // config REG_ID_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
@ -21,18 +22,31 @@ enum reg_id
REG_ID_C64_JS = 0x0D, // joystick io bits REG_ID_C64_JS = 0x0D, // joystick io bits
REG_ID_RST_PICO = 0x0E, // Pico reset REG_ID_RST_PICO = 0x0E, // Pico reset
REG_ID_SHTDW = 0x0F, // self-shutdown REG_ID_SHTDW = 0x0F, // self-shutdown
REG_ID_INT_CFG = 0x10, // IRQ config
#else
REG_ID_CFG = 0x02, //!< config
REG_ID_INT_CFG = 0x03, //!< IRQ config
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 (time in ms)
REG_ID_FRQ = 0x08, //!< poll freq cfg (time in ms)
REG_ID_TYP = 0xFF, // firmware type (0=official, others=custom) REG_ID_KEY = 0x10, //!< key status
REG_ID_FIF = 0x11, //!< fifo
REG_ID_C64_MTX = 0x12, //!< read c64 matrix
REG_ID_C64_JS = 0x13, //!< joystick io bits
REG_ID_RST = 0x20, //!< STM32 full reset
REG_ID_RST_PICO = 0x21, //!< Pico reset
REG_ID_SHTDW = 0x22, //!< self-shutdown
REG_ID_BAT = 0x30, //!< battery
#endif
REG_ID_LAST, REG_ID_LAST,
}; };
#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_OVERFLOW_INT (1 << 1) //Should an interrupt be generated when a FIFO overflow happens
#define CFG_CAPSLOCK_INT (1 << 2) //Should an interrupt be generated when Caps Lock is toggled.
#define CFG_NUMLOCK_INT (1 << 3) //Should an interrupt be generated when Num Lock is toggled.
#define CFG_KEY_INT (1 << 4)
#define CFG_PANIC_INT (1 << 5)
#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
// CFG_STICKY_MODS // Pressing and releasing a mod affects next key pressed // CFG_STICKY_MODS // Pressing and releasing a mod affects next key pressed

View File

@ -367,6 +367,14 @@ static void MX_GPIO_Init(void) {
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct); LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#ifndef UART_PICO_INTERFACE
GPIO_InitStruct.Pin = PICO_IRQ_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#endif
/**/ /**/
GPIO_InitStruct.Pin = ROW_1_Pin|ROW_2_Pin|ROW_3_Pin|ROW_4_Pin GPIO_InitStruct.Pin = ROW_1_Pin|ROW_2_Pin|ROW_3_Pin|ROW_4_Pin
|ROW_5_Pin|ROW_6_Pin|ROW_7_Pin|ROW_8_Pin; |ROW_5_Pin|ROW_6_Pin|ROW_7_Pin|ROW_8_Pin;

View File

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

View File

@ -26,8 +26,10 @@
// Private define ------------------------------------------------------------ // Private define ------------------------------------------------------------
//#define DEFAULT_LCD_BL (205) // ~40% PWM@7.81kHz (9 bits resolution) //#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_KBD_BL (20) // ~4% PWM@7.81kHz (9 bits resolution)
#define DEFAULT_LCD_BL (3) //step-4 (~50%) #define DEFAULT_LCD_BL (3) //step-4 (~50%)
#define DEFAULT_KBD_BL (0) //step-1 (0%) #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_REARM_TIMEOUT 500
#define I2CS_W_BUFF_LEN 31+1 // The last one must be only a 0 value, TODO: another cleaner way? #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 pmu_check_counter = 0;
volatile uint32_t i2cs_rearm_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 volatile uint8_t i2cs_r_idx = 0;
static uint8_t i2cs_w_buff[I2CS_W_BUFF_LEN]; static uint8_t i2cs_w_buff[I2CS_W_BUFF_LEN];
static volatile uint8_t i2cs_w_idx = 0; static volatile uint8_t i2cs_w_idx = 0;
@ -129,11 +131,33 @@ extern void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirect
if (is_write) if (is_write)
kbd_backlight_update(i2cs_r_buff[1]); kbd_backlight_update(i2cs_r_buff[1]);
i2cs_w_buff[1] = reg_get_value(REG_ID_BK2); 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) { } else if (reg == REG_ID_FIF) {
struct fifo_item item = {0}; struct fifo_item item = {0};
fifo_dequeue(&item); fifo_dequeue(&item);
i2cs_w_buff[0] = item.state; i2cs_w_buff[0] = item.state;
i2cs_w_buff[1] = item.key; i2cs_w_buff[1] = item.key;
} else if (reg == REG_ID_INT) {
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) { } else if (reg == REG_ID_VER) {
i2cs_w_buff[1] = reg_get_value(REG_ID_VER); i2cs_w_buff[1] = reg_get_value(REG_ID_VER);
} else if (reg == REG_ID_TYP) { } else if (reg == REG_ID_TYP) {
@ -185,14 +209,24 @@ extern void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
if (i2cs_state == I2CS_STATE_REG_REQUEST) { if (i2cs_state == I2CS_STATE_REG_REQUEST) {
const uint8_t is_write = (uint8_t)(i2cs_r_buff[0] & (1 << 7)); 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)); 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 || if (reg == REG_ID_BKL ||
reg == REG_ID_BK2) { reg == REG_ID_BK2 ||
if (is_write) { reg == REG_ID_CFG ||
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_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]
} }
} }
} }
@ -258,8 +292,8 @@ int main(void) {
EEPROM_ReadVariable(EEPROM_VAR_ID, (EEPROM_Value*)&result); EEPROM_ReadVariable(EEPROM_VAR_ID, (EEPROM_Value*)&result);
if ((uint16_t)result != 0xCA1C) { 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_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_OVERFLOW_INT | CFG_KEY_INT | CFG_USE_MODS | CFG_REPORT_MODS), EEPROM_SIZE16); 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); EEPROM_WriteVariable(EEPROM_VAR_ID, (EEPROM_Value)(uint16_t)0xCA1C, EEPROM_SIZE16);
#ifdef DEBUG #ifdef DEBUG
DEBUG_UART_MSG("EEPROM first start!\n\r"); DEBUG_UART_MSG("EEPROM first start!\n\r");
@ -404,54 +438,62 @@ int main(void) {
/* /*
static void lock_cb(uint8_t caps_changed, uint8_t num_changed) { static void lock_cb(uint8_t caps_changed, uint8_t num_changed) {
//uint8_t do_int = 0; uint8_t int_trig = 0;
if (caps_changed && reg_is_bit_set(REG_ID_CFG, CFG_CAPSLOCK_INT)) { if (caps_changed && reg_is_bit_set(REG_ID_CFG, CFG_CAPSLOCK_INT)) {
reg_set_bit(REG_ID_INT, INT_CAPSLOCK); reg_set_bit(REG_ID_INT, INT_CAPSLOCK);
//do_int = 1; int_trig = 1;
} }
if (num_changed && reg_is_bit_set(REG_ID_CFG, CFG_NUMLOCK_INT)) { if (num_changed && reg_is_bit_set(REG_ID_CFG, CFG_NUMLOCK_INT)) {
reg_set_bit(REG_ID_INT, INT_NUMLOCK); reg_set_bit(REG_ID_INT, INT_NUMLOCK);
//do_int = 1; int_trig = 1;
} }
// int_pin can be a LED #ifndef UART_PICO_INTERFACE
if (do_int) { if (int_trig == 1)
port_pin_set_output_level(int_pin, 0); LL_GPIO_ResetOutputPin(PICO_IRQ_GPIO_Port, PICO_IRQ_Pin); // Assert the IRQ signal to the pico
delay_ms(INT_DURATION_MS); #endif
port_pin_set_output_level(int_pin, 1);
}
} }
*/ */
static void key_cb(char key, enum key_state state) { static void key_cb(char key, enum key_state state) {
uint8_t int_trig = 0;
if (keycb_start == 0) { if (keycb_start == 0) {
fifo_flush(); fifo_flush();
return; return;
} }
if (reg_is_bit_set(REG_ID_CFG, CFG_KEY_INT)) { if (reg_is_bit_set(REG_ID_INT_CFG, INT_KEY)) {
reg_set_bit(REG_ID_INT, INT_KEY); reg_set_bit(REG_ID_INT, INT_KEY);
int_trig = 1;
} }
#ifdef DEBUG #ifdef DEBUG
// Serial1.println("key: 0x%02X/%d/%c, state: %d, blk: %d\r\n", key, key, key, state, reg_get_value(REG_ID_BKL)); DEBUG_UART_MSG("key: ");
//HAL_UART_Transmit_IT(&huart1, HP_PLUG_MSG, HP_PLUG_MSG_LEN); DEBUG_UART_MSG2(key, 1, 0);
DEBUG_UART_MSG("\n\r");
DEBUG_UART_MSG("state: ");
DEBUG_UART_MSG2(state, 1, 0);
//DEBUG_UART_MSG(" blk: ");
//DEBUG_UART_MSG2(reg_get_value(REG_ID_BKL), 1, 0);
DEBUG_UART_MSG("\n\r");
#endif #endif
const struct fifo_item item = {key, state}; const struct fifo_item item = {key, state};
if (!fifo_enqueue(item)) { if (!fifo_enqueue(item)) {
if (reg_is_bit_set(REG_ID_CFG, CFG_OVERFLOW_INT)) { if (reg_is_bit_set(REG_ID_INT_CFG, INT_OVERFLOW)) {
reg_set_bit(REG_ID_INT, INT_OVERFLOW); // INT_OVERFLOW The interrupt was generated by FIFO overflow. reg_set_bit(REG_ID_INT, INT_OVERFLOW); // INT_OVERFLOW The interrupt was generated by FIFO overflow.
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_CFG, CFG_OVERFLOW_ON)) fifo_enqueue_force(item);
} }
#ifdef DEBUG #ifndef UART_PICO_INTERFACE
//Serial1.println(key); if (int_trig == 1)
//HAL_UART_Transmit_IT(&huart1, HP_PLUG_MSG, HP_PLUG_MSG_LEN); LL_GPIO_ResetOutputPin(PICO_IRQ_GPIO_Port, PICO_IRQ_Pin); // Assert the IRQ signal to the pico
#endif #endif
} }

View File

@ -63,7 +63,8 @@ void reg_init(void) {
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(EEPROM_VAR_CFG, (EEPROM_Value*)&buff);
regs[REG_ID_CFG] = (uint8_t)(buff & 0xFF); regs[REG_ID_CFG] = (uint8_t)((buff >> 8) & 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);
regs[REG_ID_DEB] = (uint8_t)((buff >> 8) & 0xFF); regs[REG_ID_DEB] = (uint8_t)((buff >> 8) & 0xFF);
@ -92,10 +93,10 @@ uint32_t reg_check_and_save_eeprom(void) {
if (need_save == 1) { if (need_save == 1) {
if (regs_unsync[REG_ID_CFG] == 1) if (regs_unsync[REG_ID_CFG] == 1)
result |= EEPROM_WriteVariable(EEPROM_VAR_CFG, (EEPROM_Value)(uint16_t)regs[REG_ID_CFG], EEPROM_SIZE16); 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) 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) 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); 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 DEBUG = 0
# optimization # optimization
OPT = -O3 OPT = -O3
# use old I2C registers structure
I2C_REGS_COMPAT = 0
####################################### #######################################
@ -122,6 +124,10 @@ ifeq ($(DEBUG), 1)
C_DEFS += -DDEBUG C_DEFS += -DDEBUG
endif endif
ifeq ($(I2C_REGS_COMPAT), 1)
C_DEFS += -DI2C_REGS_COMPAT
endif
# AS includes # AS includes
AS_INCLUDES = AS_INCLUDES =

View File

@ -7,15 +7,28 @@ PicoCalc STM32F103R8T6 firmware.
The main differences with the original firmware are the followings: 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 (in progress) 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,
- removed stm32duino dependencies (use STM32HAL instead, maybe I'll switch to libopencm3 someday...),
- 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),
- 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,
- internal RTC access through dedicated I2C registers (WIP),
- lighten AXP2101 PMIC driver. - lighten AXP2101 PMIC driver.
## 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.
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 ## Credits
- STM32-HAL: [link](https://github.com/STMicroelectronics/stm32f1xx-hal-driver) - STM32-HAL: [link](https://github.com/STMicroelectronics/stm32f1xx-hal-driver)
- STM32-CMSIS: [link](https://github.com/STMicroelectronics/cmsis-device-f1) - STM32-CMSIS: [link](https://github.com/STMicroelectronics/cmsis-device-f1)