Jump to content

Use of LCD with Fast Scan Matrix


robinfawell

Recommended Posts

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by robinfawell
Link to comment
Share on other sites

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
 
 
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by robinfawell
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by robinfawell
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • 3 weeks later...

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 by robinfawell
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by robinfawell
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...