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);
}
Example #3
0
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;
}
Example #6
0
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;
}