reform

MNT Reform: Open Source Portable Computer
Log (Feed) | Files | Refs (Tags) | README

commit 7e64ff3ffa6b0283552d93ad2f2a15aeb29712e1
parent 31b6eb5c43cfae83b2156b5e884d17b942bc73ea
Author: Lukas F. Hartmann <lukas@mntre.com>
Date:   Wed,  5 Apr 2023 18:54:08 +0200

lpc-fw: mb2.5 support WIP

Diffstat:
Mreform2-lpc-fw/src/boards/reform2/board_reform2.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 91 insertions(+), 22 deletions(-)

diff --git a/reform2-lpc-fw/src/boards/reform2/board_reform2.c b/reform2-lpc-fw/src/boards/reform2/board_reform2.c @@ -35,13 +35,14 @@ #define REFORM_MBREV_R1 11 #define REFORM_MBREV_R2 12 // stock R2 #define REFORM_MBREV_R3 13 // R2 with "NTC instead of RNG/SS" fix +#define REFORM_MBREV_25_R1 25 // motherboard 2.5 // don't forget to set this to the correct rev for your motherboard! -#define REFORM_MOTHERBOARD_REV REFORM_MBREV_R3 +#define REFORM_MOTHERBOARD_REV REFORM_MBREV_25_R1 //#define REF2_DEBUG 1 #define FW_STRING1 "MREF2LPC" -#define FW_STRING2 "R3" -#define FW_STRING3 "20220621" +#define FW_STRING2 "R4" +#define FW_STRING3 "20230208" #define FW_REV FW_STRING1 FW_STRING2 FW_STRING3 #define POWERSAVE_SLEEP_SECONDS 1 @@ -76,7 +77,7 @@ err_t i2c_write8(uint8_t i2c_addr, uint8_t reg, uint8_t value) return ERROR_NONE; } -int16_t i2c_read16_le(uint8_t i2c_addr, uint8_t reg) +int16_t i2c_read16_be(uint8_t i2c_addr, uint8_t reg) { i2c_write_len = 2; i2c_read_len = 2; @@ -89,7 +90,20 @@ int16_t i2c_read16_le(uint8_t i2c_addr, uint8_t reg) return value; } -int16_t i2c_read16_be(uint8_t i2c_addr, uint8_t reg) +err_t i2c_write16_be(uint8_t i2c_addr, uint8_t reg, uint16_t value) +{ + i2c_write_len = 4; + i2c_read_len = 0; + i2c_write_buf[0] = i2c_addr << 1; + i2c_write_buf[1] = reg; + i2c_write_buf[2] = value>>8; + i2c_write_buf[3] = value&0xff; + i2cEngine(); + + return ERROR_NONE; +} + +int16_t i2c_read16_le(uint8_t i2c_addr, uint8_t reg) { i2c_write_len = 2; i2c_read_len = 2; @@ -102,7 +116,7 @@ int16_t i2c_read16_be(uint8_t i2c_addr, uint8_t reg) return value; } -err_t i2c_write16_be(uint8_t i2c_addr, uint8_t reg, uint16_t value) +err_t i2c_write16_le(uint8_t i2c_addr, uint8_t reg, uint16_t value) { i2c_write_len = 4; i2c_read_len = 0; @@ -352,8 +366,8 @@ void reset_discharge_bits() { // using INA260 current monitor, count amp-secs going in and out of battery // (battery gauge) void measure_and_accumulate_current() { - float raw_volts = (float)i2c_read16_le(INA260_ADDRESS, 0x2); - float raw_current = (float)i2c_read16_le(INA260_ADDRESS, 0x1); + float raw_volts = (float)i2c_read16_be(INA260_ADDRESS, 0x2); + float raw_current = (float)i2c_read16_be(INA260_ADDRESS, 0x1); volts = raw_volts * 0.00125; current = raw_current * 0.001; @@ -381,6 +395,50 @@ void measure_and_accumulate_current() { #endif } +#define INA233_ADDRESS 0x40 + +void ina233_calibrate() { + /* + current_lsb = i_max / (pow(2,15)); // 0.00030517578125 (i_max = 10 amperes) + power_lsb = 25 * current_lsb; // 0.00762939453125 + cal = 0.00512/(r_shunt * current_lsb); // 838.8608 (r_shunt = 0.02 ohms) + + m_c = 1/current_lsb // 3276.8 + m_b = 1/power_lsb // 131.072 + + see also: https://github.com/scottvr/pi-ina233/blob/master/ina233.py + */ + + uint16_t cal = 838; + + i2c_write16_le(INA233_ADDRESS, 0xd4, cal); +} + +void measure_and_accumulate_current_v25() { + float raw_volts = (float)i2c_read16_le(INA233_ADDRESS, 0x88); + float raw_current = (float)i2c_read16_le(INA233_ADDRESS, 0x89); + + volts = raw_volts * 0.00125; // TODO adjust for 20mOhms + current = raw_current * 0.00030517578125; + + if (current>-0.02 && current<0.02) current = 0; // clamp to zero + + unsigned long thisTime = delayGetSecondsActive(); + if (lastTime>0 && thisTime>lastTime) { + unsigned long secondsPassed = thisTime - lastTime; + + if (secondsPassed >= 1) { + lastTime = thisTime; + + // decrease estimated battery capacity + //capacity_accu_ampsecs -= current*(secondsPassed); + } + } else { + // timer uninitialized or timer wrap + lastTime = thisTime; + } +} + void turn_som_power_on(void) { LPC_GPIO->CLR[1] = (1 << 28); // hold in reset @@ -389,7 +447,7 @@ void turn_som_power_on(void) { LPC_GPIO->CLR[1] = (1 << 31); // USB 5v off (R1+) LPC_GPIO->CLR[0] = (1 << 7); // AUX 3v3 off (R1+) - if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) { + if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1 && REFORM_MOTHERBOARD_REV < REFORM_MBREV_25_R1) { LPC_GPIO->CLR[1] = (1 << 16); // 3v3 on LPC_GPIO->CLR[1] = (1 << 15); // 5v on } else { @@ -410,7 +468,7 @@ void turn_som_power_on(void) { void turn_som_power_off(void) { LPC_GPIO->CLR[1] = (1 << 28); // hold in reset - if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) { + if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1 && REFORM_MOTHERBOARD_REV < REFORM_MBREV_25_R1) { LPC_GPIO->SET[1] = (1 << 16); // 3v3 off LPC_GPIO->SET[1] = (1 << 15); // 5v off } else { @@ -449,7 +507,7 @@ void turn_aux_power_off(void) { void brownout_setup(void) { // Set brownout threshold to 2.63-2.71V (highest level) - // and enable brownout reset + // and enable brownout reset (BODRSTENA) LPC_SYSCON->BODCTRL = 0x3 | (1<<4); } @@ -465,6 +523,8 @@ void watchdog_feed(void) { void boardInit(void) { + brownout_setup(); + SystemCoreClockUpdate(); GPIOInit(); delayInit(); @@ -524,6 +584,11 @@ void boardInit(void) LPC_IOCON->PIO1_13 &= ~0x07; imx_uart_enabled = false; + // motherboard 2.5 introduces INA233 instead of INA260 + if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_25_R1) { + ina233_calibrate(); + } + #ifdef REF2_DEBUG sprintf(uartBuffer, "\r\nMNT Reform 2.0 MCU initialized.\r\n"); uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); @@ -664,7 +729,7 @@ void handle_commands() { // get charger system state if (state == ST_CHARGE) { - sprintf(uartBuffer,FW_REV"normal,%d,%d,%d\r",cycles_in_state,min_mah,acc_mah); + sprintf(uartBuffer,FW_REV"normal,%f\r",current); //,min_mah,acc_mah); } else if (state == ST_OVERVOLTED) { sprintf(uartBuffer,FW_REV"balancing,%d,%d,%d\r",cycles_in_state,min_mah,acc_mah); } else if (state == ST_COOLDOWN) { @@ -792,7 +857,7 @@ uint8_t spi_arg1 = 0; /** * @brief SPI command from imx poll function * Attempts to handle spi communication asynchronously and in a non-blocking way. - * + * */ void handle_spi_commands() { STATIC_ASSERT(SSP0_FIFOSIZE >= 8); @@ -800,7 +865,7 @@ void handle_spi_commands() { uint8_t len = SSP0_FIFOSIZE; // non blocking read - // read until requested buffer full or receive buffer empty + // read until requested buffer full or receive buffer empty for (uint8_t i = 0; i < len; i++ ) { // No more data in receive buffer @@ -827,7 +892,7 @@ void handle_spi_commands() { { if (spi_cmd_state == ST_EXPECT_MAGIC) { - // magic byte found, prevents garbage data + // magic byte found, prevents garbage data // in the bus from triggering a command if(spiBuf[s] == 0xB5) { @@ -845,7 +910,7 @@ void handle_spi_commands() { spi_cmd_state = ST_EXPECT_RETURN; } } - + if (spi_cmd_state != ST_EXPECT_RETURN) { // waiting for more data return; @@ -858,7 +923,7 @@ void handle_spi_commands() { // clear recieve buffer, reuse as send buffer memset(spiBuf, 0, 8); - + // execute power state command if (spi_command == 'p') { // toggle system power and/or reset imx @@ -873,10 +938,10 @@ void handle_spi_commands() { } if (spi_arg1 == 4) { turn_aux_power_off(); - } + } if (spi_arg1 == 5) { turn_aux_power_on(); - } + } spiBuf[0] = som_is_powered; } @@ -954,14 +1019,14 @@ void handle_spi_commands() { } if (imx_uart_enabled) { - sprintf(uartBuffer, "spi:res: %X %X %X %X %X %X %X %X\r\n", + sprintf(uartBuffer, "spi:res: %X %X %X %X %X %X %X %X\r\n", spiBuf[0], spiBuf[1], spiBuf[2], spiBuf[3], spiBuf[4], spiBuf[5], spiBuf[6], spiBuf[7]); uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); } // Host must wait while the LPC prepares response buffer - // If host does not read 8 bytes the previous response buffer will be stuck in here. + // If host does not read 8 bytes the previous response buffer will be stuck in here. for (uint8_t i = 0; i < SSP0_FIFOSIZE; i++) LPC_SSP0->DR = spiBuf[i]; @@ -1076,7 +1141,11 @@ int main(void) // charge current 2: ~0.2A - measure_and_accumulate_current(); + if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_25_R1) { + measure_and_accumulate_current_v25(); + } else { + measure_and_accumulate_current(); + } measure_cell_voltages_and_control_discharge(); calculate_capacity_percentage();