November 21, 2024, 12:36:33 PM

News:

Got VSA?  Want to use your Prop-SX?  Now you can!  See the VSA section of the Library forum for Prop-SX code that works with VSA.


Button Keyboard Scanner for Midi

Started by jukingeo, July 16, 2008, 08:22:03 AM

Previous topic - Next topic

jukingeo

July 16, 2008, 08:22:03 AM Last Edit: July 16, 2008, 08:28:29 AM by jukingeo
Hello all,

I have an unusual situation in which I would like to scan a key or button matrix and output the result via MIDI.  I have heard the Basic Stamp 2 WILL do this, but I am not sure how.

The goal is to create a panel with 56 buttons on it and send it out via midi.  My purpose is to use the 56 buttons to access organ stops on a virtual pipe organ program.   The BS-2 is fast enough for the job, however, I don't know how to go about a program like this.

The keyscan matrix needs to register multiple switches and know if each one is on or off.  The buttons will latch in either an on or off position, so it will not be momentary contact.   Thus because of the fixed state, speed is not a tremendous issue. 

At any rate I figured I would post here because I could see this as a project that could be expanded for other uses such as a number keypad or reading a keyboard of sorts for an interactive project.   Just in my case I would like to output the button presses of an 8 by 7 input matrix and output the results out of the last pin to affect midi program change commands.

In the very least I would like to know how to set up a keyscan matrix.

So I know I would have to set up 15 of the 16 pins in an 8 by 7 matrix and then use the last pin as an output.

My best guess is that a program would have to scan each and every matrix position and register if a button is actuated for that given position.  Then the total would be outputed into a figure that Midi would understand.  My guess is a hexidecimal output.  Thus in turn that hex value would be sent serially to a midi port.  Again that is just a guess as to how it works.

Anyway, I hope that is information enough.

Thanx,

Geo

JonnyMac

Full disclosure: I've had only one cup of coffee and no breakfast... so check this stuff carefully.  All kidding aside, while I feel confident in the program but don't have the hardware setup to test it, so proceed with caution.

Let's start with the keyboard matrix, and let's jog before we run.  Here's how I would wire a 2x8 matrix:



This circuit takes advantage of the ULN2803s on the Prop-2 providing a gentle pull-down of all keyboard pins.  To scan the keyboard we make [just] one column high, read the rows (on INL, P0-P7), and then move on. IMPORTANT: To disable a column it must be made an input, do not take it LOW.

It's been a long time since I've done any MIDI stuff with the BS2, so I had to look up one of my old Nuts & Volts columns:
-- http://www.parallax.com/dl/docs/cols/nv/vol4/col/nv94.pdf

Here's a simple program will scan a 2x8 matrix and send MIDI NoteOn and NoteOff commands.  Use this as a starting point in your project.  I did check, and there is enough RAM to expand the key arrays to seven bytes each; the only other change, then, would be to the outer loop of the scanning subroutine so that it will use P8 through P14 as columns.  Remember that each column scan takes 25 milliseconds to debounce the mechanical keys; more columns mean more time to properly scan them.

' =========================================================================
'
'   File...... 2x8_Matrix.BS2
'   Purpose... Simple MIDI controller for Prop-2
'   Author.... Jon Williams, EFX-TEK
'              Copyright (c) 2008 EFX-TEK
'              Some Rights Reserved
'              -- see http://creativecommons.org/licenses/by/3.0/
'   E-mail.... jwilliams@efx-tek.com
'   Started...
'   Updated... 16 JUL 2008
'
'   {$STAMP BS2}
'   {$PBASIC 2.5}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------


' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------

Midi            PIN     15

Col1            PIN     9                       ' key maxtix column outputs
Col0            PIN     8
KeysIn          VAR     INL                     ' key matrix row inputs


' -----[ Constants ]-------------------------------------------------------

IsOn            CON     1                       ' for active-high in/out
IsOff           CON     0

TMidi           CON     12                      ' 31.25K baud (MIDI)
Open            CON     $8000
Baud            CON     Open + TMidi

NoteOn          CON     $90
NoteOff         CON     $80


' -----[ Variables ]-------------------------------------------------------

idx             VAR     Byte
idx2            VAR     Byte

nKeys           VAR     Byte(2)                 ' new keys
oKeys           VAR     Byte(2)                 ' old keys

