// Display fancy LED pattern waiting for any button to be pressed // Wait for user to begin game inline static void wait_start() { uint8_t mask = 0; uint8_t buttons; uint8_t cnt; uint8_t led = LED0; do { set_leds(led); mask = wait_buttons(100); // 100ms max wait led = led == LED3 ? LED0 : led << 1; // next led } while (mask == 0); // wait more until all buttons are released set_leds(0); buttons = mask; do { mask = get_buttons(); buttons |= mask; } while (mask != 0); // configure game level depending on number of buttons pressed cnt = buttons_count(buttons); if (cnt == 2) game_level = 15; else if (cnt == 3) game_level = 20; else if (cnt == 4) game_level = 25; }
// Waits for button(s) press and release until timeout (ms) with debounce uint8_t wait_buttons(uint16_t time_ms) { uint8_t res = 0; // resulting buttons mask uint8_t cur = 0; // currently pressed buttons do { cur = get_buttons(); res |= cur; _delay_ms(DEBOUNCE_MS); // this delay de-bounces read time_ms -= DEBOUNCE_MS; } while (time_ms >= DEBOUNCE_MS && (res == 0 || cur != 0)); return res; }
int user_select_string(char **strings, int n) { int cursor = 0; int display_start = 0; int n_display = 20; while (1) { if (cursor>=display_start+n_display) display_start = cursor-n_display+1; if (cursor<display_start) display_start = cursor; int x = 10; int y = 5; clear_screen(); clear_text_area(x,y,60-2*x,n_display+4); y+=2; pgPrintCenter(29,red,"X = Select"); pgPrintCenter(30,red,"O = Abort"); draw_strings(strings, n, x, 7, display_start, n_display, cursor); int key = get_buttons(); if (key & PSP_CTRL_DOWN) cursor ++; if (key & PSP_CTRL_UP) cursor --; if (key & PSP_CTRL_RIGHT) cursor += n_display; if (key & PSP_CTRL_LEFT) cursor -= n_display; if (key & PSP_CTRL_CIRCLE) return -1; if (key & PSP_CTRL_CROSS) return cursor; if (cursor>=n) cursor = n-1; if (cursor<0) cursor = 0; } }
static LRESULT CALLBACK wnd_proc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { window* pw = (window*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!pw) return DefWindowProc(hwnd, msg, wParam, lParam); switch(msg) { case WM_CREATE: pw->notify(WINDOW_ON_CREATE, 0); break; case WM_DESTROY: pw->notify(WINDOW_ON_DESTROY, 0); SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); delete pw; break; case WM_SIZE: if(::IsWindow(hwnd)) { RECT rc; GetClientRect(hwnd, &rc); WINDOW_ON_SIZE_PARAMS p; p.width = rc.right - rc.left; p.height = rc.bottom - rc.top; if(pw->notify(WINDOW_ON_SIZE, &p)) { //todo: MoveWindow here as client changed requested dimensions } } break; case WM_MOVE: if(::IsWindow(hwnd)) { RECT rc; GetClientRect(hwnd, &rc); ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&rc, 1); WINDOW_ON_MOVE_PARAMS p; p.x = rc.left; p.y = rc.top; if(pw->notify(WINDOW_ON_SIZE, &p)) { //todo: MoveWindow here as client changed requested position } } break; case WM_ACTIVATE: { WINDOW_ON_ACTIVATE_PARAMS p; p.manner = LOWORD(wParam) != WA_INACTIVE; pw->notify(WINDOW_ON_ACTIVATE, &p); } break; case WM_IDLE: pw->notify(WINDOW_ON_IDLE, 0); break; case WM_CLOSE: pw->notify(WINDOW_ON_CLOSE, 0); break; case WM_TIMER: if( wParam ) { WINDOW_ON_TIMER_PARAMS p; p.id = wParam; p.cancel = false; if(!pw->notify(WINDOW_ON_TIMER, &p) || p.cancel) ::KillTimer(hwnd, wParam); } else // mouse tick timer { WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_TICK; p.buttons = MAIN_BUTTON; POINT pt; ::GetCursorPos(&pt); p.screen_x = pt.x; p.screen_y = pt.y; ::MapWindowPoints(HWND_DESKTOP,hwnd,&pt,1); p.x = pt.x; p.y = pt.y; p.alts = get_alts(); if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } return 0; case WM_ERASEBKGND: return TRUE; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); RECT ri; ::GetClipBox(hdc,&ri); w_paint(pw, hwnd, hdc, ri); EndPaint(hwnd, &ps); return 0; } case WM_PRINTCLIENT: { HDC hdc = (HDC) wParam; RECT ri; ::GetClipBox(hdc,&ri); w_paint(pw, hwnd, hdc, ri); return 0; } case WM_LBUTTONDOWN: { WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_DOWN; p.buttons = MAIN_BUTTON; p.x = GET_X_LPARAM(lParam); p.y = GET_Y_LPARAM(lParam); p.screen_x = p.x; p.screen_y = p.y; ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&p.screen_x, 1); p.alts = get_alts(wParam); ::SetTimer(hwnd,0,::GetDoubleClickTime()/4,0); // start MOUSE_TICK timer ::SetCapture(hwnd); if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } case WM_RBUTTONDOWN: { WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_DOWN; p.buttons = PROP_BUTTON; p.x = GET_X_LPARAM(lParam); p.y = GET_Y_LPARAM(lParam); p.screen_x = p.x; p.screen_y = p.y; ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&p.screen_x, 1); p.alts = get_alts(wParam); if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } case WM_LBUTTONUP: { ::KillTimer(hwnd,0); // stop MOUSE_TICK timer if(::GetCapture() == hwnd) ::ReleaseCapture(); WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_UP; p.buttons = MAIN_BUTTON; p.x = GET_X_LPARAM(lParam); p.y = GET_Y_LPARAM(lParam); p.screen_x = p.x; p.screen_y = p.y; ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&p.screen_x, 1); p.alts = get_alts(wParam); if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } case WM_RBUTTONUP: { WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_UP; p.buttons = PROP_BUTTON; p.x = GET_X_LPARAM(lParam); p.y = GET_Y_LPARAM(lParam); p.screen_x = p.x; p.screen_y = p.y; ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&p.screen_x, 1); p.alts = get_alts(wParam); if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } case WM_MOUSEMOVE: { WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_MOVE; p.buttons = get_buttons(wParam); p.x = GET_X_LPARAM(lParam); p.y = GET_Y_LPARAM(lParam); p.screen_x = p.x; p.screen_y = p.y; ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&p.screen_x, 1); p.alts = get_alts(wParam); if( !pw->mouse_inside ) { pw->mouse_inside = true; TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.dwFlags = TME_HOVER | TME_LEAVE; tme.hwndTrack = hwnd; tme.dwHoverTime = HOVER_DEFAULT; _TrackMouseEvent(&tme); WINDOW_ON_MOUSE_PARAMS t = p; t.event = MOUSE_ENTER; pw->notify(WINDOW_ON_MOUSE, &t); } if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } case WM_MOUSELEAVE: { WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_LEAVE; p.buttons = get_buttons(wParam); p.x = GET_X_LPARAM(lParam); p.y = GET_Y_LPARAM(lParam); p.screen_x = p.x; p.screen_y = p.y; ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&p.screen_x, 1); p.alts = get_alts(wParam); pw->mouse_inside = false; TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.dwFlags = TME_CANCEL; tme.hwndTrack = hwnd; tme.dwHoverTime = HOVER_DEFAULT; _TrackMouseEvent(&tme); if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } case WM_MOUSEHOVER: { WINDOW_ON_MOUSE_PARAMS p; p.event = MOUSE_IDLE; p.buttons = get_buttons(wParam); p.x = GET_X_LPARAM(lParam); p.y = GET_Y_LPARAM(lParam); p.screen_x = p.x; p.screen_y = p.y; ::MapWindowPoints(hwnd,HWND_DESKTOP,(LPPOINT)&p.screen_x, 1); p.alts = get_alts(wParam); TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.dwFlags = TME_HOVER | TME_LEAVE; tme.hwndTrack = hwnd; tme.dwHoverTime = HOVER_DEFAULT; _TrackMouseEvent(&tme); if(pw->notify(WINDOW_ON_MOUSE, &p)) return 0; break; } case WM_KEYDOWN: { WINDOW_ON_KEY_PARAMS p; p.event = KEY_DOWN; p.code = wParam; p.alts = get_alts(); if(pw->notify(WINDOW_ON_KEY, &p)) return 0; break; } case WM_KEYUP: { WINDOW_ON_KEY_PARAMS p; p.event = KEY_UP; p.code = wParam; p.alts = get_alts(); if(pw->notify(WINDOW_ON_KEY, &p)) return 0; break; } case WM_CHAR: { WINDOW_ON_KEY_PARAMS p; p.event = KEY_CHAR; p.code = wParam; p.alts = get_alts(); if(pw->notify(WINDOW_ON_KEY, &p)) return 0; break; } } return DefWindowProc(hwnd, msg, wParam, lParam); }
int main (void) { int tmp,i,res; CLKPR = 0x80; CLKPR = 0x00; // Clock prescaler Reset /*-----------------------------------------------------------------* *------------------------- Gear buttoms setup---------------------* *-----------------------------------------------------------------*/ DDRC&=~(1<<PC7); // Neutral PORTC |= (1<<PC7); // Neutral pull-up DDRE&=~(1<<PE6); // Knap1 DDRE&=~(1<<PE7); // Knap2 /* Buttoms interrupt */ EICRB |= (1<<ISC71|1<<ISC70|1<<ISC61|1<<ISC60); /* Rising edge */ EIMSK |= (1<<INT7 | 1<<INT6); uint8_t test_rx[8]; int8_t data; char streng[10]; // Recieve buffer st_cmd_t msg; // Init CAN, UART, I/O init(); uartinit(); sendtekst("UART initialized\n\r"); TWI_init(); sendtekst("TWI initialized\n\r"); sei(); /* Interrupt enable */ sendtekst("Interrupt enabled\n\r"); /*-----------------------------------------------------------------* *----------------------------Display setup -----------------------* *-----------------------------------------------------------------*/ /* Set blink rates */ set_blink_rate(LED0_7_ADDR, LED_BLINK1, 20, 100); set_blink_rate(LED0_7_ADDR, LED_BLINK2, 0, RPM_LED_DUTYCYCLE*2.56); set_blink_rate(LED8_15_ADDR, LED_BLINK1, (1.0/RPM16_RATE)*252, RPM16_DUTYCYCLE*2.56); set_blink_rate(LED8_15_ADDR, LED_BLINK2, 0, RPM_LED_DUTYCYCLE*2.56); set_blink_rate(SEG_ADDR, LED_BLINK1, 20, 100); set_blink_rate(SEG_ADDR, LED_BLINK2, 0, SEG_DUTYCYCLE*2.56); set_blink_rate(LED_BUTTONS_ADDR, LED_BLINK1, 20, 100); set_blink_rate(LED_BUTTONS_ADDR, LED_BLINK2, 0, SEG_DUTYCYCLE*2.56); /*-----------------------------------------------------------------* *----------------------------CAN interrupt setup -----------------* *-----------------------------------------------------------------*/ Can_sei(); /* Enable general can interrupt */ Can_set_tx_int(); /* Enable can tx interrupt */ Can_set_rx_int(); /* Enable can rx interrupt */ /* * Kode til hurtig test af can */ sendtekst("Config 3 mailboxes for rpm_msgid...\n\r"); msg.id.std = rpm_msgid; msg.dlc = 8; res = can_config_rx_mailbox(&msg, 3); if (res == CAN_CMD_ACCEPTED) { sendtekst("SUCCESS\n\r"); } else { sendtekst("FAIL\n\r"); } // --- Init variables /* Init user led 0 & 1 */ DDRB |= (1<<PB6 | 1<<PB5); PORTB |= (1<<PB6 | 1<<PB5); sendtekst("Beep\n\r"); display_test(); params.GearEst = 0; char dataout[] = {gear,0}; while (1) { _delay_ms(20); /* Display selected parameter */ if (mode == RPM_MODE) { set_rpm(params.rpm, LED_ON); } else if (mode == VOLTAGE_MODE) { set_voltage(params.batteryV, LED_ON); } else if (mode == WATER_TEMP_MODE) { set_water_temp(params.waterTemp, LED_ON); } // Geat buttons to CAN dataout[1] = 0; /* Format buttom states for sending */ dataout[1] |= (params.GearButDown*GEARDOWNBUT | GEARUPBUT*params.GearButUp | params.GearButNeutral*GEARNEUBUT); /* Send buttom states */ if(dataout[1] != 0) { // Hack, sender gearskiftesignal et par gange, sådan at det går igennem // Symptombehandling, sygdommen skal kureres... if (dataout[1] & (GEARDOWNBUT) == GEARDOWNBUT) indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1); if (dataout[1] & (GEARUPBUT) == GEARUPBUT) indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1); set_leds(LED_BUTTONS_ADDR, indi_leds_state); for(j=0;j<1;j++){ can_send_non_blocking(gear_msgid, dataout, 2); _delay_ms(5); } indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_2); indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_1); set_leds(LED_BUTTONS_ADDR, indi_leds_state); } /* Clear buttom states */ params.GearButDown = 0; params.GearButUp = 0; params.GearButNeutral = 0; /* Display bottons code */ buttons_state = get_buttons(LED_BUTTONS_ADDR) & (BUTTON1 | BUTTON2); if (buttons_state == 2) { indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1); indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_2); mode = VOLTAGE_MODE; } else if (buttons_state == 1) { indi_leds_state |= (LED_BLINK2<<LED_BUTTON_2); indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_1); mode = WATER_TEMP_MODE; } else if (buttons_state == 0) { indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1 | LED_BLINK2<<LED_BUTTON_2); } else { indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_1 | LED_BLINK2<<LED_BUTTON_2); mode = RPM_MODE; } /* Indicator for water temp */ if (params.waterTemp <= WATER_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI1); indi_leds_state &= ~(LED_BLINK2<<LED_INDI4); } else if (params.waterTemp > WATER_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI4); indi_leds_state &= ~(LED_BLINK2<<LED_INDI1); } /* Indicator for batt ok */ if (params.batteryV <= VOLTAGE_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI2); indi_leds_state &= ~(LED_BLINK2<<LED_INDI5); } else if (params.batteryV > VOLTAGE_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI5); indi_leds_state &= ~(LED_BLINK2<<LED_INDI2); } /* Indicator for oil pressure ok */ if (params.oilPressure <= OILPRESS_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI3); indi_leds_state &= ~(LED_BLINK2<<LED_INDI6); } else if (params.oilPressure > OILPRESS_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI6); indi_leds_state &= ~(LED_BLINK2<<LED_INDI3); } /* Indicator for Gear */ if (params.GearNeutral < 0) { SEG_N(LED_ON); } else { if (params.GearEst > 6) { SEG_OFF(); } else { switch (params.GearEst) { case 0: SEG_N(LED_ON); break; case 1: SEG_1(LED_ON); break; case 2: SEG_2(LED_ON); break; case 3: SEG_3(LED_ON); break; case 4: SEG_4(LED_ON); break; case 5: SEG_5(LED_ON); break; case 6: SEG_6(LED_ON); break; default: break; } } } /* if (params.GearNeutral == 0) { SEG_OFF(); } else if (params.GearNeutral > 0) { SEG_N(LED_BLINK2); } */ /* Set indicator leds */ set_leds(LED_BUTTONS_ADDR, indi_leds_state); /* itoa(params.batteryV, streng, 10);*/ /* sendtekst(streng);*/ /* sendtekst("\n\r"); */ PORTB ^= (1<<PB6); } return 0; }