/* main.c */ #include "sensors.h" #include "i2c.h" #include "timer.h" #include "uart.h" #include "interrupt.h" #include "event.h" #include "led.h" #include "status.h" #include "watchdog.h" #include "thrust.h" #include "panic.h" #include "sdcard.h" #include "log.h" #include "spi.h" #define PINSEL0 (*((volatile unsigned int *) 0xE002C000)) #define PINSEL1 (*((volatile unsigned int *) 0xE002C004)) #define FP0XDIR (*((volatile unsigned int *) 0x3FFFC000)) #define FP0XVAL (*((volatile unsigned int *) 0x3FFFC014)) #define SCS (*((volatile unsigned int *) 0xe01fc1a0)) #define BUTTON_PRESSED (!((FP0XVAL) & 0x00010000)) char buffer[512]; void init_pins(void) { PINSEL0 = 0x2a09a255; /* P0.0 and P0.1 assigned to UART */ /* P0.2 and P0.3 assigned to I2C */ /* P0.4 and P0.6 assigned to CAP0.[12] */ /* P0.7 and P0.9 assigned to MAT2.[02] */ /* P0.8 assigned to UART1 */ /* P0.12 and P0.13 assigned to MAT1.[01] */ /* P0.14 assigned to SPI1 */ PINSEL1 = 0x00000140; /* P0.19 and P0.20 assigned to SPI1 */ SCS = 1; FP0XDIR = 0x04200000; /* P0.26 and P0.21 are outputs */ FP0XVAL = 0x0; } #ifdef USE_UART void reply(char *str) { putstr(str); putstr("\r\n"); } #else #define reply(x) ((void)0) #endif void timer_event_handler(void) { unsigned int timestamp = timer_read(); log_put_header(timestamp); sensors_start_sample(); } void menu_handler(void); void wait_for_button_pressed(bool target) { bool pressed; led_set(!target); /* Very crude debouncing */ timer_delay_ms(100); target = target ? TRUE:FALSE; do { pressed = BUTTON_PRESSED; } while (pressed != target); led_set(pressed); } void calibrate_escs() { wait_for_button_pressed(0); putstr("Calibration mode\r\n"); wait_for_button_pressed(1); wait_for_button_pressed(0); set_thrust(0, 1.0); set_thrust(1, 1.0); set_thrust(2, 1.0); set_thrust(3, 1.0); putstr("Max throttle set\r\n"); wait_for_button_pressed(1); wait_for_button_pressed(0); set_thrust(0, 0.0); set_thrust(1, 0.0); set_thrust(2, 0.0); set_thrust(3, 0.0); putstr("Zero throttle set\r\n"); wait_for_button_pressed(1); wait_for_button_pressed(0); putstr("Exit calibration mode\r\n"); } #ifdef USE_UART void dump_buffer(char *buffer, unsigned int length, unsigned int addr); void dump_buffer(char *buffer, unsigned int length, unsigned int addr) { unsigned int i; for (i = 0; i < length; i++) { if ((i % 16) == 0) { puthex(addr+i); putstr(":"); } putstr(" "); puthex(buffer[i]); if ((i % 16) == 15) { putstr("\r\n"); } } if ((i % 16) != 0) putstr("\r\n"); } #else #define dump_buffer(a, b, c) ((void)0) #endif int main(void) { int i; init_interrupt(); init_uart(); init_i2c(); init_pins(); init_timer(); init_status(); event_register(EVENT_UART_INPUT, menu_handler); event_register(EVENT_TIMER, timer_event_handler); for (i = 0; i < 10; i++) { if (init_sdcard()) break; } putstr("Your entire life has been a mathematical error... a mathematical error I'm about to correct!\r\n"); if (BUTTON_PRESSED) calibrate_escs(); putstr("prompt> "); timer_delay_ms(1000); if (!sensors_init()) putstr("Sensor initialisation failed\r\n"); /* Flight is potentially live after this. */ timer_set_period(TIMER_MS(5)); #if 1 sensors_start_zero(); #endif led_init(); init_watchdog(); /* Good luck! */ while (1) { CHECKPOINT(0); led_update(); CHECKPOINT(1); if (!event_dispatch()) sdcard_poll(); CHECKPOINT(2); watchdog_check(); } return 0; } static int power = 0; static unsigned int sd_address = 0; unsigned int read_number(void) { unsigned int number; unsigned int base; int digit; char c; number = 0; base = 10; while (1) { if (getch(&c)) { digit = -1; if ((c == 0x0a) || (c == 0x0d)) break; putch(c); if (c == 'x') base = 16; if ((c >= '0') && (c <= '9')) digit = c - '0'; if ((c >= 'A') && (c <= 'F')) digit = c - 'A' + 10; if ((digit >= 0) && (digit < (int)base)) { number = number * base; number += digit; } } } putstr("\r\n"); return number; } void menu_handler(void) { int i; char c; while (getch(&c)) { #if 0 continue; /* Yes, let's just ignore UART input now. */ #endif if (c == 0x0a) continue; putch(c); putstr("\r\n"); switch (c & 0xdf) { case 0x0a: case 0x0d: break; case 'H': case '?': reply("Help is not available. Try a psychiatrist."); break; case 'D': sensors_dump(); break; case 'N': putstr("The time is "); puthex(timer_read()); reply("."); break; case 'I': init_sdcard(); break; case 'R': sd_address = 0; case 'S': if (sdcard_read(sd_address++, buffer, 512)) { dump_buffer(buffer, 512, (sd_address-1) * 512); reply ("SD card read success"); } else { reply("SD card read failed"); } break; case 'A': sd_address = read_number(); putstr("SD read address set to 0x"); puthex(sd_address); reply("."); break; case 'W': for (i = 0; i < 4; i++) { putstr("Width "); putint(i); putstr(": "); putint(timer_input(i)); if (!timer_valid(i)) putstr(" (invalid)"); putstr("\r\n"); } if (!timer_allvalid()) { putstr("ALL INVALID!\r\n"); } break; #if 0 case 'T': sdcard_start_write(); break; #endif case 'L': spi_drain(); break; case '0' & 0xdf: set_thrust(0, 0.0); set_thrust(1, 0.0); set_thrust(2, 0.0); set_thrust(3, 0.0); power = 0; break; #if 0 case '1' & 0xdf: power--; if (power < 0) power = 15; power = power % 16; putstr("Power setting: "); putint(power); putstr("\r\n"); set_thrust(0, ((float)power)/16.0); break; case '2' & 0xdf: power++; power = power % 16; putstr("Power setting: "); putint(power); putstr("\r\n"); set_thrust(0, ((float)power)/16.0); break; #endif #if 0 case '1' & 0xdf: set_thrust(0, 0.5); break; case '2' & 0xdf: set_thrust(1, 0.5); break; case '3' & 0xdf: set_thrust(2, 0.5); break; case '4' & 0xdf: set_thrust(3, 0.5); break; case '5' & 0xdf: set_thrust(0, 1.0); break; case '6' & 0xdf: set_thrust(1, 1.0); break; case '7' & 0xdf: set_thrust(2, 1.0); break; case '8' & 0xdf: set_thrust(3, 1.0); break; #endif case '9' & 0xdf: timer_set_pwm_invalid(0); timer_set_pwm_invalid(1); timer_set_pwm_invalid(2); timer_set_pwm_invalid(3); break; default: reply("Unrecognised command."); break; } putstr("prompt> "); } }