222 lines
7.2 KiB
C
222 lines
7.2 KiB
C
#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();
|
|
}
|
|
}
|