robinfawell Posted October 21, 2013 Report Share Posted October 21, 2013 As mentioned previously during the last few weeks on the forum I am revising my digital piano program. This based on TK's example. After a few problems I have now added a few extra functions to my program, namely:- Transpose A simple method using two momentary action membrane switches has been used. (Transpose +) and (Transpose -). I have limited the transpose range to +- 12 semitones. Hex Thumbwheel Switches I have also added a rotary (thumbwheel) 16 position hex switch to select Midi Channel. ( Later on I will use the same type of switch to control an send Midi Program Changes to my hardware Piano Module.) LCD I would like to show the Transpose status eg "Transpose +2" on a small 2 line LCD display and perhaps the name of the piano module preset. eg " Grand Piano 1" This is a new area for me. My main concern is to preserve the speed of the fast scan and to avoid any interference by the LCD program additions. Please give me a few pointers. Robin Quote Link to comment Share on other sites More sharing options...
TK. Posted October 21, 2013 Report Share Posted October 21, 2013 Hi Robin, as long as the LCD is serviced from a lower priority task, there is no danger for interferences. It's guaranteed that the scan task gets the same compute time like before. That's actually the big advantage when a realtime operating system (FreeRTOS) is used. :) The most simple way how to program this would be the usage of the APP_Background hook E.g. from http://svnmios.midibox.org/filedetails.php?repname=svn.mios32&path=%2Ftrunk%2Fapps%2Fexamples%2Fblm%2Fapp.c ///////////////////////////////////////////////////////////////////////////// // 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' : '*'); // print text on LCD screen MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("DOUT Pin #%3d %c", last_dout_pin, last_dout_value ? 'o' : '*'); } } Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
robinfawell Posted October 23, 2013 Author Report Share Posted October 23, 2013 Thanks Thorsten I will follow your suggestion and report back. Robin Quote Link to comment Share on other sites More sharing options...
robinfawell Posted October 24, 2013 Author Report Share Posted October 24, 2013 (edited) Note This message has been edited from the original. I have thought about the problem and realise that it s very likely that App_Background must be working otherwise the system would not work. I am going to conduct one or more experiments to determine what proportion of time the scanning program takes of the total time available. I suspect that this is a very high proportion. Robin Edited October 28, 2013 by robinfawell Quote Link to comment Share on other sites More sharing options...
robinfawell Posted October 31, 2013 Author Report Share Posted October 31, 2013 I have tried many different variations to Print to the LCD Display but no luck using APP_Background. I am not sure of the exact operation of this Function but believe that it is used when higher priority tasks are idle. It may be that this idle time does not occur in my program. I should confirm that I am able to display the Transpose status and the Program Change (Presets on my piano Midi Module) by placing the LCD commands in the body of Button_Modify_Toggle. However I would like to use a lower priority method if at all possible. In the near future I want to add Black Key Keyboard Delay to the program. The Timer is set to 100 us. "// initialize MIOS32 Timer #0, so that Timer() function is // called each 100 uS: MIOS32_TIMER_Init(0, 100, Timer, MIOS32_IRQ_PRIO_MID); " Could this low time period prevent APP_Background from working? Any help will be welcomed. Robin Quote Link to comment Share on other sites More sharing options...
TK. Posted October 31, 2013 Report Share Posted October 31, 2013 It may be that this idle time does not occur in my program. Oh yes, of course this could be the case. Could this low time period prevent APP_Background from working? Yes We should review your app, maybe there is a way to optimize the execution time, so that lower prio tasks can be serviced again. Could you please attach your app.c file to this posting? Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
robinfawell Posted October 31, 2013 Author Report Share Posted October 31, 2013 Thanks Thorsten. Here is my app.c // $Id: app.c 1109 2010-10-11 23:14:49Z tk $ /* * Example for a "fastscan button matrix" * * ========================================================================== * * Copyright © 2010 Thorsten Klose(tk@midibox.org) * Licensed for personal non-commercial use only. * All other rights reserved. * * ========================================================================== */ ///////////////////////////////////////////////////////////////////////////// // Include files ///////////////////////////////////////////////////////////////////////////// #include <mios32.h> #include "app.h" #include <FreeRTOS.h> #include <task.h> #include <queue.h> ///////////////////////////////////////////////////////////////////////////// // for optional debugging messages ///////////////////////////////////////////////////////////////////////////// // level >= 1: print warnings (recommended default value) // level >= 2: print debug messages for Robin's Fatar Keyboard // level >= 3: print row/column messages in addition for initial testing of matrix scan for other usecases #define DEBUG_VERBOSE_LEVEL 2 #define DEBUG_MSG MIOS32_MIDI_SendDebugMessage ///////////////////////////////////////////////////////////////////////////// // Local definitions ///////////////////////////////////////////////////////////////////////////// #define PRIORITY_TASK_MATRIX_SCAN ( tskIDLE_PRIORITY + 2 ) // scan 12 rows #define MATRIX_NUM_ROWS 12 // sink drivers used? (no for Fatar keyboard) #define MATRIX_DOUT_HAS_SINK_DRIVERS 0 // maximum number of supported pins (rowsxcolumns) = (12*16) #define KEYBOARD_NUM_PINS (12*16) // used MIDI port and channel (DEFAULT, USB0, UART0 or UART1) #define KEYBOARD_MIDI_PORT UART0 //#define KEYBOARD_MIDI_CHN DEFAULT ///////////////////////////////////////////////////////////////////////////// // Prototypes ///////////////////////////////////////////////////////////////////////////// static void TASK_MatrixScan(void *pvParameters); static void Timer(void); ///////////////////////////////////////////////////////////////////////////// // Local Variables ///////////////////////////////////////////////////////////////////////////// static u16 din_value[MATRIX_NUM_ROWS]; static volatile u32 timestamp; static u32 kb_del_fast = 30;//used to set loudness resolution static u32 kb_del_slow = 1000;//used to set loudness resolution u8 toggle_state_pedal = 0;// using momentary action membrane switch, alternately selects soft or //sostenuto pedal. Latter is grand piano type sustain u8 toggle_state_port = 1;// using momentary action membrane switch, alternately USB0 or UART0 u8 toggle_state_swell = 1;// For Swell (Vol Control) Organ Presets u8 hex_switch_state [8]; u8 kb_midi_port = 16; s8 transpose = 0; u8 kb_midi_chan = 0; u8 prg = 0; ///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // initialize all LEDs //MIOS32_BOARD_LED_Init(0xffffffff); // initialize DIN arrays int row; for(row=0; row<MATRIX_NUM_ROWS; ++row) { din_value[row] = 0xff; // default state: buttons depressed } // initialize all pins of J5C, as outputs in Push-Pull Mode u8 pin; for(pin=8; pin<11; ++pin){ MIOS32_BOARD_J5_PinInit(pin, MIOS32_BOARD_PIN_MODE_OUTPUT_PP); MIOS32_BOARD_J5_PinSet(pin, 0);}// ensures initial state of LED's are off // initialize all pins of J5A and J5B, as inputs in Pull-Up Mode for(pin=0; pin<7; ++pin) MIOS32_BOARD_J5_PinInit(pin, MIOS32_BOARD_PIN_MODE_INPUT_PU); // initialize MIOS32 Timer #0, so that Timer() function is // called each 100 uS: MIOS32_TIMER_Init(0, 100, Timer, MIOS32_IRQ_PRIO_MID); // start matrix scan task xTaskCreate(TASK_MatrixScan, (signed portCHAR *)"MatrixScan", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_MATRIX_SCAN, NULL); } ///////////////////////////////////////////////////////////////////////////// // This timer function is called periodically each 100 uS ///////////////////////////////////////////////////////////////////////////// static void Timer(void) { ++timestamp; } ///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // endless loop: print status information on LCD while( 1 ) { MIOS32_BOARD_LED_Init(0xffffffff); // 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 when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called before the shift register chain is scanned ///////////////////////////////////////////////////////////////////////////// void APP_SRIO_ServicePrepare(void) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called after the shift register chain has been scanned ///////////////////////////////////////////////////////////////////////////// void APP_SRIO_ServiceFinish(void) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called when a button has been toggled // pin_value is 1 when button released, and 0 when button pressed ///////////////////////////////////////////////////////////////////////////// void APP_DIN_NotifyToggle(u32 pin, u32 pin_value) { } ///////////////////////////////////////////////////////////////////////////// // 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) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called when a pot has been moved ///////////////////////////////////////////////////////////////////////////// void APP_AIN_NotifyChange(u32 pin, u32 pin_value) { } ///////////////////////////////////////////////////////////////////////////// // This task is called to scan the button matrix ///////////////////////////////////////////////////////////////////////////// // will be called on button pin changes (see TASK_MatrixScan) void BUTTON_NotifyToggle(u8 row, u8 column, u8 pin_value) { // determine pin number based on row/column // based on pin map for Fatar keyboard provided by Robin (see doc/ directory) // tested with utils/test_pinmap.pl static u32 switch_timestamp[KEYBOARD_NUM_PINS]; u8 second_switch =0; u8 send_note_on = 0; u8 send_note_off = 0; u32 delta = 0; u8 note_number = 0; int pin = 0; //u8 hex_val = 0; //left hand keys if((column >=0 && column <=7 ) && (row >= 0 && row <= 9) && (row % 2 == 0)){//even pin = 8 * row + 2 *(7 - column);} if((column >=0 && column <=7 ) && (row>= 0 && row <= 9) && (row % 2 == 1)){//odd pin = (8 * (row -1) + (2 * (7 - column)) + 1); } //non-key switches if((column >=0 && column <=7 ) && (row >= 10 && row <= 11)){ pin = 8* row + 7 - column; // USB/ Midi Switch choose USB for PC and UART0 for external Midi Piano Module if(pin == 95 && pin_value == 0){ toggle_state_port ^= 0x01; MIOS32_BOARD_J5_PinSet(8,!toggle_state_port); toggle_state_port == 1 ? (kb_midi_port = USB0) : (kb_midi_port = UART0); } // Hex Sw to determine midi channel u32 hex_switch_state_index = pin - 80; hex_switch_state[hex_switch_state_index] = (pin_value ==0) ? 1 :0; if(pin >=80 && pin <= 87){ //Midi Channel set by Hex Switch kb_midi_chan = ((hex_switch_state[0]) | ((hex_switch_state[1])<<1) | ((hex_switch_state[2])<<2) |((hex_switch_state[3] )<<3)); //Program Change, Hex Switch used to provide 16 presets for Midi Piano Module with only 16 presets. prg = ((hex_switch_state[4]) | ((hex_switch_state[5])<<1) | ((hex_switch_state[6])<<2) |((hex_switch_state[7] )<<3)); //second hex switch to provide program change only for DIN0 Midi Out if((toggle_state_port == 0)) MIOS32_MIDI_SendProgramChange(kb_midi_port, kb_midi_chan, prg); } // enable sustain pedal or sostenuto pedal Sw located on LH Panel if(pin == 90 && pin_value == 0) { toggle_state_pedal ^= 0x01; MIOS32_BOARD_J5_PinSet(10,toggle_state_pedal);} #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("toggle_state_port=%d, prg=%d, kb_midi_chan=%d, kb_midi_port=%d\n", toggle_state_port, prg, kb_midi_chan, kb_midi_port); #endif //soft pedal located on foot pedals if(pin == 89) {// send soft pedal CC MIOS32_MIDI_SendCC (kb_midi_port, kb_midi_chan, 67, pin_value == 0 ? 127 : 0);} // sustain pedal located on foot pedals same switch as sostenuto below if(pin == 88 && toggle_state_pedal == 0) { // send soft pedal CC MIOS32_MIDI_SendCC (kb_midi_port, kb_midi_chan, 64, pin_value == 0 ? 127: 0) ;} //sostenuto pedal located on foot pedals if(pin == 89 && toggle_state_pedal == 1) { // send sostenuto pedal CC MIOS32_MIDI_SendCC (kb_midi_port, kb_midi_chan, 66, pin_value == 0 ? 127 : 0 ) ;} //Panic button, Midi All Notes Off No Sw yet if(pin == 91 && pin_value == 0) { MIOS32_MIDI_SendCC (kb_midi_port, kb_midi_chan, 123, 0);} //transpose buttons if(pin == 92 && pin_value == 0){//pin 92 is RH Transpose Button ie + Transpose (Higher Note) transpose = transpose +1;} if(pin == 93 && pin_value == 0){//pin 93 is LH Transpose Button ie + Transpose (Lower Note) transpose = transpose -1;} if(transpose > 12){ transpose = 12;} if(transpose < -12){transpose = -12;} // Presets Arrays char * preset[15] = {"Dark Grand", "Classic Grand", "Mellow Ivory", "Rock Piano", "Warm Elect Piano", "Studio Elec Piano", "B3 Organ", "Rock Organ", "Vibes ", "Bright Vibes ", "Strng Bass/Piano", "Elect Bass/Organ", "Synth Tines", "Piano Bell", "Str Bass/E Piano"}; // Show transpose and Preset on LCD MIOS32_LCD_Clear(); MIOS32_LCD_CursorSet(0,0); MIOS32_LCD_PrintFormattedString ("%s", preset[prg]); MIOS32_LCD_CursorSet(0,1); MIOS32_LCD_PrintFormattedString ("TRANSPOSE %d",transpose); //Swell (Volume) To enable Pot to control Midi Volume forFixed Volume Organ sounds if(pin == 94 && pin_value == 0){ toggle_state_swell ^= 0x01; MIOS32_BOARD_J5_PinSet(9,toggle_state_swell);} //alter pot #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG(" transpose=%d, pin=%d, column=%d\n", transpose, pin, column); #endif } //right hand keys if((column >=8 && column <=15 ) && (row >= 0 && row <= 11) && (row % 2 == 0)){//even pin = (8 * row + 2 * (15 - column ) + 96);} if((column >=8 && column <=15 ) && (row>= 0 && row <= 11) && (row % 2 == 1)){//odd pin = (8 * (row -1) + (2 * (15 - column ) ) + 1 +96); } // following check ensures that we never continue with an unexpected/invalid pin number. // e.g. this could address a memory location outside the last_timestamp[] array! // print a warning message in this case for analysis purposes if( pin < 0 || pin >= KEYBOARD_NUM_PINS ) { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("WARNING: row=0x%02x, column=0x%02x, pin_value=%d -> pin=%d NOT MAPPED!\n", row, column, pin_value, pin); #endif return; } if(((column >=0 && column <=7 ) && (row >= 0 && row <= 9)) || ((column >=8 && column <=15 ) && (row >= 0 && row <= 11))){ // first or second switch if a key? second_switch = (pin & 1); // 0 if first switch, 1 if second switch // the note number (starting from A-0 = 21) Note use of transpose variable if((column >=0 && column <=7 ) && (row >= 0 && row <= 9)){//LH keys note_number = transpose + 21 + (pin >> 1);} if((column >=8 && column <=15 ) && (row >= 0 && row <= 11)){//RH keys note_number = transpose + 13 + (pin >> 1);} if( note_number > 127 ) // just another check to ensure that no invalid note will be sent note_number = 127; // we have three transitions which are for interest: // a) first switch changes from 1->0 (pin_value == 0): // - store the current timestamp // b) second switch changes from 1->0 (pin_value == 0): // - calculate delta between current timestamp and timestamp captured during a) // - do this only if the captured timestamp is != 0 (see also c) // - calculate velocity depending on the delay // - send Note On event // c) first switch changes from 0->1 (pin_value == 1): // - send Note Off event (resp. Note On with velocity 0) // - clear captured timestamp (allows to check for valid delay on next transition) if( pin_value == 0 ) { if( second_switch == 0 ) { // first switch switch_timestamp[pin] = timestamp; } else { // second switch delta = timestamp - switch_timestamp[pin -1]; send_note_on = 1; } } else {//pin_value = 1 if( second_switch == 1 ) { // 2nd switch switch_timestamp[pin] = 0; send_note_off = 1; } } // now we know: // - if a note on or off event should be sent // - the measured delta (note on only) if( send_note_on ) { // determine velocity depending on delta int velocity = 127 - (((delta -kb_del_fast) * 127) / (kb_del_slow-kb_del_fast)); // saturate to ensure that range 1..127 won't be exceeded if( velocity < 1 ) velocity = 1; if( velocity > 127 ) velocity = 127; MIOS32_MIDI_SendNoteOn(kb_midi_port, kb_midi_chan, note_number, velocity); #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("row=%d, column=%d, pin_value=%d -> pin=%d, timestamp=%u, delta=%d, velocity=%d,-> NOTE ON\n", row, column, pin_value, pin, timestamp, delta, velocity); #endif } else if( send_note_off ) { // send Note On with velocity 0 MIOS32_MIDI_SendNoteOn(kb_midi_port, kb_midi_chan, note_number, 0x00); #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("row=%d, column=%d, pin_value=%d -> pin=%d, timestamp=%u -> NOTE OFF\n", row, column, pin_value, pin, timestamp); #endif } else { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("row=%d, column=%d, pin_value=%d -> pin=%d, timestamp=%u -> IGNORE\n", row, column, pin_value, pin, timestamp); #endif } } } static void TASK_MatrixScan(void *pvParameters) { while( 1 ) { // wait for next timesplice (1 mS) //vTaskDelay(1 / portTICK_RATE_MS); MIOS32_SPI_TransferModeInit(MIOS32_SRIO_SPI, MIOS32_SPI_MODE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_8); // loop: // - latch DIN/DOUT values // - shift selection pattern for *next* row to DOUT registers // - read DIN values of previously selected row // since we need to select the first row before the first DIN values are latched, we loop from -1 // to handle the initial state int row; for(row=-1; row<MATRIX_NUM_ROWS; ++row) { if( row >= 0 ) { // not required for initial scan // latch DIN values MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 0); // spi, rc_pin, pin_value MIOS32_DELAY_Wait_uS(1); MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 1); // spi, rc_pin, pin_value } // determine selection mask for next row (written into DOUT registers while reading DIN registers) u16 select_row_pattern = ~(1 << (row+1)); #if MATRIX_DOUT_HAS_SINK_DRIVERS select_row_pattern ^= 0xffff; // invert selection pattern if sink drivers are connected to DOUT pins #endif // read DIN, write DOUT u8 din0 = MIOS32_SPI_TransferByte(MIOS32_SRIO_SPI, (select_row_pattern >> 8) & 0xff); u8 din1 = MIOS32_SPI_TransferByte(MIOS32_SRIO_SPI, (select_row_pattern >> 0) & 0xff); // latch new DOUT value MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 0); // spi, rc_pin, pin_value MIOS32_DELAY_Wait_uS(1); MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 1); // spi, rc_pin, pin_value if( row >= 0 ) { // combine read DIN bytes to 16bit value u16 din_pattern = (din1 << 8) | din0; // check if values have been changed via XOR combination with previously scanned value u16 changed = din_pattern ^ din_value[row]; if( changed ) { // store changed value din_value[row] = din_pattern; // notify changed value int column; for(column=0; column<16; ++column) { u16 mask = 1 << column; if( changed & mask ) BUTTON_NotifyToggle(row, column, (din_pattern & mask) ? 1 : 0); } } } } } } Please note that I have added 16 diodes to the scan matrix: 4 to provide 16 Midi channels, 4 to provide 16 program changes plus others to change midi out channel, provide soft and sustain pedal and transpose + and -. The debug messages need cleaning up. The LCD messages are placed in the body of the button_notify_toggle function. Most of the complicated code is yours from a few years back. Robin Quote Link to comment Share on other sites More sharing options...
TK. Posted November 1, 2013 Report Share Posted November 1, 2013 Ok, now I remember The problematic function isn't Timer(), because it doesn't do that much. It just increments a timestamp. Instead, TASK_MatrixScan causes the problem, because this task (with priority 2) is running in an endless loop, so that lower prio tasks will never be executed. This part should be overworked. Maybe the best way would be to take this tutorial as a template: http://svnmios.midibox.org/listing.php?repname=svn.mios32&path=%2Ftrunk%2Fapps%2Ftutorials%2F029_keyboard_velocity%2F In difference to the code that I gave you some time ago, it uses the SRIO driver. While the SRIO driver scans the shift registers via DMA, other tasks can be executed - and this gives you more than enough processing power to handle the LCD. I could integrate your code into this framework if you want (I can do and test this on sunday) But of course you could also try this by yourself :smile: Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
robinfawell Posted November 2, 2013 Author Report Share Posted November 2, 2013 Thanks Thorsten I will modify Tutorial 29 and try to introduce my variations. Robin Quote Link to comment Share on other sites More sharing options...
robinfawell Posted November 3, 2013 Author Report Share Posted November 3, 2013 (edited) Dear Thorsten I have tried the tutorial 029 code with my Fatar 88 note keyboard. There is activity on MIOS Studio but looking at the code I see that the system only uses one DIN SR. My current setup uses the newer DIO_Matrix. I use 2 DOUT SR and 2 DIN SR. I only use 12 of the 16 available DIN SR. The wiring of the Fatar KB uses 8 + 2 DIN for the LH of the KB and 8 + 4 DIN for the RH of the KB . Hence 12 DIN used. The unused 2 DIN on the LH is scanned through 16 additional diodes to provide switches for the KB pedals, 2 sets of rotary Thumbwheel switches, Transpose and other purposes. Is this sensible? I am using J5 as outputs for LED and hope to use one Analog output for Midi Volume. It would be very helpful if you could give me an idea how to add the second DIN SR. I think I can work out how to scramble the Pin numbers and notes. Thanks Robin Edit. I am in the process of trying to incorporate the structure of the tutorial 29 into my own code. I have a few more lines of code to add before I can try the program out with MIOS Studio. Edited November 3, 2013 by robinfawell Quote Link to comment Share on other sites More sharing options...
TK. Posted November 3, 2013 Report Share Posted November 3, 2013 robin1.zipHi Robin, I merged your code with the tutorial applications, and enhanced it for two DIN shift registers. This was easier at my end, since changes were required at multiple places. I also added a LCD handler which outputs the last triggered row/column/value and timestamp (if value was 0) Code attached: robin1.zip Note: mios32_config.h contains // disables the default SRIO scan routine in programming_models/traditional/main.c // allows to implement an own handler // -> see app.c, TASK_MatrixScan() #define MIOS32_DONT_SERVICE_SRIO_SCAN 1 which is essential to select the new SRIO driver mode. Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
robinfawell Posted November 4, 2013 Author Report Share Posted November 4, 2013 (edited) Thank you once again, Thorsten. I'm very grateful! I had moved a little on my own, but was unsure of some of the code I was writing. I have tested the revised program and can report that it is working to a large extent. However the transfer from SPI to SRIO has, I believe, reversed both the DIN and the DOUT bit order. This as you know causes scrambling of pins and notes and reverses the order of first and second key contacts. I need to make more detailed checks on this to determine all the changes. I know that there are routines that can reverse the bits in a word. I am also sure that the program could be altered so that the correct order of "make and break" is maintained. My pin adapter for the Fatar contacts to Dio Matrix board will need to be modified so that it will fit under the keys in the Fatar keybed. I could easily make a new one to accommodate the reversed SR connections. I will let you know how the project progresses. Regards Robin PS If limit the SRIO transfers to 12 rows,can I use a diode based matrix system with some or all the remaining rows of the 2 SRs for use with APP_DIN_NotifyToggle? Edited November 4, 2013 by robinfawell Quote Link to comment Share on other sites More sharing options...
TK. Posted November 4, 2013 Report Share Posted November 4, 2013 Hi Robin, I'm glad that the application is working at your side! :) Oh yes, I haven't considered that the DOUT pins are reverted by MIOS32_DOUT This can be fixed by reversing the selecting pattern (again). Replace following code: // transfer to DOUTs #if MATRIX_DOUT_SR1 MIOS32_DOUT_SRSet(MATRIX_DOUT_SR1-1, (selection_mask >> 0) & 0xff); #endif #if MATRIX_DOUT_SR2 MIOS32_DOUT_SRSet(MATRIX_DOUT_SR2-1, (selection_mask >> 8) & 0xff); #endif by: // transfer to DOUTs #if MATRIX_DOUT_SR1 MIOS32_DOUT_SRSet(MATRIX_DOUT_SR1-1, mios32_dout_reverse_tab[(selection_mask >> 0) & 0xff]); #endif #if MATRIX_DOUT_SR2 MIOS32_DOUT_SRSet(MATRIX_DOUT_SR2-1, mios32_dout_reverse_tab[(selection_mask >> 8) & 0xff]); #endif I guess, that no additional changes are required. Later, once your new board is finished, you could remove this change for "full MBHP compatibility" (because all application use this reversed pinning scheme for DOUTs) PS If limit the SRIO transfers to 12 rows,can I use a diode based matrix system with some or all the remaining rows of the 2 SRs for use with APP_DIN_NotifyToggle? Yes, you can scan up to 16x16 inputs without performance decrease. Just change the MATRIX_NUM_ROWS to // scan 16 rows #define MATRIX_NUM_ROWS 16 the code will always use this constant to declare arrays dimensions and to calculate offsets (e.g. as you've probably noticed, I changed "KEYBOARD_NUM_PINS" from "12*16" to "MATRIX_NUM_ROWS*16" to ensure this "self-configuration". Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
robinfawell Posted November 22, 2013 Author Report Share Posted November 22, 2013 (edited) Dear Thorsten I now have the LCD working for my needs. All the the variables that I need to display are global variables. I need to refine the code so that I avoid LCD updates for non keyboard events that do not need displaying. That should be straightforward. I have one task left. I want to incorporate a swell pedal into the system so that the keyboard has 2 modes. Piano mode where the synths are velocity sensitive. Organ mode where the synths are at a fixed loudness. To do this I plan to use CC no 7. Here is the code which I borrowed from the Examples using J5. ///////////////////////////////////////////////////////////////////////////// // This hook is called when a pot has been moved ///////////////////////////////////////////////////////////////////////////// void APP_AIN_NotifyChange(u32 pin, u32 pin_value) { //MIOS32_AIN_PinGet(3); MIOS32_BOARD_J5_PinGet(3); or MIOS32_AIN_PinGet(3); u8 value_7bit = pin_value >> 5; MIOS32_MIDI_SendCC(kb_midi_port, kb_midi_chan, 7, value_7bit); } I am using pin 3 on J5A. I get one only CC message 7 and then the core locks up. I have followed the instructions regarding masks (I have used 0x0004) and have set the AIN deadband to 31 in the config h file. Incidentally is the masking necessary if the J5 Board pins have been completely defined as either Analog, Outputs or Inputs. Also do the unused Digital defined Inputs need grounding? I have tried both the AIN_PinGet and the J5_PinGet to obtain pin_value for pin 3. I have even tried putting the code into App Background but the system also locks up. I would appreciate some guidance. Thanks Robin Edited November 22, 2013 by robinfawell Quote Link to comment Share on other sites More sharing options...
TK. Posted November 23, 2013 Report Share Posted November 23, 2013 Yes, the mask is necessary for the MIOS32_AIN driver. Unselected J5 pins don't need to be grounded, because an internal pull-up is activated in this case. Note: the correct mask for J5.A3 is 0x0008, not 0x0004 Typically you would retrieve the current analog value with MIOS32_AIN_PinGet(3), not MIOS32_BOARD_J5_PinGet(3) It's very strange that the core locks up, I've no explanation why this should happen with the function calls above. At which function call does it lock up exactly? Just remove them line by line to determine this. Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
robinfawell Posted November 25, 2013 Author Report Share Posted November 25, 2013 (edited) Hello Thorsten Thanks for correcting the AIN mask. I think that the error was caused by my failing to initialise J5 inputs properly. I was careless with the "for loops". for(pin=0; pin<7; ++pin) (MIOS32_BOARD_J5_PinInit(pin, MIOS32_BOARD_PIN_MODE_INPUT_PU)); should have been for(pin=0; pin<=7; ++pin)( MIOS32_BOARD_J5_PinInit(pin, MIOS32_BOARD_PIN_MODE_INPUT_PU)); I made this error a couple of times. There was basically nothing wrong with the APP_AIN_NotifyChange function. The CC function MIOS32_MIDI_SendCC(kb_midi_port, kb_midi_chan, 7, value_7bit); produces a smooth volume control for the organ synths. The cable length is about 50cm. I now need to wire up my new DOG LCD Display and the electronics will be complete. Thanks once again! Robin Edited November 25, 2013 by robinfawell Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.