///////////////////////////////////////////////////////////////////////////// // This timer function is periodically called each 100 uS ///////////////////////////////////////////////////////////////////////////// static void APP_Periodic_100uS(void) { // this is a very simple way to generate a nice PWM based flashing effect // for multiple LEDs from a single timer u8 *led_trigger_ptr = (u8 *)&led_trigger[0]; u8 *led_pwm_counter_ptr = (u8 *)&led_pwm_counter[0]; int i; for(i=0; i<NUM_LED_TRIGGERS; ++i, ++led_trigger_ptr, ++led_pwm_counter_ptr) { if( *led_trigger_ptr ) { if( --*led_pwm_counter_ptr ) { if( *led_pwm_counter_ptr == *led_trigger_ptr ) { if( i == 0 ) MIOS32_BOARD_LED_Set(1, 1); else MIOS32_BOARD_J5_PinSet(i-1, 1); } } else { *led_pwm_counter_ptr = LED_PWM_PERIOD; --*led_trigger_ptr; if( i == 0 ) MIOS32_BOARD_LED_Set(1, 0); else MIOS32_BOARD_J5_PinSet(i-1, 0); } } } }
///////////////////////////////////////////////////////////////////////////// // This function aborts any operations, but keeps MIDI alive (for uploading // a new firmware) // If MIDI isn't enabled, the status LED will be flashed ///////////////////////////////////////////////////////////////////////////// void _abort(void) { #ifndef MIOS32_DONT_USE_MIDI // keep MIDI alive, so that program code can be updated u32 delay_ctr = 0; while( 1 ) { ++delay_ctr; if( (delay_ctr % 100) == 0 ) { // handle timeout/expire counters and USB packages MIOS32_MIDI_Periodic_mS(); } // check for incoming MIDI packages and call hook MIOS32_MIDI_Receive_Handler(APP_MIDI_NotifyPackage); if( (delay_ctr % 10000) == 0 ) { // toggle board LED MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get()); } } #else u32 delay_ctr = 0; while( 1 ) { ++delay_ctr; if( (delay_ctr % 1000000) == 0 ) { // toggle board LED MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get()); } } #endif }
///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // if note event over MIDI channel #1 controls note of both oscillators // Note On received? if( midi_package.chn == Chn1 && (midi_package.type == NoteOn || midi_package.type == NoteOff) ) { // branch depending on Note On/Off event if( midi_package.event == NoteOn && midi_package.velocity > 0 ) { // push note into note stack NOTESTACK_Push(¬estack, midi_package.note, midi_package.velocity); } else { // remove note from note stack NOTESTACK_Pop(¬estack, midi_package.note); } // still a note in stack? if( notestack.len ) { // take first note of stack u8 note = notestack_items[0].note; u8 velocity = notestack_items[0].tag; // set frequency for both oscillators int chn; for(chn=0; chn<2; ++chn) { SYNTH_FrequencySet(chn, frqtab[note]); SYNTH_VelocitySet(chn, velocity); } // set board LED MIOS32_BOARD_LED_Set(1, 1); } else { // turn off LED (can also be used as a gate output!) MIOS32_BOARD_LED_Set(1, 0); // set velocity to 0 for all oscillators int chn; for(chn=0; chn<2; ++chn) SYNTH_VelocitySet(chn, 0x00); } #if 0 // optional debug messages NOTESTACK_SendDebugMessage(¬estack); #endif // CC#1 over MIDI channel #1 controls waveform } else if( midi_package.event == CC && midi_package.chn == Chn1 ) { int chn; for(chn=0; chn<2; ++chn) SYNTH_WaveformSet(chn, midi_package.value >> 5); // print selection print_msg = PRINT_MSG_SELECTIONS; }
///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // 1) the LED should be turned on whenever a Note On Event with velocity > 0 // has been received if( midi_package.type == NoteOn && midi_package.velocity > 0 ) MIOS32_BOARD_LED_Set(1, 1); // 2) the LED should be turned off whenever a Note Off Event or a Note On // event with velocity == 0 has been received (the MIDI spec says, that velocity 0 // should be handled like Note Off) else if( (midi_package.type == NoteOff) || (midi_package.type == NoteOn && midi_package.velocity == 0) ) MIOS32_BOARD_LED_Set(1, 0); }
///////////////////////////////////////////////////////////////////////////// // 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)); } } } }
///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // initialize all LEDs MIOS32_BOARD_LED_Init(0xffffffff); // turn off gate LED MIOS32_BOARD_LED_Set(1, 0); // create semaphores xSDCardSemaphore = xSemaphoreCreateRecursiveMutex(); // initialize file functions FILE_Init(0); // initialize MIDI handler SEQ_MIDI_OUT_Init(0); // initialize sequencer SEQ_Init(0); // install MIDI Rx callback function MIOS32_MIDI_DirectRxCallback_Init(NOTIFY_MIDI_Rx); // install sequencer task xTaskCreate(TASK_SEQ, (signed portCHAR *)"SEQ", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_SEQ, NULL); }
///////////////////////////////////////////////////////////////////////////// //! This hook is called each mS from the main task which also handles DIN, ENC //! and AIN events. You could add more jobs here, but they shouldn't consume //! more than 300 uS to ensure the responsiveness of buttons, encoders, pots. //! Alternatively you could create a dedicated task for application specific //! jobs as explained in $MIOS32_PATH/apps/tutorials/006_rtos_tasks ///////////////////////////////////////////////////////////////////////////// void APP_Tick(void) { // toggle the status LED (this is a sign of life) MIOS32_BOARD_LED_Set(0x0001, ~MIOS32_BOARD_LED_Get()); // // execute sequencer handler // MUTEX_SDCARD_TAKE; // SEQ_Handler(); // MUTEX_SDCARD_GIVE; // // send timestamped MIDI events // MUTEX_MIDIOUT_TAKE; // SEQ_MIDI_OUT_Handler(); // MUTEX_MIDIOUT_GIVE; if( hw_enabled ) { // Scan Matrix button handler MBNG_MATRIX_ButtonHandler(); // update CV outputs MBNG_CV_Update(); // update MAX72xx chain MBNG_MATRIX_MAX72xx_Update(); // handle timed AIN events (sensor mode) MBNG_AIN_Periodic(); // scan AINSER pins AINSER_Handler(APP_AINSER_NotifyChange); } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// extern "C" void APP_Background(void) { // toggle the state of all LEDs (allows to measure the execution speed with a scope) #if 0 MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); #endif }
///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // toggle Status LED on each incoming MIDI package MIOS32_BOARD_LED_Set(0x0001, ~MIOS32_BOARD_LED_Get()); // 1) the LED should be turned on whenever a Note On Event with velocity > 0 // has been received if( midi_package.type == NoteOn && midi_package.velocity > 0 ) { // determine LED number (one of 12, each octave) u8 led = midi_package.note % 12; // turn on LED MIOS32_BOARD_J5_PinSet(led, 1); } // 2) the LED should be turned off whenever a Note Off Event or a Note On // event with velocity == 0 has been received (the MIDI spec says, that velocity 0 // should be handled like Note Off) else if( (midi_package.type == NoteOff) || (midi_package.type == NoteOn && midi_package.velocity == 0) ) { // determine LED number (one of 12, each octave) u8 led = midi_package.note % 12; // turn off LED MIOS32_BOARD_J5_PinSet(led, 0); } }
static void TASK_SPI_Handler(void *pvParameters) { portTickType xLastExecutionTime; // Initialise the xLastExecutionTime variable on task entry xLastExecutionTime = xTaskGetTickCount(); // fill Tx Buffer with housenumbers { int i; for(i=0; i<TRANSFER_BUFFER_SIZE; ++i) tx_buffer[i] = i; } while( 1 ) { // wait for 100 mS vTaskDelayUntil(&xLastExecutionTime, 100 / portTICK_RATE_MS); // toggle Status LED to as a sign of live MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get()); // activate CS pin MIOS32_SPI_RC_PinSet(MASTER_SPI, MASTER_CS_PIN, 0); // spi, rc_pin, pin_value // send data non-blocking MIOS32_SPI_TransferBlock(MASTER_SPI, tx_buffer, rx_buffer, TRANSFER_BUFFER_SIZE, SPI_Callback); } }
static void TASK_SPI_Handler(void *pvParameters) { // fill Tx Buffer with housenumbers { int i; for(i=0; i<TRANSFER_BUFFER_SIZE; ++i) tx_buffer[i] = i; } while( 1 ) { int i; for(i=0; i<TRANSFER_BUFFER_SIZE; ++i) { // toggle Status LED to as a sign of live MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get()); // receive byte rx_buffer[i] = MIOS32_SPI_TransferByte(SLAVE_SPI, tx_buffer[i]); } SPI_Callback(); // print received bytes MIOS32_MIDI_SendDebugHexDump((u8 *)rx_buffer, TRANSFER_BUFFER_SIZE); } }
///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // toggle Status LED on each incoming MIDI package MIOS32_BOARD_LED_Set(0x0001, ~MIOS32_BOARD_LED_Get()); // 1) the LED should be turned on whenever a Note On Event with velocity > 0 // has been received if( midi_package.type == NoteOn && midi_package.velocity > 0 ) { // determine pin number (add offset, so that the first LED starts at C-2) u8 pin = (midi_package.note - MIDI_STARTNOTE) & 0x7f; // turn on LED MIOS32_DOUT_PinSet(pin, 1); } // 2) the LED should be turned off whenever a Note Off Event or a Note On // event with velocity == 0 has been received (the MIDI spec says, that velocity 0 // should be handled like Note Off) else if( (midi_package.type == NoteOff) || (midi_package.type == NoteOn && midi_package.velocity == 0) ) { // determine pin number (add offset, so that the first LED starts at C-2) u8 pin = (midi_package.note - MIDI_STARTNOTE) & 0x7f; // turn off LED MIOS32_DOUT_PinSet(pin, 0); } }
///////////////////////////////////////////////////////////////////////////// // This hook is called each mS from the main task which also handles DIN, ENC // and AIN events. You could add more jobs here, but they shouldn't consume // more than 300 uS to ensure the responsiveness of buttons, encoders, pots. // Alternatively you could create a dedicated task for application specific // jobs as explained in $MIOS32_PATH/apps/tutorials/006_rtos_tasks ///////////////////////////////////////////////////////////////////////////// void APP_Tick(void) { // PWM modulate the status LED (this is a sign of life) u32 timestamp = MIOS32_TIMESTAMP_Get(); MIOS32_BOARD_LED_Set(1, (timestamp % 20) <= ((timestamp / 100) % 10)); // scan AINSER pins AINSER_Handler(APP_AINSER_NotifyChange); }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // 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 hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void){ // initialize all LEDs MIOS32_BOARD_LED_Init(0xffffffff); MIOS32_BOARD_LED_Set(0xffffffff,0); phase = BS_CHECK_PHASE_STARTWAIT; MIOS32_MIDI_SendDebugMessage("Bankstick r/w check"); // setup display task xTaskCreate(TASK_Display, (signed portCHAR *)"Display", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_DISPLAY, NULL); }
///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { int i; // create semaphores xMIDIINSemaphore = xSemaphoreCreateRecursiveMutex(); xMIDIOUTSemaphore = xSemaphoreCreateRecursiveMutex(); // clear SysEx buffers for(i=0; i<NUM_SYSEX_BUFFERS; ++i) sysex_buffer_len[i] = 0; // install SysEx callback MIOS32_MIDI_SysExCallback_Init(APP_SYSEX_Parser); // read EEPROM content PRESETS_Init(0); // init terminal TERMINAL_Init(0); // init MIDImon MIDIMON_Init(0); // start uIP task UIP_TASK_Init(0); // initialize status LED MIOS32_BOARD_LED_Init(0xffffffff); MIOS32_BOARD_LED_Set(1, 0); led_pwm_counter[0] = LED_PWM_PERIOD; led_trigger[0] = LED_PWM_PERIOD; // trigger LED on startup for complete PWM cycle // initialize additional LEDs connected to J5A for(i=1; i<NUM_LED_TRIGGERS; ++i) { led_pwm_counter[i] = LED_PWM_PERIOD; led_trigger[i] = LED_PWM_PERIOD; // trigger LED on startup for complete PWM cycle MIOS32_BOARD_J5_PinInit(i-1, MIOS32_BOARD_PIN_MODE_OUTPUT_PP); MIOS32_BOARD_J5_PinSet(i-1, 0); } // initialize J5B/J5C pins as inputs with pull-up enabled // these pins control diagnostic options of the MIDI monitor for(i=4; i<12; ++i) MIOS32_BOARD_J5_PinInit(i, MIOS32_BOARD_PIN_MODE_INPUT_PU); // install timer function which is called each 100 uS MIOS32_TIMER_Init(0, 100, APP_Periodic_100uS, MIOS32_IRQ_PRIO_MID); // print welcome message on MIOS terminal MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("=====================\n"); MIOS32_MIDI_SendDebugMessage("%s\n", MIOS32_LCD_BOOT_MSG_LINE1); MIOS32_MIDI_SendDebugMessage("=====================\n"); MIOS32_MIDI_SendDebugMessage("\n"); }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // toggle the state of all LEDs (allows to measure the execution speed with a scope) #if 0 MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); #endif // for idle time measurements SEQ_STATISTICS_Idle(); }
///////////////////////////////////////////////////////////////////////////// // This hook is called when an AINSER pot has been moved ///////////////////////////////////////////////////////////////////////////// static void APP_AINSER_NotifyChange(u32 module, u32 pin, u32 pin_value) { // toggle Status LED on each AIN value change MIOS32_BOARD_LED_Set(0x0001, ~MIOS32_BOARD_LED_Get()); // convert 12bit value to 7bit value u8 value_7bit = pin_value >> 5; // send MIDI event MIOS32_MIDI_SendCC(DEFAULT, Chn1, pin + 0x10, value_7bit); }
///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { if( midi_package.type == NoteOn && midi_package.velocity > 0 ) { // change debug interface (where messages are forwarded) MIOS32_MIDI_DebugPortSet(port); // reset benchmark BENCHMARK_Reset(); portENTER_CRITICAL(); // port specific FreeRTOS function to disable tasks (nested) // turn on LED (e.g. for measurements with a scope) MIOS32_BOARD_LED_Set(0xffffffff, 1); // reset stopwatch MIOS32_STOPWATCH_Reset(); // start benchmark BENCHMARK_Start(); // capture counter value benchmark_cycles = MIOS32_STOPWATCH_ValueGet(); // turn off LED MIOS32_BOARD_LED_Set(0xffffffff, 0); portEXIT_CRITICAL(); // port specific FreeRTOS function to enable tasks (nested) // print result on MIOS terminal if( benchmark_cycles == 0xffffffff ) MIOS32_MIDI_SendDebugMessage("Time: overrun!\n"); else MIOS32_MIDI_SendDebugMessage("Time: %5d.%d mS\n", benchmark_cycles/10, benchmark_cycles%10); // print status screen print_msg = PRINT_MSG_STATUS; } }
///////////////////////////////////////////////////////////////////////////// // 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 hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // initialize all LEDs MIOS32_BOARD_LED_Init(0xffffffff); MIOS32_BOARD_LED_Set(0xffffffff, 0); // increase default verbose level (for this demo app...) MBNET_VerboseLevelSet(3); // start MBNet Task MBNET_TASK_Init(0); // start terminal TERMINAL_Init(0); }
///////////////////////////////////////////////////////////////////////////// // 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; } } }
///////////////////////////////////////////////////////////////////////////// // This hook is called when an encoder has been moved // incrementer is positive when encoder has been turned clockwise, else // it is negative ///////////////////////////////////////////////////////////////////////////// void APP_ENC_NotifyChange(u32 encoder, s32 incrementer) { // toggle Status LED on each AIN value change MIOS32_BOARD_LED_Set(0x0001, ~MIOS32_BOARD_LED_Get()); // determine relative value: 64 +/- <incrementer> int value = 64 + incrementer; // ensure that value is in range of 0..127 if( value < 0 ) value = 0; else if( value > 127 ) value = 127; // send event MIOS32_MIDI_SendCC(DEFAULT, Chn1, 0x10 + encoder, value); }
///////////////////////////////////////////////////////////////////////////// // 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 hook is called when an encoder has been moved // incrementer is positive when encoder has been turned clockwise, else // it is negative ///////////////////////////////////////////////////////////////////////////// void APP_ENC_NotifyChange(u32 encoder, s32 incrementer) { // toggle Status LED on each AIN value change MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get()); // increment to virtual position and ensure that the value is in range 0..127 int value = enc_virtual_pos[encoder] + incrementer; if( value < 0 ) value = 0; else if( value > 127 ) value = 127; // only send if value has changed if( enc_virtual_pos[encoder] != value ) { // store new value enc_virtual_pos[encoder] = value; // send event MIOS32_MIDI_SendCC(DEFAULT, Chn1, 0x10 + encoder, value); } }
///////////////////////////////////////////////////////////////////////////// // 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 called periodically each mS to handle sequencer requests ///////////////////////////////////////////////////////////////////////////// static void TASK_SEQ(void *pvParameters) { portTickType xLastExecutionTime; u16 sdcard_check_ctr = 0; // Initialise the xLastExecutionTime variable on task entry xLastExecutionTime = xTaskGetTickCount(); while( 1 ) { vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS); // execute sequencer handler SEQ_Handler(); // send timestamped MIDI events SEQ_MIDI_OUT_Handler(); // each second: check if SD Card (still) available if( ++sdcard_check_ctr >= 1000 ) { sdcard_check_ctr = 0; // use a mutex if multiple tasks access the SD Card! MUTEX_SDCARD_TAKE; s32 status = FILE_CheckSDCard(); if( status == 1 ) { MIOS32_MIDI_SendDebugMessage("SD Card connected: %s\n", FILE_VolumeLabel()); } else if( status == 2 ) { MIOS32_MIDI_SendDebugMessage("SD Card disconnected\n"); // stop sequencer SEQ_BPM_Stop(); // change filename sprintf(MID_FILE_UI_NameGet(), "No SD Card"); } else if( status == 3 ) { if( !FILE_SDCardAvailable() ) { MIOS32_MIDI_SendDebugMessage("SD Card not found\n"); // change filename sprintf(MID_FILE_UI_NameGet(), "No SD Card"); } else if( !FILE_VolumeAvailable() ) { MIOS32_MIDI_SendDebugMessage("ERROR: SD Card contains invalid FAT!\n"); MIOS32_BOARD_LED_Set(0x1, 0x0); // turn off LED // change filename sprintf(MID_FILE_UI_NameGet(), "No FAT"); // stop sequencer SEQ_BPM_Stop(); } else { // change filename sprintf(MID_FILE_UI_NameGet(), "SDCard found"); // if in auto mode and BPM generator is clocked in slave mode: // change to master mode SEQ_BPM_CheckAutoMaster(); // reset sequencer SEQ_Reset(1); // request to play the first file SEQ_PlayFileReq(0); // start sequencer SEQ_BPM_Start(); } } MUTEX_SDCARD_GIVE; } } }
///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // if note event over MIDI channel #1 controls note of both oscillators // Note On received? if( midi_package.chn == Chn1 && (midi_package.type == NoteOn || midi_package.type == NoteOff) ) { // branch depending on Note On/Off event if( midi_package.event == NoteOn && midi_package.velocity > 0 ) { // push note into note stack NOTESTACK_Push(¬estack, midi_package.note, midi_package.velocity); } else { // remove note from note stack NOTESTACK_Pop(¬estack, midi_package.note); } // still a note in stack? if( notestack.len ) { // take first note of stack u8 note = notestack_items[0].note; u8 velocity = notestack_items[0].tag; #if 0 // set frequency for both oscillators int chn; for(chn=0; chn<2; ++chn) { SYNTH_FrequencySet(chn, frqtab[note]); SYNTH_VelocitySet(chn, velocity); } #endif // play note int phrase_num = note - PHRASE_NOTE_OFFSET; while( phrase_num < 0) phrase_num += SYNTH_NUM_PHRASES; while( phrase_num > SYNTH_NUM_PHRASES ) phrase_num -= SYNTH_NUM_PHRASES; // legato... if( notestack.len == 1 ) SYNTH_PhraseStop(phrase_num); SYNTH_PhrasePlay(phrase_num, velocity); // set board LED MIOS32_BOARD_LED_Set(1, 1); } else { // turn off LED (can also be used as a gate output!) MIOS32_BOARD_LED_Set(1, 0); #if 0 // set velocity to 0 for all oscillators int chn; for(chn=0; chn<2; ++chn) SYNTH_VelocitySet(chn, 0x00); #endif } #if 0 // optional debug messages NOTESTACK_SendDebugMessage(¬estack); #endif } else if( midi_package.type == CC ) { u8 phrase_num = 0; u8 phoneme_ix = midi_package.chn; u32 value = midi_package.value; if( midi_package.cc_number < 16 ) { } else if( midi_package.cc_number < 32 ) { u8 phoneme_par = midi_package.cc_number - 16; SYNTH_PhonemeParSet(phrase_num, phoneme_ix, phoneme_par, value); } else if( midi_package.cc_number < 48 ) { u8 phrase_par = midi_package.cc_number - 32; SYNTH_PhraseParSet(phrase_num, phrase_par, value); } else if( midi_package.cc_number < 64 ) { u8 global_par = midi_package.cc_number - 48; SYNTH_GlobalParSet(global_par, value); } } }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // set LED depending on sequencer run state MIOS32_BOARD_LED_Set(1, SEQ_BPM_IsRunning() ? 1 : 0); }
///////////////////////////////////////////////////////////////////////////// // 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]); } } }