bug fix for REG_ID_BAT

The correct power-on sequence for obtaining the battery percentage is to first power on the PicoCalc with the battery inserted
Then connect the USB Type-C cable to read the battery percentage.
The battery percentage also can be retrieved via I2C communication within the UF2 program.

PicoCalc keyboard firmware updating required.
This commit is contained in:
cuu 2025-04-02 00:11:08 +08:00
parent 57aa179b2e
commit 65bf0c65a7
4 changed files with 62 additions and 17 deletions

View File

@ -26,13 +26,14 @@ int read_i2c_kbd() {
retval = i2c_write_timeout_us(I2C_KBD_MOD, I2C_KBD_ADDR, msg, 1, false, 500000); retval = i2c_write_timeout_us(I2C_KBD_MOD, I2C_KBD_ADDR, msg, 1, false, 500000);
if (retval == PICO_ERROR_GENERIC || retval == PICO_ERROR_TIMEOUT) { if (retval == PICO_ERROR_GENERIC || retval == PICO_ERROR_TIMEOUT) {
printf("i2c write error\n"); printf("read_i2c_kbd i2c write error\n");
return -1; return -1;
} }
sleep_ms(16);
retval = i2c_read_timeout_us(I2C_KBD_MOD, I2C_KBD_ADDR, (unsigned char *) &buff, 2, false, 500000); retval = i2c_read_timeout_us(I2C_KBD_MOD, I2C_KBD_ADDR, (unsigned char *) &buff, 2, false, 500000);
if (retval == PICO_ERROR_GENERIC || retval == PICO_ERROR_TIMEOUT) { if (retval == PICO_ERROR_GENERIC || retval == PICO_ERROR_TIMEOUT) {
printf("i2c read error read\n"); printf("read_i2c_kbd i2c read error read\n");
return -1; return -1;
} }
@ -54,4 +55,30 @@ int read_i2c_kbd() {
return c; return c;
} }
return -1; return -1;
}
int read_battery() {
int retval;
uint16_t buff = 0;
unsigned char msg[2];
msg[0] = 0x0b;
if (i2c_inited == 0) return -1;
retval = i2c_write_timeout_us(I2C_KBD_MOD, I2C_KBD_ADDR, msg, 1, false, 500000);
if (retval == PICO_ERROR_GENERIC || retval == PICO_ERROR_TIMEOUT) {
printf("read_battery i2c write error\n");
return -1;
}
sleep_ms(16);
retval = i2c_read_timeout_us(I2C_KBD_MOD, I2C_KBD_ADDR, (unsigned char *) &buff, 2, false, 500000);
if (retval == PICO_ERROR_GENERIC || retval == PICO_ERROR_TIMEOUT) {
printf("read_battery i2c read error read\n");
return -1;
}
if (buff != 0) {
return buff;
}
return -1;
} }

View File

@ -9,11 +9,12 @@
#define I2C_KBD_SDA 6 #define I2C_KBD_SDA 6
#define I2C_KBD_SCL 7 #define I2C_KBD_SCL 7
#define I2C_KBD_SPEED 400000 // if dual i2c, then the speed of keyboard i2c should be 10khz #define I2C_KBD_SPEED 10000 // if dual i2c, then the speed of keyboard i2c should be 10khz
#define I2C_KBD_ADDR 0x1F #define I2C_KBD_ADDR 0x1F
void init_i2c_kbd(); void init_i2c_kbd();
int read_i2c_kbd(); int read_i2c_kbd();
int read_battery();
#endif #endif

View File

