void menu_rc_setup(void) { uint8_t cursor = LINE0; uint8_t top = RCSTART; uint8_t temp = 0; int8_t values[RCITEMS]; menu_range_t range; uint8_t i = 0; uint8_t text_link; while(button != BACK) { // Load values from eeprom memcpy(&values[0],&Config.TxSeq,sizeof(int8_t) * RCITEMS); // Print menu print_menu_items(top, RCSTART, &values[0], RCITEMS, (prog_uchar*)rc_menu_ranges, RCOFFSET, (prog_uchar*)RCMenuText, cursor); // Handle menu changes update_menu(RCITEMS, RCSTART, button, &cursor, &top, &temp); range = get_menu_range ((prog_uchar*)rc_menu_ranges, temp - RCSTART); if (button == ENTER) { text_link = pgm_read_byte(&RCMenuText[temp - RCSTART]); values[temp - RCSTART] = do_menu_item(temp, values[temp - RCSTART], range, 0, text_link); } // Update value in config structure memcpy(&Config.TxSeq,&values[0],sizeof(int8_t) * RCITEMS); // Update Ch7. mixer with source from Config.FlapChan if in Aeroplane mode if (Config.MixMode == AEROPLANE) { Config.Channel[CH7].source_a = Config.FlapChan; } if (button == ENTER) { // Update channel sequence for (i = 0; i < MAX_RC_CHANNELS; i++) { if (Config.TxSeq == JRSEQ) { Config.ChannelOrder[i] = pgm_read_byte(&JR[i]); } else if (Config.TxSeq == FUTABASEQ) { Config.ChannelOrder[i] = pgm_read_byte(&FUTABA[i]); } } Save_Config_to_EEPROM(); // Save value and return } } }
void menu_battery(void) { uint8_t cursor = LINE0; uint8_t top = BATTSTART; uint8_t temp = 0; int16_t values[BATTITEMS]; menu_range_t range; uint8_t text_link = 0; uint8_t temp_cells = 0; uint16_t temp_minvoltage = 0; while(button != BACK) { // Load values from eeprom memcpy(&values[0],&Config.BatteryType,sizeof(int16_t) * BATTITEMS); // Save pre-edited values temp_cells = Config.BatteryCells; temp_minvoltage = Config.MinVoltage; // Print menu print_menu_items_16(top, BATTSTART, &values[0], (prog_uchar*)batt_menu_ranges, BATTOFFSET, (prog_uchar*)BattMenuText, cursor); // Handle menu changes update_menu(BATTITEMS, BATTSTART, button, &cursor, &top, &temp); range = get_menu_range ((prog_uchar*)batt_menu_ranges, temp - BATTSTART); if (button == ENTER) { text_link = pgm_read_byte(&BattMenuText[temp - BATTSTART]); values[temp - BATTSTART] = do_menu_item(temp, values[temp - BATTSTART], range, 0, text_link); } // See if cell number or min_volts has changed if ((temp_cells != values[1]) || (temp_minvoltage != values[4])) { values[2] = values[1] * values[4]; Config.PowerTrigger = values[2]; } // Update value in config structure memcpy(&Config.BatteryType,&values[0],sizeof(int16_t) * BATTITEMS); if (button == ENTER) { Save_Config_to_EEPROM(); // Save value and return } } }
void menu_mixer(uint8_t i) { uint8_t cursor = LINE0; uint8_t top = MIXERSTART; int8_t values[MIXERITEMS]; menu_range_t range; uint8_t temp = 0; uint8_t text_link = 0; while(button != BACK) { // Load values from eeprom memcpy(&values[0],&Config.Channel[i].source_a,sizeof(int8_t) * MIXERITEMS); // Print menu print_menu_items(top, MIXERSTART, &values[0], MIXERITEMS,(prog_uchar*)mixer_menu_ranges, MIXOFFSET, (prog_uchar*)MixerMenuText, cursor); // Handle menu changes update_menu(MIXERITEMS, MIXERSTART, button, &cursor, &top, &temp); range = get_menu_range ((prog_uchar*)mixer_menu_ranges, temp - MIXERSTART); if (button == ENTER) { text_link = pgm_read_byte(&MixerMenuText[temp - MIXERSTART]); values[temp - MIXERSTART] = do_menu_item(temp, values[temp - MIXERSTART], range, 0, text_link); } // Update value in config structure memcpy(&Config.Channel[i].source_a,&values[0],sizeof(int8_t) * MIXERITEMS); if (button == ENTER) { UpdateLimits(); // Update travel limits based on percentages Save_Config_to_EEPROM(); // Save value and return } } menu_beep(1); _delay_ms(200); }
void menu_al_control(void) { uint8_t cursor = LINE0; uint8_t top = AUTOSTART; uint8_t temp = 0; int8_t values[AUTOITEMS]; menu_range_t range; uint8_t text_link = 0; while(button != BACK) { // Load values from eeprom memcpy(&values[0],&Config.AutoMode,sizeof(int8_t) * AUTOITEMS); // Print menu print_menu_items(top, AUTOSTART, &values[0], AUTOITEMS, (prog_uchar*)auto_menu_ranges, AUTOOFFSET, (prog_uchar*)AutoMenuText, cursor); // Handle menu changes update_menu(AUTOITEMS, AUTOSTART, button, &cursor, &top, &temp); range = get_menu_range ((prog_uchar*)auto_menu_ranges, temp - AUTOSTART); if (button == ENTER) { text_link = pgm_read_byte(&AutoMenuText[temp - AUTOSTART]); values[temp - AUTOSTART] = do_menu_item(temp, values[temp - AUTOSTART], range, 0, text_link); } // Update value in config structure memcpy(&Config.AutoMode,&values[0],sizeof(int8_t) * AUTOITEMS); if (button == ENTER) { UpdateLimits(); // Update I-term limits and triggers based on percentages Save_Config_to_EEPROM(); // Save value and return } } }
void menu_mixer(uint8_t section) { static uint8_t mix_top = MIXERSTART; static uint8_t old_section; int8_t *value_ptr; int8_t values[INPUTITEMS+1]; menu_range_t range; uint8_t text_link = 0; uint8_t offset; // Index into channel structure uint8_t items; // Items in group // If submenu item has changed, reset submenu positions if (section != old_section) { mix_top = MIXERSTART; old_section = section; } // Get mixer menu offsets // 1 = input mixer data, 2 = output mixer data switch(section) { case 1: items = INPUTITEMS+1; offset = 0; value_ptr = &values[0]; break; case 2: items = OUTPUTITEMS+1; offset = INPUTITEMS+1; value_ptr = &values[0]; break; default: items = INPUTITEMS+1; offset = 0; value_ptr = &values[0]; break; } while(button != BACK) { // Load values from eeprom and insert channel number at the top of each - messy values[0] = Config.MenuChannel; if (section == 1) { memcpy(&values[1],&Config.Channel[Config.MenuChannel].source_a,(sizeof(int8_t) * INPUTITEMS)); } else { memcpy(&values[1],&Config.Channel[Config.MenuChannel].switcher,(sizeof(int8_t) * OUTPUTITEMS)); } // Print menu print_menu_items(mix_top + offset, MIXERSTART + offset, value_ptr, 1, (prog_uchar*)mixer_menu_ranges[section - 1], 0, MIXOFFSET, (prog_uchar*)MixerMenuText[section - 1], cursor); // Handle menu changes update_menu(items, MIXERSTART, offset, button, &cursor, &mix_top, &menu_temp); range = get_menu_range ((prog_uchar*)mixer_menu_ranges[section - 1], menu_temp - MIXERSTART - offset); if (button == ENTER) { text_link = pgm_read_byte(&MixerMenuText[section - 1][menu_temp - MIXERSTART - offset]); do_menu_item(menu_temp, value_ptr + (menu_temp - MIXERSTART - offset), 1, range, 0, text_link, false, 0); } // Save modified data back to Config // Copy channel number back to global switch(section) { case 1: memcpy(&Config.Channel[Config.MenuChannel].source_a,&values[1],(sizeof(int8_t) * INPUTITEMS)); Config.MenuChannel = values[0]; break; case 2: memcpy(&Config.Channel[Config.MenuChannel].switcher,&values[1],(sizeof(int8_t) * OUTPUTITEMS)); Config.MenuChannel = values[0]; break; default: break; } // Save and exit if (button == ENTER) { UpdateLimits(); // Update travel limits based on percentages Save_Config_to_EEPROM(); // Save value and return } } _delay_ms(200); }
void menu_rc_setup(uint8_t section) { int8_t *value_ptr; menu_range_t range; uint8_t text_link; uint8_t i = 0; uint8_t mult = 1; // Multiplier uint8_t offset; // Index into channel structure uint8_t items; // Items in group // If submenu item has changed, reset submenu positions if (menu_flag) { sub_top = RCSTART; menu_flag = 0; } while(button != BACK) { // Get menu offsets and load values from eeprom // 1 = RC, 2 = Failsafe, 3 = General switch(section) { case 1: // RC setup menu offset = 0; items = RCITEMS; value_ptr = &Config.RxModeIn; mult = 1; break; case 2: // Failsafe menu offset = RCITEMS; items = FSITEMS; value_ptr = &Config.FailsafeType; mult = 1; break; case 3: // General menu offset = RCITEMS + FSITEMS; items = GENERALITEMS; value_ptr = &Config.MixMode; mult = 1; break; default: offset = 0; items = RCITEMS; value_ptr = &Config.RxModeIn; mult = 1; break; } // Save pre-edited values int8_t temp_type = Config.MixMode; int8_t temp_flapchan = Config.FlapChan; int8_t temp_RxModeIn = Config.RxModeIn; // Print menu print_menu_items(sub_top + offset, RCSTART + offset, value_ptr, mult, (const unsigned char*)rc_menu_ranges[section - 1], 0, RCOFFSET, (const unsigned char*)RCMenuText[section - 1], cursor); // Handle menu changes update_menu(items, RCSTART, offset, button, &cursor, &sub_top, &menu_temp); range = get_menu_range ((const unsigned char*)rc_menu_ranges[section - 1], (menu_temp - RCSTART - offset)); if (button == ENTER) { text_link = pgm_read_byte(&RCMenuText[section - 1][menu_temp - RCSTART - offset]); do_menu_item(menu_temp, value_ptr + (menu_temp - RCSTART - offset), mult, range, 0, text_link, false, 0); } if (button == ENTER) { // Update Ch5. mixer with source from Config.FlapChan if in Aeroplane mode and source changed if ((Config.MixMode == AEROPLANE) && (Config.FlapChan != temp_flapchan)) { Config.Channel[CH5].source_a = Config.FlapChan; } // Reset serial in channel masks every time the input type is changed if (temp_RxModeIn != Config.RxModeIn) { Xtreme_Chanmask = 0; Xtreme_RSS = 0; Spektrum_Chanmask_0 = 0; Spektrum_Chanmask_1 = 0; Spektrum_frameloss = 0; SBUS_Flags = 0; // Clear channel data for (i = 0; i < MAX_RC_CHANNELS; i++) { RxChannel[i] = 0; // Unused Spektrum channels set to NULL if (Config.RxModeOut == SPEKTRUM) { ExtChannel[i] = 0xFFFF; } // Unused channels set to mid-way else if (Config.RxModeOut == SBUS) { ExtChannel[i] = 0x400; } // Xtreme doesn't care else { ExtChannel[i] = 0; } } } // If model type has changed, reload preset if ((section == 3) && (temp_type != Config.MixMode)) { switch(Config.MixMode) // Load selected mix { case AEROPLANE: get_preset_mix(AEROPLANE_MIX); break; case FWING: get_preset_mix(FLYING_WING_MIX); break; case MANUAL: // Clear all channel info memset(&Config.Channel[0].value,0,(sizeof(channel_t) * MAX_OUTPUTS)); // Preset important settings for (i = 0; i < MAX_OUTPUTS; i++) { Config.Channel[i].source_a = i; // Set to mirror the inputs Config.Channel[i].source_a_volume = 100; Config.Channel[i].source_b = NOCHAN; Config.Channel[i].output_b = UNUSED; Config.Channel[i].output_c = UNUSED; } break; default: break; } } init_int(); // In case RC type has changed, reinitialise interrupts init_uart(); // and UART UpdateLimits(); // Update I-term limits and triggers based on percentages #ifdef KK21 // Update MPU6050 LPF writeI2Cbyte(MPU60X0_DEFAULT_ADDRESS, MPU60X0_RA_CONFIG, (6 - Config.MPU6050_LPF)); #endif // Update channel sequence for (i = 0; i < MAX_RC_CHANNELS; i++) { if (Config.TxSeq == FUTABASEQ) { Config.ChannelOrder[i] = pgm_read_byte(&FUTABA[i]); } else { Config.ChannelOrder[i] = pgm_read_byte(&JR[i]); } } Save_Config_to_EEPROM(); // Save value and return Wait_BUTTON4(); // Wait for user's finger off the button } } }
void menu_rc_setup(uint8_t section) { static uint8_t rc_top = RCSTART; int8_t *value_ptr; menu_range_t range; uint8_t text_link; uint8_t i = 0; uint8_t mult = 1; // Multiplier uint8_t offset; // Index into channel structure uint8_t items; // Items in group uint16_t temp16_1; // If submenu item has changed, reset submenu positions if (menu_flag) { rc_top = RCSTART; menu_flag = 0; } while(button != BACK) { // Get menu offsets and load values from eeprom // 1 = RC, 2 = Failsafe, 3 = General, 4 = Battery switch(section) { case 1: // RC setup menu offset = 0; items = RCITEMS; value_ptr = &Config.RxMode; mult = 1; break; case 2: // Failsafe menu offset = RCITEMS; items = FSITEMS; value_ptr = &Config.FailsafeType; mult = 1; break; case 3: // General menu offset = RCITEMS + FSITEMS; items = GENERALITEMS; value_ptr = &Config.MixMode; mult = 1; break; case 4: // Battery menu offset = RCITEMS + FSITEMS + GENERALITEMS; items = BATTITEMS; value_ptr = &Config.BatteryType; mult = 4; break; default: offset = 0; items = RCITEMS; value_ptr = &Config.RxMode; mult = 1; break; } // Save pre-edited values int8_t temp_type = Config.MixMode; int8_t temp_cells = Config.BatteryCells; int8_t temp_minvoltage = Config.MinVoltage; int8_t temp_flapchan = Config.FlapChan; // Print menu print_menu_items(rc_top + offset, RCSTART + offset, value_ptr, mult, (prog_uchar*)rc_menu_ranges[section - 1], 0, RCOFFSET, (prog_uchar*)RCMenuText[section - 1], cursor); // Handle menu changes update_menu(items, RCSTART, offset, button, &cursor, &rc_top, &menu_temp); range = get_menu_range ((prog_uchar*)rc_menu_ranges[section - 1], (menu_temp - RCSTART - offset)); if (button == ENTER) { text_link = pgm_read_byte(&RCMenuText[section - 1][menu_temp - RCSTART - offset]); do_menu_item(menu_temp, value_ptr + (menu_temp - RCSTART - offset), mult, range, 0, text_link, false, 0); } if (button == ENTER) { // Update Ch7. mixer with source from Config.FlapChan if in Aeroplane mode and source changed if ((Config.MixMode == AEROPLANE) && (Config.FlapChan != temp_flapchan)) { Config.Channel[CH7].source_a = Config.FlapChan; } // See if cell number or min_volts has changed if ((temp_cells != Config.BatteryCells) || (temp_minvoltage != Config.MinVoltage)) { // Recalculate if more cells temp16_1 = Config.MinVoltage; temp16_1 = temp16_1 * Config.BatteryCells; temp16_1 = temp16_1 / 10; Config.PowerTrigger = (int8_t)temp16_1; } // If model type has changed, reload preset if ((section == 3) && (temp_type != Config.MixMode)) { switch(Config.MixMode) // Load selected mix { case AEROPLANE: get_preset_mix(AEROPLANE_MIX); break; case FWING: get_preset_mix(FLYING_WING_MIX); break; case CAMSTAB: get_preset_mix(CAM_STAB); break; case MANUAL: // Clear all channel info memset(&Config.Channel[0].value,0,(sizeof(channel_t) * PSUEDO_OUTPUTS)); // Preset important settings for (i = 0; i < PSUEDO_OUTPUTS; i++) { Config.Channel[i].source_a = NOCHAN; Config.Channel[i].source_b = NOCHAN; Config.Channel[i].output_b = UNUSED; Config.Channel[i].output_c = UNUSED; Config.Channel[i].output_d = UNUSED; } break; default: break; } } init_int(); // In case RC type has changed, reinitialise interrupts init_uart(); // and UART UpdateIMUvalues(); // Update IMU variables UpdateLimits(); // Update I-term limits and triggers based on percentages #ifdef KK21 // Update MPU6050 LPF writeI2Cbyte(MPU60X0_DEFAULT_ADDRESS, MPU60X0_RA_CONFIG, Config.MPU6050_LPF); #endif // Update channel sequence for (i = 0; i < MAX_RC_CHANNELS; i++) { if (Config.TxSeq == FUTABASEQ) { Config.ChannelOrder[i] = (uint8_t)pgm_read_byte(&FUTABA[i]); } else { Config.ChannelOrder[i] = (uint8_t)pgm_read_byte(&JR[i]); } } Save_Config_to_EEPROM(); // Save value and return } } }
void menu_servo_setup(uint8_t section) { int8_t *value_ptr = &Config.Servo_reverse[0]; menu_range_t range; uint8_t text_link; uint8_t i = 0; bool servo_enable = false; bool zero_setting = false; // If submenu item has changed, reset submenu positions if (menu_flag) { sub_top = SERVOSTART; menu_flag = 0; } // Get menu offsets // 1 = Reverse, 2 = Min, 3 = Max while(button != BACK) { // Load values from eeprom for (i = 0; i < SERVOITEMS; i++) { switch(section) { case 1: break; case 2: value_ptr = &Config.min_travel[0]; servo_enable = true; zero_setting = true; break; case 3: value_ptr = &Config.max_travel[0]; servo_enable = true; zero_setting = true; break; default: break; } } // Print menu print_menu_items(sub_top, SERVOSTART, value_ptr, 1, (const unsigned char*)servo_menu_ranges[section - 1], 1, SERVOOFFSET, (const unsigned char*)ServoMenuText[section - 1], cursor); // Handle menu changes update_menu(SERVOITEMS, SERVOSTART, 0, button, &cursor, &sub_top, &menu_temp); range = get_menu_range ((const unsigned char*)servo_menu_ranges[section - 1], 0); if (button == ENTER) { text_link = pgm_read_byte(&ServoMenuText[section - 1][menu_temp - SERVOSTART]); // Zero limits if adjusting if (zero_setting) { value_ptr[menu_temp - SERVOSTART] = 0; } // Do not allow servo enable for throttle if in CPPM mode if ((Config.Channel[menu_temp - SERVOSTART].P1_source_a == THROTTLE) && (Config.RxMode == CPPM_MODE)) { servo_enable = false; } do_menu_item(menu_temp, value_ptr + (menu_temp - SERVOSTART), 1, range, 0, text_link, servo_enable, (menu_temp - SERVOSTART)); } // Disable servos servo_enable = false; if (button == ENTER) { UpdateLimits(); // Update actual servo trims Save_Config_to_EEPROM(); // Save value and return } } }
void menu_flight(uint8_t mode) { int8_t *value_ptr; menu_range_t range; uint8_t text_link; int8_t temp_gyro_roll = 0; int8_t temp_gyro_pitch = 0; int8_t temp_gyro_yaw = 0; // If submenu item has changed, reset submenu positions if (menu_flag) { sub_top = FLIGHTSTART; menu_flag = 0; } while(button != BACK) { value_ptr = &Config.FlightMode[mode-1].StabMode; // Save pre-edited value for gyro types temp_gyro_roll = Config.FlightMode[mode - 1].Roll_type; temp_gyro_pitch = Config.FlightMode[mode - 1].Pitch_type; temp_gyro_yaw = Config.FlightMode[mode - 1].Yaw_type; // Print menu print_menu_items(sub_top, FLIGHTSTART, value_ptr, 1, (const unsigned char*)flight_menu_ranges, 0, FLIGHTOFFSET, (const unsigned char*)FlightMenuText, cursor); // Handle menu changes update_menu(FLIGHTITEMS, FLIGHTSTART, 0, button, &cursor, &sub_top, &menu_temp); range = get_menu_range ((const unsigned char*)flight_menu_ranges, (menu_temp - FLIGHTSTART)); if (button == ENTER) { text_link = pgm_read_byte(&FlightMenuText[menu_temp - FLIGHTSTART]); do_menu_item(menu_temp, value_ptr + (menu_temp - FLIGHTSTART), 1, range, 0, text_link, false, 0); } // Preset I-limits when gyro mode changes if (button == ENTER) { // If roll gyro type has changed, reset to an appropriate start point if (temp_gyro_roll != Config.FlightMode[mode-1].Roll_type) { // Use Gyro type value to preset limits if(Config.FlightMode[mode-1].Roll_type == LOCK) { Config.FlightMode[mode - 1].Roll_limit = 125; } else { Config.FlightMode[mode - 1].Roll_limit = 0; } } if (temp_gyro_pitch != Config.FlightMode[mode-1].Pitch_type) { if(Config.FlightMode[mode-1].Pitch_type == LOCK) { Config.FlightMode[mode - 1].Pitch_limit = 125; } else { Config.FlightMode[mode - 1].Pitch_limit = 0; } } if (temp_gyro_yaw != Config.FlightMode[mode-1].Yaw_type) { if(Config.FlightMode[mode-1].Yaw_type == LOCK) { Config.FlightMode[mode - 1].Yaw_limit = 125; } else { Config.FlightMode[mode - 1].Yaw_limit = 0; } } UpdateLimits(); // Update I-term limits and triggers based on percentages Save_Config_to_EEPROM(); // Save value and return Wait_BUTTON4(); // Wait for user's finger off the button } } }