///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { int i; struct ntp_tm tm; const char *month_names[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; const char *weekday_names[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; mios32_sys_time_t t; char timestring[64]; // clear LCD screen MIOS32_LCD_Clear(); // endless loop: print status information on LCD while( 1 ) { // new message requested? // TODO: add FreeRTOS specific queue handling! u8 new_msg = PRINT_MSG_NONE; portENTER_CRITICAL(); // port specific FreeRTOS function to disable tasks (nested) if( print_msg ) { new_msg = print_msg; print_msg = PRINT_MSG_NONE; // clear request } portEXIT_CRITICAL(); // port specific FreeRTOS function to enable tasks (nested) switch( new_msg ) { case PRINT_MSG_INIT: MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("see README.txt "); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintString("for details "); break; case PRINT_MSG_STATUS: { MIOS32_LCD_CursorSet(0, 0); // request status screen again (will stop once a new screen is requested by another task) print_msg = PRINT_MSG_STATUS; } break; } t = MIOS32_SYS_TimeGet(); // convert ntp seconds since 1900 into useful time structure ntp_tmtime(t.seconds, &tm); // honour dailight savings ntp_dst(&tm); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_SMALL); MIOS32_LCD_CursorSet(15, 12); MIOS32_LCD_PrintFormattedString("%s %02d %s %04d %02d:%02d:%02d", weekday_names[tm.weekday], tm.day, month_names[tm.month-1], tm.year,tm.hour, tm.minute, tm.second); } }
///////////////////////////////////////////////////////////////////////////// // Clear Screen // IN: - // OUT: returns < 0 on errors ///////////////////////////////////////////////////////////////////////////// s32 APP_LCD_Clear(void) { int x, y; // use default font MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); // clear whole 128x128 screen with background colour // ST7637 specific function to set view APP_LCD_SetRect_For_Cmd(0, 0, APP_LCD_WIDTH, APP_LCD_HEIGHT); // Send command to write data on the LCD screen. APP_LCD_Cmd(ST7637_RAMWR); for(x=0; x<APP_LCD_WIDTH; ++x) { for(y=0; y<APP_LCD_HEIGHT; ++y) { APP_LCD_Data(lcd_bcolour & 0xff); APP_LCD_Data(lcd_bcolour >> 8); } } // set cursor to initial position APP_LCD_CursorSet(0, 0); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Clear Screen // IN: - // OUT: returns < 0 on errors ///////////////////////////////////////////////////////////////////////////// s32 APP_LCD_Clear(void) { s32 error = 0; u8 x, y; // use default font MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); // select all LCDs error |= MIOS32_LCD_CursorSet(0, 0); // send data for(y=0; y<APP_LCD_HEIGHT; y=y+4) { error |= APP_LCD_GCursorSet(0, y); MIOS32_BOARD_J15_DataSet(0x00); MIOS32_BOARD_J15_RS_Set(1); // RS pin used to control DC for(x=0; x<APP_LCD_WIDTH; ++x){ MIOS32_BOARD_J15_SerDataShift(0x00); } } // set X=0, Y=0 error |= MIOS32_LCD_CursorSet(0, 0); return error; }
///////////////////////////////////////////////////////////////////////////// // Clear Screen // IN: - // OUT: returns < 0 on errors ///////////////////////////////////////////////////////////////////////////// s32 APP_LCD_Clear(void) { s32 error = 0; u8 x, y; // use default font MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); // send data for(y=0; y<8; ++y) { error |= MIOS32_LCD_CursorSet(0, y); // select all LCDs #if APP_LCD_USE_J10_FOR_CS MIOS32_BOARD_J10_Set(0x00); #else MIOS32_BOARD_J15_DataSet(0x00); #endif MIOS32_BOARD_J15_RS_Set(1); // RS pin used to control DC for(x=0; x<128; ++x) MIOS32_BOARD_J15_SerDataShift(0x00); } // set X=0, Y=0 error |= MIOS32_LCD_CursorSet(0, 0); return error; }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // print static screen MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); // clear LCD MIOS32_LCD_Clear(); // endless loop - LED will flicker on each iteration while( 1 ) { // toggle the state of all LEDs (allows to measure the execution speed with a scope) MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); // X/Y "position" of displays (see also comments in $MIOS32_PATH/modules/app_lcd/pcd8544/README.txt) const u8 lcd_x[8] = {0, 1, 2, 0, 1, 2, 0, 1}; // CS#0..7 const u8 lcd_y[8] = {0, 0, 0, 1, 1, 1, 2, 2}; u8 i; for(i=0; i<8; ++i) { u8 x_offset = 84*lcd_x[i]; u8 y_offset = 6*8*lcd_y[i]; // print text MIOS32_LCD_GCursorSet(x_offset + 0, y_offset + 0*8); MIOS32_LCD_PrintFormattedString(" PCD8544 #%d", i+1); MIOS32_LCD_GCursorSet(x_offset + 0, y_offset + 2*8); MIOS32_LCD_PrintString(" powered by "); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_BIG); MIOS32_LCD_GCursorSet(x_offset + 0, y_offset + 3*8); MIOS32_LCD_PrintString("MIOS"); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_GCursorSet(x_offset + 64, y_offset + 4*8); MIOS32_LCD_PrintString("32"); } } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // print static screen MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); // clear LCD MIOS32_LCD_Clear(); u8 last_touchpanel_x = 0; u8 last_touchpanel_y = 0; // endless loop - LED will flicker on each iteration while( 1 ) { // toggle the state of all LEDs (allows to measure the execution speed with a scope) MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); // check for X/Y coordinate changes if( touchpanel_x != last_touchpanel_x || touchpanel_y != last_touchpanel_y ) { // clear marker at last position MIOS32_LCD_GCursorSet(last_touchpanel_x, last_touchpanel_y / 2); MIOS32_LCD_PrintChar(' '); // clear coordinate at the left/right side if required if( (last_touchpanel_x < 64 && touchpanel_x >= 64) || (last_touchpanel_x >= 64 && touchpanel_x < 64) ) { MIOS32_LCD_GCursorSet((last_touchpanel_x < 64) ? 128-5*6 : 0, 0*8); MIOS32_LCD_PrintString(" "); MIOS32_LCD_GCursorSet((last_touchpanel_x < 64) ? 128-5*6 : 0, 1*8); MIOS32_LCD_PrintString(" "); } // set marker at new position MIOS32_LCD_GCursorSet(touchpanel_x, touchpanel_y / 2); MIOS32_LCD_PrintChar('x'); // print new coordinates MIOS32_LCD_GCursorSet((touchpanel_x < 64) ? 128-5*6 : 0, 0*8); MIOS32_LCD_PrintFormattedString("X:%3d", touchpanel_x); MIOS32_LCD_GCursorSet((touchpanel_x < 64) ? 128-5*6 : 0, 1*8); MIOS32_LCD_PrintFormattedString("Y:%3d", touchpanel_y); // store new position last_touchpanel_x = touchpanel_x; last_touchpanel_y = touchpanel_y; } } }
///////////////////////////////////////////////////////////////////////////// //! transfers the buffer to LCDs //! \param[in] force if != 0, it is ensured that the whole screen will be refreshed, regardless //! if characters have changed or not ///////////////////////////////////////////////////////////////////////////// s32 BUFLCD_Update(u8 force) { int next_x = -1; int next_y = -1; int x, y; u32 bufpos_len = BUFLCD_MaxBufferGet(); int phys_y = buflcd_offset_y; for(y=0; y<buflcd_device_num_y*buflcd_device_height; ++y, ++phys_y) { u32 bufpos = y * buflcd_device_num_x * buflcd_device_width; if( bufpos >= bufpos_len ) break; u8 *ptr = (u8 *)&lcd_buffer[bufpos]; #if BUFLCD_SUPPORT_GLCD_FONTS u8 *font_ptr = (u8 *)&lcd_buffer[bufpos + (BUFLCD_BUFFER_SIZE/2)]; #endif int phys_x = buflcd_offset_x; int device = (buflcd_device_num_x * (phys_y / buflcd_device_height)) - 1; for(x=0; x<(buflcd_device_num_x * buflcd_device_width) && bufpos < bufpos_len; ++x, ++phys_x, ++bufpos) { if( (phys_x % buflcd_device_width) == 0 ) ++device; if( force || !(*ptr & 0x80) #if BUFLCD_SUPPORT_GLCD_FONTS || (glcd_font_handling && !(*font_ptr & 0x80)) #endif ) { #if BUFLCD_SUPPORT_GLCD_FONTS u8 *glcd_font = NULL; if( glcd_font_handling ) { switch( *font_ptr & 0x7f ) { case 'n': glcd_font = (u8 *)GLCD_FONT_NORMAL; break; case 'i': glcd_font = (u8 *)GLCD_FONT_NORMAL_INV; break; case 'b': glcd_font = (u8 *)GLCD_FONT_BIG; break; case 's': glcd_font = (u8 *)GLCD_FONT_SMALL; break; case 't': glcd_font = (u8 *)GLCD_FONT_TINY; break; case 'k': glcd_font = (u8 *)GLCD_FONT_KNOB_ICONS; break; case 'h': glcd_font = (u8 *)GLCD_FONT_METER_ICONS_H; break; case 'v': glcd_font = (u8 *)GLCD_FONT_METER_ICONS_V; break; default: glcd_font = NULL; // no character will be print } MIOS32_LCD_FontInit(glcd_font); } #endif if( x != next_x || y != next_y ) { #if BUFLCD_SUPPORT_GLCD_FONTS if( glcd_font_handling && glcd_font ) { // temporary use pseudo-font to ensure that Y is handled equaly for all fonts u8 pseudo_font[4]; // just to ensure... #if MIOS32_LCD_FONT_WIDTH_IX != 0 || MIOS32_LCD_FONT_HEIGHT_IX != 1 || MIOS32_LCD_FONT_X0_IX != 2 || MIOS32_LCD_FONT_OFFSET_IX != 3 # error "Please adapt this part for new LCD Font parameter positions!" #endif pseudo_font[MIOS32_LCD_FONT_WIDTH_IX] = glcd_font[MIOS32_LCD_FONT_WIDTH_IX]; pseudo_font[MIOS32_LCD_FONT_HEIGHT_IX] = 1*8; // forced! pseudo_font[MIOS32_LCD_FONT_X0_IX] = glcd_font[MIOS32_LCD_FONT_X0_IX]; pseudo_font[MIOS32_LCD_FONT_OFFSET_IX] = glcd_font[MIOS32_LCD_FONT_OFFSET_IX]; MIOS32_LCD_FontInit((u8 *)&pseudo_font); } #endif MIOS32_LCD_DeviceSet(device); MIOS32_LCD_CursorSet(phys_x % buflcd_device_width, phys_y % buflcd_device_height); #if BUFLCD_SUPPORT_GLCD_FONTS if( glcd_font_handling ) { // switch back to original font MIOS32_LCD_FontInit(glcd_font); } #endif } #if BUFLCD_SUPPORT_GLCD_FONTS if( !glcd_font_handling || glcd_font ) #endif MIOS32_LCD_PrintChar(*ptr & 0x7f); MIOS32_IRQ_Disable(); // must be atomic *ptr |= 0x80; #if BUFLCD_SUPPORT_GLCD_FONTS *font_ptr |= 0x80; #endif MIOS32_IRQ_Enable(); next_y = y; next_x = x+1; // for multiple LCDs: ensure that cursor is set when we reach the next partition if( (next_x % buflcd_device_width) == 0 ) next_x = -1; } ++ptr; #if BUFLCD_SUPPORT_GLCD_FONTS ++font_ptr; #endif } } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Initializes application specific LCD driver // IN: <mode>: optional configuration // OUT: returns < 0 if initialisation failed ///////////////////////////////////////////////////////////////////////////// s32 APP_LCD_Init(u32 mode) { GPIO_InitTypeDef GPIO_InitStructure; s32 delay; // set LCD type mios32_lcd_parameters.lcd_type = MIOS32_LCD_TYPE_GLCD_CUSTOM; // set initial font and colours MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_BColourSet(0xffffff); MIOS32_LCD_FColourSet(0x000000); // control lines PIN_BL(1); PIN_RS(1); PIN_RD(1); PIN_CS(1); PIN_WR(1); PIN_RST(1); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = APP_LCD_BL_PIN; GPIO_Init(APP_LCD_BL_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = APP_LCD_RS_PIN; GPIO_Init(APP_LCD_RS_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = APP_LCD_RD_PIN; GPIO_Init(APP_LCD_RD_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = APP_LCD_WR_PIN; GPIO_Init(APP_LCD_WR_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = APP_LCD_CS_PIN; GPIO_Init(APP_LCD_CS_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = APP_LCD_RST_PIN; GPIO_Init(APP_LCD_RST_PORT, &GPIO_InitStructure); // Apply hardware reset PIN_RST(0); for(delay=0; delay<0x500; ++delay); PIN_RST(1); for(delay=0; delay<0x500; ++delay); // configure data pins as outputs GPIO_InitStructure.GPIO_Pin = APP_LCD_D_PINS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(APP_LCD_D_PORT, &GPIO_InitStructure); //----------- software reset ------------------------------------------------ APP_LCD_Cmd(ST7637_SWRESET); //----------- disable autoread + Manual read once --------------------------- APP_LCD_Cmd( ST7637_AUTOLOADSET ); // Auto Load Set 0xD7 APP_LCD_Data( 0xBF ); // Auto Load Disable APP_LCD_Cmd( ST7637_EPCTIN ); // EE Read/write mode 0xE0 APP_LCD_Data( 0x00 ); // Set read mode APP_LCD_Cmd( ST7637_EPMRD ); // Read active 0xE3 APP_LCD_Cmd( ST7637_EPCTOUT ); // Cancel control 0xE1 //---------------------------------- Sleep OUT ------------------------------ APP_LCD_Cmd( ST7637_DISPOFF ); // display off 0x28 APP_LCD_Cmd( ST7637_SLPOUT ); // Sleep Out 0x11 //--------------------------------Vop setting-------------------------------- APP_LCD_Cmd( ST7637_VOPSET ); // Set Vop by initial Module 0xC0 APP_LCD_Data( 0xFB ); // Vop = 13.64 APP_LCD_Data( 0x00 ); // base on Module //----------------------------Set Register----------------------------------- APP_LCD_Cmd( ST7637_BIASSEL ); // Bias select 0xC3 APP_LCD_Data( 0x00 ); // 1/12 Bias, base on Module APP_LCD_Cmd( ST7637_BSTBMPXSEL ); // Setting Booster times 0xC4 APP_LCD_Data( 0x05 ); // Booster X 8 APP_LCD_Cmd( ST7637_BSTEFFSEL ); // Booster eff 0xC5 APP_LCD_Data( 0x11 ); // BE = 0x01 (Level 2) APP_LCD_Cmd( ST7637_VGSORCSEL ); // Vg with booster x2 control 0xcb APP_LCD_Data( 0x01 ); // Vg from Vdd2 APP_LCD_Cmd( ST7637_ID1SET ); // ID1 = 00 0xcc APP_LCD_Data( 0x00 ); // APP_LCD_Cmd( ST7637_ID3SET ); // ID3 = 00 0xce APP_LCD_Data( 0x00 ); // APP_LCD_Cmd( ST7637_COMSCANDIR ); // Glass direction APP_LCD_Data( 0xC0 ); // APP_LCD_Cmd( ST7637_ANASET ); // Analog circuit setting 0xd0 APP_LCD_Data( 0x1D ); // APP_LCD_Cmd( ST7637_PTLMOD ); // PTL mode set APP_LCD_Data( 0x18 ); // power normal mode APP_LCD_Cmd( ST7637_INVOFF ); // Display Inversion OFF 0x20 APP_LCD_Cmd( ST7637_CASET ); // column range APP_LCD_Data( 0x04 ); // APP_LCD_Data( 0x83 ); // APP_LCD_Cmd( ST7637_RASET ); // raw range APP_LCD_Data( 0x04 ); // APP_LCD_Data( 0x83 ); // APP_LCD_Cmd( ST7637_COLMOD ); // Color mode = 65k 0x3A APP_LCD_Data( 0x05 ); // APP_LCD_Cmd( ST7637_MADCTR ); // Memory Access Control 0x36 APP_LCD_Data( V12_MADCTRVAL ); APP_LCD_Cmd( ST7637_DUTYSET ); // Duty = 132 duty 0xb0 APP_LCD_Data( 0x7F ); APP_LCD_Cmd( ST7637_DISPON ); // Display ON APP_LCD_Cmd( ST7637_FRAMESET ); // Gamma APP_LCD_Data( 0x00 ); // APP_LCD_Data( 0x03 ); // APP_LCD_Data( 0x05 ); // APP_LCD_Data( 0x07 ); // APP_LCD_Data( 0x09 ); // APP_LCD_Data( 0x0B ); // APP_LCD_Data( 0x0D ); // APP_LCD_Data( 0x0F ); // APP_LCD_Data( 0x11 ); // APP_LCD_Data( 0x13 ); // APP_LCD_Data( 0x15 ); // APP_LCD_Data( 0x17 ); // APP_LCD_Data( 0x19 ); // APP_LCD_Data( 0x1B ); // APP_LCD_Data( 0x1D ); // APP_LCD_Data( 0x1F ); // return 0; // no error }
///////////////////////////////////////////////////////////////////////////// //! This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { const u16 sdcard_check_delay = 1000; u16 sdcard_check_ctr = 0; u8 lun_available = 0; static u8 isInMainPage = 1; SCS_DisplayUpdateInMainPage(0); MBNG_LCD_SpecialCharsReInit(); u32 last_timestamp = MIOS32_TIMESTAMP_Get(); while( 1 ) { //vTaskDelay(1 / portTICK_RATE_MS); // Background task: use timestamp mechanism to generate delay while( MIOS32_TIMESTAMP_Get() == last_timestamp ); last_timestamp = MIOS32_TIMESTAMP_Get(); // call SCS handler MUTEX_LCD_TAKE; MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); SCS_Tick(); SCS_DisplayUpdateInMainPage((MBNG_EVENT_MidiLearnModeGet() || MBNG_EVENT_EventLearnIdGet()) ? 1 : 0); // LCD output in mainpage if( SCS_MenuStateGet() == SCS_MENU_STATE_MAINPAGE && !MBNG_EVENT_MidiLearnModeGet() && !MBNG_EVENT_EventLearnIdGet() ) { u8 force = isInMainPage == 0; if( force ) { // page change MBNG_LCD_SpecialCharsReInit(); MBNG_LCD_CursorSet(SCS_LCD_DeviceGet(), SCS_LCD_OffsetXGet(), SCS_LCD_OffsetYGet() + 0); MBNG_LCD_PrintSpaces(SCS_NumMenuItemsGet()*SCS_MENU_ITEM_WIDTH); MBNG_LCD_CursorSet(SCS_LCD_DeviceGet(), SCS_LCD_OffsetXGet(), SCS_LCD_OffsetYGet() + 1); MBNG_LCD_PrintSpaces(SCS_NumMenuItemsGet()*SCS_MENU_ITEM_WIDTH); } MBNG_EVENT_UpdateLCD(force); // handles .NGR file execution MBNG_FILE_R_CheckRequest(); isInMainPage = 1; // static reminder } else { if( isInMainPage && (MBNG_EVENT_MidiLearnModeGet() || MBNG_EVENT_EventLearnIdGet()) ) { SCS_LCD_Update(1); // force display update when learn mode is entered in mainpage } isInMainPage = 0; // static reminder } // handles .NGR file execution MBNG_FILE_R_CheckRequest(); MUTEX_LCD_GIVE; // -> keyboard handler KEYBOARD_Periodic_1mS(); // MIDI In/Out monitor MIDI_PORT_Period1mS(); // call MIDI event tick MBNG_EVENT_Tick(); // each second: check if SD Card (still) available if( msd_state == MSD_DISABLED && ++sdcard_check_ctr >= sdcard_check_delay ) { sdcard_check_ctr = 0; MUTEX_SDCARD_TAKE; s32 status = FILE_CheckSDCard(); if( status == 1 ) { DEBUG_MSG("SD Card connected: %s\n", FILE_VolumeLabel()); // stop sequencer SEQ_BPM_Stop(); // load all file infos MBNG_FILE_LoadAllFiles(1); // including HW info // select the first bank MBNG_EVENT_SelectedBankSet(1); // immediately go to next step sdcard_check_ctr = sdcard_check_delay; } else if( status == 2 ) { DEBUG_MSG("SD Card disconnected\n"); // invalidate all file infos MBNG_FILE_UnloadAllFiles(); // stop sequencer SEQ_BPM_Stop(); // change status MBNG_FILE_StatusMsgSet("No SD Card"); MUTEX_LCD_TAKE; MBNG_LCD_CursorSet(0, 0, 0); MBNG_LCD_PrintString("*** No SD Card *** "); MBNG_LCD_ClearScreenOnNextMessage(); MUTEX_LCD_GIVE; } else if( status == 3 ) { if( !FILE_SDCardAvailable() ) { DEBUG_MSG("SD Card not found\n"); MBNG_FILE_StatusMsgSet("No SD Card"); MUTEX_LCD_TAKE; MBNG_LCD_CursorSet(0, 0, 0); MBNG_LCD_PrintString("*** No SD Card *** "); MBNG_LCD_ClearScreenOnNextMessage(); MUTEX_LCD_GIVE; } else if( !FILE_VolumeAvailable() ) { DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n"); MBNG_FILE_StatusMsgSet("No FAT"); MUTEX_LCD_TAKE; MBNG_LCD_CursorSet(0, 0, 0); MBNG_LCD_PrintString("* No FAT on SD Card * "); MBNG_LCD_ClearScreenOnNextMessage(); MUTEX_LCD_GIVE; } else { MBNG_FILE_StatusMsgSet(NULL); // create the default files if they don't exist on SD Card MBNG_FILE_CreateDefaultFiles(); } hw_enabled = 1; // enable hardware after first read... } MUTEX_SDCARD_GIVE; } // MSD driver if( msd_state != MSD_DISABLED ) { MUTEX_SDCARD_TAKE; switch( msd_state ) { case MSD_SHUTDOWN: // switch back to USB MIDI MIOS32_USB_Init(1); msd_state = MSD_DISABLED; break; case MSD_INIT: // LUN not mounted yet lun_available = 0; // enable MSD USB driver MUTEX_J16_TAKE; if( MSD_Init(0) >= 0 ) msd_state = MSD_READY; else msd_state = MSD_SHUTDOWN; MUTEX_J16_GIVE; break; case MSD_READY: // service MSD USB driver MSD_Periodic_mS(); // this mechanism shuts down the MSD driver if SD card has been unmounted by OS if( lun_available && !MSD_LUN_AvailableGet(0) ) msd_state = MSD_SHUTDOWN; else if( !lun_available && MSD_LUN_AvailableGet(0) ) lun_available = 1; break; } MUTEX_SDCARD_GIVE; } } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // print static screen MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_BColourSet(0x000000); MIOS32_LCD_FColourSet(0xffffff); // clear LCD MIOS32_LCD_Clear(); // print text MIOS32_LCD_CursorSet(3, 3); MIOS32_LCD_PrintString("ST7637 LCD"); MIOS32_LCD_CursorSet(7, 5); MIOS32_LCD_PrintString("powered by"); // endless loop: print animations u8 mios_r = 0; u8 mios_g = 0; u8 mios_b = 0; u8 dir = 1; u8 knob_icon_ctr[4] = {0, 3, 6, 9}; // memo: 12 icons u8 knob_icon_delay_ctr[4] = {0, 2, 4, 6}; const u8 knob_icon_x[4] = {0, 100, 0, 100}; // memo: icon width 28 const u8 knob_icon_y[4] = {0, 0, 104, 104}; // memo: icon height 24 u8 vmeter_icon_ctr[2] = {0, 5}; // memo: 28 icons (14 used) u8 vmeter_icon_dir[2] = {1, 1}; u8 vmeter_icon_delay_ctr[2] = {1, 4}; const u8 vmeter_icon_x[2] = {0, 120}; // memo: icon width 8 const u8 vmeter_icon_y[2] = {48, 48}; // memo: icon height 32 u8 hmeter_icon_ctr[2] = {6, 11}; // memo: 28 icons (14 used) u8 hmeter_icon_dir[2] = {1, 0}; u8 hmeter_icon_delay_ctr[2] = {4, 2}; const u8 hmeter_icon_x[2] = {50, 50}; // memo: icon width 28 const u8 hmeter_icon_y[2] = {0, 120}; // memo: icon height 8 while( 1 ) { s32 i; // toggle the state of all LEDs (allows to measure the execution speed with a scope) MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); // colour-cycle "MIOS32" up and down :-) // ST7637 supports 5bit r, 6bit g and 5bit b if( dir ) { if( mios_r < 0x1f ) ++mios_r; else if( mios_g < 0x3f ) ++mios_g; else if( mios_b < 0x1f ) ++mios_b; else dir = 0; } else { if( mios_r > 0x00 ) --mios_r; else if( mios_g > 0x00 ) --mios_g; else if( mios_b > 0x00 ) --mios_b; else dir = 1; } // set new colour MIOS32_LCD_FColourSet((mios_r << 16) | (mios_g << 8) | mios_b); // print "MIOS32" MIOS32_LCD_FontInit((u8 *)GLCD_FONT_BIG); MIOS32_LCD_GCursorSet(16, 52); MIOS32_LCD_PrintString("MIOS32"); // icons with different colour MIOS32_LCD_FColourSet(((dir?mios_r:~mios_r) << 16) | (~mios_g << 8) | (dir?mios_b:~mios_b)); // print turning Knob icons at all edges MIOS32_LCD_FontInit((u8 *)GLCD_FONT_KNOB_ICONS); // memo: 12 icons, icon size: 28x24 for(i=0; i<4; ++i) { if( ++knob_icon_delay_ctr[i] > 10 ) { knob_icon_delay_ctr[i] = 0; if( ++knob_icon_ctr[i] >= 12 ) knob_icon_ctr[i] = 0; } MIOS32_LCD_GCursorSet(knob_icon_x[i], knob_icon_y[i]); MIOS32_LCD_PrintChar(knob_icon_ctr[i]); } // print vmeter icons MIOS32_LCD_FontInit((u8 *)GLCD_FONT_METER_ICONS_V); // memo: 28 icons, 14 used, icon size: 8x32 for(i=0; i<2; ++i) { if( ++vmeter_icon_delay_ctr[i] > 5 ) { vmeter_icon_delay_ctr[i] = 0; if( vmeter_icon_dir[i] ) { if( ++vmeter_icon_ctr[i] >= 13 ) vmeter_icon_dir[i] = 0; } else { if( --vmeter_icon_ctr[i] < 1 ) vmeter_icon_dir[i] = 1; } } MIOS32_LCD_GCursorSet(vmeter_icon_x[i], vmeter_icon_y[i]); MIOS32_LCD_PrintChar(vmeter_icon_ctr[i]); } // print hmeter icons MIOS32_LCD_FontInit((u8 *)GLCD_FONT_METER_ICONS_H); // memo: 28 icons, 14 used, icon size: 28x8 for(i=0; i<2; ++i) { if( ++hmeter_icon_delay_ctr[i] > 7 ) { hmeter_icon_delay_ctr[i] = 0; if( hmeter_icon_dir[i] ) { if( ++hmeter_icon_ctr[i] >= 13 ) hmeter_icon_dir[i] = 0; } else { if( --hmeter_icon_ctr[i] < 1 ) hmeter_icon_dir[i] = 1; } } MIOS32_LCD_GCursorSet(hmeter_icon_x[i], hmeter_icon_y[i]); MIOS32_LCD_PrintChar(hmeter_icon_ctr[i]); } } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { #define MAX_LCDS 16 int num_lcds = mios32_lcd_parameters.num_x * mios32_lcd_parameters.num_y; if( num_lcds > MAX_LCDS ) { MIOS32_MIDI_SendDebugMessage("WARNING: this application only supports up to 16 displays!\n"); num_lcds = MAX_LCDS; } // clear LCDs { u8 n; for(n=0; n<num_lcds; ++n) { MIOS32_LCD_DeviceSet(n); MIOS32_LCD_Clear(); } } u8 vmeter_icon_ctr[MAX_LCDS][2] = {{0,5},{3,14},{7,1},{3,9},{13,6},{10,2},{1,4},{6,2},{13,6},{10,2},{1,4},{6,2},{1,2},{13,14},{5,5},{6,1}}; // memo: 28 icons (14 used) u8 vmeter_icon_dir[MAX_LCDS][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}}; u8 vmeter_icon_delay_ctr[MAX_LCDS][2] = {{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4}}; const u8 vmeter_icon_x[2] = {0, 120}; // memo: icon width 8 const u8 vmeter_icon_y[2] = {12, 12}; // memo: icon height 32 u8 hmeter_icon_ctr[MAX_LCDS][2] = {{6,11},{2,27},{23,1},{15,6},{18,9},{10,12},{3,25},{26,7},{18,9},{10,12},{3,25},{26,7},{6,9},{18,18},{20,10},{3,10}}; // memo: 28 icons (14 used) u8 hmeter_icon_dir[MAX_LCDS][2] = {{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0}}; u8 hmeter_icon_delay_ctr[MAX_LCDS][2] = {{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2}}; const u8 hmeter_icon_x[2] = {20, 80}; // memo: icon width 28 const u8 hmeter_icon_y[2] = {60, 60}; // memo: icon height 8 // print configured LCD parameters MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("SSD1306 Demo started."); MIOS32_MIDI_SendDebugMessage("Configured LCD Parameters in MIOS32 Bootloader Info Range:\n"); MIOS32_MIDI_SendDebugMessage("lcd_type: 0x%02x (%s)\n", mios32_lcd_parameters.lcd_type, MIOS32_LCD_LcdTypeName(mios32_lcd_parameters.lcd_type)); MIOS32_MIDI_SendDebugMessage("num_x: %4d\n", mios32_lcd_parameters.num_x); MIOS32_MIDI_SendDebugMessage("num_y: %4d\n", mios32_lcd_parameters.num_y); MIOS32_MIDI_SendDebugMessage("width: %4d\n", mios32_lcd_parameters.width); MIOS32_MIDI_SendDebugMessage("height: %4d\n", mios32_lcd_parameters.height); MIOS32_MIDI_SendDebugMessage("Testing %d LCDs\n", num_lcds); if( mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_GLCD_SSD1306 && mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_GLCD_SSD1306_ROTATED ) { // print warning if correct LCD hasn't been selected MIOS32_MIDI_SendDebugMessage("WARNING: your core module hasn't been configured for the SSD1306 GLCD!\n"); MIOS32_MIDI_SendDebugMessage("Please do this with the bootloader update application!\n"); } // print static screen MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); // endless loop - LED will flicker on each iteration while( 1 ) { // wait some mS MIOS32_DELAY_Wait_uS(10000); // toggle the state of all LEDs (allows to measure the execution speed with a scope) MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); u8 n; for(n=0; n<num_lcds; ++n) { int i; #if 0 // X/Y "position" of displays const u8 lcd_x[MAX_LCDS] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; // CS#0..7 const u8 lcd_y[MAX_LCDS] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; // X/Y "position" of displays u8 x_offset = 128*lcd_x[n]; u8 y_offset = 64*lcd_y[n]; #else // TK: expired! LCDs now addressed via MIOS32_LCD_DeviceSet() u8 x_offset = 0; u8 y_offset = 0; MIOS32_LCD_DeviceSet(n); #endif // print text MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_GCursorSet(x_offset + 6*6, y_offset + 1*8); MIOS32_LCD_PrintFormattedString("SSD1306 #%d", n+1); MIOS32_LCD_GCursorSet(x_offset + 6*6, y_offset + 2*8); MIOS32_LCD_PrintString("powered by "); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_BIG); MIOS32_LCD_GCursorSet(x_offset + 3*6, y_offset + 3*8); MIOS32_LCD_PrintString("MIOS32"); // print vmeter icons MIOS32_LCD_FontInit((u8 *)GLCD_FONT_METER_ICONS_V); // memo: 28 icons, 14 used, icon size: 8x32 for(i=0; i<2; ++i) { if( ++vmeter_icon_delay_ctr[n][i] ) { vmeter_icon_delay_ctr[n][i] = 0; if( vmeter_icon_dir[n][i] ) { if( ++vmeter_icon_ctr[n][i] >= 13 ) vmeter_icon_dir[n][i] = 0; } else { if( --vmeter_icon_ctr[n][i] < 1 ) vmeter_icon_dir[n][i] = 1; } } MIOS32_LCD_GCursorSet(vmeter_icon_x[i]+x_offset, vmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintChar(vmeter_icon_ctr[n][i]); } // print hmeter icons for(i=0; i<2; ++i) { MIOS32_LCD_FontInit((u8 *)GLCD_FONT_METER_ICONS_H); // memo: 28 icons, 14 used, icon size: 28x8 if( ++hmeter_icon_delay_ctr[n][i] > 7 ) { hmeter_icon_delay_ctr[n][i] = 0; if( hmeter_icon_dir[n][i] ) { if( ++hmeter_icon_ctr[n][i] >= 13 ) hmeter_icon_dir[n][i] = 0; } else { if( --hmeter_icon_ctr[n][i] < 1 ) hmeter_icon_dir[n][i] = 1; } } MIOS32_LCD_GCursorSet(hmeter_icon_x[i]+x_offset, hmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintChar(hmeter_icon_ctr[n][i]); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); if( i == 0 ) { MIOS32_LCD_GCursorSet(0+x_offset, hmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintFormattedString("%d", hmeter_icon_ctr[n][i]*4); } else { MIOS32_LCD_GCursorSet(128-3*6+x_offset, hmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintFormattedString("%3d", hmeter_icon_ctr[n][i]*4); } } } } }
///////////////////////////////////////////////////////////////////////////// // Prints the display content on screen (should be called from a low-prio task!) ///////////////////////////////////////////////////////////////////////////// void MbCvScope::tick(void) { bool ongoingCapture = displayBufferHead < MBCV_SCOPE_DISPLAY_BUFFER_SIZE; if( displayUpdateReq || ongoingCapture ) { displayUpdateReq = false; u16 displayHeight = 48; u16 displayWidth = 128; // create snapshot of buffer to ensure a consistent screen u8 tmpBuffer[MBCV_SCOPE_DISPLAY_BUFFER_SIZE]; memcpy(tmpBuffer, displayBuffer, MBCV_SCOPE_DISPLAY_BUFFER_SIZE); mios32_lcd_bitmap_t bitmap; bitmap.height = 8; bitmap.width = 128; bitmap.line_offset = 0; bitmap.colour_depth = 1; u8 bitmapMemory[128]; bitmap.memory = (u8 *)&bitmapMemory[0]; for(int y=0; y<displayHeight; y+=8) { u8 *bufferPtr = tmpBuffer; u8 *bitmapPtr = bitmap.memory; for(int x=0; x<displayWidth; ++x) { u8 value = *(bufferPtr++); if( value >= y && value <= (y+7) ) { *(bitmapPtr++) = 1 << (value % 8); } else { *(bitmapPtr++) = 0x00; } } { MUTEX_LCD_TAKE; if( showOnMainScreen ) APP_SelectMainLCD(); else APP_SelectScopeLCDs(); MIOS32_LCD_DeviceSet(displayNum); MIOS32_LCD_GCursorSet(0, y); MIOS32_LCD_BitmapPrint(bitmap); if( !showOnMainScreen ) APP_SelectMainLCD(); MUTEX_LCD_GIVE; } } if( !showOnMainScreen ) { MUTEX_LCD_TAKE; APP_SelectScopeLCDs(); MIOS32_LCD_DeviceSet(displayNum); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_CursorSet(0, 7); if( source > 0 ) { MIOS32_LCD_PrintFormattedString("CV%d ", source); } else { MIOS32_LCD_PrintFormattedString("--- "); } if( capturedMinValue == MBCV_SCOPE_DISPLAY_MIN_RESET_VALUE ) { MIOS32_LCD_PrintFormattedString("Min:???%%"); } else { u32 percent = ((capturedMinValue + 0x8000) * 100) / 65535; MIOS32_LCD_PrintFormattedString("Min:%3d%%", percent); } if( capturedMaxValue == MBCV_SCOPE_DISPLAY_MAX_RESET_VALUE ) { MIOS32_LCD_PrintFormattedString(" Max:???%%"); } else { u32 percent = ((capturedMaxValue + 0x8000) * 100) / 65535; MIOS32_LCD_PrintFormattedString(" Max:%3d%%", percent); } APP_SelectMainLCD(); MUTEX_LCD_GIVE; } } }