Jump to content

Fast Scan Matrix Example


robinfawell
 Share

Recommended Posts

I have nearly finished my FATAR based digital piano. It is working with the code kindly written by TK with some minor work by me with on the soft and sustain pedals. The case and stand are complete. The piano works well with two exceptions.

1)

As suggested by TK, I want the Keyboard Max and Min delay variables to be defined by two Hex switches.

There is an unused section of the scan matrix that I have used successfully to control the pedals referred to above. I have also tried to use the "empty" switch positions of the matrix with the hex switches and although it works to some extent, it is not convenient.

I want to program to read the two hex switches immediately after switch-on. I don't need them to be variable during normal operation.

Is it feasible to incorporate the relevant code into the initialisation section where it can be read and used by the system.?

Incidentally it is very difficult to decide on suitable values. At present I am using a fast delay of 4 and a slow delay of 60. My current thinking is that I may need to reduce the latter(perhaps to 30).

I am thinking of using the IO's of J5B and J5C for the 2 X 4 inputs from the hex switches. I believe that the main problem in trying to use the scan matrix is that that the switches are only read when the values change.

2)

System speed.

The resolution of the delay referred to in 1) above is 1 mS. I would like reduce this value progressively. I have looked in the repository to find where the frequency is pre-scaled without success. There may be several other changes needed to speed up the application. Any pointers would be appreciated.

Regards Robin

Link to comment
Share on other sites

About 1 week has elapsed since I asked 2 questions about the Fast Scan Example.

Question 1

I have spent some time on Question 1 and seem to have solved the problem with some fairly simple code in the initialisation section. I can now define the two keyboard delay variables with either hex or BCD rotary switches. This means that the two variables will be determined by reading the two switches at switch-on. These are used to determine the loudness (velocity) sensitivity of each note. You will need to read TK's code to see the relevance.

Question 2

I would like to explore how fast the system can run. The main benefit will be that the velocity resolution will be improved. It looks as if a practical Fast Keyboard Delay will be 3 or 4 mS and the Slow Delay somewhere about 30 mS. Bear in mind that the the delay measurement is accurate to 1 mS. This means that loud notes could have an error of 1 in 3 ie 33%.

From the Functions reference the speed of the system is fixed by the following Function.

s32 MIOS32_SPI_TransferModeInit ( u8 spi,

mios32_spi_mode_t spi_mode,

mios32_spi_prescaler_t spi_prescaler

)

(Re-)initializes SPI peripheral transfer mode By default, all SPI peripherals are configured with MIOS32_SPI_MODE_CLK1_PHASE1 and MIOS32_SPI_PRESCALER_128

This seems to be defined in

s32 MIOS32_SRIO_Init(u32 mode)

