Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
cdee81d3ff | |||
e1a77fc1ca | |||
efab6c2ff3 | |||
4d93c9d2e2 | |||
fb2b213392 | |||
8985f3d3a3 |
@ -324,8 +324,8 @@ uint8_t AXP2101_isDropWarningLevel1Irq(void);
|
|||||||
uint8_t AXP2101_isVbusRemoveIrq(void);
|
uint8_t AXP2101_isVbusRemoveIrq(void);
|
||||||
uint8_t AXP2101_isBatInsertIrq(void);
|
uint8_t AXP2101_isBatInsertIrq(void);
|
||||||
uint8_t AXP2101_isBatRemoveIrq(void);
|
uint8_t AXP2101_isBatRemoveIrq(void);
|
||||||
uint8_t AXP2101_isPekeyShortPressIrq(void);
|
uint8_t AXP2101_isPkeyShortPressIrq(void);
|
||||||
uint8_t AXP2101_isPekeyLongPressIrq(void);
|
uint8_t AXP2101_isPkeyLongPressIrq(void);
|
||||||
uint8_t AXP2101_isBatChargeDoneIrq(void);
|
uint8_t AXP2101_isBatChargeDoneIrq(void);
|
||||||
uint8_t AXP2101_isBatChargeStartIrq(void);
|
uint8_t AXP2101_isBatChargeStartIrq(void);
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#define EEPROM_VAR_ID (0) // 16b: Init ID: 0xCA1C
|
#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_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_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
|
#define EEPROM_VAR_BCKL (3) // 16b: LCD(15:8) + KBD(7:0) backlight step indice
|
||||||
|
|
||||||
//-------------------------------------------library configuration-------------------------------------------
|
//-------------------------------------------library configuration-------------------------------------------
|
||||||
|
@ -27,9 +27,7 @@
|
|||||||
#include "stm32f1xx_ll_utils.h"
|
#include "stm32f1xx_ll_utils.h"
|
||||||
#include "stm32f1xx_ll_pwr.h"
|
#include "stm32f1xx_ll_pwr.h"
|
||||||
#include "stm32f1xx_ll_dma.h"
|
#include "stm32f1xx_ll_dma.h"
|
||||||
#include "stm32f1xx_ll_rtc.h"
|
|
||||||
#include "stm32f1xx_ll_gpio.h"
|
#include "stm32f1xx_ll_gpio.h"
|
||||||
#include "stm32f1xx_ll_tim.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAL_INTERFACE_H_
|
#ifndef HAL_INTERFACE_H_
|
||||||
@ -130,12 +128,30 @@ extern "C" {
|
|||||||
#define PICO_SDA_GPIO_Port GPIOB
|
#define PICO_SDA_GPIO_Port GPIOB
|
||||||
|
|
||||||
|
|
||||||
|
// Structure definition ---------------------------------------------------------------
|
||||||
|
typedef union {
|
||||||
|
uint32_t raw;
|
||||||
|
RTC_TimeTypeDef _s;
|
||||||
|
} RTC_TimeTypeDef_u;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint32_t raw;
|
||||||
|
RTC_DateTypeDef _s;
|
||||||
|
} RTC_DateTypeDef_u;
|
||||||
|
|
||||||
|
|
||||||
// Global variables definition --------------------------------------------------------
|
// Global variables definition --------------------------------------------------------
|
||||||
extern volatile uint32_t systicks_counter;
|
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 rtc_reg_xor_events;
|
||||||
|
extern volatile RTC_TimeTypeDef_u rtc_alarm_time;
|
||||||
|
extern volatile RTC_DateTypeDef_u rtc_alarm_date;
|
||||||
|
|
||||||
|
|
||||||
// Global functions definition --------------------------------------------------------
|
// Global functions definition --------------------------------------------------------
|
||||||
|
void SystemClock_Config(void);
|
||||||
HAL_StatusTypeDef HAL_Interface_init(void);
|
HAL_StatusTypeDef HAL_Interface_init(void);
|
||||||
|
|
||||||
__STATIC_INLINE uint32_t uptime_ms(void) { return systicks_counter; }
|
__STATIC_INLINE uint32_t uptime_ms(void) { return systicks_counter; }
|
||||||
|
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,44 +8,73 @@ 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)
|
||||||
REG_ID_DEB = 0x06, // debounce cfg
|
REG_ID_DEB = 0x06, // debounce cfg
|
||||||
REG_ID_FRQ = 0x07, // poll freq cfg
|
REG_ID_FRQ = 0x07, // poll freq cfg
|
||||||
REG_ID_RST = 0x08, // STM32 full reset
|
REG_ID_PWR_CTRL = 0x08, // Power control (0: idle, 1: pico reset, 2: system reset, 3: reserved, 4: sleep, 5: full-shutdown)
|
||||||
REG_ID_FIF = 0x09, // fifo
|
REG_ID_FIF = 0x09, // fifo
|
||||||
REG_ID_BK2 = 0x0A, // keyboard backlight (0-9)
|
REG_ID_BK2 = 0x0A, // keyboard backlight (0-9)
|
||||||
REG_ID_BAT = 0x0B, // battery
|
REG_ID_BAT = 0x0B, // battery
|
||||||
REG_ID_C64_MTX = 0x0C,// read c64 matrix
|
REG_ID_C64_MTX = 0x0C,// read c64 matrix
|
||||||
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_INT_CFG = 0x0E, // IRQ config
|
||||||
REG_ID_SHTDW = 0x0F, // self-shutdown
|
REG_ID_RTC_CFG = 0x0F, // RTC general config
|
||||||
REG_ID_INT_CFG = 0x10, // IRQ config
|
REG_ID_RTC_DATE = 0x10, // RTC date
|
||||||
|
REG_ID_RTC_TIME = 0x11, // RTC time
|
||||||
|
REG_ID_RTC_ALARM_DATE = 0x12, // RTC alarm date
|
||||||
|
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_INT_CFG = 0x03, //!< IRQ config
|
REG_ID_SYS_CFG = 0x02, //!< config
|
||||||
REG_ID_INT = 0x04, //!< interrupt status
|
REG_ID_INT_CFG = 0x03, //!< IRQ config
|
||||||
REG_ID_BKL = 0x05, //!< backlight steps (0-9)
|
REG_ID_PWR_CTRL = 0x04, //!< Power control (0: idle, 1: pico reset, 2: system reset, 3: reserved, 4: sleep, 5: full-shutdown)
|
||||||
REG_ID_BK2 = 0x06, //!< keyboard backlight (0-9)
|
REG_ID_RTC_CFG = 0x05, //!< RTC general config
|
||||||
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
|
// TODO: REG_ID_CFG_1 - 32b (RW)
|
||||||
REG_ID_FIF = 0x11, //!< fifo
|
REG_ID_DEB = 0x06, //!< debounce cfg (time in ms)
|
||||||
REG_ID_C64_MTX = 0x12, //!< read c64 matrix
|
REG_ID_FRQ = 0x07, //!< poll freq cfg (time in ms)
|
||||||
REG_ID_C64_JS = 0x13, //!< joystick io bits
|
REG_ID_BKL = 0x08, //!< backlight steps (0-9)
|
||||||
|
REG_ID_BK2 = 0x09, //!< keyboard backlight (0-9)
|
||||||
|
|
||||||
REG_ID_RST = 0x20, //!< STM32 full reset
|
// TODO: REG_ID_RTC_DATE - 32b (RW)
|
||||||
REG_ID_RST_PICO = 0x21, //!< Pico reset
|
REG_ID_RTC_DATE = 0x0A, //!< RTC date
|
||||||
REG_ID_SHTDW = 0x22, //!< self-shutdown
|
// TODO: REG_ID_RTC_TIME - 32b (RW)
|
||||||
|
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
|
||||||
@ -61,6 +90,12 @@ enum reg_id {
|
|||||||
#define KEY_NUMLOCK (1 << 6)
|
#define KEY_NUMLOCK (1 << 6)
|
||||||
#define KEY_COUNT_MASK 0x1F //0x1F == 31
|
#define KEY_COUNT_MASK 0x1F //0x1F == 31
|
||||||
|
|
||||||
|
#define RTC_CFG_RUN_ALARM (1 << 0) // b0: Set the RTC alarm active.
|
||||||
|
#define RTC_CFG_REARM (1 << 1) // b1: If set, the RTC alarm will rearm for the next day trigger (if RTC_CFG_DATE_ALARM is set, repeat every day after the target date is reached)
|
||||||
|
#define RTC_CFG_DATE_ALARM (1 << 2) // b2: If set, check when alarm trig for the precise date, otherwise return to normal behavior (or sleep if wake-up)
|
||||||
|
#define RTC_CFG_PBTN_ALARM_IGNORE (1 << 3) // b3: If unset, override the power button shutdown behavior to keep the STM32 "alive" for the RTC to operate.
|
||||||
|
//#define RTC_CFG_SLEEP_MODE (1 << 4) // 0 = normal sleep (pico is shutdown, STM32 enter in low power state ~1.2mA); 1 = deep sleep (pico is shutdown, STM32 enter a stop state ~24uA)
|
||||||
|
|
||||||
|
|
||||||
uint8_t reg_get_value(enum reg_id reg);
|
uint8_t reg_get_value(enum reg_id reg);
|
||||||
uint8_t* reg_raw_access(void);
|
uint8_t* reg_raw_access(void);
|
||||||
|
15
Core/Inc/rtc.h
Normal file
15
Core/Inc/rtc.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "stm32f1xx_hal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RTC_H_
|
||||||
|
#define RTC_H_
|
||||||
|
|
||||||
|
void i2cs_fill_buffer_RTC_date(uint8_t* const buff, const volatile RTC_DateTypeDef* const date_s);
|
||||||
|
void i2cs_fill_buffer_RTC_time(uint8_t* const buff, const volatile RTC_TimeTypeDef* const time_s);
|
||||||
|
void i2cs_RTC_date_from_buffer(volatile RTC_DateTypeDef* const date_s, const uint8_t* const buff);
|
||||||
|
void i2cs_RTC_time_from_buffer(volatile RTC_TimeTypeDef* const time_s, const uint8_t* const buff);
|
||||||
|
|
||||||
|
uint32_t rtc_run_alarm(void);
|
||||||
|
uint32_t rtc_stop_alarm(void);
|
||||||
|
|
||||||
|
#endif /* RTC_H_ */
|
@ -57,7 +57,7 @@
|
|||||||
/*#define HAL_HCD_MODULE_ENABLED */
|
/*#define HAL_HCD_MODULE_ENABLED */
|
||||||
/*#define HAL_PWR_MODULE_ENABLED */
|
/*#define HAL_PWR_MODULE_ENABLED */
|
||||||
/*#define HAL_RCC_MODULE_ENABLED */
|
/*#define HAL_RCC_MODULE_ENABLED */
|
||||||
/*#define HAL_RTC_MODULE_ENABLED */
|
#define HAL_RTC_MODULE_ENABLED
|
||||||
/*#define HAL_SD_MODULE_ENABLED */
|
/*#define HAL_SD_MODULE_ENABLED */
|
||||||
/*#define HAL_MMC_MODULE_ENABLED */
|
/*#define HAL_MMC_MODULE_ENABLED */
|
||||||
/*#define HAL_SDRAM_MODULE_ENABLED */
|
/*#define HAL_SDRAM_MODULE_ENABLED */
|
||||||
|
@ -65,6 +65,7 @@ void USART1_IRQHandler(void);
|
|||||||
#ifdef UART_PICO_INTERFACE
|
#ifdef UART_PICO_INTERFACE
|
||||||
void USART3_IRQHandler(void);
|
void USART3_IRQHandler(void);
|
||||||
#endif
|
#endif
|
||||||
|
void RTC_Alarm_IRQHandler(void);
|
||||||
/* USER CODE BEGIN EFP */
|
/* USER CODE BEGIN EFP */
|
||||||
|
|
||||||
/* USER CODE END EFP */
|
/* USER CODE END EFP */
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
#define VERSION_H_
|
#define VERSION_H_
|
||||||
|
|
||||||
#define VERSION_MAJOR (0)
|
#define VERSION_MAJOR (0)
|
||||||
#define VERSION_MINOR (3)
|
#define VERSION_MINOR (6)
|
||||||
|
|
||||||
#endif /* VERSION_H_ */
|
#endif /* VERSION_H_ */
|
||||||
|
@ -173,14 +173,14 @@ uint8_t AXP2101_isBatRemoveIrq(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t AXP2101_isPekeyShortPressIrq(void) {
|
uint8_t AXP2101_isPkeyShortPressIrq(void) {
|
||||||
uint8_t mask = XPOWERS_AXP2101_PKEY_SHORT_IRQ >> 8;
|
uint8_t mask = XPOWERS_AXP2101_PKEY_SHORT_IRQ >> 8;
|
||||||
if (intRegister[1] & mask)
|
if (intRegister[1] & mask)
|
||||||
return ((statusRegister[1] & mask) == mask);
|
return ((statusRegister[1] & mask) == mask);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t AXP2101_isPekeyLongPressIrq(void) {
|
uint8_t AXP2101_isPkeyLongPressIrq(void) {
|
||||||
uint8_t mask = XPOWERS_AXP2101_PKEY_LONG_IRQ >> 8;
|
uint8_t mask = XPOWERS_AXP2101_PKEY_LONG_IRQ >> 8;
|
||||||
if (intRegister[1] & mask)
|
if (intRegister[1] & mask)
|
||||||
return ((statusRegister[1] & mask) == mask);
|
return ((statusRegister[1] & mask) == mask);
|
||||||
|
@ -18,11 +18,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hal_interface.h"
|
#include "hal_interface.h"
|
||||||
|
#include "stm32f1xx_hal_flash_ex.h"
|
||||||
|
|
||||||
|
|
||||||
I2C_HandleTypeDef hi2c1;
|
I2C_HandleTypeDef hi2c1;
|
||||||
I2C_HandleTypeDef hi2c2;
|
I2C_HandleTypeDef hi2c2;
|
||||||
|
|
||||||
|
RTC_HandleTypeDef hrtc;
|
||||||
|
|
||||||
TIM_HandleTypeDef htim1;
|
TIM_HandleTypeDef htim1;
|
||||||
TIM_HandleTypeDef htim2;
|
TIM_HandleTypeDef htim2;
|
||||||
TIM_HandleTypeDef htim3;
|
TIM_HandleTypeDef htim3;
|
||||||
@ -34,6 +37,10 @@ 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_DateTypeDef_u rtc_alarm_date = {.raw = 0x00010101};
|
||||||
|
|
||||||
static void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
|
static void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
|
||||||
|
|
||||||
|
|
||||||
@ -123,7 +130,6 @@ static void MX_I2C2_Init(void) {
|
|||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_IWDG_Init(void) {
|
static void MX_IWDG_Init(void) {
|
||||||
#ifndef DEBUG
|
|
||||||
LL_IWDG_Enable(IWDG);
|
LL_IWDG_Enable(IWDG);
|
||||||
LL_IWDG_EnableWriteAccess(IWDG);
|
LL_IWDG_EnableWriteAccess(IWDG);
|
||||||
LL_IWDG_SetPrescaler(IWDG, LL_IWDG_PRESCALER_32);
|
LL_IWDG_SetPrescaler(IWDG, LL_IWDG_PRESCALER_32);
|
||||||
@ -131,7 +137,6 @@ static void MX_IWDG_Init(void) {
|
|||||||
while (LL_IWDG_IsReady(IWDG) != 1) {}
|
while (LL_IWDG_IsReady(IWDG) != 1) {}
|
||||||
|
|
||||||
LL_IWDG_ReloadCounter(IWDG);
|
LL_IWDG_ReloadCounter(IWDG);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,28 +145,47 @@ static void MX_IWDG_Init(void) {
|
|||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_RTC_Init(void) {
|
static void MX_RTC_Init(void) {
|
||||||
LL_RTC_InitTypeDef RTC_InitStruct = {0};
|
RTC_TimeTypeDef sTime = {0};
|
||||||
LL_RTC_TimeTypeDef RTC_TimeStruct = {0};
|
RTC_DateTypeDef DateToUpdate = {0};
|
||||||
|
|
||||||
LL_PWR_EnableBkUpAccess();
|
|
||||||
/* Enable BKP CLK enable for backup registers */
|
|
||||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_BKP);
|
|
||||||
/* Peripheral clock enable */
|
|
||||||
LL_RCC_EnableRTC();
|
|
||||||
|
|
||||||
|
/** Initialize RTC Only
|
||||||
|
*/
|
||||||
|
hrtc.Instance = RTC;
|
||||||
|
hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
|
||||||
|
hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
|
||||||
|
if (HAL_RTC_Init(&hrtc) != HAL_OK)
|
||||||
|
Error_Handler();
|
||||||
|
|
||||||
/** Initialize RTC and set the Time and Date
|
/** Initialize RTC and set the Time and Date
|
||||||
*/
|
*/
|
||||||
RTC_InitStruct.AsynchPrescaler = 0xFFFFFFFFU;
|
sTime.Hours = 0x0;
|
||||||
LL_RTC_Init(RTC, &RTC_InitStruct);
|
sTime.Minutes = 0x0;
|
||||||
LL_RTC_SetAsynchPrescaler(RTC, 0xFFFFFFFFU);
|
sTime.Seconds = 0x0;
|
||||||
|
|
||||||
/** Initialize RTC and set the Time and Date
|
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
|
||||||
*/
|
Error_Handler();
|
||||||
RTC_TimeStruct.Hours = 0;
|
|
||||||
RTC_TimeStruct.Minutes = 0;
|
DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;
|
||||||
RTC_TimeStruct.Seconds = 0;
|
DateToUpdate.Month = RTC_MONTH_JANUARY;
|
||||||
LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_TimeStruct);
|
DateToUpdate.Date = 0x1;
|
||||||
|
DateToUpdate.Year = 0x0;
|
||||||
|
|
||||||
|
if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK)
|
||||||
|
Error_Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RTC fake initialization Function, used when RTC is already alive (after a wake-up reset)
|
||||||
|
* @param None
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
static void MX_RTC_Init2(void) {
|
||||||
|
hrtc.Instance = RTC;
|
||||||
|
hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
|
||||||
|
hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
|
||||||
|
hrtc.Lock = HAL_UNLOCKED;
|
||||||
|
HAL_RTC_MspInit(&hrtc);
|
||||||
|
hrtc.State = HAL_RTC_STATE_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -355,7 +379,7 @@ static void MX_GPIO_Init(void) {
|
|||||||
/**/
|
/**/
|
||||||
GPIO_InitStruct.Pin = SYS_LED_Pin;
|
GPIO_InitStruct.Pin = SYS_LED_Pin;
|
||||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
|
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
|
||||||
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
|
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
|
||||||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
|
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
|
||||||
LL_GPIO_Init(SYS_LED_GPIO_Port, &GPIO_InitStruct);
|
LL_GPIO_Init(SYS_LED_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
@ -529,6 +553,41 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RTC MSP Initialization
|
||||||
|
* This function configures the hardware resources used in this example
|
||||||
|
* @param hrtc: RTC handle pointer
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) {
|
||||||
|
if (hrtc->Instance == RTC) {
|
||||||
|
HAL_PWR_EnableBkUpAccess();
|
||||||
|
/* Enable BKP CLK enable for backup registers */
|
||||||
|
__HAL_RCC_BKP_CLK_ENABLE();
|
||||||
|
/* Peripheral clock enable */
|
||||||
|
__HAL_RCC_RTC_ENABLE();
|
||||||
|
/* RTC interrupt Init */
|
||||||
|
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);
|
||||||
|
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RTC MSP De-Initialization
|
||||||
|
* This function freeze the hardware resources used in this example
|
||||||
|
* @param hrtc: RTC handle pointer
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc) {
|
||||||
|
if (hrtc->Instance == RTC) {
|
||||||
|
/* Peripheral clock disable */
|
||||||
|
__HAL_RCC_RTC_DISABLE();
|
||||||
|
|
||||||
|
/* RTC interrupt DeInit */
|
||||||
|
HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief TIM_Base MSP Initialization
|
* @brief TIM_Base MSP Initialization
|
||||||
* This function configures the hardware resources used in this example
|
* This function configures the hardware resources used in this example
|
||||||
@ -740,7 +799,9 @@ void assert_failed(uint8_t *file, uint32_t line)
|
|||||||
|
|
||||||
void flash_one_time(uint32_t ts, uint8_t restore_status) {
|
void flash_one_time(uint32_t ts, uint8_t restore_status) {
|
||||||
for (size_t i = 0; i < ts; i++) {
|
for (size_t i = 0; i < ts; i++) {
|
||||||
LL_IWDG_ReloadCounter(IWDG);
|
//#ifndef DEBUG
|
||||||
|
// LL_IWDG_ReloadCounter(IWDG);
|
||||||
|
//#endif
|
||||||
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
|
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
|
||||||
HAL_Delay(400);
|
HAL_Delay(400);
|
||||||
LL_GPIO_SetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
|
LL_GPIO_SetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
|
||||||
@ -759,6 +820,7 @@ void flash_one_time(uint32_t ts, uint8_t restore_status) {
|
|||||||
*/
|
*/
|
||||||
HAL_StatusTypeDef HAL_Interface_init(void) {
|
HAL_StatusTypeDef HAL_Interface_init(void) {
|
||||||
HAL_StatusTypeDef result = HAL_OK;
|
HAL_StatusTypeDef result = HAL_OK;
|
||||||
|
FLASH_OBProgramInitTypeDef flash_s;
|
||||||
|
|
||||||
result |= HAL_Init();
|
result |= HAL_Init();
|
||||||
if (result != HAL_OK)
|
if (result != HAL_OK)
|
||||||
@ -766,16 +828,42 @@ HAL_StatusTypeDef HAL_Interface_init(void) {
|
|||||||
|
|
||||||
SystemClock_Config();
|
SystemClock_Config();
|
||||||
|
|
||||||
|
// Control wake-up state
|
||||||
|
//if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST))
|
||||||
|
//__HAL_RCC_CLEAR_RESET_FLAGS();
|
||||||
|
// Use SRAM backup registers to check if we have soft-reset
|
||||||
|
HAL_PWR_EnableBkUpAccess();
|
||||||
|
|
||||||
MX_GPIO_Init();
|
MX_GPIO_Init();
|
||||||
MX_I2C1_Init();
|
MX_I2C1_Init();
|
||||||
MX_I2C2_Init();
|
MX_I2C2_Init();
|
||||||
MX_RTC_Init();
|
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) != 0)
|
||||||
|
MX_RTC_Init2();
|
||||||
|
else
|
||||||
|
MX_RTC_Init();
|
||||||
MX_USART1_UART_Init();
|
MX_USART1_UART_Init();
|
||||||
MX_USART3_UART_Init();
|
MX_USART3_UART_Init();
|
||||||
MX_IWDG_Init();
|
//#ifndef DEBUG
|
||||||
|
// MX_IWDG_Init();
|
||||||
|
//#endif
|
||||||
MX_TIM1_Init();
|
MX_TIM1_Init();
|
||||||
MX_TIM3_Init();
|
MX_TIM3_Init();
|
||||||
MX_TIM2_Init();
|
MX_TIM2_Init();
|
||||||
|
|
||||||
|
// Check options registers values
|
||||||
|
HAL_FLASHEx_OBGetConfig(&flash_s);
|
||||||
|
//if ((flash_s.USERConfig & (OB_STOP_NO_RST | OB_STDBY_NO_RST)) != 0) {
|
||||||
|
if ((flash_s.USERConfig & (OB_STOP_NO_RST | OB_STDBY_NO_RST)) == 0) {
|
||||||
|
HAL_FLASH_Unlock();
|
||||||
|
HAL_FLASH_OB_Unlock();
|
||||||
|
//flash_s.USERConfig &= (uint8_t)~(OB_STOP_NO_RST | OB_STDBY_NO_RST); // Enable reset when sleep
|
||||||
|
flash_s.USERConfig |= (uint8_t)(OB_STOP_NO_RST | OB_STDBY_NO_RST); // Disable reset when sleep
|
||||||
|
HAL_FLASHEx_OBProgram(&flash_s);
|
||||||
|
HAL_FLASH_OB_Launch(); // Reset system
|
||||||
|
|
||||||
|
// We should never reach this point
|
||||||
|
for ( ;; ) {}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
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];
|
||||||
|
383
Core/Src/main.c
383
Core/Src/main.c
@ -11,6 +11,13 @@
|
|||||||
*
|
*
|
||||||
* SYS_LED and COL_x are open-drain, output logic is inverted.
|
* SYS_LED and COL_x are open-drain, output logic is inverted.
|
||||||
*
|
*
|
||||||
|
* Unless requested by the user through REG_ID_PWR_CTRL register or by removing
|
||||||
|
* the batteries, pressing the power button when running now put the STM32 in
|
||||||
|
* low-power stop mode and shutdown the PICO board.
|
||||||
|
* It's the only mean to keep the RTC functional.
|
||||||
|
* A full shutdown using AXP2101 power-off or by removing the batteries will
|
||||||
|
* reset the RTC and disable auto wake-up feature.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hal_interface.h"
|
#include "hal_interface.h"
|
||||||
@ -20,7 +27,9 @@
|
|||||||
#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"
|
||||||
|
|
||||||
|
|
||||||
// Private define ------------------------------------------------------------
|
// Private define ------------------------------------------------------------
|
||||||
@ -30,9 +39,7 @@
|
|||||||
#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_FREQ (KEY_POLL_TIME)
|
||||||
#define DEFAULT_KBD_DEB (KEY_HOLD_TIME)
|
#define DEFAULT_KBD_DEB (KEY_HOLD_TIME)
|
||||||
|
#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)
|
||||||
@ -42,18 +49,14 @@
|
|||||||
|
|
||||||
|
|
||||||
// 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 ---------------------------------------------------------
|
||||||
extern I2C_HandleTypeDef hi2c1;
|
extern I2C_HandleTypeDef hi2c1;
|
||||||
extern I2C_HandleTypeDef hi2c2;
|
extern I2C_HandleTypeDef hi2c2;
|
||||||
|
|
||||||
|
extern RTC_HandleTypeDef hrtc;
|
||||||
|
|
||||||
extern TIM_HandleTypeDef htim1;
|
extern TIM_HandleTypeDef htim1;
|
||||||
extern TIM_HandleTypeDef htim2;
|
extern TIM_HandleTypeDef htim2;
|
||||||
extern TIM_HandleTypeDef htim3;
|
extern TIM_HandleTypeDef htim3;
|
||||||
@ -68,18 +71,12 @@ 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
|
||||||
|
|
||||||
|
volatile uint8_t stop_mode_active = 0;
|
||||||
|
|
||||||
volatile uint8_t pmu_irq = 0;
|
volatile uint8_t pmu_irq = 0;
|
||||||
static uint32_t pmu_online = 0;
|
static uint32_t pmu_online = 0;
|
||||||
|
|
||||||
@ -93,6 +90,8 @@ static void sync_bat(void);
|
|||||||
static void printPMU(void);
|
static void printPMU(void);
|
||||||
#endif
|
#endif
|
||||||
static void check_pmu_int(void);
|
static void check_pmu_int(void);
|
||||||
|
static void sys_prepare_sleep(void);
|
||||||
|
static void sys_wake_sleep(void);
|
||||||
|
|
||||||
extern void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
|
extern void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
|
||||||
if (htim == &htim2) {
|
if (htim == &htim2) {
|
||||||
@ -100,159 +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) {
|
|
||||||
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_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_RST) {
|
|
||||||
if (is_write)
|
|
||||||
reg_set_value(REG_ID_RST, 1);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_RST);
|
|
||||||
} else if (reg == REG_ID_RST_PICO) {
|
|
||||||
if (is_write)
|
|
||||||
reg_set_value(REG_ID_RST_PICO, 1);
|
|
||||||
i2cs_w_buff[1] = reg_get_value(REG_ID_RST_PICO);
|
|
||||||
} else if (reg == REG_ID_SHTDW) {
|
|
||||||
if (is_write) {
|
|
||||||
reg_set_value(REG_ID_SHTDW, 1);
|
|
||||||
return; // Ignore answer, everything will be shutdown
|
|
||||||
}
|
|
||||||
i2cs_w_buff[1] = 0;
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
||||||
@ -281,12 +127,12 @@ int main(void) {
|
|||||||
if (result != HAL_OK)
|
if (result != HAL_OK)
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
|
|
||||||
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin); // I'm alive!
|
|
||||||
|
|
||||||
// Start the systick timer
|
// Start the systick timer
|
||||||
if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)
|
if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
|
|
||||||
|
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin); // I'm alive!
|
||||||
|
|
||||||
// EEPROM emulation init
|
// EEPROM emulation init
|
||||||
if (EEPROM_Init() != EEPROM_SUCCESS)
|
if (EEPROM_Init() != EEPROM_SUCCESS)
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
@ -306,6 +152,15 @@ int main(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check RTC SRAM first run
|
||||||
|
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) == 0) {
|
||||||
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0xCA1C);
|
||||||
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, ((rtc_alarm_time.raw & 0xFF) << 8) | DEFAULT_RCT_CFG);
|
||||||
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, rtc_alarm_time.raw >> 16);
|
||||||
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, rtc_alarm_date.raw & 0xFFFF);
|
||||||
|
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, rtc_alarm_date.raw >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
// I2C-Pico interface registers
|
// I2C-Pico interface registers
|
||||||
reg_init();
|
reg_init();
|
||||||
HAL_Delay(10);
|
HAL_Delay(10);
|
||||||
@ -374,6 +229,7 @@ int main(void) {
|
|||||||
AXP2101_clearIrqStatus();
|
AXP2101_clearIrqStatus();
|
||||||
AXP2101_enableIRQ(XPOWERS_AXP2101_BAT_INSERT_IRQ |
|
AXP2101_enableIRQ(XPOWERS_AXP2101_BAT_INSERT_IRQ |
|
||||||
XPOWERS_AXP2101_BAT_REMOVE_IRQ | // BATTERY
|
XPOWERS_AXP2101_BAT_REMOVE_IRQ | // BATTERY
|
||||||
|
XPOWERS_AXP2101_WARNING_LEVEL1_IRQ |
|
||||||
XPOWERS_AXP2101_VBUS_INSERT_IRQ |
|
XPOWERS_AXP2101_VBUS_INSERT_IRQ |
|
||||||
XPOWERS_AXP2101_VBUS_REMOVE_IRQ | // VBUS
|
XPOWERS_AXP2101_VBUS_REMOVE_IRQ | // VBUS
|
||||||
XPOWERS_AXP2101_PKEY_SHORT_IRQ |
|
XPOWERS_AXP2101_PKEY_SHORT_IRQ |
|
||||||
@ -403,7 +259,9 @@ int main(void) {
|
|||||||
low_bat();
|
low_bat();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
LL_IWDG_ReloadCounter(IWDG);
|
//#ifndef DEBUG
|
||||||
|
// LL_IWDG_ReloadCounter(IWDG);
|
||||||
|
//#endif
|
||||||
|
|
||||||
// Re-arm I2CS in case of lost master signal
|
// Re-arm I2CS in case of lost master signal
|
||||||
if (i2cs_state != I2CS_STATE_IDLE && ((uptime_ms() - i2cs_rearm_counter) > I2CS_REARM_TIMEOUT))
|
if (i2cs_state != I2CS_STATE_IDLE && ((uptime_ms() - i2cs_rearm_counter) > I2CS_REARM_TIMEOUT))
|
||||||
@ -414,36 +272,89 @@ int main(void) {
|
|||||||
keyboard_process();
|
keyboard_process();
|
||||||
hw_check_HP_presence();
|
hw_check_HP_presence();
|
||||||
|
|
||||||
|
// Check RTC new events to process
|
||||||
|
if (rtc_reg_xor_events != 0) {
|
||||||
|
if ((rtc_reg_xor_events & RTC_CFG_RUN_ALARM) == RTC_CFG_RUN_ALARM) {
|
||||||
|
if (reg_get_value(REG_ID_RTC_CFG) & RTC_CFG_RUN_ALARM) {
|
||||||
|
if (rtc_run_alarm() != HAL_OK)
|
||||||
|
reg_set_value(REG_ID_RTC_CFG, reg_get_value(REG_ID_RTC_CFG) & (uint8_t)~RTC_CFG_RUN_ALARM);
|
||||||
|
} else {
|
||||||
|
if (rtc_stop_alarm() != HAL_OK)
|
||||||
|
reg_set_value(REG_ID_RTC_CFG, reg_get_value(REG_ID_RTC_CFG) | RTC_CFG_RUN_ALARM);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_reg_xor_events &= (uint8_t)~RTC_CFG_RUN_ALARM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check internal status
|
// Check internal status
|
||||||
if (reg_get_value(REG_ID_SHTDW) == 1) { // Nominal full system shutdown as requested from I2C bus
|
switch (reg_get_value(REG_ID_PWR_CTRL)) {
|
||||||
reg_set_value(REG_ID_SHTDW, 0);
|
case 1:
|
||||||
|
reg_set_value(REG_ID_PWR_CTRL, 0);
|
||||||
|
HAL_Delay(200); // Wait for final I2C answer
|
||||||
|
if (HAL_I2C_DisableListen_IT(&hi2c1) != HAL_OK)
|
||||||
|
Error_Handler();
|
||||||
|
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
|
|
||||||
|
HAL_Delay(200); // No need to use keyboard, so a simple delay should suffice
|
||||||
|
LL_GPIO_SetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
|
LL_GPIO_SetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
if (HAL_I2C_EnableListen_IT(&hi2c1) != HAL_OK)
|
||||||
|
Error_Handler();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
reg_set_value(REG_ID_PWR_CTRL, 0);
|
||||||
|
HAL_Delay(200); // Wait for final I2C answer
|
||||||
|
if (HAL_I2C_DisableListen_IT(&hi2c1) != HAL_OK)
|
||||||
|
Error_Handler();
|
||||||
|
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
|
|
||||||
|
NVIC_SystemReset();
|
||||||
|
break;
|
||||||
|
|
||||||
|
//case 3:
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
reg_set_value(REG_ID_PWR_CTRL, 0);
|
||||||
|
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
|
AXP2101_setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
|
||||||
|
|
||||||
|
stop_mode_active = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
reg_set_value(REG_ID_PWR_CTRL, 0);
|
||||||
|
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
|
AXP2101_setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
|
||||||
|
|
||||||
|
AXP2101_shutdown(); // Full shudown will rip the RTC configuration! Need to be reset at next reboot.
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stop_mode_active == 1) {
|
||||||
|
/* Prepare peripherals to the low-power mode */
|
||||||
|
sys_prepare_sleep();
|
||||||
|
|
||||||
|
/* Low-power mode entry */
|
||||||
|
//HAL_WWDG_Disable();
|
||||||
|
HAL_SuspendTick();
|
||||||
|
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
|
||||||
|
SystemClock_Config();
|
||||||
|
HAL_ResumeTick();
|
||||||
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
AXP2101_setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
|
HAL_Delay(500);
|
||||||
|
|
||||||
AXP2101_shutdown();
|
/* Wake-up peripherals from low-power mode */
|
||||||
} else if (reg_get_value(REG_ID_RST) == 1) { // Try to reset only the STM32
|
sys_wake_sleep();
|
||||||
reg_set_value(REG_ID_RST, 0);
|
|
||||||
HAL_Delay(200); // Wait for final I2C answer
|
|
||||||
if (HAL_I2C_DisableListen_IT(&hi2c1) != HAL_OK)
|
|
||||||
Error_Handler();
|
|
||||||
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
|
||||||
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
|
||||||
|
|
||||||
NVIC_SystemReset();
|
|
||||||
} else if (reg_get_value(REG_ID_RST_PICO) == 1) { // Reset only the Pico
|
|
||||||
reg_set_value(REG_ID_RST_PICO, 0);
|
|
||||||
HAL_Delay(200); // Wait for final I2C answer
|
|
||||||
if (HAL_I2C_DisableListen_IT(&hi2c1) != HAL_OK)
|
|
||||||
Error_Handler();
|
|
||||||
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
|
||||||
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
|
||||||
|
|
||||||
HAL_Delay(200); // No need to use keyboard, so a simple delay should suffice
|
|
||||||
LL_GPIO_SetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
|
||||||
LL_GPIO_SetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
|
||||||
if (HAL_I2C_EnableListen_IT(&hi2c1) != HAL_OK)
|
|
||||||
Error_Handler();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,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
|
||||||
@ -720,7 +631,7 @@ __STATIC_INLINE void check_pmu_int(void) {
|
|||||||
#endif
|
#endif
|
||||||
stop_chg();
|
stop_chg();
|
||||||
}
|
}
|
||||||
if (AXP2101_isPekeyShortPressIrq()) {
|
if (AXP2101_isPkeyShortPressIrq()) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
DEBUG_UART_MSG("PMU: isPekeyShortPress\n\r");
|
DEBUG_UART_MSG("PMU: isPekeyShortPress\n\r");
|
||||||
|
|
||||||
@ -738,9 +649,15 @@ __STATIC_INLINE void check_pmu_int(void) {
|
|||||||
|
|
||||||
printPMU();
|
printPMU();
|
||||||
#endif
|
#endif
|
||||||
// enterPmuSleep(); //TODO: implement sleep mode, RTC, etc.?
|
if (stop_mode_active == 1) {
|
||||||
|
stop_mode_active = 0;
|
||||||
|
LL_GPIO_SetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
|
LL_GPIO_SetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
} else {
|
||||||
|
// enterPmuSleep(); //TODO: replace by pico reset if Shift key is pressed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (AXP2101_isPekeyLongPressIrq()) {
|
if (AXP2101_isPkeyLongPressIrq()) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
DEBUG_UART_MSG("PMU: isPekeyLongPress\n\r");
|
DEBUG_UART_MSG("PMU: isPekeyLongPress\n\r");
|
||||||
#endif
|
#endif
|
||||||
@ -748,10 +665,16 @@ __STATIC_INLINE void check_pmu_int(void) {
|
|||||||
//uint8_t data[4] = {1, 2, 3, 4};
|
//uint8_t data[4] = {1, 2, 3, 4};
|
||||||
//PMU.writeDataBuffer(data, XPOWERS_AXP2101_DATA_BUFFER_SIZE);
|
//PMU.writeDataBuffer(data, XPOWERS_AXP2101_DATA_BUFFER_SIZE);
|
||||||
|
|
||||||
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
if (stop_mode_active == 1) {
|
||||||
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
stop_mode_active = 0;
|
||||||
AXP2101_setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
|
LL_GPIO_SetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
AXP2101_shutdown();
|
LL_GPIO_SetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
} else {
|
||||||
|
LL_GPIO_ResetOutputPin(SP_AMP_EN_GPIO_Port, SP_AMP_EN_Pin);
|
||||||
|
LL_GPIO_ResetOutputPin(PICO_EN_GPIO_Port, PICO_EN_Pin);
|
||||||
|
AXP2101_setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
|
||||||
|
stop_mode_active = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (PMU.isPekeyNegativeIrq()) {
|
/*if (PMU.isPekeyNegativeIrq()) {
|
||||||
@ -808,3 +731,49 @@ __STATIC_INLINE void check_pmu_int(void) {
|
|||||||
AXP2101_clearIrqStatus();
|
AXP2101_clearIrqStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__STATIC_INLINE void sys_prepare_sleep(void) {
|
||||||
|
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
|
|
||||||
|
AXP2101_disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
|
||||||
|
AXP2101_clearIrqStatus();
|
||||||
|
AXP2101_enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ |
|
||||||
|
XPOWERS_AXP2101_PKEY_LONG_IRQ |
|
||||||
|
XPOWERS_AXP2101_WARNING_LEVEL1_IRQ
|
||||||
|
);
|
||||||
|
lcd_backlight_off();
|
||||||
|
kbd_backlight_off();
|
||||||
|
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
|
||||||
|
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3);
|
||||||
|
GPIO_InitStruct.Pin = SYS_LED_Pin;
|
||||||
|
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
|
||||||
|
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
|
||||||
|
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||||
|
LL_GPIO_Init(SYS_LED_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
LL_GPIO_SetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
__STATIC_INLINE void sys_wake_sleep(void) {
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
|
|
||||||
|
GPIO_InitStruct.Pin = SYS_LED_Pin;
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
||||||
|
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
|
||||||
|
HAL_GPIO_Init(SYS_LED_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
|
||||||
|
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
|
||||||
|
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
|
||||||
|
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
|
||||||
|
HAL_Delay(300);
|
||||||
|
kbd_backlight_on();
|
||||||
|
lcd_backlight_on();
|
||||||
|
AXP2101_enableIRQ(XPOWERS_AXP2101_BAT_INSERT_IRQ |
|
||||||
|
XPOWERS_AXP2101_BAT_REMOVE_IRQ | // BATTERY
|
||||||
|
XPOWERS_AXP2101_VBUS_INSERT_IRQ |
|
||||||
|
XPOWERS_AXP2101_VBUS_REMOVE_IRQ | // VBUS
|
||||||
|
XPOWERS_AXP2101_PKEY_SHORT_IRQ |
|
||||||
|
XPOWERS_AXP2101_PKEY_LONG_IRQ | // POWER KEY
|
||||||
|
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ |
|
||||||
|
XPOWERS_AXP2101_BAT_CHG_START_IRQ // CHARGE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
#include "regs.h"
|
#include "regs.h"
|
||||||
|
|
||||||
#include "hal_interface.h"
|
#include "hal_interface.h"
|
||||||
|
#include "stm32f1xx_hal_rtc_ex.h"
|
||||||
#include "eeprom.h"
|
#include "eeprom.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
@ -25,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,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) {
|
||||||
uint16_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);
|
||||||
@ -74,6 +82,17 @@ void reg_init(void) {
|
|||||||
regs[REG_ID_BKL] = (uint8_t)((buff >> 8) & 0xFF);
|
regs[REG_ID_BKL] = (uint8_t)((buff >> 8) & 0xFF);
|
||||||
regs[REG_ID_BK2] = (uint8_t)(buff & 0xFF);
|
regs[REG_ID_BK2] = (uint8_t)(buff & 0xFF);
|
||||||
|
|
||||||
|
buff = 0;
|
||||||
|
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
|
||||||
|
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3) << 16;
|
||||||
|
regs[REG_ID_RTC_CFG] = (uint8_t)(buff & 0xFF);
|
||||||
|
rtc_alarm_time.raw = (uint8_t)((buff >> 8) & 0xFFFFFF);
|
||||||
|
|
||||||
|
buff = 0;
|
||||||
|
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);
|
||||||
|
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5) << 16;
|
||||||
|
rtc_alarm_date.raw = buff;
|
||||||
|
|
||||||
regs[REG_ID_BAT] = 0; //default .no battery ,no charging
|
regs[REG_ID_BAT] = 0; //default .no battery ,no charging
|
||||||
|
|
||||||
regs[REG_ID_TYP] = 0xCA; // That's me :3
|
regs[REG_ID_TYP] = 0xCA; // That's me :3
|
||||||
@ -86,23 +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_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_DR3, rtc_alarm_time.raw >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_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;
|
||||||
|
81
Core/Src/rtc.c
Normal file
81
Core/Src/rtc.c
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
|
#include "hal_interface.h"
|
||||||
|
#include "regs.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern RTC_HandleTypeDef hrtc;
|
||||||
|
|
||||||
|
extern void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
|
||||||
|
uint8_t rtc_conf = reg_get_value(REG_ID_RTC_CFG);
|
||||||
|
RTC_DateTypeDef date_s = {0};
|
||||||
|
uint8_t date_valid = 1;
|
||||||
|
|
||||||
|
if ((rtc_conf & RTC_CFG_DATE_ALARM) == RTC_CFG_DATE_ALARM) {
|
||||||
|
HAL_RTC_GetDate(hrtc, &date_s, RTC_FORMAT_BIN);
|
||||||
|
if (date_s.Year != rtc_alarm_date._s.Year ||
|
||||||
|
date_s.Month != rtc_alarm_date._s.Month ||
|
||||||
|
date_s.Date != rtc_alarm_date._s.Date)
|
||||||
|
date_valid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_stop_alarm();
|
||||||
|
if (date_valid == 1) {
|
||||||
|
if ((rtc_conf & RTC_CFG_REARM) == RTC_CFG_REARM)
|
||||||
|
rtc_run_alarm();
|
||||||
|
} else {
|
||||||
|
rtc_run_alarm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cs_fill_buffer_RTC_date(uint8_t* const date_buff, const volatile RTC_DateTypeDef* const date_s) {
|
||||||
|
if (date_s == NULL || date_buff == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
date_buff[0] = date_s->Year;
|
||||||
|
date_buff[1] = date_s->Month;
|
||||||
|
date_buff[2] = date_s->Date;
|
||||||
|
date_buff[3] = date_s->WeekDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cs_fill_buffer_RTC_time(uint8_t* const time_buff, const volatile RTC_TimeTypeDef* const time_s) {
|
||||||
|
if (time_s == NULL || time_buff == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
time_buff[0] = time_s->Hours;
|
||||||
|
time_buff[1] = time_s->Minutes;
|
||||||
|
time_buff[2] = time_s->Seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cs_RTC_date_from_buffer(volatile RTC_DateTypeDef* const date_s, const uint8_t* const date_buff) {
|
||||||
|
if (date_s == NULL || date_buff == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
date_s->Year = date_buff[0] <= 99? date_buff[0] : 99;
|
||||||
|
date_s->Month = (date_buff[1] > 0 && date_buff[1] <= 12)? date_buff[1] : 12;
|
||||||
|
date_s->Date = (date_buff[2] > 0 && date_buff[2] <= 99)? date_buff[2] : 99;
|
||||||
|
//data_s.WeekDay - this element is automatically recomputed
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cs_RTC_time_from_buffer(volatile RTC_TimeTypeDef* const time_s, const uint8_t* const time_buff) {
|
||||||
|
if (time_s == NULL || time_buff == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
time_s->Hours = time_buff[0] <= 23 ? time_buff[0] : 23;
|
||||||
|
time_s->Minutes = time_buff[1] <= 59 ? time_buff[1] : 59;
|
||||||
|
time_s->Seconds = time_buff[2] <= 59 ? time_buff[2] : 59;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t rtc_run_alarm(void) {
|
||||||
|
RTC_AlarmTypeDef alarm_s;
|
||||||
|
|
||||||
|
alarm_s.Alarm = RTC_ALARM_A;
|
||||||
|
alarm_s.AlarmTime.Hours = rtc_alarm_time._s.Hours;
|
||||||
|
alarm_s.AlarmTime.Minutes = rtc_alarm_time._s.Minutes;
|
||||||
|
alarm_s.AlarmTime.Seconds = rtc_alarm_time._s.Seconds;
|
||||||
|
return (uint32_t)HAL_RTC_SetAlarm_IT(&hrtc, &alarm_s, RTC_FORMAT_BIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t rtc_stop_alarm(void) {
|
||||||
|
return (uint32_t)HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
|
||||||
|
}
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
|
|
||||||
extern I2C_HandleTypeDef hi2c1;
|
extern I2C_HandleTypeDef hi2c1;
|
||||||
|
extern RTC_HandleTypeDef hrtc;
|
||||||
extern TIM_HandleTypeDef htim2;
|
extern TIM_HandleTypeDef htim2;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
extern UART_HandleTypeDef huart1;
|
extern UART_HandleTypeDef huart1;
|
||||||
@ -146,3 +147,10 @@ void USART3_IRQHandler(void) {
|
|||||||
HAL_UART_IRQHandler(&huart3);
|
HAL_UART_IRQHandler(&huart3);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles RTC alarm interrupt through EXTI line 17.
|
||||||
|
*/
|
||||||
|
void RTC_Alarm_IRQHandler(void) {
|
||||||
|
HAL_RTC_AlarmIRQHandler(&hrtc);
|
||||||
|
}
|
||||||
|
@ -76,17 +76,16 @@ Mcu.Pin47=VP_IWDG_VS_IWDG
|
|||||||
Mcu.Pin48=VP_RTC_VS_RTC_Activate
|
Mcu.Pin48=VP_RTC_VS_RTC_Activate
|
||||||
Mcu.Pin49=VP_RTC_VS_RTC_Calendar
|
Mcu.Pin49=VP_RTC_VS_RTC_Calendar
|
||||||
Mcu.Pin5=PC0
|
Mcu.Pin5=PC0
|
||||||
Mcu.Pin50=VP_RTC_No_RTC_Output
|
Mcu.Pin50=VP_SYS_VS_ND
|
||||||
Mcu.Pin51=VP_SYS_VS_ND
|
Mcu.Pin51=VP_SYS_VS_Systick
|
||||||
Mcu.Pin52=VP_SYS_VS_Systick
|
Mcu.Pin52=VP_TIM1_VS_ClockSourceINT
|
||||||
Mcu.Pin53=VP_TIM1_VS_ClockSourceINT
|
Mcu.Pin53=VP_TIM2_VS_ClockSourceINT
|
||||||
Mcu.Pin54=VP_TIM2_VS_ClockSourceINT
|
Mcu.Pin54=VP_TIM3_VS_ClockSourceINT
|
||||||
Mcu.Pin55=VP_TIM3_VS_ClockSourceINT
|
|
||||||
Mcu.Pin6=PC1
|
Mcu.Pin6=PC1
|
||||||
Mcu.Pin7=PC2
|
Mcu.Pin7=PC2
|
||||||
Mcu.Pin8=PC3
|
Mcu.Pin8=PC3
|
||||||
Mcu.Pin9=PA0-WKUP
|
Mcu.Pin9=PA0-WKUP
|
||||||
Mcu.PinsNb=56
|
Mcu.PinsNb=55
|
||||||
Mcu.ThirdPartyNb=0
|
Mcu.ThirdPartyNb=0
|
||||||
Mcu.UserConstants=
|
Mcu.UserConstants=
|
||||||
Mcu.UserName=STM32F103R8Tx
|
Mcu.UserName=STM32F103R8Tx
|
||||||
@ -103,6 +102,7 @@ NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
|||||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||||
|
NVIC.RTC_Alarm_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.SysTick_IRQn=true\:1\:0\:true\:false\:true\:false\:true\:false
|
NVIC.SysTick_IRQn=true\:1\:0\:true\:false\:true\:false\:true\:false
|
||||||
NVIC.TIM2_IRQn=true\:1\:0\:true\:false\:true\:true\:true\:true
|
NVIC.TIM2_IRQn=true\:1\:0\:true\:false\:true\:true\:true\:true
|
||||||
@ -413,12 +413,12 @@ ProjectManager.ProjectName=picocalc_BIOS_jcs
|
|||||||
ProjectManager.ProjectStructure=
|
ProjectManager.ProjectStructure=
|
||||||
ProjectManager.RegisterCallBack=
|
ProjectManager.RegisterCallBack=
|
||||||
ProjectManager.StackSize=0x400
|
ProjectManager.StackSize=0x400
|
||||||
ProjectManager.TargetToolchain=STM32CubeIDE
|
ProjectManager.TargetToolchain=Makefile
|
||||||
ProjectManager.ToolChainLocation=
|
ProjectManager.ToolChainLocation=
|
||||||
ProjectManager.UAScriptAfterPath=
|
ProjectManager.UAScriptAfterPath=
|
||||||
ProjectManager.UAScriptBeforePath=
|
ProjectManager.UAScriptBeforePath=
|
||||||
ProjectManager.UnderRoot=true
|
ProjectManager.UnderRoot=false
|
||||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_I2C1_Init-I2C1-false-HAL-true,4-MX_I2C2_Init-I2C2-false-HAL-true,5-MX_RTC_Init-RTC-false-LL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true,7-MX_USART3_UART_Init-USART3-false-HAL-true,8-MX_IWDG_Init-IWDG-false-LL-true,9-MX_TIM1_Init-TIM1-false-HAL-true,10-MX_TIM3_Init-TIM3-false-HAL-true,11-MX_TIM2_Init-TIM2-false-HAL-true
|
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_I2C1_Init-I2C1-false-HAL-true,4-MX_I2C2_Init-I2C2-false-HAL-true,5-MX_RTC_Init-RTC-false-HAL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true,7-MX_USART3_UART_Init-USART3-false-HAL-true,8-MX_IWDG_Init-IWDG-false-LL-true,9-MX_TIM1_Init-TIM1-false-HAL-true,10-MX_TIM3_Init-TIM3-false-HAL-true,11-MX_TIM2_Init-TIM2-false-HAL-true
|
||||||
RCC.ADCFreqValue=2000000
|
RCC.ADCFreqValue=2000000
|
||||||
RCC.AHBCLKDivider=RCC_SYSCLK_DIV2
|
RCC.AHBCLKDivider=RCC_SYSCLK_DIV2
|
||||||
RCC.AHBFreq_Value=4000000
|
RCC.AHBFreq_Value=4000000
|
||||||
@ -474,8 +474,6 @@ USART3.IPParameters=VirtualMode
|
|||||||
USART3.VirtualMode=VM_ASYNC
|
USART3.VirtualMode=VM_ASYNC
|
||||||
VP_IWDG_VS_IWDG.Mode=IWDG_Activate
|
VP_IWDG_VS_IWDG.Mode=IWDG_Activate
|
||||||
VP_IWDG_VS_IWDG.Signal=IWDG_VS_IWDG
|
VP_IWDG_VS_IWDG.Signal=IWDG_VS_IWDG
|
||||||
VP_RTC_No_RTC_Output.Mode=RTC_OUT_NO
|
|
||||||
VP_RTC_No_RTC_Output.Signal=RTC_No_RTC_Output
|
|
||||||
VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled
|
VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled
|
||||||
VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate
|
VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate
|
||||||
VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar
|
VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar
|
||||||
|
76
CubeMX/picocalc_power_sequence.pcs
Normal file
76
CubeMX/picocalc_power_sequence.pcs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#PCC Sequence - do not modify
|
||||||
|
#Wed May 21 14:12:50 CEST 2025
|
||||||
|
PCC.Battery=16850
|
||||||
|
PCC.Battery.Capacity=3000.0
|
||||||
|
PCC.Battery.InParallel=2
|
||||||
|
PCC.Battery.InSeries=1
|
||||||
|
PCC.Battery.SelfDischarge=0.08
|
||||||
|
PCC.Checker=false
|
||||||
|
PCC.Datasheet=DS5319_Rev17
|
||||||
|
PCC.Line=STM32F103
|
||||||
|
PCC.MCU=STM32F103R(8-B)Tx
|
||||||
|
PCC.PartNumber=STM32F103R8Tx
|
||||||
|
PCC.Seq0=4
|
||||||
|
PCC.Seq0.Step0.Average_Current=3.41 mA
|
||||||
|
PCC.Seq0.Step0.CPU_Frequency=4 MHz
|
||||||
|
PCC.Seq0.Step0.Category=In DS Table
|
||||||
|
PCC.Seq0.Step0.DMIPS=5.0
|
||||||
|
PCC.Seq0.Step0.Duration=0.1 ms
|
||||||
|
PCC.Seq0.Step0.Frequency=8 MHz
|
||||||
|
PCC.Seq0.Step0.Memory=FLASH
|
||||||
|
PCC.Seq0.Step0.Mode=RUN
|
||||||
|
PCC.Seq0.Step0.Oscillator=HSE
|
||||||
|
PCC.Seq0.Step0.Peripherals=APB1-Bridge APB2-Bridge GPIOA GPIOB GPIOC GPIOD I2C1 I2C2 PVD/BOR PWR RTC TIM1 TIM2 TIM3 WWDG
|
||||||
|
PCC.Seq0.Step0.TaMax=104.49
|
||||||
|
PCC.Seq0.Step0.User's_Consumption=0 mA
|
||||||
|
PCC.Seq0.Step0.Vcore=No Scale
|
||||||
|
PCC.Seq0.Step0.Vdd=3.3
|
||||||
|
PCC.Seq0.Step0.Voltage_Source=Battery
|
||||||
|
PCC.Seq0.Step1.Average_Current=1.7 mA
|
||||||
|
PCC.Seq0.Step1.CPU_Frequency=4 MHz
|
||||||
|
PCC.Seq0.Step1.Category=In DS Table
|
||||||
|
PCC.Seq0.Step1.DMIPS=5.0
|
||||||
|
PCC.Seq0.Step1.Duration=1 ms
|
||||||
|
PCC.Seq0.Step1.Frequency=8 MHz
|
||||||
|
PCC.Seq0.Step1.Memory=RAM/FLASH
|
||||||
|
PCC.Seq0.Step1.Mode=SLEEP
|
||||||
|
PCC.Seq0.Step1.Oscillator=HSE
|
||||||
|
PCC.Seq0.Step1.Peripherals=APB1-Bridge APB2-Bridge GPIOA GPIOB GPIOC GPIOD I2C1 I2C2 RTC TIM1 TIM2 TIM3 WWDG
|
||||||
|
PCC.Seq0.Step1.TaMax=104.75
|
||||||
|
PCC.Seq0.Step1.User's_Consumption=0 mA
|
||||||
|
PCC.Seq0.Step1.Vcore=No Scale
|
||||||
|
PCC.Seq0.Step1.Vdd=3.3
|
||||||
|
PCC.Seq0.Step1.Voltage_Source=Battery
|
||||||
|
PCC.Seq0.Step2.Average_Current=24 \u00B5A
|
||||||
|
PCC.Seq0.Step2.CPU_Frequency=0 Hz
|
||||||
|
PCC.Seq0.Step2.Category=In DS Table
|
||||||
|
PCC.Seq0.Step2.DMIPS=0.0
|
||||||
|
PCC.Seq0.Step2.Duration=1 ms
|
||||||
|
PCC.Seq0.Step2.Frequency=0 Hz
|
||||||
|
PCC.Seq0.Step2.Memory=n/a
|
||||||
|
PCC.Seq0.Step2.Mode=STOP
|
||||||
|
PCC.Seq0.Step2.Oscillator=Regulator_ON
|
||||||
|
PCC.Seq0.Step2.Peripherals=RTC*
|
||||||
|
PCC.Seq0.Step2.TaMax=105
|
||||||
|
PCC.Seq0.Step2.User's_Consumption=0 mA
|
||||||
|
PCC.Seq0.Step2.Vcore=No Scale
|
||||||
|
PCC.Seq0.Step2.Vdd=3.3
|
||||||
|
PCC.Seq0.Step2.Voltage_Source=Battery
|
||||||
|
PCC.Seq0.Step3.Average_Current=2 \u00B5A
|
||||||
|
PCC.Seq0.Step3.CPU_Frequency=0 Hz
|
||||||
|
PCC.Seq0.Step3.Category=In DS Table
|
||||||
|
PCC.Seq0.Step3.DMIPS=0.0
|
||||||
|
PCC.Seq0.Step3.Duration=1 ms
|
||||||
|
PCC.Seq0.Step3.Frequency=0 Hz
|
||||||
|
PCC.Seq0.Step3.Memory=n/a
|
||||||
|
PCC.Seq0.Step3.Mode=STANDBY
|
||||||
|
PCC.Seq0.Step3.Oscillator=ALL CLOCKS OFF
|
||||||
|
PCC.Seq0.Step3.Peripherals=RTC*
|
||||||
|
PCC.Seq0.Step3.TaMax=105
|
||||||
|
PCC.Seq0.Step3.User's_Consumption=0 mA
|
||||||
|
PCC.Seq0.Step3.Vcore=No Scale
|
||||||
|
PCC.Seq0.Step3.Vdd=3.3
|
||||||
|
PCC.Seq0.Step3.Voltage_Source=Battery
|
||||||
|
PCC.Series=STM32F1
|
||||||
|
PCC.Temperature=25
|
||||||
|
PCC.Vdd=3.3
|
14
Makefile
14
Makefile
@ -2,8 +2,9 @@
|
|||||||
# Generic Makefile (based on gcc)
|
# Generic Makefile (based on gcc)
|
||||||
#
|
#
|
||||||
# ChangeLog :
|
# ChangeLog :
|
||||||
|
# 2025-05-09 - Added I2C_REGS_COMPAT option
|
||||||
# 2025-04-25 - Tuned for PicoCalc firmware project
|
# 2025-04-25 - Tuned for PicoCalc firmware project
|
||||||
# 2017-02-10 - Several enhancements + project update mode
|
# 2017-02-10 - Several enhancements + project update mode
|
||||||
# 2015-07-22 - first version
|
# 2015-07-22 - first version
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ Core/Src/eeprom.c \
|
|||||||
Core/Src/fifo.c \
|
Core/Src/fifo.c \
|
||||||
Core/Src/keyboard.c \
|
Core/Src/keyboard.c \
|
||||||
Core/Src/regs.c \
|
Core/Src/regs.c \
|
||||||
|
Core/Src/rtc.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_gpio.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_gpio.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \
|
||||||
@ -61,7 +63,8 @@ Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
|
|||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rtc.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c \
|
||||||
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc_ex.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
|
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
|
||||||
@ -152,6 +155,7 @@ endif
|
|||||||
|
|
||||||
|
|
||||||
# Generate dependency information
|
# Generate dependency information
|
||||||
|
CFLAGS_ASM := $(CFLAGS)
|
||||||
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
|
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
|
||||||
|
|
||||||
|
|
||||||
@ -175,6 +179,7 @@ all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET
|
|||||||
#######################################
|
#######################################
|
||||||
# list of objects
|
# list of objects
|
||||||
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
|
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
|
||||||
|
OBJECTS_ASM = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.s)))
|
||||||
vpath %.c $(sort $(dir $(C_SOURCES)))
|
vpath %.c $(sort $(dir $(C_SOURCES)))
|
||||||
# list of ASM program objects
|
# list of ASM program objects
|
||||||
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
|
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
|
||||||
@ -185,12 +190,15 @@ vpath %.S $(sort $(dir $(ASMM_SOURCES)))
|
|||||||
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
|
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
|
||||||
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
|
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
|
||||||
|
|
||||||
|
$(BUILD_DIR)/%.s: %.c Makefile | $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS_ASM) -fverbose-asm -S $< -o $@
|
||||||
|
|
||||||
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
|
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
|
||||||
$(AS) -c $(CFLAGS) $< -o $@
|
$(AS) -c $(CFLAGS) $< -o $@
|
||||||
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
|
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
|
||||||
$(AS) -c $(CFLAGS) $< -o $@
|
$(AS) -c $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
|
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) $(OBJECTS_ASM) Makefile
|
||||||
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
|
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
|
||||||
$(SZ) $@
|
$(SZ) $@
|
||||||
|
|
||||||
|
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