@ -204,10 +204,14 @@ void pwm_interrupt_handler() {
} }
int main() { int main() {
char buf[64];
stdio_init_all();
set_sys_clock_khz(133000, true); set_sys_clock_khz(133000, true);
stdio_init_all();
uart_init(uart0, 115200);
uart_set_format(uart0, 8, 1, UART_PARITY_NONE); // 8-N-1
uart_set_fifo_enabled(uart0, false);
init_i2c_kbd(); init_i2c_kbd();
lcd_init(); lcd_init();
@ -225,7 +229,17 @@ int main() {
psram_spi_inst_t psram_spi = psram_spi_init_clkdiv(pio1, -1,1.0f,true); psram_spi_inst_t psram_spi = psram_spi_init_clkdiv(pio1, -1,1.0f,true);
psram_test(&psram_spi); psram_test(&psram_spi);
// if we need battery information
// ** we should power on the picocalc only with batteries
// ** then plug the type c cable
// otherwise we won't get working battery infos
sleep_ms(2000);
int bat_pcnt = read_battery();
sprintf(buf,"battery percent is %d\n",bat_pcnt>>8);
printf(buf);
lcd_print_string(buf);
while (1) { while (1) {
int c = lcd_getc(0); int c = lcd_getc(0);

View File

@ -42,6 +42,8 @@ uint8_t write_buffer_len = 0;
uint8_t io_matrix[9];//for IO matrix,last bytye is the restore key(c64 only) uint8_t io_matrix[9];//for IO matrix,last bytye is the restore key(c64 only)
uint8_t js_bits=0xff;// c64 joystick bits uint8_t js_bits=0xff;// c64 joystick bits
static int current_bat_pcnt = 0;
unsigned long time_uptime_ms() { return millis(); } unsigned long time_uptime_ms() { return millis(); }
void lock_cb(bool caps_changed, bool num_changed) { void lock_cb(bool caps_changed, bool num_changed) {
@ -134,12 +136,10 @@ void receiveEvent(int howMany) {
write_buffer[1] = reg_get_value(REG_ID_BKL); write_buffer[1] = reg_get_value(REG_ID_BKL);
} break; } break;
case REG_ID_BAT:{ case REG_ID_BAT:{
//Serial1.print("REG_ID_BAT getBatteryPercent:");Serial1.print(current_bat_pcnt);Serial1.println("%");
write_buffer[0] = reg; write_buffer[0] = reg;
if (PMU.isBatteryConnect()) { write_buffer[1] = (uint8_t)current_bat_pcnt;
write_buffer[1] = PMU.getBatteryPercent();
}else{
write_buffer[1] = 0x00;
}
}break; }break;
case REG_ID_KEY: { case REG_ID_KEY: {
write_buffer[0] = fifo_count(); write_buffer[0] = fifo_count();
@ -229,19 +229,20 @@ void printPMU() {
} }
void check_pmu_int() { void check_pmu_int() {
/// 40 secs check battery percent
int pcnt; int pcnt;
if (!pmu_online) return; if (!pmu_online) return;
if (time_uptime_ms() - run_time > 40000) { if (time_uptime_ms() - run_time > 20000) {
run_time = millis(); // reset time run_time = millis(); // reset time
pcnt = PMU.getBatteryPercent(); pcnt = PMU.getBatteryPercent();
//Serial1.print("check_pmu_int: ");Serial1.print(pcnt);Serial1.println();
if (pcnt < 0) { // disconnect if (pcnt < 0) { // disconnect
pcnt = 0; pcnt = 0;
pmu_status = 0xff; pmu_status = 0xff;
current_bat_pcnt = pcnt;
} else { // battery connected } else { // battery connected
current_bat_pcnt = pcnt;
if (PMU.isCharging()) { if (PMU.isCharging()) {
pmu_status = bitSet(pcnt, 7); pmu_status = bitSet(pcnt, 7);
} else { } else {
@ -304,11 +305,12 @@ void check_pmu_int() {
} else { } else {
pmu_status = pcnt; pmu_status = pcnt;
} }
current_bat_pcnt = pcnt;
Serial1.println("isBatInsert"); Serial1.println("isBatInsert");
} }
if (PMU.isBatRemoveIrq()) { if (PMU.isBatRemoveIrq()) {
pmu_status = 0xff; pmu_status = 0xff;
current_bat_pcnt = 0;
Serial1.println("isBatRemove"); Serial1.println("isBatRemove");
stop_chg(); stop_chg();
} }
@ -359,6 +361,7 @@ void check_pmu_int() {
pcnt = 0; pcnt = 0;
pmu_status = 0xff; pmu_status = 0xff;
} }
current_bat_pcnt = pcnt;
pmu_status = bitClear(pcnt, 7); pmu_status = bitClear(pcnt, 7);
Serial1.println("isBatChagerDone"); Serial1.println("isBatChagerDone");
stop_chg(); stop_chg();
@ -369,6 +372,7 @@ void check_pmu_int() {
pcnt = 0; pcnt = 0;
pmu_status = 0xff; pmu_status = 0xff;
} }
current_bat_pcnt = pcnt;
pmu_status = bitSet(pcnt, 7); pmu_status = bitSet(pcnt, 7);
Serial1.println("isBatChagerStart"); Serial1.println("isBatChagerStart");
if(PMU.isBatteryConnect()) { if(PMU.isBatteryConnect()) {
@ -517,8 +521,7 @@ void setup() {
// 5% ~= 3.5V // 5% ~= 3.5V
// 1% ~= 3.4V // 1% ~= 3.4V
PMU.setLowBatShutdownThreshold(1); //This is related to the battery charging and discharging logic. If you're not sure what you're doing, please don't modify it, as it could damage the battery. PMU.setLowBatShutdownThreshold(1); //This is related to the battery charging and discharging logic. If you're not sure what you're doing, please don't modify it, as it could damage the battery.
run_time = 0; run_time = 0;
keycb_start = 1; keycb_start = 1;
low_bat(); low_bat();