firmware: Allow to read/write single registers from a charger
This code uses existing system command functionality. The I2C registers are placed in front of system command register, to allow for a single transaction proxied I2C A reads/writes. Not tested, yet.
This commit is contained in:
parent
c3272eb4ef
commit
394af632aa
149
firmware/main.c
149
firmware/main.c
@ -36,6 +36,9 @@
|
|||||||
#ifndef CONFIG_STOCK_FW
|
#ifndef CONFIG_STOCK_FW
|
||||||
#define CONFIG_STOCK_FW 1
|
#define CONFIG_STOCK_FW 1
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef CONFIG_I2C_A
|
||||||
|
#define CONFIG_I2C_A 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define USB_DEBUG 0
|
#define USB_DEBUG 0
|
||||||
|
|
||||||
@ -573,6 +576,8 @@ static uint8_t crc8(const uint8_t *pdata, size_t nbytes)
|
|||||||
|
|
||||||
#include "registers.h"
|
#include "registers.h"
|
||||||
|
|
||||||
|
#define REG_SYS(n) ctl_regs[REG_SYS_##n - REG_SYS_CONFIG]
|
||||||
|
|
||||||
// all the variables are volatile because they can be accessed
|
// all the variables are volatile because they can be accessed
|
||||||
// from interrupt context of I2C interrupt handler
|
// from interrupt context of I2C interrupt handler
|
||||||
|
|
||||||
@ -592,12 +597,15 @@ static volatile uint8_t __idata ro_regs[REG_KEYMATRIX_STATE_END + 1] = {
|
|||||||
#endif
|
#endif
|
||||||
#if CONFIG_STOCK_FW
|
#if CONFIG_STOCK_FW
|
||||||
REG_FW_FEATURES_STOCK_FW |
|
REG_FW_FEATURES_STOCK_FW |
|
||||||
|
#endif
|
||||||
|
#if CONFIG_I2CA
|
||||||
|
REG_FW_FEATURES_I2CA |
|
||||||
#endif
|
#endif
|
||||||
0,
|
0,
|
||||||
[REG_KEYMATRIX_SIZE] = 0xc6, // 12 x 6
|
[REG_KEYMATRIX_SIZE] = 0xc6, // 12 x 6
|
||||||
};
|
};
|
||||||
|
|
||||||
static volatile uint8_t ctl_regs[3] = {0, 0, 0};
|
static volatile uint8_t ctl_regs[5] = {0, 0, 0, 0, 0};
|
||||||
static volatile __bit sys_cmd_run = 0;
|
static volatile __bit sys_cmd_run = 0;
|
||||||
|
|
||||||
static volatile uint8_t reg_addr = 0;
|
static volatile uint8_t reg_addr = 0;
|
||||||
@ -970,9 +978,137 @@ static void self_test_run(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
// {{{ System commands
|
// {{{ I2C A forwarding
|
||||||
|
|
||||||
#define REG_SYS(n) ctl_regs[REG_SYS_##n - REG_SYS_CONFIG]
|
#if CONFIG_I2C_A
|
||||||
|
|
||||||
|
#define CHARGER_ADDR 0x75u
|
||||||
|
|
||||||
|
// returns 1 on success
|
||||||
|
static __bit poll_flag(uint8_t flag)
|
||||||
|
{
|
||||||
|
// set timeout for the duration of single transfer at 100kHz + some
|
||||||
|
// slack for slave clock stretching
|
||||||
|
T0_SET_TIMEOUT(2 * 250); // 250us
|
||||||
|
|
||||||
|
while (!TF0) {
|
||||||
|
if (P0_I2CASF & flag) {
|
||||||
|
P0_I2CASF &= ~flag;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __bit i2c_a_send_addr(uint8_t addr)
|
||||||
|
{
|
||||||
|
P0_I2CASA = addr;
|
||||||
|
|
||||||
|
P0_I2CACR1 |= BIT(7); // strobe
|
||||||
|
|
||||||
|
if (!poll_flag(BIT(0)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(P0_I2CACR1 & BIT(2))) // ACK
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __bit i2c_a_send_data(uint8_t data)
|
||||||
|
{
|
||||||
|
P0_I2CADB = data;
|
||||||
|
|
||||||
|
P0_I2CACR1 |= BIT(7); // strobe
|
||||||
|
|
||||||
|
if (!poll_flag(BIT(0)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(P0_I2CACR1 & BIT(2))) // ACK
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_a_stop(void)
|
||||||
|
{
|
||||||
|
P0_I2CACR1 |= BIT(4); // stop
|
||||||
|
poll_flag(BIT(2));
|
||||||
|
|
||||||
|
// and finaly do a reset just in case
|
||||||
|
P0_I2CACR2 &= ~BIT(5);
|
||||||
|
P0_I2CACR2 |= BIT(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t i2c_a_read(void)
|
||||||
|
{
|
||||||
|
uint8_t status = 0xff;
|
||||||
|
|
||||||
|
// reset FSM
|
||||||
|
P0_I2CACR2 &= ~BIT(5);
|
||||||
|
P0_I2CACR2 |= BIT(5);
|
||||||
|
|
||||||
|
if (!i2c_a_send_addr(CHARGER_ADDR))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!i2c_a_send_data(REG_SYS(I2CA_ADDR)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!i2c_a_send_addr(CHARGER_ADDR | BIT(0)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
P0_I2CACR1 |= BIT(7) | BIT(4); // strobe + stop
|
||||||
|
if (!poll_flag(BIT(2))) // poll for stop bit
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
// read received data
|
||||||
|
REG_SYS(I2CA_DATA) = P0_I2CBDB;
|
||||||
|
|
||||||
|
status = 0;
|
||||||
|
err:
|
||||||
|
i2c_a_stop();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t i2c_a_write(void)
|
||||||
|
{
|
||||||
|
uint8_t status = 0xff;
|
||||||
|
|
||||||
|
// reset FSM
|
||||||
|
P0_I2CACR2 &= ~BIT(5);
|
||||||
|
P0_I2CACR2 |= BIT(5);
|
||||||
|
|
||||||
|
if (!i2c_a_send_addr(CHARGER_ADDR))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!i2c_a_send_data(REG_SYS(I2CA_ADDR)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!i2c_a_send_data(REG_SYS(I2CA_DATA)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
status = 0;
|
||||||
|
err:
|
||||||
|
i2c_a_stop();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_a_init(void)
|
||||||
|
{
|
||||||
|
PAGESW = 0;
|
||||||
|
|
||||||
|
// un-powerdown I2CA
|
||||||
|
P0_DEVPD2 &= ~BIT(0);
|
||||||
|
|
||||||
|
P0_I2CACR1 = BIT(6); // master mode
|
||||||
|
P0_I2CACR2 = BIT(5) | 0x07 << 1 | BIT(0); // 100kHz mode, enable
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
// {{{ System commands
|
||||||
|
|
||||||
static void exec_system_command(void)
|
static void exec_system_command(void)
|
||||||
{
|
{
|
||||||
@ -991,6 +1127,10 @@ static void exec_system_command(void)
|
|||||||
#endif
|
#endif
|
||||||
} else if (REG_SYS(COMMAND) == REG_SYS_COMMAND_USB_IAP) {
|
} else if (REG_SYS(COMMAND) == REG_SYS_COMMAND_USB_IAP) {
|
||||||
jump_to_usb_bootloader = 1;
|
jump_to_usb_bootloader = 1;
|
||||||
|
} else if (REG_SYS(COMMAND) == REG_SYS_COMMAND_I2CA_READ) {
|
||||||
|
REG_SYS(COMMAND) = i2c_a_read();
|
||||||
|
} else if (REG_SYS(COMMAND) == REG_SYS_COMMAND_I2CA_WRITE) {
|
||||||
|
REG_SYS(COMMAND) = i2c_a_write();
|
||||||
} else {
|
} else {
|
||||||
REG_SYS(COMMAND) = 0xff;
|
REG_SYS(COMMAND) = 0xff;
|
||||||
goto out_done;
|
goto out_done;
|
||||||
@ -1778,6 +1918,9 @@ void main(void)
|
|||||||
puts("ppkb firmware " FW_REVISION_STR " (user)\n");
|
puts("ppkb firmware " FW_REVISION_STR " (user)\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_I2C_A
|
||||||
|
i2c_a_init();
|
||||||
|
#endif
|
||||||
i2c_slave_init();
|
i2c_slave_init();
|
||||||
|
|
||||||
T1_SET_TIMEOUT(40000);
|
T1_SET_TIMEOUT(40000);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define REG_FW_FEATURES_FLASHING_MODE BIT(1)
|
#define REG_FW_FEATURES_FLASHING_MODE BIT(1)
|
||||||
#define REG_FW_FEATURES_SELF_TEST BIT(2)
|
#define REG_FW_FEATURES_SELF_TEST BIT(2)
|
||||||
#define REG_FW_FEATURES_STOCK_FW BIT(3)
|
#define REG_FW_FEATURES_STOCK_FW BIT(3)
|
||||||
|
#define REG_FW_FEATURES_I2CA BIT(4)
|
||||||
|
|
||||||
#define REG_KEYMATRIX_SIZE 0x06
|
#define REG_KEYMATRIX_SIZE 0x06
|
||||||
#define REG_KEYMATRIX_STATE_CRC8 0x07
|
#define REG_KEYMATRIX_STATE_CRC8 0x07
|
||||||
@ -42,12 +43,17 @@
|
|||||||
#define REG_SYS_CONFIG_SCAN_BLOCK BIT(0)
|
#define REG_SYS_CONFIG_SCAN_BLOCK BIT(0)
|
||||||
#define REG_SYS_CONFIG_USB_DEBUG_EN BIT(1)
|
#define REG_SYS_CONFIG_USB_DEBUG_EN BIT(1)
|
||||||
|
|
||||||
#define REG_SYS_COMMAND 0x21
|
#define REG_SYS_I2CA_ADDR 0x21
|
||||||
|
#define REG_SYS_I2CA_DATA 0x22
|
||||||
|
|
||||||
|
#define REG_SYS_COMMAND 0x23
|
||||||
#define REG_SYS_COMMAND_MCU_RESET 'r'
|
#define REG_SYS_COMMAND_MCU_RESET 'r'
|
||||||
#define REG_SYS_COMMAND_SELFTEST 't'
|
#define REG_SYS_COMMAND_SELFTEST 't'
|
||||||
#define REG_SYS_COMMAND_USB_IAP 'i'
|
#define REG_SYS_COMMAND_USB_IAP 'i'
|
||||||
|
#define REG_SYS_COMMAND_I2CA_READ 'R'
|
||||||
|
#define REG_SYS_COMMAND_I2CA_WRITE 'W'
|
||||||
|
|
||||||
#define REG_SYS_USER_APP_BLOCK 0x22
|
#define REG_SYS_USER_APP_BLOCK 0x24
|
||||||
#define REG_SYS_USER_APP_BLOCK_MAGIC 0x53
|
#define REG_SYS_USER_APP_BLOCK_MAGIC 0x53
|
||||||
|
|
||||||
#define REG_FLASH_DATA_START 0x70
|
#define REG_FLASH_DATA_START 0x70
|
||||||
|
Loading…
Reference in New Issue
Block a user