tmpNew          VAR     Byte                    ' temporary, new
tmpOld          VAR     Byte                    ' temporary, old

note            VAR     Byte                    ' midi note to send


' -----[ Initialization ]--------------------------------------------------

Reset:


' -----[ Program Code ]----------------------------------------------------

Main:
  GOSUB Scan_Matrix
  note = 60                                     ' start at middle C

  FOR idx = 0 TO 1                              ' scan array bytes
    tmpNew = nKeys(idx)
    tmpOld = oKeys(idx)
    FOR idx2 = 0 TO 7                           ' scan bits in byte
      IF tmpNew.LOWBIT(idx2) = IsOn THEN        ' pressed?
        IF tmpOld.LOWBIT(idx2) = IsOff THEN     ' new press?
          SEROUT Midi, Baud, [NoteOn, note, 127]
        ENDIF
      ELSE                                      ' released
        IF tmpOld.LOWBIT(idx2) = IsOn THEN      ' new release?
          SEROUT Midi, Baud, [NoteOff, note, 127]
        ENDIF
      ENDIF
      note = note + 1
    NEXT
    oKeys(idx) = nKeys(idx)                     ' save for next cycle
  NEXT

  GOTO Main


' -----[ Subroutines ]-----------------------------------------------------

' Scans 2x8 keyboard matrix
' -- columns are P8 and P9
' -- rows are P0..P7
' -- make column an input to deactivate

Scan_Matrix:
  FOR idx = 8 TO 9                              ' scan all columns
    HIGH idx                                    ' activate the column
    tmpNew = %11111111                          ' assume pressed
    FOR idx2 = 1 TO 5
      tmpNew = tmpNew & KeysIn                  ' scan & debounce
      PAUSE 5
    NEXT
    nKeys(idx-8) = tmpNew                       ' move to keys array
    INPUT idx                                   ' deactivate colum
  NEXT
  RETURN

' -------------------------------------------------------------------------


' -------------------------------------------------------------------------


' -------------------------------------------------------------------------


' -------------------------------------------------------------------------


' -------------------------------------------------------------------------


' -----[ User Data ]-------------------------------------------------------
Jon McPhalen
EFX-TEK Hollywood Office

jukingeo

Hello Jon,

Thank you for the information and program.  I do have a couple quick questions.

1) In the matrix itself, don't you need diodes in there someplace to avoid 'reverse' action of keys being pressed
2) In terms of speed and actual function, I am not going to use this for a standard keyboard, but rather a button bank.  The big difference in being that the switches will STAY ON (latched), when activated.

To make things clearer, take a look at this picture of an organ:

http://www.theatreorgans.com/walnuthill/rr20stopsweep06.jpg

The switches are actually levers and whether they are up or down will indicate which stop is on or off.  Thus, my educated guess would be that the program would scan these switches X amount of times each second to see if they change state.  If they do, then it would yield a program change message change and thus change the preset on a soundfont synth.

So by right in this situation a fast keyscan really isn't necessary, but as you can see that there very well could be a situation where you can go from one stop pressed to all of them...and everything in between.

As to the actual sent message, I will ask the guys in the JOrgan forum and see what it is.  I believe it is a hexadecimal figure that is sent to the synth to update the program register.

Thanx,

Geo

JonnyMac

1) You don't need steering diodes when you can make IO pins Hi-Z (inputs) -- this is why I stress that you must make a deactivated column an input versus low.  Steering diodes are only required on circuit that always drive one way or another.  I have used the scheme described above on BASIC Stamps and the SX without any problems; that said, the 470s are in place as protection... just in case.  If you want extra protection from programming errors put inline 470s into P0 - P7 as well.

2) You can call the scanning routine as [in]frequently as you need.  The code in the main loop simply checks for a change of state and determines direction.  Another way to do this is with a third set of variables and some XORing (look for a program I posted called Rizzo_Relays to see this in action).  But with 56 switches that is out of the question in terms of RAM.  Luckily, PBASIC has nice bit access features that make scanning through the switch array pretty simple.
Jon McPhalen
EFX-TEK Hollywood Office

jukingeo

Hello Jon,

Thanx for the info and the program.  It will be a bit before I can get the panel put together, but I will come back with the results.   I am still working out the kinks on the computer/sound end right now.  The system is Linux based and I am still very new to it and adjusting to the learning curve.

Geo