{

in the mios32/trunk/common/mios32_srio.c file.

Is it the just a matter of altering the pre-scalar values or are there RTOS or other implications?

Regards Robin

Edited by robinfawell
Link to comment
Share on other sites

Hi Robin,

for other readers who don't know the discussed application: http://svnmios.midibox.org/listing.php?repname=svn.mios32&path=%2Ftrunk%2Fapps%2Fexamples%2Ffastscan_button_matrix_16x16%2F

In this special case, where the SRIOs are not scanned by the 1 mS FreeRTOS Task (like for common MIOS32 applications), but in an endless loop located in TASK_MatrixScan(), only the SPI transfer rate limits the bandwidth.

You could increase the transfer rate by writing:


MIOS32_SPI_TransferModeInit(MIOS32_SRIO_SPI, MIOS32_SPI_MODE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_64);
[/code]

at the top of the TASK_MatrixScan() function (before the while-loop is entered)

Even PRESCALER_32 or PRESCALER_16 could work, please report which values are working ok for you, this would be interesting!

Note: it would be possible to scan at even higher speeds by using a 74HC541 based output buffer for serial signals like I did for the MBHP_CORE_LPC17 module (more infos on this topic if required)

Best Regards, Thorsten.

Link to comment
Share on other sites

Hello Thorsten

I have inserted the SPI initiate function as follows

static void TASK_MatrixScan(void *pvParameters)

{

MIOS32_SPI_TransferModeInit(MIOS32_SRIO_SPI, MIOS32_SPI_MODE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_4);

  while( 1 ) {

    // wait for next timesplice (1 mS)

    vTaskDelay(1 / portTICK_RATE_MS);


    // determine timestamp (we need it for delay 

Please note that the prescalar value of 4 seems to work! It seems to be too good to be true!

Is there a way to check that that the transfer rate is being increased?

Robin

Link to comment
Share on other sites

Hi Thorsten

This evening I inserted the "SPI Prescalar" statement where I think you meant, not where I place it initially! It seems to work with a pre-scalar value of 8 .

I need to do further work over a longer period of time with the soft synth to be sure. I will report back later to confirm this.

MIOS STUDIO gives the normal 4 timestamp values with each press of the key.

Later Edit

I've been looking at the Function used to determine the delay. This is derived from timestamp.

 // determine timestamp (we need it for delay measurements)

    mios32_sys_time_t t = MIOS32_SYS_TimeGet();

    u32 timestamp = 1000*t.seconds + t.fraction_ms;

Speeding up the system will not improve the minimum resolution ie 1mS.

Is there some way to improve the minimum time resolution or are we forced to examine another method??

Robin

Edited by robinfawell
Link to comment
Share on other sites

Hi Robin,

you could use the stopwatch to measure even more accurate delays.

A usage example can be found here:

http://www.midibox.org/mios32/manual/group___m_i_o_s32___s_t_o_p_w_a_t_c_h.html

With the resolution "1" (instead of 100 like shown in this example), you will get microsecond accurate delays from 0..65335 uS (delays >65 mS will lead to an overrun)

Following code in TASK_MatrixScan() is the reason why the scan is done each mS:


// wait for next timesplice (1 mS)
vTaskDelay(1 / portTICK_RATE_MS);
[/code]

just remove it (or comment it out) - done! :)

The operating system (FreeRTOS) takes care that higher priority tasks are still executed.

TASK_MatrixScan() has a lower priority (2) as all other tasks (exception: background task), and will be executed when nothing else is to do.

Best Regards, Thorsten.

Link to comment
Share on other sites

MIOS STOPWATCH Operation and further thoughts

4th Edit I have removed all my ramblings about how to use the MIOS STOPWATCH. The were completely wrong.

Here is a small section of code that shows how MIOS STOPWATCH can be used to measure the delay between two switches closing.

This is needed to determine the velocity of the Note On Midi signal.

The initialisation and declaration of some of the variables are not shown.

 // We have three transitions which are of interest:

  // a) first switch changes from 1->0 (pin_value == 0):

  //    - Reset Stopwatch and set the Reset Flag = 1

  //	- do this only if the Reset Flag is 0

  // b) second switch changes from 1->0 (pin_value == 0):

  //    - measure delay using the MIOS32_STOPWATCH_ValueGet() function 

  //    - 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 Reset Flag


	int key_ix = pin & 0xfffffffe;

	int delay = -1;  

	u8 send_note_on = 0;

	u8 send_note_off = 0;


	if( pin_value == 0 ) {

    if(( second_switch == 0 ) && (SW_Reset_Flag[key_ix] == 0)){ // first switch	

	MIOS32_STOPWATCH_Reset();

	SW_Reset_Flag[key_ix] = 1;


    } else 	{ // second switch      

	delay = MIOS32_STOPWATCH_ValueGet();	

	send_note_on = 1;

			}						

						 } else {

    if( second_switch == 0 ) { // first switch

    (SW_Reset_Flag[key_ix] = 0);

    send_note_off = 1;

							 }	

								}

This code is based on Thorsten's original example using timestamps.

The changes above enable the resolution to be improved. I now am using 0.1mS rather than 1mS. If necessary the resolution could be even smaller.

Thank you again Thorsten for suggesting the idea.

Best Regards Robin

Edited by robinfawell
Link to comment
Share on other sites

  • 1 month later...

My ideas to use MIOS STOPWATCH for delay measurement were faulty.

There is a possibility that the method could work provide two problems can be overcome.

Operation of MIOS STOPWATCH

Can multiple Time measurements be made following a single Reset command.

Can the Reset Function be programmed to occur at Regular time intervals on a continuous basis?

A time period of 1 second would be ideal. However I think that it would be possible to use a lower period eg 50 - 60 mS.?

I will appreciate any help with the two questions.

Thanks Robin

Link to comment
Share on other sites

The stopwatch is only working with 16bit resolution (on a STM32), this is limited by the timers which are available on STM32.

However, later you want to measure the delay for multiple keys in parallel, using the stopwatch for such a purpose is the wrong way.

(I proposed it since I guessed that you wanted to measure delays for experimental reasons - but now I'm thinking a step further)

It would be better if you would capture a timestamp instead.

E.g. you could use a MIOS32_TIMER based interrupt, which increments a u32 variable each 100 uS (I think that this resolution is good enough for your purposes).

See http://svnmios.midibox.org/filedetails.php?repname=svn.mios32&path=%2Ftrunk%2Fapps%2Ftutorials%2F007_mios32_timer%2Fapp.c for a programming example.

Instead of the pwm_* counter stuff, you would declare a


static volatile u32 timestamp;
[/code] variable in the app.c header, and you would write:
[code]
static void PWM_Timer(void)
{
++timestamp;
}
in the PWM_Timer function, which is called each 100 uS Now you have to capture the current timestamp when the first switch is activated just store the current value in an array - the array has to be dimensioned based on the number of switches you want to handle, e.g.:

static u32 switch_timestamp[64];
// for up to 64 switches
[/code] Execute this in your handler when the first switch is activated:
[code]
if( pin_ix < 64 ) // just to ensure that the access is within the array
switch_timestamp[pin_ix] = timestamp;
When the second switch is activated, you can determine the delay with:

u32 delta = timestamp - switch_timestamp[pin_ix];
[/code]

This gives you the number of timestamp ticks.

The appr. time is delta * 100 uS

Best Regards, Thorsten.

Link to comment
Share on other sites

Thank you again Thorsten

The timestamp method using the MIOS Timer is now working. It provides a better "time" resolution than before.

I intend to use the MIOS STOPWATCH to measure the scan rate.

We will then know the scan parameters more accurately.

I'm guessing that that the system has 10X the resolution of the original 1mS scan rate.

The fastest (loudest) figure from the original system was about 3 - 4 Ms.

With the latest program the loudest key strike corresponds to a delta count of about 35.

I should add that these figures are based on a SPI prescaler of 8.

I have incorporated several soft synths into a trial version of Mixcraft. This means that I can select various piano or organ sounds with a finger press on my touch sensitive monitor.

I am very pleased with the result.

All that remains is to incorporate an organ volume pedal and I will be finished.

Of course I still need to make a matching piano stool in beech wood!

Best Wishes Robin

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...
 Share

×
×
  • Create New...