// ----------------------------------------------------------------------------- /// @file hwValidationMenu.c /// @brief Description // ----------------------------------------------------------------------------- // Micro-Key bv // Industrieweg 28, 9804 TG Noordhorn // Postbus 92, 9800 AB Zuidhorn // The Netherlands // Tel: +31 594 503020 // Fax: +31 594 505825 // Email: support@microkey.nl // Web: www.microkey.nl // ----------------------------------------------------------------------------- /// $Revision$ /// $Author$ /// $Date$ // (c) 2017 Micro-Key bv // ----------------------------------------------------------------------------- /// @file hwValidationMenu.c /// @ingroup {group_name} // ----------------------------------------------------------------------------- // Include files // ----------------------------------------------------------------------------- #include "hwValidationMenu.h" #include "DisplayDevice.h" #include "gpio.h" #include "internalADC.h" #include "PCBA.h" #include "MAX5715.h" #include "nhd0420.h" #include "Logger.h" #include "keypadMatrix.h" // ----------------------------------------------------------------------------- // Constant and macro definitions // ----------------------------------------------------------------------------- #define MENU_DRAW_SELECTED(index) if( index == self->menuItemSelected ) { menuItems[index] = '*'; } else { menuItems[index] = ' '; } #define CMD_BUFFER_SIZE (10) #define HW_VALIDATION_MENU_DAC_MAX_VALUE (4095) // ----------------------------------------------------------------------------- // Type definitions // ----------------------------------------------------------------------------- typedef enum { CONSOLE_MAIN_MENU, CONSOLE_TEST_POWER, CONSOLE_TEST_DISPLAY, CONSOLE_TEST_ADC, CONSOLE_TEST_DAC, CONSOLE_TEST_INTERLOCK, CONSOLE_TEST_SOLENOID, CONSOLE_TEST_RELAY, CONSOLE_TEST_GENERIC, CONSOLE_IDLE }Menu_States_t; typedef enum { DISPLAY_MENU_MAIN, DISPLAY_MENU_POWER, DISPLAY_MENU_DISPLAY, DISPLAY_MENU_ADC, DISPLAY_MENU_DAC, DISPLAY_MENU_INTERLOCK, DISPLAY_MENU_SOLENOID, DISPLAY_MENU_RELAY, DISPLAY_MENU_GENERIC }Display_States_t; typedef enum { BUTTON_ENTER, BUTTON_UP, BUTTON_DOWN, BUTTON_RIGHT, BUTTON_LEFT, BUTTON_PASSPHRASE }Button_Pressed_t; // ----------------------------------------------------------------------------- // File-scope variables // ----------------------------------------------------------------------------- static const char conInfHeader[] = "*******************************************************************************\r\n" "** Photonis - something **\r\n" "** **\r\n" "*******************************************************************************\r\n" " \r\n"; static const char conInfMainMenu[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " MAIN MENU \r\n" " Select one of the options: \r\n" " [%c] Test Power \r\n" " [%c] Test Display \r\n" " [%c] Test ADCs \r\n" " [%c] Test DACs \r\n" " [%c] Test Interlocks \r\n" " [%c] Test Solenoids \r\n" " [%c] Test relays \r\n" " [%c] Test Keypad/EEPROM/PCB variant \r\n" " \r\n"; enum { MENU_MAIN_POWER, MENU_MAIN_DISPLAY, MENU_MAIN_ADC, MENU_MAIN_DAC, MENU_MAIN_INTERLOCK, MENU_MAIN_SOLENOID, MENU_MAIN_RELAY, MENU_MAIN_GENERIC, MENU_MAIN_LAST }; static const char conTestPower[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST POWER \r\n" " \r\n" " Control the 6V5 power supply \r\n" " \r\n" " [%c] Power on 6V5 \r\n" " [%c] Power off 6V5 \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_POWER_ON, MENU_TEST_POWER_OFF, MENU_TEST_POWER_BACK, MENU_TEST_POWER_LAST }; static const char conTestDisplay[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST Display \r\n" " \r\n" " Test the display and backlight \r\n" " \r\n" " [%c] Set backlight to 10%% \r\n" " [%c] Set backlight to 50%% \r\n" " [%c] Set backlight to 100%% \r\n" " [%c] Show text on display \r\n" " [%c] Clear display content \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_DISPLAY_BL_10, MENU_TEST_DISPLAY_BL_50, MENU_TEST_DISPLAY_BL_100, MENU_TEST_DISPLAY_SHOW_TEXT, MENU_TEST_DISPLAY_CLEAR_DISPLAY, MENU_TEST_DISPLAY_BACK, MENU_TEST_DISPLAY_LAST }; static const char conTestADC[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST ADC[0-2] \r\n" " \r\n" " Test the ADC channel 0-2 \r\n" " \r\n" " [%c] Read channel 0 \r\n" " [%c] Read channel 1 \r\n" " [%c] Read channel 2 \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_ADC_CH_0, MENU_TEST_ADC_CH_1, MENU_TEST_ADC_CH_2, MENU_TEST_ADC_BACK, MENU_TEST_ADC_LAST }; static const char conTestDAC[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST DAC[0-2] \r\n" " \r\n" " Test the DAC channel 0-2 \r\n" " \r\n" " [%c] Set DAC CH0 to 0V \r\n" " [%c] Set DAC CH0 to 1.25V \r\n" " [%c] Set DAC CH0 to 2.5V \r\n" " [%c] Set DAC CH0 to 5.0V \r\n" " [%c] Set DAC CH1 to 0V \r\n" " [%c] Set DAC CH1 to 1.25V \r\n" " [%c] Set DAC CH1 to 2.5V \r\n" " [%c] Set DAC CH1 to 5.0V \r\n" " [%c] Set DAC CH2 to 0V \r\n" " [%c] Set DAC CH2 to 1.25V \r\n" " [%c] Set DAC CH2 to 2.5V \r\n" " [%c] Set DAC CH2 to 5.0V \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_DAC_CH_0_0V0, MENU_TEST_DAC_CH_0_1V25, MENU_TEST_DAC_CH_0_2V5, MENU_TEST_DAC_CH_0_5V0, MENU_TEST_DAC_CH_1_0V0, MENU_TEST_DAC_CH_1_1V25, MENU_TEST_DAC_CH_1_2V5, MENU_TEST_DAC_CH_1_5V0, MENU_TEST_DAC_CH_2_0V0, MENU_TEST_DAC_CH_2_1V25, MENU_TEST_DAC_CH_2_2V5, MENU_TEST_DAC_CH_2_5V0, MENU_TEST_DAC_BACK, MENU_TEST_DAC_LAST }; static const char conTestInterlock[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST Interlock \r\n" " \r\n" " Test the interlock [1-2] \r\n" " \r\n" " [%c] Read Interlock 1 \r\n" " [%c] Read Interlock 2 (Tesla only) \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_INTERLOCK_1, MENU_TEST_INTERLOCK_2, MENU_TEST_INTERLOCK_BACK, MENU_TEST_INTERLOCK_LAST }; static const char conTestSolenoid[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST Solenoid \r\n" " \r\n" " Test the solenoid [1-2] \r\n" " \r\n" " [%c] Toggle Solenoid \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_SOLENOID_TOGGLE, MENU_TEST_SOLENOID_BACK, MENU_TEST_SOLENOID_LAST }; static const char conTestRelays[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST Relays \r\n" " \r\n" " Test the relays [1-6] \r\n" " \r\n" " [%c] Toggle Relay 1 \r\n" " [%c] Toggle Relay 2 \r\n" " [%c] Toggle Relay 3 \r\n" " [%c] Toggle Relay 4 \r\n" " [%c] Toggle Relay 5 \r\n" " [%c] Toggle Relay 6 \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_RELAYS_TOGGLE_1, MENU_TEST_RELAYS_TOGGLE_2, MENU_TEST_RELAYS_TOGGLE_3, MENU_TEST_RELAYS_TOGGLE_4, MENU_TEST_RELAYS_TOGGLE_5, MENU_TEST_RELAYS_TOGGLE_6, MENU_TEST_RELAYS_BACK, MENU_TEST_RELAYS_LAST }; static const char conTestGeneric[] = ANSI_TERMINAL_RESET ANSI_TERMINAL_HOME " TEST KEYPAD/EEPROM/PCB VARIANT \r\n" " \r\n" " Test the relays [1-6] \r\n" " \r\n" " [%c] Read keypad \r\n" " [%c] Test EEPROM \r\n" " [%c] Get PCB variant \r\n" " [%c] Back \r\n" " \r\n"; enum { MENU_TEST_GENERIC_KEYPAD, MENU_TEST_GENERIC_EEPROM, MENU_TEST_GENERIC_PCB_VARIANT, MENU_TEST_GENERIC_BACK, MENU_TEST_GENERIC_LAST }; // ----------------------------------------------------------------------------- // Function declarations // ----------------------------------------------------------------------------- static void hwValidationMenuTask(void *parameters); static void hwValidationMenuSM(struct HwValidationMenu* self, Button_Pressed_t button ); static void hwValidationMenuUpdate( struct HwValidationMenu* self ); static void hwValidationMenuDisplay(struct HwValidationMenu* self, Display_States_t display ); static ErrorStatus hwValidationMenuReceiveMessage(struct HwValidationMenu* self, uint8_t * pData, uint16_t numBytes ); static ErrorStatus hwValidationMenuSetDac(struct HwValidationMenu* self, struct MAX5715_DAC* dac, uint16_t value); // ----------------------------------------------------------------------------- // Function definitions // ----------------------------------------------------------------------------- ErrorStatus HwValidationMenu_construct(struct HwValidationMenu* self, struct IODevice* ioDevice, struct HwValidationMenuItems* testItems, int taskPriority, uint16_t stackSize) { ErrorStatus returnValue = SUCCESS; if (!self->initialized) { self->ioDevice = ioDevice; self->testItems = testItems; self->taskPriority = taskPriority; self->stackSize = stackSize; self->menuItemSelected = 0; if (xTaskCreate(hwValidationMenuTask, (const char*)"HwValidationMenu", self->stackSize, self, self->taskPriority, &self->taskHandle) != pdTRUE) { returnValue = ERROR; LOGGER_ERROR(mainLog, "Starting hw validation menu task failed"); } else { LOGGER_INFO(mainLog, "hw validation menu task started"); } } else { returnValue = ERROR; } return returnValue; } static void hwValidationMenuTask(void *parameters) { struct HwValidationMenu* self = (struct HwValidationMenu*)parameters; while(1) { hwValidationMenuUpdate(self); vTaskDelay(100); } } // catch keyboard input, relay to hwValidationMenuSM() void hwValidationMenuUpdate( struct HwValidationMenu* self ) { uint8_t cmdBuff[CMD_BUFFER_SIZE] = {0}; ErrorStatus returnValue = SUCCESS; // Wait for the first character of an incoming command returnValue = hwValidationMenuReceiveMessage(self, &cmdBuff[0], 1 ); if( returnValue != SUCCESS ) return; // Capture ENTER if( (cmdBuff[0] == '\n') || (cmdBuff[0] == '\r') ) { hwValidationMenuSM(self, BUTTON_ENTER ); } // Capture directional keys else if( cmdBuff[0] == '\e' ) { // wait for 2 more characters returnValue = hwValidationMenuReceiveMessage(self, &cmdBuff[1], 2 ); if( returnValue != SUCCESS ) return; if( cmdBuff[1] != '[' ) return; if( cmdBuff[2] == 'A') // 'e' '[' 'A' { hwValidationMenuSM(self, BUTTON_UP ); } else if( cmdBuff[2] == 'B' ) // 'e' '[' 'B' { hwValidationMenuSM(self, BUTTON_DOWN ); } else if( cmdBuff[2] == 'C' ) // 'e' '[' 'C' { hwValidationMenuSM(self, BUTTON_RIGHT ); } else if( cmdBuff[2] == 'D' ) // 'e' '[' 'D' { hwValidationMenuSM(self, BUTTON_LEFT ); } } // Flush other characters else { ; // do nothing, essentially flush UART buffer } } // traverse menu based on buttons pressed, update console with // selected menu item using hwValidationMenuDisplay() static void hwValidationMenuSM(struct HwValidationMenu* self, Button_Pressed_t button ) { static Menu_States_t menuState = CONSOLE_IDLE; int outputBufferLength = 0; switch( menuState ) { case CONSOLE_IDLE : if( button == BUTTON_ENTER ) { menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } break; case CONSOLE_MAIN_MENU : if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_MAIN_LAST - 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_MAIN_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } else if( button == BUTTON_ENTER ) { // Go to selected menu if( self->menuItemSelected == MENU_MAIN_POWER ) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_POWER; hwValidationMenuDisplay(self, DISPLAY_MENU_POWER ); } else if( self->menuItemSelected == MENU_MAIN_DISPLAY) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_DISPLAY; hwValidationMenuDisplay(self, DISPLAY_MENU_DISPLAY ); } else if( self->menuItemSelected == MENU_MAIN_ADC) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_ADC; hwValidationMenuDisplay(self, DISPLAY_MENU_ADC ); } else if( self->menuItemSelected == MENU_MAIN_DAC ) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_DAC; hwValidationMenuDisplay(self, DISPLAY_MENU_DAC ); } else if( self->menuItemSelected == MENU_MAIN_INTERLOCK ) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_INTERLOCK; hwValidationMenuDisplay(self, DISPLAY_MENU_INTERLOCK ); } else if( self->menuItemSelected == MENU_MAIN_SOLENOID ) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_SOLENOID; hwValidationMenuDisplay(self, DISPLAY_MENU_SOLENOID ); } else if( self->menuItemSelected == MENU_MAIN_RELAY ) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_RELAY; hwValidationMenuDisplay(self, DISPLAY_MENU_RELAY ); } else if( self->menuItemSelected == MENU_MAIN_GENERIC ) { self->menuItemSelected = 0; menuState = CONSOLE_TEST_GENERIC; hwValidationMenuDisplay(self, DISPLAY_MENU_GENERIC ); } } break; case CONSOLE_TEST_POWER: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_POWER_LAST - 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_POWER ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_POWER_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_POWER ); } else if( button == BUTTON_ENTER ) { if( self->menuItemSelected == MENU_TEST_POWER_ON ) { // Turn on 6V5 power ( enable active low ) if(GPIO_setValue(self->testItems->power6v5Enable, false) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Power: Off\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Power: Failure\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_POWER_OFF ) { //Turn on 6V5 power ( enable active low ) if( GPIO_setValue(self->testItems->power6v5Enable, true) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Power: Off\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Power: Failure\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_POWER_BACK ) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; case CONSOLE_TEST_DISPLAY: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_DISPLAY_LAST - 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_DISPLAY ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_DISPLAY_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_DISPLAY ); } else if( button == BUTTON_ENTER ) { if( self->menuItemSelected == MENU_TEST_DISPLAY_BL_10) { // Set display backlight to 10% if( DisplayDevice_setBrightness(self->testItems->display, 1) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Display: bl set to 10%%\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Display: failed to set bl\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_DISPLAY_BL_50 ) { // Set display backlight to 50% if( DisplayDevice_setBrightness(self->testItems->display, 4) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Display: bl set to 50%%\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Display: failed to set bl\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_DISPLAY_BL_100 ) { // Set display backlight to 100% if( DisplayDevice_setBrightness(self->testItems->display, 8) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Display: bl set to 100%%\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Display: failed to set bl\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_DISPLAY_SHOW_TEXT ) { const char buffer[] = "Display Test Text"; if( DisplayDevice_write(self->testItems->display, buffer, sizeof(buffer), 2, 2) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Display: text written\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Display: write failed\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_DISPLAY_CLEAR_DISPLAY ) { // Clear display if( DisplayDevice_clear(self->testItems->display) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Display: cleared\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Display: Clear failed\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_DISPLAY_BACK ) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; // case CONSOLE_TEST_KEYPAD: // outputBufferLength = sprintf(self->outputBuffer, "[TODO] KEYPAD TEST\r\n"); // IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); // // No sub items // // TODO: Implement test // break; case CONSOLE_TEST_ADC: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_ADC_LAST - 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_ADC ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_ADC_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_ADC ); } else if( button == BUTTON_ENTER ) { uint16_t adcValue = 0; if( self->menuItemSelected == MENU_TEST_ADC_CH_0) { if(ADCChannel_read(&self->testItems->internalADC->channel[0], &adcValue) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "ADC0 value:%d\r\n", adcValue); } else { outputBufferLength = sprintf(self->outputBuffer, "ADC0: failed to read\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_ADC_CH_1 ) { if(ADCChannel_read(&self->testItems->internalADC->channel[1], &adcValue) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "ADC1 value:%d\r\n", adcValue); } else { outputBufferLength = sprintf(self->outputBuffer, "ADC1: failed to read\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_ADC_CH_2 ) { if(ADCChannel_read(&self->testItems->internalADC->channel[2], &adcValue) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "ADC2 value:%d\r\n", adcValue); } else { outputBufferLength = sprintf(self->outputBuffer, "ADC2: failed to read\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_ADC_BACK ) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; case CONSOLE_TEST_DAC: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_DAC_LAST - 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_DAC ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_DAC_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_DAC ); } else if( button == BUTTON_ENTER ) { // DAC 0 if( self->menuItemSelected == MENU_TEST_DAC_CH_0_0V0) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[0], 0); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_0_1V25 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[0], HW_VALIDATION_MENU_DAC_MAX_VALUE / 4); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_0_2V5 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[0], HW_VALIDATION_MENU_DAC_MAX_VALUE / 2); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_0_5V0 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[0], HW_VALIDATION_MENU_DAC_MAX_VALUE); } // DAC 1 else if( self->menuItemSelected == MENU_TEST_DAC_CH_1_0V0) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[1], 0); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_1_1V25 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[1], HW_VALIDATION_MENU_DAC_MAX_VALUE / 4); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_1_2V5 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[1], HW_VALIDATION_MENU_DAC_MAX_VALUE / 2); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_1_5V0 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[1], HW_VALIDATION_MENU_DAC_MAX_VALUE); } // DAC 2 else if( self->menuItemSelected == MENU_TEST_DAC_CH_2_0V0) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[2], 0); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_2_1V25 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[2], HW_VALIDATION_MENU_DAC_MAX_VALUE / 4); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_2_2V5 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[2], HW_VALIDATION_MENU_DAC_MAX_VALUE / 2); } else if (self->menuItemSelected == MENU_TEST_DAC_CH_2_5V0 ) { hwValidationMenuSetDac(self, &self->testItems->externalDAC->dac[2], HW_VALIDATION_MENU_DAC_MAX_VALUE); } else if (self->menuItemSelected == MENU_TEST_DAC_BACK) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; case CONSOLE_TEST_INTERLOCK: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_INTERLOCK_LAST- 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_INTERLOCK ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_INTERLOCK_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_INTERLOCK ); } else if( button == BUTTON_ENTER ) { bool value1 = false; bool value2 = false; if( self->menuItemSelected == MENU_TEST_INTERLOCK_1) { if( GPIO_getValue(self->testItems->interlock1, &value1) == SUCCESS && GPIO_getValue(self->testItems->interlock2, &value2) == SUCCESS ){ outputBufferLength = sprintf(self->outputBuffer, "Interlock: NO: %d - NC: %d\r\n", value1, value2); } else { outputBufferLength = sprintf(self->outputBuffer, "Interlock: Failure\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_INTERLOCK_2 ) { if(pcba->pcba == Tesla) { if( GPIO_getValue(self->testItems->tesla1, &value1) == SUCCESS && GPIO_getValue(self->testItems->tesla2, &value2) == SUCCESS ){ outputBufferLength = sprintf(self->outputBuffer, "Interlock (tesla): NO: %d - NC: %d\r\n", value1, value2); } else { outputBufferLength = sprintf(self->outputBuffer, "Interlock: Failure\r\n"); } } else { outputBufferLength = sprintf(self->outputBuffer, "Interlock: Only available on Tesla PCBA\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_INTERLOCK_BACK ) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; case CONSOLE_TEST_SOLENOID: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_SOLENOID_LAST- 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_SOLENOID ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_SOLENOID_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_SOLENOID ); } else if( button == BUTTON_ENTER ) { bool value = false; if( self->menuItemSelected == MENU_TEST_SOLENOID_TOGGLE) { if( GPIO_getValue(self->testItems->solenoid, &value) == SUCCESS) { // Invert current value value = !value; if( GPIO_setValue(self->testItems->solenoid, value) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Solenoid: Toggled\r\n"); } else { outputBufferLength = sprintf(self->outputBuffer, "Solenoid: Failed to set value\r\n"); } } else { outputBufferLength = sprintf(self->outputBuffer, "Solenoid: Failed to get value\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_SOLENOID_BACK ) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; case CONSOLE_TEST_RELAY: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_RELAYS_LAST- 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_RELAY ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_RELAYS_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_RELAY ); } else if( button == BUTTON_ENTER ) { struct Gpio* relay = NULL; bool value = false; if( (self->menuItemSelected >= MENU_TEST_RELAYS_TOGGLE_1) && (self->menuItemSelected <= MENU_TEST_RELAYS_TOGGLE_6) ) { switch(self->menuItemSelected) { case MENU_TEST_RELAYS_TOGGLE_1: relay = self->testItems->mcp0Relay; break; case MENU_TEST_RELAYS_TOGGLE_2: relay = self->testItems->mcp1Relay; break; case MENU_TEST_RELAYS_TOGGLE_3: relay = self->testItems->mcp2Relay; break; case MENU_TEST_RELAYS_TOGGLE_4: relay = self->testItems->cat0Relay; break; case MENU_TEST_RELAYS_TOGGLE_5: relay = self->testItems->cat1Relay; break; case MENU_TEST_RELAYS_TOGGLE_6: relay = self->testItems->cat2Relay; break; default: relay = NULL; break; } if( GPIO_getValue(relay, &value) == SUCCESS ) { value = !value; if(GPIO_setValue(relay, value) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "Relay: set value to: %d\r\n", value); } else { outputBufferLength = sprintf(self->outputBuffer, "Relay: Failed to set value\r\n"); } } else { outputBufferLength = sprintf(self->outputBuffer, "Relay: Failed to get current value\r\n"); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_RELAYS_BACK ) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; // case CONSOLE_TEST_PCB_VARIANT: // if(self->testItems->pcba) // { // const struct Pcba* pcba = self->testItems->pcba; // outputBufferLength = sprintf(self->outputBuffer, "PCBA: %d - %s\r\n", (int)pcba->pcba, pcba->name); // } // IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); // break; // case CONSOLE_TEST_EEPROM: // // No sub test // //TODO: implement test // outputBufferLength = sprintf(self->outputBuffer, "[TODO] EEPROM TEST\r\n"); // IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); // break; case CONSOLE_TEST_GENERIC: if( button == BUTTON_UP ) { if( self->menuItemSelected == 0 ) self->menuItemSelected = (MENU_TEST_GENERIC_LAST- 1); else self->menuItemSelected--; hwValidationMenuDisplay(self, DISPLAY_MENU_GENERIC ); } else if( button == BUTTON_DOWN ) { if( self->menuItemSelected == (MENU_TEST_GENERIC_LAST - 1) ) self->menuItemSelected = 0; else self->menuItemSelected++; hwValidationMenuDisplay(self, DISPLAY_MENU_GENERIC ); } else if( button == BUTTON_ENTER ) { if( self->menuItemSelected == MENU_TEST_GENERIC_KEYPAD) { char key; Keypad_KeyState keyState; char data[CMD_BUFFER_SIZE] = {0}; size_t actualLength; char buffer[sizeof(struct KeypadQueueItem) / sizeof(char)]; ErrorStatus returnValueKeypad = SUCCESS; outputBufferLength = sprintf(self->outputBuffer, "Keypad test started. Press Esc to stop this test.\r\n"); IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); while( 1 ) { IODevice_read(self->ioDevice, data, 1, &actualLength); // Check if ESC has been pressed if(actualLength == 1 && data[0] == 0x1B) { break; } if(self->testItems->keypad == NULL){ outputBufferLength = sprintf(self->outputBuffer, "Keypad not initialized\r\n"); IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); break; } returnValueKeypad = IODevice_read(&self->testItems->keypad->device, buffer, sizeof(struct KeypadQueueItem) / sizeof(char), &actualLength); if (returnValueKeypad == SUCCESS) { struct KeypadQueueItem* rxQueueItem = (struct KeypadQueueItem*)buffer; keyState = rxQueueItem->keyEvent; if(keyState == RELEASED){ outputBufferLength = sprintf(self->outputBuffer, "KEYPAD: Pressed %d-%d\r\n", rxQueueItem->rowCoordinate, rxQueueItem->columnCoordinate); } else { outputBufferLength = sprintf(self->outputBuffer, "KEYPAD: Released %d-%d\r\n", rxQueueItem->rowCoordinate, rxQueueItem->columnCoordinate); } } else { outputBufferLength = sprintf(self->outputBuffer, "KEYPAD: Read error\r\n"); } } outputBufferLength = sprintf(self->outputBuffer, "Keypad test exited\r\n"); IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if( self->menuItemSelected == MENU_TEST_GENERIC_EEPROM) { outputBufferLength = sprintf(self->outputBuffer, "[TODO] EEPROM TEST\r\n"); IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if( self->menuItemSelected == MENU_TEST_GENERIC_PCB_VARIANT) { if(self->testItems->pcba) { const struct Pcba* pcba = self->testItems->pcba; outputBufferLength = sprintf(self->outputBuffer, "PCBA: %d - %s\r\n", (int)pcba->pcba, pcba->name); } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); } else if (self->menuItemSelected == MENU_TEST_GENERIC_BACK ) { // Back to main menu self->menuItemSelected = 0; menuState = CONSOLE_MAIN_MENU; hwValidationMenuDisplay(self, DISPLAY_MENU_MAIN ); } } break; default: // Do not so much break; } } // render current menu items static void hwValidationMenuDisplay(struct HwValidationMenu* self, Display_States_t display ) { uint8_t menuIndex; char menuItems[ CON_INF_MAX_MENU_ITEMS ]; int menu_length = 0; switch( display ) { case DISPLAY_MENU_MAIN : // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_MAIN_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char menuBuffer[ sizeof( conInfMainMenu ) ]; menu_length = sprintf( menuBuffer, conInfMainMenu, menuItems[MENU_MAIN_POWER], menuItems[MENU_MAIN_DISPLAY], menuItems[MENU_MAIN_ADC], menuItems[MENU_MAIN_DAC], menuItems[MENU_MAIN_INTERLOCK], menuItems[MENU_MAIN_SOLENOID], menuItems[MENU_MAIN_RELAY], menuItems[MENU_MAIN_GENERIC] ); // Write message to debout interface IODevice_write(self->ioDevice, menuBuffer, menu_length); break; case DISPLAY_MENU_POWER: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_POWER_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char powerMenuBuffer[ sizeof( conTestPower ) ]; menu_length = sprintf( powerMenuBuffer, conTestPower, menuItems[MENU_TEST_POWER_ON], menuItems[MENU_TEST_POWER_OFF], menuItems[MENU_TEST_POWER_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, powerMenuBuffer, menu_length); break; case DISPLAY_MENU_DISPLAY: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_DISPLAY_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char displayMenuBuffer[ sizeof( conTestDisplay ) ]; menu_length = sprintf( displayMenuBuffer, conTestDisplay, menuItems[MENU_TEST_DISPLAY_BL_10], menuItems[MENU_TEST_DISPLAY_BL_50], menuItems[MENU_TEST_DISPLAY_BL_100], menuItems[MENU_TEST_DISPLAY_SHOW_TEXT], menuItems[MENU_TEST_DISPLAY_CLEAR_DISPLAY], menuItems[MENU_TEST_DISPLAY_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, displayMenuBuffer, menu_length); break; case DISPLAY_MENU_ADC: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_ADC_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char adcMenuBuffer[ sizeof( conTestADC ) ]; menu_length = sprintf( adcMenuBuffer, conTestADC, menuItems[MENU_TEST_ADC_CH_0], menuItems[MENU_TEST_ADC_CH_1], menuItems[MENU_TEST_ADC_CH_2], menuItems[MENU_TEST_ADC_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, adcMenuBuffer, menu_length); break; case DISPLAY_MENU_DAC: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_DAC_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char dacMenuBuffer[ sizeof( conTestDAC ) ]; menu_length = sprintf( dacMenuBuffer, conTestDAC, menuItems[MENU_TEST_DAC_CH_0_0V0], menuItems[MENU_TEST_DAC_CH_0_1V25], menuItems[MENU_TEST_DAC_CH_0_2V5], menuItems[MENU_TEST_DAC_CH_0_5V0], menuItems[MENU_TEST_DAC_CH_1_0V0], menuItems[MENU_TEST_DAC_CH_1_1V25], menuItems[MENU_TEST_DAC_CH_1_2V5], menuItems[MENU_TEST_DAC_CH_1_5V0], menuItems[MENU_TEST_DAC_CH_2_0V0], menuItems[MENU_TEST_DAC_CH_2_1V25], menuItems[MENU_TEST_DAC_CH_2_2V5], menuItems[MENU_TEST_DAC_CH_2_5V0], menuItems[MENU_TEST_DAC_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, dacMenuBuffer, menu_length); break; case DISPLAY_MENU_INTERLOCK: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_INTERLOCK_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char interlockMenuBuffer[ sizeof( conTestInterlock ) ]; menu_length = sprintf( interlockMenuBuffer, conTestInterlock, menuItems[MENU_TEST_INTERLOCK_1], menuItems[MENU_TEST_INTERLOCK_2], menuItems[MENU_TEST_INTERLOCK_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, interlockMenuBuffer, menu_length); break; case DISPLAY_MENU_SOLENOID: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_SOLENOID_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char solenoidMenuBuffer[ sizeof( conTestSolenoid ) ]; menu_length = sprintf( solenoidMenuBuffer, conTestSolenoid, menuItems[MENU_TEST_SOLENOID_TOGGLE], menuItems[MENU_TEST_SOLENOID_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, solenoidMenuBuffer, menu_length); break; case DISPLAY_MENU_RELAY: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_RELAYS_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char relayMenuBuffer[ sizeof( conTestRelays ) ]; menu_length = sprintf( relayMenuBuffer, conTestRelays, menuItems[MENU_TEST_RELAYS_TOGGLE_1], menuItems[MENU_TEST_RELAYS_TOGGLE_2], menuItems[MENU_TEST_RELAYS_TOGGLE_3], menuItems[MENU_TEST_RELAYS_TOGGLE_4], menuItems[MENU_TEST_RELAYS_TOGGLE_5], menuItems[MENU_TEST_RELAYS_TOGGLE_6], menuItems[MENU_TEST_RELAYS_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, relayMenuBuffer, menu_length); break; // case DISPLAY_MENU_KEYPAD: // break; // case DISPLAY_MENU_PCB_VARIANT: // break; // case DISPLAY_MENU_EEPROM: // break; case DISPLAY_MENU_GENERIC: // Put an asterisk (*) at the selected item in the menu for( menuIndex = 0; menuIndex < MENU_TEST_GENERIC_LAST; menuIndex++ ) { MENU_DRAW_SELECTED(menuIndex); } // Fill buffer with menu items char genericMenuBuffer[ sizeof( conTestGeneric) ]; menu_length = sprintf( genericMenuBuffer, conTestGeneric, menuItems[MENU_TEST_GENERIC_KEYPAD], menuItems[MENU_TEST_GENERIC_EEPROM], menuItems[MENU_TEST_GENERIC_PCB_VARIANT], menuItems[MENU_TEST_GENERIC_BACK] ); // Write message to debout interface IODevice_write(self->ioDevice, genericMenuBuffer, menu_length); break; default: //Do nothing break; } } static ErrorStatus hwValidationMenuReceiveMessage(struct HwValidationMenu* self, uint8_t * pData, uint16_t numBytes) { size_t actual_length = 0; ErrorStatus returnValue = SUCCESS; while(numBytes > 0) { if(IODevice_read(self->ioDevice, (char *)pData, numBytes, &actual_length) == SUCCESS) { numBytes -= actual_length; pData += actual_length; } else { returnValue = ERROR; break; } vTaskDelay(1); } return returnValue; } static ErrorStatus hwValidationMenuSetDac(struct HwValidationMenu* self, struct MAX5715_DAC* dac, uint16_t value) { int outputBufferLength = 0; ErrorStatus returnValue = SUCCESS; if( MAX5715Channel_setValue(dac, value) == SUCCESS) { outputBufferLength = sprintf(self->outputBuffer, "DAC: Set to %d\r\n", value); } else { outputBufferLength = sprintf(self->outputBuffer, "DAC: Failed to set\r\n"); returnValue = ERROR; } IODevice_write(self->ioDevice, self->outputBuffer, outputBufferLength); return returnValue; }