void cstart(void) { uint16_t* p_gdt_limit; uint32_t* p_gdt_base; uint16_t* p_idt_limit; uint32_t* p_idt_base; display_str("\n\n\n\n\n\n\n\n\n\n\n\n\n\n" "=====<cstart> begins=====\n"); /* copy GDT from LOADER to new GDT */ memcpy(&gdt, (void*)(*((uint32_t*)(&gdt_ptr[2]))), /* base of old GDT */ *((uint16_t*)(&gdt_ptr[0])) + 1); /* limit of old GDT */ p_gdt_limit = (uint16_t*)(&gdt_ptr[0]); p_gdt_base = (uint32_t*)(&gdt_ptr[2]); *p_gdt_limit = GDT_SIZE * sizeof(descriptor_t) - 1; *p_gdt_base = (uint32_t)&gdt; p_idt_limit = (uint16_t*)(&idt_ptr[0]); p_idt_base = (uint32_t*)(&idt_ptr[2]); *p_idt_limit = IDT_SIZE * sizeof(gate_t) - 1; *p_idt_base = (uint32_t)&idt; init_port(); display_str("=====<cstart> ends=====\n"); }
void set_volume(void) { uint8_t mode = SHOW_MENU; uint8_t volume; timeoutcounter = INACTIVITYTIMEOUT;; volume = eeprom_read_byte((uint8_t *)EE_VOLUME); while (1) { if (just_pressed || pressed) { timeoutcounter = INACTIVITYTIMEOUT;; // timeout w/no buttons pressed after 3 seconds? } else if (!timeoutcounter) { //timed out! displaymode = SHOW_TIME; return; } if (just_pressed & 0x1) { // mode change return; } if (just_pressed & 0x2) { just_pressed = 0; if (mode == SHOW_MENU) { // start! mode = SET_VOL; // display volume if (volume) { display_str("vol high"); display[5] |= 0x1; } else { display_str("vol low"); } display[6] |= 0x1; display[7] |= 0x1; display[8] |= 0x1; } else { displaymode = SHOW_TIME; return; } } if (just_pressed & 0x4) { just_pressed = 0; if (mode == SET_VOL) { volume = !volume; if (volume) { display_str("vol high"); display[5] |= 0x1; } else { display_str("vol low"); } display[6] |= 0x1; display[7] |= 0x1; display[8] |= 0x1; eeprom_write_byte((uint8_t *)EE_VOLUME, volume); speaker_init(); beep(4000, 1); } } } }
void set_region(void) { uint8_t mode = SHOW_MENU; timeoutcounter = INACTIVITYTIMEOUT;; region = eeprom_read_byte((uint8_t *)EE_REGION); while (1) { if (just_pressed || pressed) { timeoutcounter = INACTIVITYTIMEOUT;; // timeout w/no buttons pressed after 3 seconds? } else if (!timeoutcounter) { //timed out! displaymode = SHOW_TIME; return; } if (just_pressed & 0x1) { // mode change return; } if (just_pressed & 0x2) { just_pressed = 0; if (mode == SHOW_MENU) { // start! mode = SET_REG; // display region if (region == REGION_US) { display_str("usa-12hr"); } else { display_str("eur-24hr"); } } else { displaymode = SHOW_TIME; return; } } if (just_pressed & 0x4) { just_pressed = 0; if (mode == SET_REG) { region = !region; if (region == REGION_US) { display_str("usa-12hr"); } else { display_str("eur-24hr"); } eeprom_write_byte((uint8_t *)EE_REGION, region); } } } }
void set_dimmer(void) { uint8_t mode = SHOW_MENU; timeoutcounter = INACTIVITYTIMEOUT;; while (1) { if (just_pressed || pressed) { timeoutcounter = INACTIVITYTIMEOUT;; // timeout w/no buttons pressed after 3 seconds? } else if (!timeoutcounter) { //timed out! displaymode = SHOW_TIME; return; } if (just_pressed & 0x1) { // mode change return; } if (just_pressed & 0x2) { just_pressed = 0; if (mode == SHOW_MENU) { // start! mode = SET_DIMMER; if (dimmer_on) { display_str("dimr on "); } else { display_str("dimr off"); } } else { displaymode = SHOW_TIME; return; } } if (just_pressed & 0x4) { just_pressed = 0; if (mode == SET_DIMMER) { dimmer_on = !dimmer_on; if (dimmer_on) { display_str("dimr on "); dimmer_update(); } else { display_str("dimr off"); set_vfd_brightness(brightness_level); } eeprom_write_byte((uint8_t *)EE_DIMMER, dimmer_on); } } } }
// This turns on/off the alarm when the switch has been // set. It also displays the alarm time void setalarmstate(void) { if (ALARM_PIN & _BV(ALARM)) { // Don't display the alarm/beep if we already have if (!alarm_on) { // alarm on! alarm_on = 1; // reset snoozing snoozetimer = 0; // show the status on the VFD tube display_str("alarm on"); // its not actually SHOW_SNOOZE but just anything but SHOW_TIME displaymode = SHOW_SNOOZE; delayms(1000); // show the current alarm time set display_alarm(alarm_h, alarm_m); delayms(1000); // after a second, go back to clock mode displaymode = SHOW_TIME; } } else { if (alarm_on) { // turn off the alarm alarm_on = 0; snoozetimer = 0; if (alarming) { // if the alarm is going off, we should turn it off // and quiet the speaker DEBUGP("alarm off"); alarming = 0; TCCR1B &= ~_BV(CS11); // turn it off! PORTB |= _BV(SPK1) | _BV(SPK2); } } } }
// When the alarm is going off, pressing a button turns on snooze mode // this sets the snoozetimer off in MAXSNOOZE seconds - which turns on // the alarm again void setsnooze(void) { //snoozetimer = eeprom_read_byte((uint8_t *)EE_SNOOZE); //snoozetimer *= 60; // convert minutes to seconds snoozetimer = MAXSNOOZE; DEBUGP("snooze"); display_str("snoozing"); displaymode = SHOW_SNOOZE; delayms(1000); displaymode = SHOW_TIME; }
void exception_handler(int vec_no, int err_code, int eip, int cs, int eflags) { int i; int text_color = 0x74; char* err_msg[] = { "#DE divide error", "#DB reserved", "-- nmi interrupt", "#BP breakpoint", "#OF overflow", "#BR bound range exceeded", "#UD invalid opcode (undefined opcode)", "#NM device not available (no match coprocessor)", "#DF double fault", " coprocessor segment overrun (reserved)", "#TS invalid tss", "#NP segment not present", "#SS stack segment fault", "#GP general protection", "#PF page fault", "-- (intel reserved. do not use)", "#MF x87 FPU floating-point error (math fault)", "#AC alignment check", "#MC machine check", "#XF SIMD floating-point exception" }; disp_pos = 0; for (i = 0; i < 80 * 5; ++i) display_str(" "); disp_pos = 0; display_color_str("exception! --> ", text_color); display_color_str(err_msg[vec_no], text_color); display_color_str("\n\n", text_color); display_color_str("eflags: ", text_color); display_int(eflags); display_color_str("cs: ", text_color); display_int(cs); display_color_str("eip: ", text_color); display_int(eip); if (0xffffffff != err_code) { display_color_str("error code: ", text_color); display_int(err_code); } }
void set_brightness(void) { uint8_t mode = SHOW_MENU; timeoutcounter = INACTIVITYTIMEOUT;; while (1) { if (just_pressed || pressed) { timeoutcounter = INACTIVITYTIMEOUT;; // timeout w/no buttons pressed after 3 seconds? } else if (!timeoutcounter) { //timed out! displaymode = SHOW_TIME; eeprom_write_byte((uint8_t *)EE_BRIGHT, brightness_level); return; } if (just_pressed & 0x1) { // mode change return; } if (just_pressed & 0x2) { just_pressed = 0; if (mode == SHOW_MENU) { // start! mode = SET_BRITE; // display brightness set_vfd_brightness(brightness_level); display_str("brite "); display[7] = pgm_read_byte(numbertable_p + (brightness_level / 10)) | 0x1; display[8] = pgm_read_byte(numbertable_p + (brightness_level % 10)) | 0x1; } else { displaymode = SHOW_TIME; eeprom_write_byte((uint8_t *)EE_BRIGHT, brightness_level); return; } } if ((just_pressed & 0x4) || (pressed & 0x4)) { just_pressed = 0; if (mode == SET_BRITE) { brightness_level += BRIGHTNESS_INCREMENT; if (brightness_level > BRIGHTNESS_MAX) brightness_level = BRIGHTNESS_MIN; display[7] = pgm_read_byte(numbertable_p + (brightness_level / 10)) | 0x1; display[8] = pgm_read_byte(numbertable_p + (brightness_level % 10)) | 0x1; set_vfd_brightness(brightness_level); } } } }
int main(void) { // uint8_t i; uint8_t mcustate; // turn boost off TCCR0B = 0; BOOST_DDR |= _BV(BOOST); BOOST_PORT &= ~_BV(BOOST); // pull boost fet low // check if we were reset mcustate = MCUSR; MCUSR = 0; wdt_disable(); // now turn it back on... 2 second time out //WDTCSR |= _BV(WDP0) | _BV(WDP1) | _BV(WDP2); //WDTCSR = _BV(WDE); wdt_enable(WDTO_2S); kickthedog(); // we lost power at some point so lets alert the user // that the time may be wrong (the clock still works) timeunknown = 1; // have we read the time & date from eeprom? restored = 0; // setup uart uart_init(BRRL_192); //DEBUGP("VFD Clock"); DEBUGP("!"); //DEBUGP("turning on anacomp"); // set up analog comparator ACSR = _BV(ACBG) | _BV(ACIE); // use bandgap, intr. on toggle! // settle! if (ACSR & _BV(ACO)) { // hmm we should not interrupt here ACSR |= _BV(ACI); // even in low power mode, we run the clock DEBUGP("clock init"); clock_init(); } else { // we aren't in low power mode so init stuff // init io's initbuttons(); VFDSWITCH_PORT &= ~_BV(VFDSWITCH); DEBUGP("turning on buttons"); // set up button interrupts DEBUGP("turning on alarmsw"); // set off an interrupt if alarm is set or unset EICRA = _BV(ISC00); EIMSK = _BV(INT0); displaymode = SHOW_TIME; DEBUGP("vfd init"); vfd_init(); dimmer_init(); DEBUGP("boost init"); brightness_level = eeprom_read_byte((uint8_t *)EE_BRIGHT); boost_init(brightness_level); sei(); region = eeprom_read_byte((uint8_t *)EE_REGION); DEBUGP("speaker init"); speaker_init(); beep(4000, 1); DEBUGP("clock init"); clock_init(); DEBUGP("alarm init"); setalarmstate(); } DEBUGP("done"); while (1) { //_delay_ms(100); kickthedog(); //uart_putc_hex(ACSR); if (ACSR & _BV(ACO)) { // DEBUGP("SLEEPYTIME"); gotosleep(); continue; } //DEBUGP("."); if (just_pressed & 0x1) { just_pressed = 0; switch(displaymode) { case (SHOW_TIME): displaymode = SET_ALARM; display_str("set alarm"); set_alarm(); break; case (SET_ALARM): displaymode = SET_TIME; display_str("set time"); set_time(); timeunknown = 0; break; case (SET_TIME): displaymode = SET_DATE; display_str("set date"); set_date(); break; case (SET_DATE): displaymode = SET_BRIGHTNESS; display_str("set brit"); set_brightness(); break; case (SET_BRIGHTNESS): displaymode = SET_DIMMER; display_str("set dimr"); set_dimmer(); break; case (SET_DIMMER): displaymode = SET_VOLUME; display_str("set vol "); set_volume(); break; case (SET_VOLUME): displaymode = SET_REGION; display_str("set regn"); set_region(); break; /* case (SET_REGION): displaymode = SET_SNOOZE; display_str("set snoz"); set_snooze(); break; */ default: displaymode = SHOW_TIME; } } else if ((just_pressed & 0x2) || (just_pressed & 0x4)) { just_pressed = 0; displaymode = NONE; display_date(DAY); kickthedog(); delayms(1500); kickthedog(); displaymode = SHOW_TIME; } } }
// We can display the current date! void display_date(uint8_t style) { // This type is mm-dd-yy OR dd-mm-yy depending on our pref. if (style == DATE) { display[0] = 0; display[6] = display[3] = 0x02; // put dashes between num if (region == REGION_US) { // mm-dd-yy display[1] = pgm_read_byte(numbertable_p + (date_m / 10)); display[2] = pgm_read_byte(numbertable_p + (date_m % 10)); display[4] = pgm_read_byte(numbertable_p + (date_d / 10)); display[5] = pgm_read_byte(numbertable_p + (date_d % 10)); } else { // dd-mm-yy display[1] = pgm_read_byte(numbertable_p + (date_d / 10)); display[2] = pgm_read_byte(numbertable_p + (date_d % 10)); display[4] = pgm_read_byte(numbertable_p + (date_m / 10)); display[5] = pgm_read_byte(numbertable_p + (date_m % 10)); } // the yy part is the same display[7] = pgm_read_byte(numbertable_p + (date_y / 10)); display[8] = pgm_read_byte(numbertable_p + (date_y % 10)); } else if (style == DAY) { // This is more "Sunday June 21" style uint16_t month, year; uint8_t dotw; // Calculate day of the week month = date_m; year = 2000 + date_y; if (date_m < 3) { month += 12; year -= 1; } dotw = (date_d + (2 * month) + (6 * (month+1)/10) + year + (year/4) - (year/100) + (year/400) + 1) % 7; // Display the day first display[8] = display[7] = 0; switch (dotw) { case 0: display_str("sunday"); break; case 1: display_str("monday"); break; case 2: display_str("tuesday"); break; case 3: display_str("wednsday"); break; case 4: display_str("thursday"); break; case 5: display_str("friday"); break; case 6: display_str("saturday"); break; } // wait one seconds about delayms(1000); // Then display the month and date display[6] = display[5] = display[4] = 0; switch (date_m) { case 1: display_str("jan"); break; case 2: display_str("feb"); break; case 3: display_str("march"); break; case 4: display_str("april"); break; case 5: display_str("may"); break; case 6: display_str("june"); break; case 7: display_str("july"); break; case 8: display_str("augst"); break; case 9: display_str("sept"); break; case 10: display_str("octob"); break; case 11: display_str("novem"); break; case 12: display_str("decem"); break; } display[7] = pgm_read_byte(numbertable_p + (date_d / 10)); display[8] = pgm_read_byte(numbertable_p + (date_d % 10)); } }
SCSAPI_VOID telemetry_frame_end(const scs_event_t /*event*/, const void *const /*event_info*/, const scs_context_t /*context*/) { if (!serial_port.is_valid()) return; const unsigned long now = GetTickCount(); const unsigned long diff = now - last_update; if (diff < 50) return; last_update = now; const float speed_mph = telemetry.speed * METERS_PER_SEC_TO_MILES_PER_HOUR; const float speed_kph = telemetry.speed * METERS_PER_SEC_TO_KM_PER_HOUR; const float fuel_ratio = telemetry.fuel / telemetry.fuel_capacity; unsigned idx = 0; memset(packet, 0, PACKET_MAX_SIZE); #define PUT_BYTE(X) packet[idx++] = (unsigned char)(X) #define PUT_BYTE_FLOAT(X) packet[idx++] = (unsigned char)(float_to_byte(X)) #define GETFLTOPT(X) (option_file.get_option_float(X, 1.0f)) // Packet header PUT_BYTE(PACKET_SYNC); PUT_BYTE(PACKET_VER); // Convert data for output by servos // Adjust the constant values to map to servo range PUT_BYTE_FLOAT(fabs(telemetry.speed) * GETFLTOPT("factor_speed")); // Absolute value for when reversing PUT_BYTE_FLOAT(telemetry.engine_rpm * GETFLTOPT("factor_engine_rpm")); PUT_BYTE_FLOAT(telemetry.brake_air_pressure * GETFLTOPT("factor_brake_air_pressure")); PUT_BYTE_FLOAT(telemetry.brake_temperature * GETFLTOPT("factor_brake_temperature")); PUT_BYTE_FLOAT(fuel_ratio * GETFLTOPT("factor_fuel_ratio")); // Fuel level PUT_BYTE_FLOAT(telemetry.oil_pressure * GETFLTOPT("factor_oil_pressure")); PUT_BYTE_FLOAT(telemetry.oil_temperature * GETFLTOPT("factor_oil_temperature")); PUT_BYTE_FLOAT(telemetry.water_temperature * GETFLTOPT("factor_water_temperature")); PUT_BYTE_FLOAT(telemetry.battery_voltage * GETFLTOPT("factor_battery_voltage")); // Pack data for LEDs into bytes // Truck lights PUT_BYTE(PACKBOOL( 0, telemetry.light_parking, telemetry.light_lblinker, telemetry.light_rblinker, telemetry.light_low_beam, telemetry.light_high_beam, telemetry.light_brake, telemetry.light_reverse)); // Warning lights PUT_BYTE(PACKBOOL( telemetry.parking_brake, telemetry.motor_brake, telemetry.brake_air_pressure_warning, telemetry.brake_air_pressure_emergency, telemetry.fuel_warning, telemetry.battery_voltage_warning, telemetry.oil_pressure_warning, telemetry.water_temperature_warning)); // Enabled flags PUT_BYTE(PACKBOOL( 0,0,0,0,0, 0, telemetry.electric_enabled, telemetry.engine_enabled)); // Build string for LCD display std::stringstream ss; ss.width(3); ss << abs(int(speed_mph)); ss << " MPH"; ss << " G "; if (telemetry.engine_gear > 0) { ss << "D"; ss.width(2); ss << telemetry.engine_gear; } else if (telemetry.engine_gear == 0) { ss << "N "; } else { ss << "R"; ss.width(2); ss << abs(telemetry.engine_gear); } ss << "\n"; ss.width(3); ss << abs(int(speed_kph)); ss << " KPH"; ss << " F "; ss.width(3); ss << int(fuel_ratio * 100.0f) << "%"; ss.width(3); ss << abs(int(speed_kph)); std::string display_str(ss.str()); // Write length of string PUT_BYTE(display_str.size()); // Followed by string display_str.copy((char*)&packet[idx], PACKET_MAX_SIZE - idx); idx += display_str.size(); serial_port.write(packet, idx); }