/* Simple simulator for Kinetis KL25Z MCU * Main implementation file. * Add this file to your project to be build with your sources. * Requires C++11 support. */ #include "simul_kl25z.h" #include #include #include #include #include #include #include #include #include //////////////////////////////////////////////////////////////// // Delay with time in milliseconds void delay(unsigned int mseconds) { clock_t goal = mseconds + clock(); while (goal > clock() ) ; } // simple delay with some default value void delay(void) { delay(500); } // clear screen void myclear(){ #if defined(__linux__) || defined(__unix__) || defined(__APPLE__) system("clear"); #endif #if defined(_WIN32) || defined(_WIN64) system("cls"); #endif } // Buffers used by drivers to print to screen char gLEDsBuffer[256]; char gLCDBuffer[256]; // mutex to protect access to screen std::mutex gScreenMutex; void WriteLEDsToScreen(); // in drv_gpio void WriteLCDToScreen(); // in drv_lcd void WriteLEDsToBuffer(char* buffer); // in drv_gpio void WriteLCDToBuffer(char* buffer); // in drv_lcd ///////////////////////////////////////////////////// static SIM_Peripheral sim_peripheral_object; SIM_Peripheral* SIM = &sim_peripheral_object; // Port C module (needed for ADC input on port C) static PORT_Peripheral portc_peripheral_object; PORT_Peripheral* PORTC = &portc_peripheral_object; ////////////////////////////////////////////////// // GPIO driver code static bool gInitialized; static FRDM_kit_pinmode gPinModes[LAST_PIN]; static uint8_t gPinOutputValues[LAST_PIN]; static const char* gLedNames[] = {"LD1", "LD2", "LD3", "RED", "GREEN", "BLUE" }; // Status of input pins constexpr int MAX_SWITCHES = 4; static bool gSwitchInputs[MAX_SWITCHES]; // mutex to protect the switch input variable std::mutex gMutexSwitches; // Background thread to process key press void task1(std::string msg) { (void)msg; while(1) { char c = getchar(); gMutexSwitches.lock(); switch(c) { case '1': // toggle input state when key is pressed gSwitchInputs[0] = !gSwitchInputs[0]; break; case '2': gSwitchInputs[1] = !gSwitchInputs[1]; break; case '3': gSwitchInputs[2] = !gSwitchInputs[2]; break; case '4': gSwitchInputs[3] = !gSwitchInputs[3]; break; } gMutexSwitches.unlock(); } // while 1 } // Thread to process screen refresh.... void taskScreen() { while(1) { myclear(); printf("KL25Z Simulation, version %d.%d\n\n", VERSION_MAJOR, VERSION_MINOR); gScreenMutex.lock(); printf(gLEDsBuffer); printf(gLCDBuffer); gScreenMutex.unlock(); // print status of switches printf("\n\n%5c%5c%5c%5c", gSwitchInputs[0] ? 'X' : '-', gSwitchInputs[1] ? 'X' : '-', gSwitchInputs[2] ? 'X' : '-', gSwitchInputs[3] ? 'X' : '-' ); printf("\n SW1 SW2 SW3 SW4\n"); delay(80); } } // This will create thread when the program starts... std::thread t1(task1, "Hello"); std::thread t2(taskScreen); /* Initialize the gpio driver for LEDs and push buttons. */ void GPIO_Initialize(void) { gInitialized = true; for ( int i=0; iUpdateData(); } // handler for write to CFG1[0] only to indicate we have valid settings void AdcStartConversion(unsigned int data) { //std::cout << "Start conversion " << data << '\n'; // For our pin - channel 11 check the pin config, for other channels just // skip test and simulated that conversion completed. This is needed for // calibration etc. int channel = (data & ADC_SC1_ADCH_MASK) >> ADC_SC1_ADCH_SHIFT; if ( channel == 11 ) { if ( ADC0->IsPinConfigValid() ) ADC0->mConversionStarted = true; } else { // conversion must be started for any other channel, also for calibration ADC0->mConversionStarted = true; } ADC0->UpdateData(); } void ADC_Peripheral::UpdateData() { // test if clock is enabled if ( (SIM->SCGC6 & SIM_SCGC6_ADC0_MASK) == 0 ) { printf("BSOD - Default ISR :) \nADC - clock not enabled!\n"); while (1) ; } if ( mConversionStarted ) { // get next value for ADC if channel is 11 if ( (SC1[0] & 0x1F) == ADC_SC1_ADCH(11) ) { // rozliseni int mode = (CFG1 & ADC_CFG1_MODE_MASK) >> ADC_CFG1_MODE_SHIFT; int shift = 0; switch ( mode) { case 0: // 8 bit shift = 0; PRINT_DGMSG("ADC resolution is 8 bit."); break; case 1: // 12 bit shift = 4; PRINT_DGMSG("ADC resolution is 12 bit."); break; case 2: // 10 bit shift = 2; PRINT_DGMSG("ADC resolution is 10 bit."); break; case 3: // 16 bit shift = 8; PRINT_DGMSG("ADC resolution is 16 bit."); break; } R[0].data = adc_values[mCurrentDataIndex++] << shift; if ( mCurrentDataIndex >= MAX_ADC_VALUES ) mCurrentDataIndex = 0; } SC1[0].data |= ADC_SC1_COCO_MASK; // set conversion complete flag mConversionStarted = false; } } // end ADC driver code ////////////////////////////////////////////////// //////////////////////////////////////////////////////////// // LCD driver code static bool gLcdInitialized; static char gDispData[4][21]; static int gRow, gColumn; void WriteLCDToScreen() { //clear(); printf("\n\nLCD-----------------\n"); //printf("123456789ABCDEFGHIJK\n"); for ( int i=0; i<4; i++ ) printf("%s\n", gDispData[i]); printf("---------------------\n"); } void WriteLCDToBuffer(char* buffer) { //clear(); char buff[512]; gScreenMutex.lock(); buffer[0] = '\0'; sprintf(buff, "\n\nLCD-----------------\n"); strcat(buffer, buff); //printf("123456789ABCDEFGHIJK\n"); for ( int i=0; i<4; i++ ) { sprintf(buff, "%s\n", gDispData[i]); strcat(buffer, buff); } sprintf(buff, "---------------------\n"); strcat(buffer, buff); gScreenMutex.unlock(); } /* initialize display */ void LCD_initialize(void) { gLcdInitialized = true; gRow = 0; // 1 - 4 gColumn = 0; // 1 - 20 } void LCD_set_cursor(uint8_t line, uint8_t column) { if ( line > 0 && line < 5) gRow = line - 1; if ( column > 0 && column < 21 ) gColumn = column - 1; } void LCD_putch(char c) { if ( !gLcdInitialized ) { printf("BSOD - Default ISR :) \nLCD driver not initialized!\n"); while (1) ; } if ( gColumn > 19 ) { printf("Warning: LCD writing beyond last column!\n"); return; } if ( gRow > 3 ) { printf("Warning: LCD writing below last line!\n"); return; } gDispData[gRow][gColumn] = c; gColumn++; if ( gColumn > 19 ) gColumn = 0; // update screen WriteLCDToBuffer(gLCDBuffer); } void LCD_puts(const char* str) { if ( !gLcdInitialized ) { printf("BSOD - Default ISR :) \nLCD driver not initialized!\n"); while (1) ; } char* p = gDispData[gRow]; int len = 20 - gColumn; if ( len > 0) { strncpy(p + gColumn, str, len); gDispData[gRow][gColumn+len] = '\0'; gColumn += strlen(str); } else { printf("Warning: LCD writing beyond last column!\n"); return; } WriteLCDToBuffer(gLCDBuffer); } void LCD_clear(void) { if ( !gLcdInitialized ) { printf("BSOD - Default ISR :) \nLCD driver not initialized!\n"); while (1) ; } gRow = 0; // 1 - 4 gColumn = 0; for ( int i = 0; i<4; i++ ) { for ( int j = 0; j<20; j++) { gDispData[i][j] = ' '; } } WriteLCDToBuffer(gLCDBuffer); } void LCD_backlight_on(void) { printf("Warning: LCD_backlight_on not implemented.\n"); } void LCD_backlight_off(void) { printf("Warning: LCD_backlight_off not implemented.\n"); } // end LCD driver code ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // SYSTICK driver code // Simulate systick driver functions // Functions implemented in simul_kl25z.cpp void SYSTICK_initialize(void) { // do nothing } uint32_t SYSTICK_millis(void) { return (uint32_t)clock(); } uint32_t SYSTICK_micros(void) { return SYSTICK_millis() * 1000; } void SYSTICK_delay_ms(uint32_t millis) { delay(millis); } // end SYSTICK driver code //////////////////////////////////////////////////////////////////