///////////////////////////////////////////////////////////////////////////// // 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) { const char root_name[12*2] = "C C#D D#E F F#G G#A A#B "; // init LCD MIOS32_LCD_Clear(); // endless loop 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()); if( display_update ) { display_update = 0; MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("Root: "); char *selected_root_name = (char *)&root_name[2*selected_root]; MIOS32_LCD_PrintChar(*selected_root_name++); MIOS32_LCD_PrintChar(*selected_root_name); MIOS32_LCD_CursorSet(0, 1); if( selected_scale == 0 ) { MIOS32_LCD_PrintString("No Scale "); } else { MIOS32_LCD_PrintString(SCALE_NameGet(selected_scale-1)); } } } }
///////////////////////////////////////////////////////////////////////////// // 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; }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // clear LCD screen MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("see README.txt "); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintString("for details "); // send delay min/max changes to MIOS terminal while( 1 ) { if( print_message ) { MIOS32_IRQ_Disable(); u32 c_total_delay = total_delay; u32 c_midi_clock_ctr = midi_clock_ctr; delay_t c_d_tick = d_tick; delay_t c_d_beat = d_beat; print_message = 0; MIOS32_IRQ_Enable(); u32 bpm = 60000000 / c_d_beat.delay_last; u32 avg = c_midi_clock_ctr ? (c_total_delay / c_midi_clock_ctr) : 0; MIOS32_MIDI_SendDebugMessage("BPM %d.%d - tick min/avg/max = %d.%03d/%d.%03d/%d.%03d\n", bpm / 1000, bpm % 1000, c_d_tick.delay_min / 1000, c_d_tick.delay_min % 1000, avg / 1000, avg % 1000, c_d_tick.delay_max / 1000, c_d_tick.delay_max % 1000); } } }
///////////////////////////////////////////////////////////////////////////// // 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); } }
///////////////////////////////////////////////////////////////////////////// // Customized HardFault Handler which prints out debugging informations ///////////////////////////////////////////////////////////////////////////// void HardFault_Handler_c(unsigned int * hardfault_args) { // from the book: "The definiteve guide to the ARM Cortex-M3" volatile unsigned int stacked_r0; volatile unsigned int stacked_r1; volatile unsigned int stacked_r2; volatile unsigned int stacked_r3; volatile unsigned int stacked_r12; volatile unsigned int stacked_lr; volatile unsigned int stacked_pc; volatile unsigned int stacked_psr; stacked_r0 = ((unsigned long) hardfault_args[0]); stacked_r1 = ((unsigned long) hardfault_args[1]); stacked_r2 = ((unsigned long) hardfault_args[2]); stacked_r3 = ((unsigned long) hardfault_args[3]); stacked_r12 = ((unsigned long) hardfault_args[4]); stacked_lr = ((unsigned long) hardfault_args[5]); stacked_pc = ((unsigned long) hardfault_args[6]); stacked_psr = ((unsigned long) hardfault_args[7]); MIOS32_MIDI_SendDebugMessage("Hard Fault PC = %08x\n", stacked_pc); // ensure that at least the PC will be sent MIOS32_MIDI_SendDebugMessage("==================\n"); MIOS32_MIDI_SendDebugMessage("!!! HARD FAULT !!!\n"); MIOS32_MIDI_SendDebugMessage("==================\n"); MIOS32_MIDI_SendDebugMessage("R0 = %08x\n", stacked_r0); MIOS32_MIDI_SendDebugMessage("R1 = %08x\n", stacked_r1); MIOS32_MIDI_SendDebugMessage("R2 = %08x\n", stacked_r2); MIOS32_MIDI_SendDebugMessage("R3 = %08x\n", stacked_r3); MIOS32_MIDI_SendDebugMessage("R12 = %08x\n", stacked_r12); MIOS32_MIDI_SendDebugMessage("LR = %08x\n", stacked_lr); MIOS32_MIDI_SendDebugMessage("PC = %08x\n", stacked_pc); MIOS32_MIDI_SendDebugMessage("PSR = %08x\n", stacked_psr); MIOS32_MIDI_SendDebugMessage("BFAR = %08x\n", (*((volatile unsigned long *)(0xE000ED38)))); MIOS32_MIDI_SendDebugMessage("CFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED28)))); MIOS32_MIDI_SendDebugMessage("HFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED2C)))); MIOS32_MIDI_SendDebugMessage("DFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED30)))); MIOS32_MIDI_SendDebugMessage("AFSR = %08x\n", (*((volatile unsigned long *)(0xE000ED3C)))); #ifndef MIOS32_DONT_USE_LCD // TODO: here we should select the normal font - but only if available! // MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_BColourSet(0xffffff); MIOS32_LCD_FColourSet(0x000000); MIOS32_LCD_DeviceSet(0); MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("!! HARD FAULT !!"); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("at PC=0x%08x", stacked_pc); #endif _abort(); }
///////////////////////////////////////////////////////////////////////////// //! Used during startup to print the boot message, which consists of two lines //! specified with MIOS32_LCD_BOOT_MSG_LINE1 and MIOS32_LCD_BOOT_MSG_LINE2.<BR> //! Both lines should be adapted in the mios32_config.h file of an application.<BR> //! The message is automatically print by the programming model after each reset.<BR> //! It will also be returned on a SysEx query. //! \return < 0 on errors ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_LCD_PrintBootMessage(void) { s32 status = 0; status |= MIOS32_LCD_DeviceSet(0); status |= MIOS32_LCD_CursorSet(0, 0); status |= MIOS32_LCD_PrintString(MIOS32_LCD_BOOT_MSG_LINE1); status |= MIOS32_LCD_CursorSet(0, 1); status |= MIOS32_LCD_PrintString(MIOS32_LCD_BOOT_MSG_LINE2); return status; }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // init LCD MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("see README.txt "); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintString("for details "); // endless loop while( 1 ) { // do nothing } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // 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_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); MIOS32_LCD_PrintFormattedString("A%3d M%3d D%3d", seq_midi_out_allocated, seq_midi_out_max_allocated, seq_midi_out_dropouts); MIOS32_LCD_CursorSet(0, 1); if( benchmark_cycles == 0xffffffff ) MIOS32_LCD_PrintFormattedString("Time: overrun "); else MIOS32_LCD_PrintFormattedString("Time: %5d.%d mS ", benchmark_cycles/10, benchmark_cycles%10); // request status screen again (will stop once a new screen is requested by another task) print_msg = PRINT_MSG_STATUS; } break; } } }
///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { if( high_prio ) return 0; // there are no high-priority updates int i; MIOS32_LCD_CursorSet(0, 0); for(i=0; i<16; ++i) { float bpm = seq_core_bpm_preset_tempo[i]; switch( i ) { case 4: MIOS32_LCD_CursorSet(0, 2); break; case 8: MIOS32_LCD_CursorSet(0, 4); break; case 12: MIOS32_LCD_CursorSet(0, 6); break; } if( i == seq_core_bpm_preset_num ) { MIOS32_LCD_PrintFormattedString(ui_cursor_flash ? "> <" : ">%3d<", (int)bpm); } else { MIOS32_LCD_PrintFormattedString(" %3d ", (int)bpm); } } MIOS32_LCD_CursorSet(0, 1); for(i=0; i<16; ++i) { float ramp = seq_core_bpm_preset_ramp[i]; switch( i ) { case 4: MIOS32_LCD_CursorSet(0, 3); break; case 8: MIOS32_LCD_CursorSet(0, 5); break; case 12: MIOS32_LCD_CursorSet(0, 7); break; } if( i == seq_core_bpm_preset_num ) { MIOS32_LCD_PrintFormattedString(ui_cursor_flash ? "> <" : ">%2ds<", (int)ramp); } else { MIOS32_LCD_PrintFormattedString(" %2ds ", (int)ramp); } } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // init LCD MIOS32_LCD_Clear(); // endless loop: print status information on LCD 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()); // print text on LCD screen MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintFormattedString("DIN Pin #%3d %c", last_din_pin, last_din_value ? 'o' : '*'); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("Enc. #%2d (%s)", last_enc, last_enc_dir ? "Right" : "Left "); } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // init LCD 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 IRQs (nested) if( print_msg ) { new_msg = print_msg; print_msg = PRINT_MSG_NONE; // clear request } portEXIT_CRITICAL(); // port specific FreeRTOS function to enable IRQs (nested) switch( new_msg ) { case PRINT_MSG_INIT: MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintFormattedString("see README.txt "); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("for details "); break; case PRINT_MSG_SELECTIONS: { // waveform names const u8 waveform_name[SYNTH_NUM_WAVEFORMS][4] = { "Tri", "Saw", "Pul", "Sin" }; MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintFormattedString(" L R "); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString(" %s %s ", waveform_name[SYNTH_WaveformGet(0)], waveform_name[SYNTH_WaveformGet(1)]); } break; } } }
void vApplicationStackOverflowHook(xTaskHandle xTask, signed portCHAR *pcTaskName) { MIOS32_MIDI_SendDebugMessage("======================\n"); MIOS32_MIDI_SendDebugMessage("!!! STACK OVERFLOW !!!\n"); MIOS32_MIDI_SendDebugMessage("======================\n"); MIOS32_MIDI_SendDebugMessage("Function: %s\n", pcTaskName); #ifndef MIOS32_DONT_USE_LCD // TODO: here we should select the normal font - but only if available! // MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_BColourSet(0xffffff); MIOS32_LCD_FColourSet(0x000000); MIOS32_LCD_DeviceSet(0); MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("!! STACK OVERFLOW !!"); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("in Task %s", pcTaskName); #endif _abort(); }
///////////////////////////////////////////////////////////////////////////// // enabled in FreeRTOSConfig.h ///////////////////////////////////////////////////////////////////////////// void vApplicationMallocFailedHook(void) { #ifndef MIOS32_DONT_USE_LCD // TODO: here we should select the normal font - but only if available! // MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_BColourSet(0xffffff); MIOS32_LCD_FColourSet(0x000000); MIOS32_LCD_DeviceSet(0); MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("FATAL: FreeRTOS "); // 16 chars MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintString("Malloc Error!!! "); // 16 chars #endif #ifndef MIOS32_DONT_USE_MIDI // Note: message won't be sent if MIDI task cannot be created! MIOS32_MIDI_SendDebugMessage("FATAL: FreeRTOS Malloc Error!!!\n"); #endif _abort(); }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // clear LCD MIOS32_LCD_Clear(); // print text MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("READY."); // endless loop 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()); } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // 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_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; } } }
///////////////////////////////////////////////////////////////////////////// //! Initializes LCD driver //! \param[in] mode currently only mode 0 supported //! \return < 0 if initialisation failed ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_LCD_Init(u32 mode) { s32 ret; // currently only mode 0 supported if( mode != 0 ) return -1; // unsupported mode // fetch config from BSL info range MIOS32_LCD_ParametersFetchFromBslInfoRange(); // disable font bitmap font_bitmap.width = 0; // set initial cursor map for character LCDs u8 cursor_map[] = {0x00, 0x40, 0x14, 0x54}; // offset line 0/1/2/3 MIOS32_LCD_CursorMapSet(cursor_map); // note: this has to be done before APP_LCD_Init() is called, so that // the driver is able to modify the default cursor mapping // usage example: "dog" LCDs #if !defined(MIOS32_FAMILY_EMULATION) // initial delay - some LCDs need this! MIOS32_DELAY_Wait_uS(50000); #endif // call application specific init function if( (ret=APP_LCD_Init(mode)) < 0 ) return ret; // clear screen MIOS32_LCD_Clear(); // set character and graphical cursor to initial position MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_GCursorSet(0, 0); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // _exit() for newer newlib versions ///////////////////////////////////////////////////////////////////////////// void exit(int par) { #ifndef MIOS32_DONT_USE_LCD // TODO: here we should select the normal font - but only if available! // MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_BColourSet(0xffffff); MIOS32_LCD_FColourSet(0x000000); MIOS32_LCD_DeviceSet(0); MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("Goodbye!"); #endif #ifndef MIOS32_DONT_USE_MIDI // Note: message won't be sent if MIDI task cannot be created! MIOS32_MIDI_SendDebugMessage("Goodbye!\n"); #endif // pro forma: since this is a noreturn function, loop endless and call _abort (which will never exit) while( 1 ) _abort(); }
///////////////////////////////////////////////////////////////////////////// // 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]); } } }
///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { // layout: // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // No Patterns available as long as the Session hasn't been created! // Please press EXIT and create a new Session! // Main Page // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // A1: Breakbeats 2 16.16 A4: Breakbeat full 10:10:10 // ____ ____ ____ ____ T01: Track Name x__x __x_ ____ ____ 126 BPM // Remix Page // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // MIX .... UMIX .... UMIX .... .... MIX .... .... .... .... .... .... .... .... // In preview_mode we can state tracks to Mix state only(on/off), on normal mode // we can state track do DMix state only(on/off) // Options Page // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // A1: Breakbeats 2 Auto save Auto rset Abtn. Api // Save Name Copy Paste Trk Delay Off On On // Edit Name Page // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // A1: <xxxxxxxxxxxxxxxxxxxx> // .,!1 ABC2 DEF3 GHI4 JKL5 MNO6 PQRS7 TUV8 WXYZ9 -_ 0 Char <> Del Ins OK // Track Delay Page // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // -10 +230 -45 -22 +23 -43 +221 -32 -210 +230 -45 -322 +323 -43 +221 -32 // for this we could use t->bpm_tick_delay, but we need a way to saving // this values inside the track pattern if( SEQ_FILE_FormattingRequired() ) { if( high_prio ) return 0; MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString(" No Patterns available "); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintString("as long as theSession "); MIOS32_LCD_CursorSet(0, 2); MIOS32_LCD_PrintString("hasn't been created!"); MIOS32_LCD_CursorSet(0, 3); MIOS32_LCD_PrintString("Please press EXIT and"); MIOS32_LCD_CursorSet(0, 4); MIOS32_LCD_PrintString("create a new Session! "); MIOS32_LCD_CursorSet(0, 5); SEQ_LCD_PrintSpaces(21); MIOS32_LCD_CursorSet(0, 6); SEQ_LCD_PrintSpaces(21); MIOS32_LCD_CursorSet(0, 7); SEQ_LCD_PrintSpaces(21); return 0; } switch( selected_page ) { /////////////////////////////////////////////////////////////////////////// // REMIX PAGE case PAGE_REMIX: { // Remix Page // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // 1M 2 3M 4 5 6 7 8 9 10 11 12 13 14 15 16 // ... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... // <--------------------------------------><--------------------------------------> // 1D 2 3D 4 5 6 7 8 9 10 11 12 13 14 15 16 // .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... if( high_prio ) { /////////////////////////////////////////////////////////////////////////// // frequently update VU meters and step position counter u8 track; //u8 spacer = 0; MIOS32_LCD_CursorSet(0, 1); seq_core_trk_t *t = &seq_core_trk[0]; for(track=0; track<16; ++t, ++track) { //if( !(track % 4) && (track!=0) ) // spacer++; //MIOS32_LCD_CursorSet(track+spacer, 1); switch( track ) { case 0: MIOS32_LCD_CursorSet(0, 1); break; case 4: MIOS32_LCD_CursorSet(0, 3); break; case 8: MIOS32_LCD_CursorSet(0, 5); break; case 12: MIOS32_LCD_CursorSet(0, 7); break; } //SEQ_LCD_PrintVBar(t->vu_meter >> 4); SEQ_LCD_PrintHBar(t->vu_meter >> 3); } } else { // not high_prio u8 track; MIOS32_LCD_CursorSet(0, 0); SEQ_LCD_PrintSpaces(1); for(track=0; track<16; ++track) { switch( track ) { case 0: MIOS32_LCD_CursorSet(1, 0); break; case 4: MIOS32_LCD_CursorSet(0, 2); break; case 8: MIOS32_LCD_CursorSet(0, 4); break; case 12: MIOS32_LCD_CursorSet(0, 6); break; } // print the mixed state info if( seq_pattern_remix_map & (1 << track) ) { MIOS32_LCD_PrintFormattedString("%dM", track+1); if (track < 9) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintSpaces(2); } // print the demixed state info } else if ( ( seq_pattern_remix_map ^ seq_pattern_demix_map ) & (1 << track) ) { MIOS32_LCD_PrintFormattedString("%dD", track+1); if (track < 9) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintSpaces(2); } }else { MIOS32_LCD_PrintFormattedString("%d", track+1); if (track < 9) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintSpaces(3); } } } SEQ_LCD_PrintSpaces(1); } } break; /////////////////////////////////////////////////////////////////////////// // OPTION PAGE case PAGE_OPTION: { // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // A1: Breakbeats 2 Auto save Abtn. Api // Save Name Copy Paste Off On /////////////////////////////////////////////////////////////////////////// // Current Pattern Name SEQ_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); SEQ_LCD_PrintPattern(seq_pattern[0]); MIOS32_LCD_PrintFormattedString(": %s", seq_pattern_name[0]); /////////////////////////////////////////////////////////////////////////// // Options Labels Left Side MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintString("Save "); MIOS32_LCD_PrintString("Name "); MIOS32_LCD_PrintString("Copy "); MIOS32_LCD_PrintString("Paste"); //MIOS32_LCD_CursorSet(30, 1); //MIOS32_LCD_PrintString("Trk Delay "); /////////////////////////////////////////////////////////////////////////// // Options Labels Right Side MIOS32_LCD_CursorSet(0, 2); MIOS32_LCD_PrintString("Auto save "); //MIOS32_LCD_PrintString("Auto rset "); MIOS32_LCD_PrintString("Abtn. Api "); MIOS32_LCD_CursorSet(0, 3); if (auto_save) { MIOS32_LCD_PrintString(" On "); } else { MIOS32_LCD_PrintString(" Off "); } //if (auto_reset) { // MIOS32_LCD_PrintString(" On "); //} else { // MIOS32_LCD_PrintString(" Off "); //} if (ableton_api) { MIOS32_LCD_PrintString(" On "); } else { MIOS32_LCD_PrintString(" Off "); } } break; /////////////////////////////////////////////////////////////////////////// // PATTERN NAME EDIT PAGE case PAGE_NAME_EDIT: { u8 i; SEQ_LCD_Clear(); MIOS32_LCD_CursorSet(0, 0); SEQ_LCD_PrintPattern(seq_pattern[0]); MIOS32_LCD_PrintString(": "); for(i=0; i<20; ++i) MIOS32_LCD_PrintChar(seq_pattern_name[ui_selected_group][i]); // insert flashing cursor if( ui_cursor_flash ) { MIOS32_LCD_CursorSet(3 + ((ui_edit_name_cursor < 5) ? 1 : 2) + ui_edit_name_cursor, 0); MIOS32_LCD_PrintChar('*'); } SEQ_UI_KeyPad_LCD_Msg(); MIOS32_LCD_CursorSet(10, 7); MIOS32_LCD_PrintString("Back"); //return 0; } break; /////////////////////////////////////////////////////////////////////////// // TRACK DELAY PAGE case PAGE_TRK_DELAY: { // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // -10 +230 -45 -22 +23 -43 +221 -32 -210 +230 -45 -322 +323 -43 +221 -32 u8 track; MIOS32_LCD_CursorSet(0, 2); for(track=0; track<16; ++track) { MIOS32_LCD_PrintFormattedString("%d", track); if (track < 11) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintSpaces(3); } } MIOS32_LCD_CursorSet(1, 2); for(track=0; track<16; ++track) { MIOS32_LCD_PrintFormattedString("%d", track); //MIOS32_LCD_PrintFormattedString("%d", 0); if (track < 11) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintSpaces(3); } } } break; /////////////////////////////////////////////////////////////////////////// // MAIN PAGE case PAGE_MAIN: { // 0000000000111111111122222222223333333333 0000000000111111111122222222223333333333 // 0123456789012345678901234567890123456789 0123456789012345678901234567890123456789 // <--------------------------------------> <--------------------------------------> // A1: Breakbeats 2 16.16 A4: Breakbeat full 10:10:10 // ____ ____ ____ ____ T01: Track Name x__x __x_ ____ ____ 126 BPM //MIOS32_LCD_CursorSet(0, 0); //SEQ_LCD_PrintSpaces(); if( high_prio ) { /////////////////////////////////////////////////////////////////////////// // Frequently update VU meters u8 track; u8 spacer = 0; seq_core_trk_t *t = &seq_core_trk[0]; for(track=0; track<16; ++t, ++track) { if( !(track % 4) && (track!=0) ) spacer++; MIOS32_LCD_CursorSet(track+spacer, 2); //if( seq_core_trk_muted & (1 << track) ) // SEQ_LCD_PrintVBar('M'); //else SEQ_LCD_PrintVBar(t->vu_meter >> 4); } if ( remix_mode && preview_mode ) { spacer = 0; seq_core_trk_t *t = &seq_core_trk[0]; for(track=0; track<16; ++t, ++track) { if( !(track % 4) && (track!=0) ) spacer++; MIOS32_LCD_CursorSet((track+spacer), 6); if( !( seq_pattern_remix_map & (1 << track) ) ) SEQ_LCD_PrintVBar(t->vu_meter >> 4); } } /////////////////////////////////////////////////////////////////////////// // Print Pattern Relative Sequencer Position // MIOS32_LCD_CursorSet(28, 0); // u32 tick = SEQ_BPM_TickGet(); // tick = tick - seq_pattern_start_tick; // u32 ticks_per_step = SEQ_BPM_PPQN_Get() / 4; // u32 ticks_per_measure = ticks_per_step * (seq_core_steps_per_measure+1); // u32 measure = (tick / ticks_per_measure) + 1; // u32 step = ((tick % ticks_per_measure) / ticks_per_step) + 1; //u32 microstep = tick % ticks_per_step; //MIOS32_LCD_PrintFormattedString("%8u.%3d.%3d", measure, step, microstep); // MIOS32_LCD_PrintFormattedString("%8u.%3d", measure, step); } else { // not high_prio
static void TASK_Display(void *pvParameters){ char * err_on; s32 msg_countdown = 0; while(1){ switch(phase){ case BS_CHECK_PHASE_STARTWAIT: if(msg_countdown != -phase){ MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0,0); MIOS32_LCD_PrintString("Bankstick check"); MIOS32_LCD_CursorSet(0,1); MIOS32_LCD_PrintString("Push a button/key.."); MIOS32_MIDI_SendDebugMessage("Push any button or MIDI-key to start the check.."); msg_countdown = -phase; } break; case BS_CHECK_PHASE_START: msg_countdown = -phase; phase = BS_CHECK_PHASE_INIT; break; case BS_CHECK_PHASE_WRITE: MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0,0); MIOS32_LCD_PrintFormattedString("Write blocks 0x%04X",block); MIOS32_LCD_CursorSet(0,1); MIOS32_LCD_PrintFormattedString("Bankstick %d, Run %d",bs,run+1); if(msg_countdown <= 0){ MIOS32_MIDI_SendDebugMessage("Write blocks 0x%04X (bankstick %d, run %d)",block,bs,run+1); msg_countdown = 0;// restart message countdown if it was disabled } break; case BS_CHECK_PHASE_READ: MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0,0); MIOS32_LCD_PrintFormattedString("Read blocks 0x%04X",block); MIOS32_LCD_CursorSet(0,1); MIOS32_LCD_PrintFormattedString("Bankstick %d, Run %d",bs,run+1); if(msg_countdown <= 0){ MIOS32_MIDI_SendDebugMessage("Read blocks 0x%04X (bankstick %d, run %d)",block,bs,run+1); msg_countdown = 0;// restart message countdown if it was disabled } break; case BS_CHECK_PHASE_FINISHED: if(msg_countdown != -phase){// was this stuff already printed/ sent do debug condsole? msg_countdown = -phase;// disable further message output in this phase MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0,0); if(last_error){ switch(last_error){ case BS_CHECK_ERROR_AVAILABLE: err_on = "available"; break; case BS_CHECK_ERROR_INIT: err_on = "init"; break; case BS_CHECK_ERROR_WRITE: err_on = "write"; break; case BS_CHECK_ERROR_CHECK_WRITE_FINISHED: err_on = "write wait"; break; case BS_CHECK_ERROR_READ: err_on = "read"; break; case BS_CHECK_ERROR_COMPARE: err_on = "compare"; break; } MIOS32_LCD_PrintFormattedString("Err: %s %d",err_on,last_error_code); MIOS32_LCD_CursorSet(0,1); MIOS32_LCD_PrintFormattedString("BS:%d B:0x%04x R:%d",bs,block,run); MIOS32_MIDI_SendDebugMessage("Error on %s, Error code %d, Bankstick %d, Block %d, Run %d", err_on,last_error_code,bs,block,run); } else{ MIOS32_LCD_PrintFormattedString("Bankstick check"); MIOS32_LCD_CursorSet(0,1); MIOS32_LCD_PrintFormattedString("success (%d runs)",BS_CHECK_NUM_RUNS); MIOS32_MIDI_SendDebugMessage("Banstick check finished successfully (%d runs)!",BS_CHECK_NUM_RUNS); } MIOS32_MIDI_SendDebugMessage("Push any button or MIDI-key to re-start the check.."); } break; } // if msg_countdown is < 0, don't change it (used to stop further message output by phase) if(msg_countdown >= 0) msg_countdown = msg_countdown ? msg_countdown - 1 : DISPLAY_TASK_MSG_COUNTDOWN_STARTVALUE; // wait DISPLAY_TASK_DELAY mS vTaskDelay(DISPLAY_TASK_DELAYMS / portTICK_RATE_MS); } }
///////////////////////////////////////////////////////////////////////////// // 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; } } }
///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( depressed ) return 0; // ignore when button depressed // reset tap tempo if any button != GP16 has been pressed if( button != SEQ_UI_BUTTON_GP16 ) resetTapTempo(); #if 0 // leads to: comparison is always true due to limited range of data type if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) { #else if( button <= SEQ_UI_BUTTON_GP16 ) { #endif switch( button ) { case SEQ_UI_BUTTON_GP6: case SEQ_UI_BUTTON_GP7: // fire preset SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]); return 1; case SEQ_UI_BUTTON_GP8: // enter preset selection page SEQ_UI_PageSet(SEQ_UI_PAGE_BPM_PRESETS); return 1; } // re-use encoder handler - only select UI item, don't increment return Encoder_Handler((int)button, 0); } // remaining buttons: switch( button ) { case SEQ_UI_BUTTON_Select: case SEQ_UI_BUTTON_Right: if( ++ui_selected_item >= NUM_OF_ITEMS ) ui_selected_item = 0; return 1; // value always changed case SEQ_UI_BUTTON_Left: if( ui_selected_item == 0 ) ui_selected_item = NUM_OF_ITEMS-1; else --ui_selected_item; return 1; // value always changed case SEQ_UI_BUTTON_Up: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); case SEQ_UI_BUTTON_Down: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); } return -1; // invalid or unsupported button } ///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { if( high_prio ) return 0; // there are no high-priority updates // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Mode Preset Tempo Ramp Fire Preset MClk In/Out Ext. Tap // Master 1 140.0 1s Preset Page USB1 I:on O:off Restart Tempo /////////////////////////////////////////////////////////////////////////// MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString(" Mode Preset Tempo "); MIOS32_LCD_CursorSet(0, 2); MIOS32_LCD_PrintString("Ramp Fire Preset"); MIOS32_LCD_CursorSet(0, 4); MIOS32_LCD_PrintString("MClk In/Out"); MIOS32_LCD_PrintString(seq_core_state.EXT_RESTART_REQ ? "Ongoing" : " Ext. "); MIOS32_LCD_PrintString(" Tap "); /////////////////////////////////////////////////////////////////////////// MIOS32_LCD_CursorSet(0, 1); if( ui_selected_item == ITEM_MODE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(6); } else { const char mode_str[3][7] = { " Auto ", "Master", "Slave "}; MIOS32_LCD_PrintString((char *)mode_str[SEQ_BPM_ModeGet()]); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_PRESET && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(2); } else { MIOS32_LCD_PrintFormattedString("%2d", seq_core_bpm_preset_num+1); } SEQ_LCD_PrintSpaces(3); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_BPM && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { float bpm = seq_core_bpm_preset_tempo[seq_core_bpm_preset_num]; MIOS32_LCD_PrintFormattedString("%3d.%d", (int)bpm, (int)(10*bpm)%10); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_RAMP && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { float ramp = seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]; MIOS32_LCD_PrintFormattedString("%2ds", (int)ramp); } /////////////////////////////////////////////////////////////////////////// MIOS32_LCD_PrintString(" Preset Page "); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_MCLK_PORT && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { MIOS32_LCD_PrintString(SEQ_MIDI_PORT_ClkNameGet(SEQ_MIDI_PORT_ClkIxGet(selected_mclk_port))); } SEQ_LCD_PrintSpaces(1); /////////////////////////////////////////////////////////////////////////// MIOS32_LCD_PrintString("I:"); if( ui_selected_item == ITEM_MCLK_IN && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { s32 status = SEQ_MIDI_ROUTER_MIDIClockInGet(selected_mclk_port); if( !SEQ_MIDI_PORT_ClkCheckAvailable(selected_mclk_port) ) status = -1; // MIDI In port not available switch( status ) { case 0: MIOS32_LCD_PrintString("off"); break; case 1: MIOS32_LCD_PrintString("on "); break; default: MIOS32_LCD_PrintString("---"); } } SEQ_LCD_PrintSpaces(1); /////////////////////////////////////////////////////////////////////////// MIOS32_LCD_PrintString("O:"); if( ui_selected_item == ITEM_MCLK_OUT && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { s32 status = SEQ_MIDI_ROUTER_MIDIClockOutGet(selected_mclk_port); if( !SEQ_MIDI_PORT_ClkCheckAvailable(selected_mclk_port) ) status = -1; // MIDI Out port not available switch( status ) { case 0: MIOS32_LCD_PrintString("off"); break; case 1: MIOS32_LCD_PrintString("on "); break; default: MIOS32_LCD_PrintString("---"); } } SEQ_LCD_PrintSpaces(3); // DIN Sync moved to CV configuration SEQ_LCD_PrintSpaces(3+4); /////////////////////////////////////////////////////////////////////////// MIOS32_LCD_PrintString("Restart Tempo"); return 0; // no error } ///////////////////////////////////////////////////////////////////////////// // Local exit function ///////////////////////////////////////////////////////////////////////////// static s32 EXIT_Handler(void) { s32 status = 0; if( store_file_required ) { // write config file MUTEX_SDCARD_TAKE; if( (status=SEQ_FILE_C_Write(seq_file_session_name)) < 0 ) SEQ_UI_SDCardErrMsg(2000, status); MUTEX_SDCARD_GIVE; store_file_required = 0; } return status; }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { int num_lcds = mios32_lcd_parameters.num_x * mios32_lcd_parameters.num_y; // print configured LCD parameters MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("Multi-CLCD 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); if( mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_CLCD && mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_CLCD_DOG ) { // print warning if correct LCD hasn't been selected MIOS32_MIDI_SendDebugMessage("WARNING: your core module hasn't been configured for CLCD or CLCD_DOG!\n"); MIOS32_MIDI_SendDebugMessage("Please do this with the bootloader update application!\n"); } // initialize all LCDs (although programming_models/traditional/main.c will only initialize the first two) int lcd; for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_MIDI_SendDebugMessage("Initialize LCD #%d\n", lcd+1); MIOS32_LCD_DeviceSet(lcd); if( MIOS32_LCD_Init(0) < 0 ) { MIOS32_MIDI_SendDebugMessage("Failed - no response from LCD #%d.%d\n", (lcd % mios32_lcd_parameters.num_x) + 1, (lcd / mios32_lcd_parameters.num_x) + 1); } } // init special characters for all LCDs for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_LCD_DeviceSet(lcd); MIOS32_LCD_SpecialCharsInit((u8 *)charset_vert_bars); MIOS32_LCD_Clear(); } // print text on all LCDs for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_LCD_DeviceSet(lcd); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintFormattedString("LCD #%d.%d", (lcd % mios32_lcd_parameters.num_x) + 1, (lcd / mios32_lcd_parameters.num_x) + 1); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("READY."); } // print animated vertical bar while( 1 ) { int i, j; for(i=0; i<8; ++i) { // print vertical bars depending on i for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_LCD_DeviceSet(lcd); MIOS32_LCD_CursorSet(12, 0); for(j=0; j<8; ++j) { u8 c = (i + j) % 8; MIOS32_LCD_PrintChar(c); } } // wait for 100 mS for(j=0; j<100; ++j) MIOS32_DELAY_Wait_uS(1000); } } }
///////////////////////////////////////////////////////////////////////////// //! 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 }
///////////////////////////////////////////////////////////////////////////// // This task handles the control surface ///////////////////////////////////////////////////////////////////////////// static void TASK_Period_1mS_LP(void *pvParameters) { u16 sdcard_check_ctr = 0; MIOS32_LCD_Clear(); while( 1 ) { vTaskDelay(1 / portTICK_RATE_MS); // call SCS handler SCS_Tick(); // each second: check if SD Card (still) available if( ++sdcard_check_ctr >= 1000 ) { sdcard_check_ctr = 0; MUTEX_SDCARD_TAKE; s32 status = FILE_CheckSDCard(); if( status == 1 ) { DEBUG_MSG("SD Card connected: %s\n", FILE_VolumeLabel()); // load all file infos SYNTH_FILE_LoadAllFiles(1); // including HW info } else if( status == 2 ) { DEBUG_MSG("SD Card disconnected\n"); // invalidate all file infos SYNTH_FILE_UnloadAllFiles(); // change status SYNTH_FILE_StatusMsgSet("No SD Card"); } else if( status == 3 ) { if( !FILE_SDCardAvailable() ) { DEBUG_MSG("SD Card not found\n"); SYNTH_FILE_StatusMsgSet("No SD Card"); } else if( !FILE_VolumeAvailable() ) { DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n"); SYNTH_FILE_StatusMsgSet("No FAT"); } else { int bank; for(bank=0; bank<SYNTH_FILE_B_NUM_BANKS; ++bank) { u8 numPatches = SYNTH_FILE_B_NumPatches(bank); if( numPatches ) { DEBUG_MSG("Bank #%d contains %d patches\n", bank+1, numPatches); } else { DEBUG_MSG("Bank #%d not found - creating new one\n", bank+1); if( (status=SYNTH_FILE_B_Create(bank)) < 0 ) { DEBUG_MSG("Failed to create Bank #%d (status: %d)\n", bank+1, status); } else { DEBUG_MSG("Bank #%d successfully created!\n", bank+1); int numPatches = SYNTH_FILE_B_NumPatches(bank); int patch; for(patch=0; patch<numPatches; ++patch) { DEBUG_MSG("Writing Bank %d Patch #%d\n", bank+1, patch+1); MIOS32_LCD_CursorSet(0, 0); // TMP - use message system later MIOS32_LCD_PrintFormattedString("Write Patch %d.%03d ", bank+1, patch+1); MIOS32_LCD_CursorSet(0, 1); // TMP - use message system later MIOS32_LCD_PrintFormattedString("Please wait... "); u8 sourceGroup = 0; u8 rename_if_empty_name = 0; if( (status=SYNTH_FILE_B_PatchWrite(bank, patch, sourceGroup, rename_if_empty_name)) < 0 ) { DEBUG_MSG("Failed to write patch #%d into bank #%d (status: %d)\n", patch+1, bank+1, status); } } SCS_DisplayUpdateRequest(); } } } // disable status message and print patch SYNTH_FILE_StatusMsgSet(NULL); status = SYNTH_FILE_UnloadAllFiles(); status = SYNTH_FILE_LoadAllFiles(1); if( status < 0 ) { DEBUG_MSG("Failed to load the newly created files!\n"); } else { u8 initialBank = 0; u8 initialPatch = 0; u8 targetGroup = 0; if( (status=SYNTH_FILE_B_PatchRead(initialBank, initialPatch, targetGroup)) < 0 ) { char buffer[100]; sprintf(buffer, "Patch %c%03d", 'A'+initialBank, initialPatch+1); SCS_Msg(SCS_MSG_ERROR_L, 1000, "Failed to read", buffer); } else { // char buffer[100]; // sprintf(buffer, "Patch %c%03d", 'A'+initialBank, initialPatch+1); // SCS_Msg(SCS_MSG_L, 1000, buffer, "read!"); } } } } MUTEX_SDCARD_GIVE; } } }