void menu_main(void) { static uint8_t main_cursor = LINE0; // These are now static so as to remember the main menu position static uint8_t main_temp = 0; static uint8_t old_menu = 0; button = NONE; // Wait until user's finger is off button 1 Wait_BUTTON1(); while(button != BACK) { // Clear buffer before each update clear_buffer(buffer); // Print menu print_menu_frame(0); // Frame for (uint8_t i = 0; i < 4; i++) { LCD_Display_Text(main_top+i,(const unsigned char*)Verdana8,ITEMOFFSET,(uint8_t)pgm_read_byte(&lines[i])); // Lines } print_cursor(main_cursor); // Cursor write_buffer(buffer,1); // Poll buttons when idle poll_buttons(true); // Handle menu changes update_menu(MAINITEMS, MAINSTART, 0, button, &main_cursor, &main_top, &main_temp); // If main menu item has changed, reset sub-menu positions // and flag to sub-menus that positions need to be reset if (main_temp != old_menu) { cursor = LINE0; menu_temp = 0; old_menu = main_temp; menu_flag = 1; } // If ENTER pressed, jump to menu if (button == ENTER) { do_main_menu_item(main_temp); button = NONE; // Wait until user's finger is off button 1 Wait_BUTTON1(); } } }
//********************************************************************** // Print menu items primary subroutine // // Usage: // top = position in submenu list // start = start of submenu text list. (top - start) gives the offset into the list. // values = pointer to array of values to change // multiplier = display/actual if type = 2, otherwise defaults to 1 // menu_ranges = pointer to array of min/max/inc/style/defaults // rangetype = unique (0) all values are different, copied (1) all values are the same // MenuOffsets = originally an array, now just a fixed horizontal offset for the value text // text_link = pointer to the text list for the values if not numeric // cursor = cursor position //********************************************************************** void print_menu_items(uint8_t top, uint8_t start, int8_t values[], uint8_t mult, prog_uchar* menu_ranges, uint8_t rangetype, uint8_t MenuOffsets, prog_uchar* text_link, uint8_t cursor) { menu_range_t range1; uint8_t multiplier; // Clear buffer before each update clear_buffer(buffer); print_menu_frame(0); // Print each line for (uint8_t i = 0; i < 4; i++) { LCD_Display_Text(top+i,(prog_uchar*)Verdana8,ITEMOFFSET,(uint8_t)pgm_read_byte(&lines[i])); // Handle unique or copied ranges (to reduce space) if (rangetype == 0) { // Use each unique entry memcpy_P(&range1, &menu_ranges[(top+i - start)* sizeof(range1)], sizeof(range1)); } else { // Use just the first entry in array for all memcpy_P(&range1, &menu_ranges[0], sizeof(range1)); } if (range1.style == 2) { multiplier = mult; } else { multiplier = 1; } print_menu_text((values[top+i - start] * multiplier), range1.style, (pgm_read_byte(&text_link[top+i - start]) + values[top+i - start]), MenuOffsets, (uint8_t)pgm_read_byte(&lines[i])); } print_cursor(cursor); // Cursor write_buffer(buffer,1); poll_buttons(true); }
void menu_main(void) { static uint8_t cursor = LINE0; // These are now static so as to remember the menu position static uint8_t top = MAINSTART; static uint8_t temp = 0; button = NONE; // Wait until user's finger is off button 1 while(BUTTON1 == 0) { _delay_ms(50); } while(button != BACK) { // Clear buffer before each update clear_buffer(buffer); // Print menu print_menu_frame(0); // Frame LCD_Display_Text(top,(prog_uchar*)Verdana8,ITEMOFFSET,LINE0); // First line LCD_Display_Text(top+1,(prog_uchar*)Verdana8,ITEMOFFSET,LINE1); // Second line LCD_Display_Text(top+2,(prog_uchar*)Verdana8,ITEMOFFSET,LINE2); // Third line LCD_Display_Text(top+3,(prog_uchar*)Verdana8,ITEMOFFSET,LINE3); // Fourth line print_cursor(cursor); // Cursor write_buffer(buffer,1); // Poll buttons when idle poll_buttons(); // Handle menu changes update_menu(MAINITEMS, MAINSTART, button, &cursor, &top, &temp); if (button == ENTER) { do_main_menu_item(temp); button = NONE; } } menu_beep(1); _delay_ms(200); }
int main(void) { CPU_PRESCALE(0); setup(); while (TRUE) { if (_override) { if (_latch) shift_sequence(); } else { CLRBIT(PORTB, OVERRIDE); char pina = poll_buttons(PINA); if (ISSET(pina, BTN1)) { _override = TRUE; setup_move(&seq, DFP); } else if (ISSET(pina, BTN2)) { _override = TRUE; setup_move(&seq, BDK); } else if (ISSET(pina, BTN3)) { _override = TRUE; setup_move(&seq, FDFP); } else if (ISSET(pina, BTN4)) { _override = TRUE; setup_move(&seq, BDFP); }else if (ISSET(pina, DIR_CONTROL)) { if (dir == RIGHT_DIR) dir = LEFT_DIR; else dir = RIGHT_DIR; } _delay_ms(1); } } }
void do_menu_item(uint8_t menuitem, int8_t *values, uint8_t mult, menu_range_t range, int8_t offset, uint8_t text_link, bool servo_enable, int16_t servo_number) { mugui_size16_t size; int16_t temp16; int8_t i; int16_t value = (int8_t)*values; uint8_t display_update = 0; uint8_t servo_update = 0; uint8_t button_update = 0; uint8_t button_inc = 0; bool button_lock = false; bool first_time = true; // Multiply value for display only if style is 2 if (range.style == 2) { value = value * mult; } else mult = 1; button = NONE; // Reset servo to neutral unless it is for the throttle channel in CPPM mode if (servo_enable && !((Config.Channel[servo_number].source_a == THROTTLE) && (Config.RxMode == CPPM_MODE))) { temp16 = Config.Limits[servo_number].trim; temp16 = ((temp16 << 2) / 10); // Span back to what the output wants // Give servos time to settle for (i = 0; i < 25; i++) { cli(); output_servo_ppm_asm3(servo_number, temp16); sei(); _delay_ms(10); } } // This is a loop that cycles until Button 4 is pressed (Save) // The GLCD updating slows servo updates down too much so only update the GLCD periodically // When not updating the GLCD the servo should be updated at 50Hz (20ms) while (button != ENTER) { // Increment loopcount so that we can time various things display_update++; servo_update++; // Vary the button increment delay depending on the function if (servo_enable) { button_inc = 20; // For servos } else { button_inc = 1; // For everything else } // Increment button timer when pressed if (button != NONE) { button_update++; // Release button lock after button_inc loops if (button_update > button_inc) { button_lock = false; button_update = 0; } } // Remove lock when not pressed else { button_update = 0; button_lock = false; } // Display update if (!servo_enable || // Non-servo value or ((display_update >= 32) && (button != NONE)) || // Servo value and 32 cycles passed but only with a button pressed or... (first_time)) // First time into routine { display_update = 0; first_time = false; clear_buffer(buffer); // Print title gLCDprint_Menu_P((char*)pgm_read_word(&text_menu[menuitem]), (prog_uchar*)Verdana14, 0, 0); // Print value if ((range.style == 0) || (range.style == 2)) // numeric and numeric * 4 { // Write numeric value, centered on screen mugui_text_sizestring(itoa(value,pBuffer,10), (prog_uchar*)Verdana14, &size); mugui_lcd_puts(itoa(value,pBuffer,10),(prog_uchar*)Verdana14,((128-size.x)/2)+offset,25); } else // text { // Write text, centered on screen pgm_mugui_scopy((char*)pgm_read_word(&text_menu[text_link + value])); // Copy string to pBuffer mugui_text_sizestring((char*)pBuffer, (prog_uchar*)Verdana14, &size); LCD_Display_Text(text_link + value, (prog_uchar*)Verdana14,((128-size.x)/2),25); } // Print bottom markers print_menu_frame(1); // Write from buffer write_buffer(buffer,1); } // Poll buttons when idle // Don't use button acceleration when moving servos // And don't block the code with poll_buttons() if (servo_enable) { button = (PINB & 0xf0); button_multiplier = 1; } else { poll_buttons(true); } // Handle cursor Up/Down limits if (button == DOWN) { if (button_lock == false) { button_lock = true; value = value - (range.increment * button_multiplier); button_update = 0; } } if (button == UP) { if (button_lock == false) { button_lock = true; value = value + (range.increment * button_multiplier); button_update = 0; } } if (button == BACK) { value = (range.default_value * mult); } // Limit values to set ranges if (value < (range.lower * mult)) { value = range.lower * mult; } if (value > (range.upper * mult)) { value = range.upper * mult; } // Update contrast setting if (menuitem == CONTRAST) { st7565_set_brightness(value); // debug } // Set servo position if required and update every 4 * 5ms = 20ms if ((servo_enable) && (servo_update >= 4)) { servo_update = 0; temp16 = scale_percent(value); // Convert to servo position (from %) temp16 = (((temp16 << 2) + (int16_t)5) / (int16_t)10); // Span back to what the output wants cli(); output_servo_ppm_asm3(servo_number, temp16); sei(); } // Loop rate = 5ms (200Hz) _delay_ms(5); } // while (button != ENTER) // Exit button = ENTER; // Divide value from that displayed if style = 2 if (range.style == 2) { value = value / mult; } *values = (int8_t)value; }
int main() { uint8_t index; uint8_t menulen; uint8_t button_pressed = UINT8_MAX - 1; uint16_t i; uint8_t pass_len; //Since we are waiting indefinitely for input from keyboard, //the watchdog is not applicable anymore //wdt_enable(WDTO_1S); // enable 1s watchdog timer init(); for (i = 0; i < sizeof(keyboard_report); i++) // clear report initially ((uchar *) &keyboard_report)[i] = 0; usbDeviceDisconnect(); // enforce re-enumeration for (i = 0; i < 250; i++) { // wait 500 ms //wdt_reset(); _delay_ms(2); } usbDeviceConnect(); // Enable interrupts after re-enumeration sei(); //Enable this to reinitialize passwords/EEPROM //eeprom_write_byte(0,0); pass_no = read_passwords(&passwords); index = 0; mode = MODE_MENU; menulen = MENU_LENGTH; while (1) { //wdt_reset(); // keep the watchdog happy usbPoll(); //Only display stuff if a button was pressed //(most likely something changed on the screen) if (button_pressed != UINT8_MAX) { lcd_clrscr(); if (mode == MODE_MENU) { strcpy_P(stringBuffer, (PGM_P) pgm_read_word(&(menu_items[index]))); lcd_puts(stringBuffer); } else { lcd_puts(passwords[index]); } } button_pressed = poll_buttons(); switch (button_pressed) { case MENU: //Get back to the main menu mode = MODE_MENU; index = 0; menulen = MENU_LENGTH; toggle_led(PB0); break; case CYCLE: //Prepare next item for display if (index < menulen - 1) { lcd_clrscr(); index++; } else { index = 0; } toggle_led(PB0); break; case SELECT: if (mode == MODE_MENU) { //We can add password directly from the MENU mode (main menu) if (index == MODE_ADD) { uint8_t pass_len; pass_len = input_password(); if (pass_len > 0) { stringBuffer[pass_len] = '\0'; passwords = realloc(passwords, (pass_no + 1) * sizeof(char*)); passwords[pass_no] = malloc(pass_len * sizeof(char)); strcpy(passwords[pass_no], stringBuffer); pass_no++; menulen = pass_no; write_passwords(pass_no, passwords); } //Get back to the MENU mode (main menu) mode = MODE_MENU; menulen = MENU_LENGTH; toggle_led(PB0); } else { //Enter the corresponding mode mode = index; index = 0; menulen = pass_no; } } else { //in SEND, REMOVE or CHANGE mode if (index < menulen) { switch (mode) { case MODE_SEND: //Send password to the PC strcpy(stringBuffer, passwords[index]); messagePtr = 0; messageState = STATE_SEND; //Stay in the SEND mode displaying the same password break; case MODE_REMOVE: //Remove password free(passwords[index]); for (i = index; i < pass_no - 1; i++) { passwords[i] = passwords[i + 1]; } pass_no--; passwords = realloc(passwords, pass_no * sizeof(char*)); write_passwords(pass_no, passwords); //Stay in the REMOVE mode, but display the first password index = 0; menulen = pass_no; break; case MODE_CHANGE: pass_len = input_password(); if (pass_len > 0) { stringBuffer[pass_len] = '\0'; passwords[index] = realloc(passwords[index], pass_len); strcpy(passwords[index], stringBuffer); write_passwords(pass_no, passwords); } //Stay in the CHANGE mode, but display the first password index = 0; toggle_led(PB0); break; } } } break; } // characters are sent when messageState == STATE_SEND if (usbInterruptIsReady() && messageState == STATE_SEND) { messageState = buildReport(); usbSetInterrupt((void *) &keyboard_report, sizeof(keyboard_report)); } } return 0; }