Jump to content

C wrapper and switching matrix -> an easy way to do that


pilo

Recommended Posts

Hi!

here's my source code for handling a switching matrix with the C apps, using DIN and DOUT :

int row

...
void Init(void) __wparam
{
  int i;

  /* Matrix Init */
  for(i = 0; i < 8;i++) {
    MIOS_DOUT_PinSet1(i);
  }

  row = 0;
  MIOS_DOUT_PinSet0(0);
}

...

void SR_Service_Prepare(void) __wparam
{
  MIOS_DOUT_PinSet1(row); 
  row++;
  if(row > 7) row = 0;
  MIOS_DOUT_PinSet0(row);
}

void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam
{
  MIOS_LCD_CursorSet(0x00); 
  MIOS_LCD_PrintBCD5(pin); 
  MIOS_LCD_CursorSet(0x40); 
  MIOS_LCD_PrintBCD5(row); 
}

Works well. Maybe need too add some bouncing handling stuff too. And there's a small shift in the switch row number  ;D

Link to comment
Share on other sites

A nice solution - but take care: if something is blocking the mainthread (e.g. an incoming MIDI stream), it can happen that the "row" number has been changed before DIN_NotifyToggle() is called. However, for simple applications (which don't use the MIDI merger or which are not heavily loaded by other tasks) such corner cases propably never happen

Best Regards, Thorsten.

Link to comment
Share on other sites

Actually the row number seems to be increment before the notify togle event is called.

So I tried this (I know I shouldn't call anything in SR_Service_Finish).

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an button has been toggled
// pin_value is 1 when button released, and 0 when button pressed
/////////////////////////////////////////////////////////////////////////////
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam
{

  if(pin == 128) {
    unsigned char i;

    for(i = 0; i < 8; i++) {
      MIOS_MF_FaderMove(i, 800);
    }
  }

  if(pin == 129) {
    unsigned char i;

    for(i = 0; i < 8; i++) {
      MIOS_MF_FaderMove(i, 400);
    }
  }
  if(pin == 130) {
    unsigned char i;

    for(i = 0; i < 8; i++) {
      MIOS_MF_FaderMove(i, 000);
    }
  }


  else if(pin > 8) {
    MIOS_LCD_CursorSet(0x00); 
    MIOS_LCD_PrintBCD5(pin); 
  }
  
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after the shift register have been loaded
/////////////////////////////////////////////////////////////////////////////
void SR_Service_Finish(void) __wparam
{
  unsigned char i;
  unsigned char row_tmp = row;
  for(i = 0; i < 8; i++) {
    if(MIOS_DIN_PinGet(i) == 0) {
      DIN_NotifyToggle(128+row_tmp*8 + i, 1);
    }
  }
  MIOS_DOUT_PinSet1(row); 
  row++;
  if(row > 7) row = 0;
  MIOS_DOUT_PinSet0(row);
}

But i still haven't got the right rown number... and I'm still trying to find where I am wrong. Maybe another solution is to update the row number and DOUT state, if DIN notify toggle has got a higher "priority" than USER_tick?

Link to comment
Share on other sites

Hi Pilo,

it's very dangerous to call DIN_NotifyToggle from an interrupt service routine. One point is, that it will be called anyhow - it's called from the mainthread on any change in DIN registers. Another point is, that SR_Service_Finish() could interrupt a function from the mainthread which uses the same resources like your (misused) DIN_NotifyToggle routine.

Suggestion: within the interrupt service routine you should only store the pin values in an array, which contains so much bytes like required for your matrix (note that one byte contains 8 bits: for 8 DIN pins)

Add another array to notify changes. Just set the appr. bit within the array to 1 once a DIN value has been modified from the ISR

Then write a new function which is called from Tick(), and which checks for the notifier. If it is set, clear the bit and call DIN_NotifyToggle with the appr. arguments.

Note: any modifications on the notifier array from the main thread should be atomic. Means: this (small code part --- not the whole routine!) should not be interrupted.

Interrupts can be disabled with "INTCONbits.GIE = 0;", and they can be enabled again with "INTCONbits.GIE = 1;"

Another remark: I would write such code in assembler, and would call a C function on any DIN changes. SDCC produces very large code on array accesses, you can propably boost your DIN matrix handler by factor 10 and more, when you are implementing the handler in assembly language.

An example is already given in the sm_example1, it calls the SM_NotifyToggle function, from there you could branch to a C function (see MIOS wrapper code how to do this)

Best Regards, Thorsten.

Link to comment
Share on other sites

thank you thorsten !

actually I wanted to make a 100% C sm driver, as you already wrote an assembler version :)

it's very dangerous to call DIN_NotifyToggle from an interrupt service routine.

I knew that I will be blame for doing this  :-[ :P

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