int axp_calculate_rdc(void) { struct axp_adc_res axp_adc; char buf[100]; int32_t i_lo, i_hi; int32_t v_lo, v_hi; int32_t rdc_cal = 0; if (ocv > 4000) { // don't calculate rdc when ocv is too high return 0; } axp_write(0x33, 0xc1); // set charge current to 400mA udelay(500000); axp_read_adc(&axp_adc); i_lo = ABS(axp_ibat_to_mA(axp_adc.ichar_res)-axp_ibat_to_mA(axp_adc.idischar_res)); v_lo = (axp_adc.vbat_res * 1100) / 1000; axp_write(0x33, 0xc9); // set charge current to 1.2A udelay(500000); axp_read_adc(&axp_adc); i_hi = ABS(axp_ibat_to_mA(axp_adc.ichar_res)-axp_ibat_to_mA(axp_adc.idischar_res)); v_hi = (axp_adc.vbat_res * 1100) / 1000; rdc_cal = (v_hi - v_lo) * 1000 / (i_hi - i_lo); sprintf(buf, "i_lo:%4d, i_hi:%4d, u_lo:%4d, u_hi:%4d, rdc:%4d\n", i_lo, i_hi, v_lo, v_hi, rdc_cal); terminal_print(0, 36, buf); if (rdc_cal < 0 || rdc_cal >= 300) { // usually RDC will not greater than 300 mhom return 0; } return rdc_cal; }
int axp_battery_calibrate_init(void) { uint8_t val; axp_read(0x01, &val); if (!(val & 0x20)) { terminal_print(0, 35, "ERROR, NO battery is connected to system\n"); return 0; } axp_read(0x30, &val); val |= 0x03; axp_write(0x30, val); axp_read(0x84, &val); val &= ~0xc0; val |= 0x80; axp_write(0x84, val); // set ADC sample rate to 100KHz axp_write(0x82, 0xff); // open all ADC axp_write(0x31, 0x03); // shutdown when battery voltage < 2.9V axp_write(0x33, 0xc8); // set charge current to 1.1A axp_write(0xb8, 0x20); // clear coulomb counter axp_write(0xb8, 0x80); // start coulomb counter return 1; }
static void inline update_energy_discharge(int ocv, int energy, int coulomb, int coulomb_p) { int i = 0; char buf[100] = {}; for (i = 0; i < 16; i++) { if (ocv < battery_energy_discharge[i].ocv && !battery_energy_discharge[i].updated_flag) { battery_energy_discharge[i].energy = energy; battery_energy_discharge[i].coulomb = coulomb; battery_energy_discharge[i].coulomb_p = coulomb_p; battery_energy_discharge[i].updated_flag = 1; //sprintf(buf, "update energy %9lld for %4d mV, index:%2d\n", // battery_energy_discharge[i].energy, battery_energy_discharge[i].ocv, i); //terminal_print(0, 35, buf); sprintf(buf, "%2d, %4d, %9lld, %4d, %4d,\n", i, battery_energy_discharge[i].ocv, battery_energy_discharge[i].energy, battery_energy_discharge[i].coulomb, battery_energy_discharge[i].coulomb_p); terminal_print(60, 12 + i, buf); } } }
/* Help execution */ static void help_p(int argc, const char **argv) { const struct method *m = commands; const struct interface **ip = interfaces; const struct interface *i; if (argc == 1) { terminal_print("haltest allows to call Android HAL methods.\n"); terminal_print("\nAvailable commands:\n"); while (0 != strcmp(m->name, "")) { terminal_print("\t%s %s\n", m->name, (m->help ? m->help : "")); m++; } terminal_print("\nAvailable interfaces to use:\n"); while (NULL != *ip) { terminal_print("\t%s\n", (*ip)->name); ip++; } terminal_print("\nTo get help on methods for each interface type:\n"); terminal_print("\n\thelp <inerface>\n"); terminal_print("\nBasic scenario:\n\tbluetooth init\n"); terminal_print("\tbluetooth enable\n\tbluetooth start_discovery\n"); terminal_print("\tbluetooth get_profile_interface handsfree\n"); terminal_print("\thandsfree init\n\n"); return; } i = get_interface(argv[1]); if (i == NULL) { haltest_error("No such interface\n"); return; } help_print_interface(i); }
void isr_default(void) { terminal_print("I've been interrupted!"); // pic_end_eod() }
void TestTilesets() { terminal_set("window.title='Omni: tilesets'"); terminal_composition(TK_ON); // Load tilesets terminal_set("U+E100: ../Media/Runic.png, size=8x16"); terminal_set("U+E200: ../Media/Tiles.png, size=32x32, align=top-left"); terminal_set("U+E300: ../Media/fontawesome-webfont.ttf, size=24x24, spacing=3x2, codepage=../Media/fontawesome-codepage.txt"); terminal_set("zodiac font: ../Media/Zodiac-S.ttf, size=24x36, spacing=3x3, codepage=437"); terminal_clear(); terminal_color("white"); terminal_print(2, 1, "[color=orange]1.[/color] Of course, there is default font tileset."); terminal_print(2, 3, "[color=orange]2.[/color] You can load some arbitrary tiles and use them as glyphs:"); terminal_print ( 2+3, 4, "Fire rune ([color=red][U+E102][/color]), " "water rune ([color=lighter blue][U+E103][/color]), " "earth rune ([color=darker green][U+E104][/color])" ); terminal_print(2, 6, "[color=orange]3.[/color] Tiles are not required to be of the same size as font symbols:"); terminal_put(2+3+0, 7, 0xE200+7); terminal_put(2+3+5, 7, 0xE200+8); terminal_put(2+3+10, 7, 0xE200+9); terminal_print(2, 10, "[color=orange]4.[/color] Like font characters, tiles may be freely colored and combined:"); terminal_put(2+3+0, 11, 0xE200+8); terminal_color("lighter orange"); terminal_put(2+3+5, 11, 0xE200+8); terminal_color("orange"); terminal_put(2+3+10, 11, 0xE200+8); terminal_color("dark orange"); terminal_put(2+3+15, 11, 0xE200+8); terminal_color("white"); std::vector<int> order = {11, 10, 14, 12, 13}; for (int i=0; i<order.size(); i++) { terminal_put(2+3+25+i*4, 11, 0xE200+order[i]); terminal_put(2+3+25+(order.size()+1)*4, 11, 0xE200+order[i]); } terminal_put(2+3+25+order.size()*4, 11, 0xE200+15); terminal_print(2, 14, "[color=orange]5.[/color] And tiles can even come from TrueType fonts like this:"); for (int i=0; i<6; i++) { terminal_put(2+3+i*5, 15, 0xE300+i); } terminal_print(2+3, 18, "...or like this:\n[font=zodiac]D F G S C"); terminal_refresh(); for (int key=0; key!=TK_CLOSE && key!=TK_ESCAPE; key=terminal_read()); // Clean up terminal_set("U+E100: none; U+E200: none; U+E300: none; zodiac font: none"); terminal_composition(TK_OFF); }
void terminal_println(const char* string) { terminal_print(string); terminal_print("\r\n"); }
int axp_battery_calibrate(void) { uint64_t energy_c = 0; uint64_t energy_p = 0; int prev_coulomb = 0; int prev_ocv = 0; int prev_ibat = 0; int key; int ibat_cnt = 0; int i; int64_t energy_top;//, energy_visible; int base, offset, range_charge, percent, range_discharge; char buf[200] = {}; int size; int rdc_average = 0, rdc_total = 0, rdc_cnt = 0, rdc_update_flag = 0; int ocv_0 = 2; int rdc_tmp = 0; int charge_eff; ClearScreen(); terminal_print(0, 7, "=============================== WARNING ================================\n"); terminal_print(0, 8, "Battery calibrate will take several hours to finish. Before calibrate, \n"); terminal_print(0, 9, "make sure you have discharge battery with voltage between to 3.0V ~ 3.05V.\n"); terminal_print(0, 10, "during test, you can press key 'Q' to quit this process.\n"); terminal_print(0, 11, "'R' = run calibration, 'Q' = quit. Your Choise:\n"); while (1) { if (tstc()) { key = getc(); if (key == 'r' || key == 'R') { break; } if (key == 'q' || key == 'Q') { goto out; } } udelay(10000); } /* * Note: If you observed rdc readed from register had large * different with rdc calculated(more than +-15mohm), you should * reset rdc with calculated value and redo this test. */ prev_ocv = axp_get_ocv(); axp_read(0x00, (uint8_t *)buf); if ((buf[0] & 0x50) && prev_ocv < 3800) { terminal_print(0, 13, "Calibrate RDC now...\n"); for (i = 0; i < 10; i++) { rdc_tmp = axp_calculate_rdc(); if (rdc_tmp) { rdc_total += rdc_tmp; rdc_cnt++; } } if (rdc_cnt) { rdc_average = rdc_total / rdc_cnt; sprintf(buf, "RDC set to %d mohm\n", rdc_average); terminal_print(0, 35, buf); axp_set_rdc(rdc_average); // update your calulated RDC here } else { terminal_print(0, 35, "WRONG with rdc calculate, we stop this test now!!!\n"); goto out; } } if (!axp_battery_calibrate_init()) { goto out; } #ifdef CONFIG_VIDEO_AMLLCD if (panel_oper.set_bl_level) { // to save system current consume panel_oper.set_bl_level(10); } #endif ClearScreen(); terminal_print(0, 1, "'Q' = quit, 'S' = Skip this step\n"); terminal_print(0, 4, "coulomb energy_c ibat prev_ibat ocv" " prev_ocv coulomb_p vbat rdc\n"); axp_update_calibrate(0); prev_coulomb = coulomb; prev_ocv = ocv; prev_ibat = ibat; for (i = 0; i < 4; i++) { ocv_array[i] = prev_ocv; } while (1) { if (tstc()) { key = getc(); if (key == 'Q' || key == 'q') { terminal_print(0, 35, "You have aborted calibrate manually\n"); goto out; } if (key == 'S' || key == 's') { terminal_print(0, 35, "Skip charging calibrate\n"); break; } } rdc_tmp = axp_update_calibrate(1); if (rdc_tmp) { rdc_total += rdc_tmp; rdc_cnt++; } if (ocv > 3520 && !rdc_update_flag) { if (rdc_cnt) { rdc_average = rdc_total / rdc_cnt; axp_set_rdc(rdc_average); sprintf(buf, "RDC set to %d mohm, rdc_total:%d, cnt:%d\n", rdc_average, rdc_total, rdc_cnt); terminal_print(0, 35, buf); rdc_update_flag = 1; } else { terminal_print(0, 35, "WRONG with rdc calculate, we stop this test now!!!\n"); goto out; } } energy_c += (coulomb - prev_coulomb) * ((ocv + prev_ocv) / 2); energy_p = energy_c; do_div(energy_p, 3700); update_energy_charge(update_ocv(ocv), energy_c, coulomb, energy_p); size = sprintf(buf, "%4d, %12lld, %4d, %4d, %4d, %4d,", coulomb, energy_c, ibat, prev_ibat, ocv, prev_ocv); size += sprintf(buf + size, " %4d, %4d, %4d \n", (int32_t)energy_p, vbat_i, rdc_r); buf[size] = '\0'; terminal_print(0, 5, buf); prev_coulomb = coulomb; prev_ocv = ocv; prev_ibat = ibat; udelay(1000000); if (ibat <= 100) { // charging finished ibat_cnt++; if (ibat_cnt > 50) { break; } } } rdc_average = rdc_total / rdc_cnt; size = sprintf(buf, "During charge, rdc_total=%d, rdc_cnt:%d, rdc_average:%d \n", rdc_total, rdc_cnt, rdc_average); terminal_print(0, 36, buf); axp_set_rdc(rdc_average); energy_top = energy_c; terminal_print(0, 10, "============= RESULT FOR CHARGE ================\n"); terminal_print(0, 11, "i, ocv, energy, c, c_e, off, %%\n"); offset = battery_energy_charge[15].coulomb_p - battery_energy_charge[2].coulomb_p; i = (battery_energy_charge[3].coulomb_p - battery_energy_charge[2].coulomb_p) * 100; if ((i / offset) >= 3) { ocv_0 = 2; terminal_print(0, 35, "We set zero reference ocv to 3414mV\n"); } else { ocv_0 = 3; terminal_print(0, 35, "We set zero reference ocv to 3555mV\n"); } base = battery_energy_charge[ocv_0].coulomb_p; range_charge = battery_energy_charge[15].coulomb_p - base; for (i = 0; i < 16; i++) { energy_p = battery_energy_charge[i].energy * 100; if (i <= ocv_0) { offset = 0; percent = 0; } else { offset = battery_energy_charge[i].coulomb_p - base; percent = 100 * (offset + range_charge / 200) / range_charge; } size = sprintf(buf, "%2d, %4d, %9lld, %4d, %4d, %4d, %3d \n", i, battery_energy_charge[i].ocv, battery_energy_charge[i].energy, battery_energy_charge[i].coulomb, battery_energy_charge[i].coulomb_p, offset, percent); buf[size] = '\0'; terminal_print(0, 12 + i, buf); } energy_p = energy_top; do_div(energy_p, 3700); size = sprintf(buf, "Total charge energy:%9lld(mV * mAh) = %5dmAh@3700mV\n", energy_top, (int32_t)energy_p); buf[size] = '\0'; terminal_print(0, 30, buf); size = sprintf(buf, "Energy visible:%5dmAh@3700mV, percent:%2d\n", range_charge, range_charge * 100 / (int32_t)energy_p); buf[size] = '\0'; terminal_print(0, 31, buf); /* * test for discharge */ terminal_print(0, 35, "Please unplug DC power, then press 'R' to contine\n"); while (1) { if (tstc()) { key = getc(); if (key == 'r' || key == 'R') { break; } if (key == 'q' || key == 'Q') { goto out; } } udelay(10000); } terminal_print(0, 35, "do discharge calibration now, please don't plug DC power during test!\n"); #ifdef CONFIG_VIDEO_AMLLCD if (panel_oper.set_bl_level) { // to fast discharge panel_oper.set_bl_level(200); } #endif energy_c = 0; while (1) { if (tstc()) { key = getc(); if (key == 'Q' || key == 'q') { terminal_print(0, 35, "You have aborted calibrate manually\n"); goto out; } if (key == 'S' || key == 's') { terminal_print(0, 35, "Skip discharging calibrate\n"); break; } } axp_update_calibrate(0); energy_c += (prev_coulomb - coulomb) * ((ocv + prev_ocv) / 2); energy_p = energy_c; do_div(energy_p, 3700); update_energy_discharge(update_ocv(ocv), energy_c, coulomb, energy_p); size = sprintf(buf, "%4d, %12lld, %4d, %4d, %4d, %4d,", coulomb, energy_c, ibat, prev_ibat, ocv, prev_ocv); size += sprintf(buf + size, " %4d, %4d, %4d \n", (int32_t)energy_p, vbat_i, rdc_r); buf[size] = '\0'; terminal_print(0, 5, buf); prev_coulomb = coulomb; prev_ocv = ocv; prev_ibat = ibat; udelay(1000000); if (ocv < 3350) { terminal_print(0, 35, "ocv is too low, we stop discharging test now!\n"); break; } } energy_top = energy_c; terminal_print(60, 10, "============ RESULT FOR DISCHARGE ==============\n"); terminal_print(60, 11, "i, ocv, energy, c, c_e, off, %%\n"); base = battery_energy_discharge[15].coulomb_p; range_discharge = battery_energy_discharge[ocv_0].coulomb_p - base; for (i = 0; i < 16; i++) { energy_p = battery_energy_discharge[i].energy * 100; if (i < ocv_0) { offset = 0; percent = 0; } else { offset = battery_energy_discharge[i].coulomb_p - base; percent = 100 - 100 * (offset + range_discharge / 200) / range_discharge; } size = sprintf(buf, "%2d, %4d, %9lld, %4d, %4d, %4d, %3d \n", i, battery_energy_discharge[i].ocv, battery_energy_discharge[i].energy, battery_energy_discharge[i].coulomb, battery_energy_discharge[i].coulomb_p, offset, percent); buf[size] = '\0'; terminal_print(60, 12 + i, buf); } energy_p = energy_top; do_div(energy_p, 3700); size = sprintf(buf, "Energy visible:%5dmAh@3700mV \n", range_discharge); buf[size] = '\0'; terminal_print(60, 30, buf); charge_eff = (100 * (range_discharge + range_charge / 200)) / range_charge; if (charge_eff >= 100) { charge_eff = 99; } size = sprintf(buf, "Charging efficient:%d%% \n", charge_eff); buf[size] = '\0'; terminal_print(60, 31, buf); out: terminal_print(0, 38, "\n\n"); return 1; }