reform

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

commit 2cb5500401e4bae52bbfe6244cc99d2a92150539
parent 51bf3cf03a540a9299e4d27681478fad6fe78526
Author: mntmn <lukas@mntmn.com>
Date:   Tue,  3 Nov 2020 18:07:28 +0100

reform2-lpc-fw: support D4 and R1 motherboard revisions

Diffstat:
Mreform2-lpc-fw/src/boards/reform2/board_reform2.c | 196+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 138 insertions(+), 58 deletions(-)

diff --git a/reform2-lpc-fw/src/boards/reform2/board_reform2.c b/reform2-lpc-fw/src/boards/reform2/board_reform2.c @@ -29,7 +29,16 @@ #include "protocol/protocol.h" #endif +#define REFORM_MBREV_D2 2 +#define REFORM_MBREV_D3 3 +#define REFORM_MBREV_D4 4 +#define REFORM_MBREV_R1 11 +#define REFORM_MBREV_R2 12 + +// don't forget to set this! +#define REFORM_MOTHERBOARD_REV REFORM_MBREV_D4 //#define REF2_DEBUG 1 +#define FW_REV "R2 " #define INA260_ADDRESS 0x4e #define LTC4162F_ADDRESS 0x68 @@ -158,45 +167,67 @@ uint8_t spir[64]; #define OVERVOLTAGE_START_VALUE 3.61 #define OVERVOLTAGE_STOP_VALUE 3.55 -#define UNDERVOLTAGE_VALUE 2.55 -#define UNDERVOLTAGE_CRITICAL_VALUE 2.4 -#define MISSING_VALUE 5 -#define FULLY_CHARGED_VOLTAGE (3.5*8.0) - -void measure_cell_voltages_and_control_discharge() { - // delay is measured in "ticks", which are basically ms? +#define UNDERVOLTAGE_VALUE 2.45 +#define UNDERVOLTAGE_CRITICAL_VALUE 2.3 +#define MISSING_VALUE 4.0 +#define FULLY_CHARGED_VOLTAGE 3.5 +void set_discharge_bits(uint16_t bits) { // 0x10: WRCFG, write config spir[0] = 0x01; spir[1] = 0xc7; spir[2] = 0xe1; // set cdc to 2 = continuous measurement - spir[3] = discharge_bits&0xff; // first 8 bits of discharge switches - spir[4] = (discharge_bits&0xf00)>>8; // last 4 bits of discharge switches - + spir[3] = bits&0xff; // first 8 bits of discharge switches + spir[4] = (bits&0xf00)>>8; // last 4 bits of discharge switches + spir[5] = 0x0; spir[6] = 0x0; spir[7] = 0x0; - if (state == ST_CHARGE) { - // we're in normal charge mode, so remove charge current limit - LPC_GPIO->SET[1] |= (1 << 25); - } else { - // we're discharging (balancing), or full charged, - // so limit charge current - // also don't charge if we have missing cells - LPC_GPIO->CLR[1] |= (1 << 25); - } - uint8_t pec = 0x41; for (int i=2; i<=7; i++) { pec = calc_pec(spir[i], pec); } spir[8] = pec; - + LPC_GPIO->CLR[1] = (1 << 23); ssp1Send(spir, 9); LPC_GPIO->SET[1] = (1 << 23); +} + +void disable_charge_current(void) { + if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) { + LPC_GPIO->SET[1] |= (1 << 25); + } else { + LPC_GPIO->CLR[1] |= (1 << 25); + } +} + +void enable_charge_current(void) { + if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) { + LPC_GPIO->CLR[1] |= (1 << 25); + } else { + LPC_GPIO->SET[1] |= (1 << 25); + } +} + +void measure_cell_voltages_and_control_discharge() { + // first, turn off any discharging + set_discharge_bits(0); + + // defensive: make sure not to charge with any discharge bits + // turned on, regardless of state + if (state == ST_CHARGE && discharge_bits == 0) { + // we're in normal charge mode, so remove charge current limit + enable_charge_current(); + } else { + // we're discharging (balancing), or full charged, + // so limit charge current + // also don't charge if we have missing cells + disable_charge_current(); + set_discharge_bits(discharge_bits); + } // 0x10: STCVDC, start adc spir[0] = 0x60; @@ -205,12 +236,13 @@ void measure_cell_voltages_and_control_discharge() { ssp1Send(spir, 2); LPC_GPIO->SET[1] = (1 << 23); + // delay is measured in "ticks", which are basically ms? delay(50); // FIXME tunable // 0x4: RDCV, read all cell voltages spir[0] = 0x4; spir[1] = 0xdc; - + LPC_GPIO->CLR[1] = (1 << 23); ssp1Send(spir, 2); memset(spir, 0, 32); @@ -300,7 +332,7 @@ void measure_and_accumulate_current() { if (secondsPassed >= 1) { lastTime = thisTime; - + // decrease estimated battery capacity capacity_accu_ampsecs -= current*(secondsPassed); } @@ -326,19 +358,60 @@ float chg_vbat; void turn_som_power_on(void) { LPC_GPIO->CLR[1] = (1 << 28); // hold in reset - LPC_GPIO->SET[1] = (1 << 16); // 3v3, high = on - LPC_GPIO->SET[0] = (1 << 20); // PCIe, high = on - LPC_GPIO->SET[1] = (1 << 15); // 5v, high = on - LPC_GPIO->SET[1] = (1 << 19); // 1v2, high = on + + LPC_GPIO->CLR[0] = (1 << 20); // PCIe off + LPC_GPIO->CLR[1] = (1 << 19); // 1v2 off + 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) { + LPC_GPIO->CLR[1] = (1 << 16); // 3v3 on + LPC_GPIO->CLR[1] = (1 << 15); // 5v on + } else { + LPC_GPIO->SET[1] = (1 << 16); // 3v3 on + LPC_GPIO->SET[1] = (1 << 15); // 5v on + } + + LPC_GPIO->SET[0] = (1 << 20); // PCIe on + LPC_GPIO->SET[1] = (1 << 19); // 1v2 on + LPC_GPIO->SET[1] = (1 << 31); // USB 5v on (R1+) + LPC_GPIO->SET[0] = (1 << 7); // AUX 3v3 on (R1+) + LPC_GPIO->SET[1] = (1 << 28); // release reset } +// TODO: power leak into USB_5V when turned off (~1.5V) +// try to desolder: +// - R152 (spkvdd) +// - R43/R44 (hdmi i2c pullups) -> disappeared! +// - FB15 (BL_VCC, unlikely) +// - R61 (USB_VBUS of TUSB, unlikely) + +// power leak of 0.5V into AUX_3V3 +// - FB1 +// no, power is leaking through pullups of OVERCUR pins + void turn_som_power_off(void) { LPC_GPIO->CLR[1] = (1 << 28); // hold in reset - LPC_GPIO->CLR[1] = (1 << 19); // 1v2, high = on - LPC_GPIO->CLR[1] = (1 << 15); // 5v, high = on - LPC_GPIO->CLR[0] = (1 << 20); // PCIe, high = on - LPC_GPIO->CLR[1] = (1 << 16); // 3v3, high = on + + if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) { + LPC_GPIO->SET[1] = (1 << 16); // 3v3 off + LPC_GPIO->SET[1] = (1 << 15); // 5v off + } else { + LPC_GPIO->CLR[1] = (1 << 16); // 3v3 off + LPC_GPIO->CLR[1] = (1 << 15); // 5v off + } + + LPC_GPIO->CLR[0] = (1 << 20); // PCIe off + LPC_GPIO->CLR[1] = (1 << 19); // 1v2 off + LPC_GPIO->CLR[1] = (1 << 31); // USB 5v off (R1+) + LPC_GPIO->CLR[0] = (1 << 7); // AUX 3v3 off (R1+) +} + +void turn_periph_power_on(void) { +} + +void turn_periph_power_off(void) { } void brownout_setup(void) { @@ -357,13 +430,13 @@ void watchdog_feed(void) { void watchdog_setup(void) { LPC_SYSCON->SYSAHBCLKCTRL |= (1<<15); // WWDT enable - - LPC_SYSCON->WDTOSCCTRL = + + LPC_SYSCON->WDTOSCCTRL = (1<<5) | // FREQSEL 0.6MHz 31; // DIVSEL 64 (31+1)*2 - + LPC_SYSCON->PDRUNCFG &= ~(1<<6); // WDTOSC_PD disable - + LPC_WWDT->CLKSEL = 1; // WDOSC LPC_WWDT->TC = 0xffff/5; // timeout counter, ~5 seconds @@ -371,7 +444,7 @@ void watchdog_setup(void) { LPC_WWDT->MOD = 0; LPC_WWDT->MOD |= WWDT_WDMOD_WDRESET; // enable WDRESET (watchdog resets system) LPC_WWDT->MOD |= WWDT_WDMOD_WDEN; // watchdog enable - + watchdog_feed(); } @@ -381,28 +454,35 @@ void boardInit(void) GPIOInit(); delayInit(); - // 5V regulator on/off + // Set up GPIO directions + + // 5V regulator (U7) on/off LPC_GPIO->DIR[1] |= (1 << 15); - // 3V3 rail transistor on/off + // 3V3 regulator (U12) on/off LPC_GPIO->DIR[1] |= (1 << 16); - // 1V2 regulator on/off + // 1V2 regulator (U13) on/off LPC_GPIO->DIR[1] |= (1 << 19); - // PCIe 1 power supply transistor + // PCIe 1 power supply transistor (1V5 regulator U19 and 3V3 load switch) LPC_GPIO->DIR[0] |= (1 << 20); + // USB 5V rail on/off (U24) (board revision R-1+) + LPC_GPIO->DIR[1] |= (1 << 31); + // AUX 3V3 power rail on/off (U27), and downstream 1V8 (U17) (board revision R-1+) + LPC_GPIO->DIR[0] |= (1 << 7); // IMX Wake LPC_GPIO->DIR[1] |= (1 << 24); // IMX Reset LPC_GPIO->DIR[1] |= (1 << 28); - + // RNG/SS pin of LTC4020: control/limit charge current LPC_GPIO->DIR[1] |= (1 << 25); // start with low charge current - LPC_GPIO->CLR[1] |= (1 << 25); - + disable_charge_current(); + + // initially turn the system off turn_som_power_off(); - + uartInit(CFG_UART_BAUDRATE); i2cInit(I2CMASTER); @@ -448,7 +528,7 @@ void handle_commands() { // 4 command letter expected // 5 syntax error (unexpected character) // 6 command letter entered - + if (cmd_state>=ST_EXPECT_DIGIT_0 && cmd_state<=ST_EXPECT_DIGIT_3) { // read number or command if (chr >= '0' && chr <= '9') { @@ -499,7 +579,7 @@ void handle_commands() { sprintf(uartBuffer,"\n"); uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); } - + // execute if (remote_cmd == 'p') { // toggle system 5V power @@ -531,17 +611,17 @@ void handle_commands() { else if (remote_cmd == 's') { // get charger system state if (state == ST_CHARGE) { - sprintf(uartBuffer,"idle/charging [%d]\r",cycles_in_state); + sprintf(uartBuffer,FW_REV"idle/charging [%d]\r",cycles_in_state); } else if (state == ST_OVERVOLTED) { - sprintf(uartBuffer,"balancing [%d]\r",cycles_in_state); + sprintf(uartBuffer,FW_REV"balancing [%d]\r",cycles_in_state); } else if (state == ST_UNDERVOLTED) { - sprintf(uartBuffer,"undervolt [%d]\r",cycles_in_state); + sprintf(uartBuffer,FW_REV"undervoltage [%d]\r",cycles_in_state); } else if (state == ST_MISSING) { - sprintf(uartBuffer,"cell missing [%d]\r",cycles_in_state); + sprintf(uartBuffer,FW_REV"missing cells (%d)[%d]\r",num_missing_cells,cycles_in_state); } else if (state == ST_FULLY_CHARGED) { - sprintf(uartBuffer,"fully charged [%d]\r",cycles_in_state); + sprintf(uartBuffer,FW_REV"fully charged [%d]\r",cycles_in_state); } else { - sprintf(uartBuffer,"unknown %d [%d]\r",state,cycles_in_state); + sprintf(uartBuffer,FW_REV"unknown %d [%d]\r",state,cycles_in_state); } uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); } @@ -553,7 +633,7 @@ void handle_commands() { undervoltage_bits &(1<<n)?'u':'.', overvoltage_bits &(1<<n)?'o':'.', discharge_bits &(1<<n)?'d':'.'); - + uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); } else if (remote_cmd == 'S') { @@ -577,7 +657,7 @@ void handle_commands() { } else { // if we never reached full charge, // we don't really know where we are. - + sprintf(uartBuffer,"? %%\r\n"); uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); } @@ -590,7 +670,7 @@ void handle_commands() { sprintf(uartBuffer, "error:command\r\n"); uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); } - + cmd_state = ST_EXPECT_DIGIT_0; cmd_number = 0; } else { @@ -618,7 +698,7 @@ void report_to_spi(void) if (!reached_full_charge) { percentage = -1; } - + snprintf(report, REPORT_MAX, "(%dmV %dmA %d%%)\n", (int)(volts*1000.0), (int)(current*1000.0), percentage); report[63] = 0; @@ -629,7 +709,7 @@ int main(void) { boardInit(); reset_discharge_bits(); - + state = ST_CHARGE; cycles_in_state = 0; @@ -639,7 +719,7 @@ int main(void) //watchdog_setup(); //sprintf(uartBuffer, "\r\nwatchdog_setup() completed.\r\n"); //uartSend((uint8_t*)uartBuffer, strlen(uartBuffer)); - + while (1) { // algorithm idea: