Jump to content

Scan Matrix extended : VOIRINOV


julienvoirin

Recommended Posts

Here is a completly amazing control surface for your favorite sequencer or synthesizer :

It's a machine capable of playing Notes, Control Change and Program Changes

Photos are available at http://www.midibox.org/forum/index.php?topic=9655.0

Here is how it is made :

The machine is composed by 3 things :

1 - A 64 buttons keyboard, design of TK with the scan matrix

http://www.ucapps.de/mbhp/mbhp_scan_matrix1.pdf

2 - A control surface with 4 buttons, one jack for a footswitch and one clickable encoder and several LEDs

3 - Classic stuff from ucapps : 1 core (pic 18f452), 1DINX2, 1 DOUTX2, midi and supply connector, and things removed from the trash.

How to connect it :

Connect DINX2 and DOUTX2 at the core, ports J8 and J9.

Connect the Scan Matrix to the first Shift Register (SR1) of DIN & DOUT

Connect the encoder to pin 0&1 of SR2, the Clic at pin2 (on the 2nd DIN)

Connect the Jack at pin4 of SR2 (on the 2nd DIN)

Connect Button A,B,C,D at respectively pins 5, 6, 7, 8 of the 2nd DIN. Don't forget the ground !!

Connect the LEDs to the SR of the 2nd DOUT :

4 green leds to pin 0 1 2 3

1 red led to pin 4

1 yellow led to pin 5

a tricolor led to pins 6 & 7 (red/green/yellow fluo)

Connect a light to the supply

Connect a light to pin J14 of the core.

How it works :

Button A = Note mode, and midi channel choosing ;

indicated by the 4 green leds. Coding hard to understand (a bit llke BinaryCodedDecimal, but different)

Button B = Program Change Mode ; indicated by red led

Button C : Control change mode ; indicated by yellow led

Button D : switch between the layers : A, B or C

Rq : Layer is a manner to have 128 virtual buttons with only 64 real ones.

Layer A corresponds to buttons 0 to 63 (led red fluo),

layer B corresponds to buttons 64 to 127(led green fluo)

and layer C is a mix of A & B, buttons 32 to 96 (led yellow fluo).

You choose which mode you want by pressing the corresponding button.

WARNING : The midi channel is selected by the note mode button.

For example I want to play a note c-1 at channel 4 :

Start the device. I press 4 times on buttonA, that means I am in midi channel 4, it is indicated by the 4th leds highlighted.

Then I choose the layer : it will be layer A because we are looking for the first note in MIDI (note 00).

the layer LED must be red fluo. If it's not, press several time on buttonD until LED become red fluo.

Then play on the Keyboard the 1st button (up left corner).

the velocity is given by the encoder : turn clockwise to increase, anticlockwise to decrease, or press the click to get the maximum velocity.

By default at start up the velocity is 100 (0x64).

For example i want to send a program change message : 52

Press buttonB, choose layer A, then press the 52th button of the keyboard !

or choose layer C and press the 20th button of the keyboard. (32+20=52)

This manner is easy to command a drummachine which has its patterns defined by PC message (ex : Machinedrum, MPC, Jomox, etc).

The midi channel is always defined by buttonA.

That means that you have to pass by Note mode to change the channel.

To choose the channel you push the button A and the channel increase ; when it reaches 16, it then fall back to channel 1.

Leds show the corresponding midi channel, but coding 16 values with only 4 LEDs is a bit like speaking with an Alien : complicated.

Now I want to modulate Control change 13 at channel5 :

Choose channel 5 by pressing buttonA until the leds indicate that you are in channel 5 (look in main.c it is explained)

then switch to CC mode by pressing buttonC

Then choose CC13 by pressing the 13th button of the keyboard.

then modulate with the encoder !!

Press the footswitch (connected to the jack) to start your favorite sequencer.

Whatever the mode be, the light connected to pin J14 of the core is highlighted when you send a midi message.

Have fun and send me feedback if you like it !!

In several months a special sequencer will maybe exist, based on this design with an additionnal Display.

Link to comment
Share on other sites

  • 1 month later...

I don't know ! 

I ve found 8 of them in a trash ; seems to be interphones. As my friend told I was making "Voirinof" (notice the russian accent), it was the perfect case for (70's Eastern Europe style). Buttons where included, and 1x DIN5P too  ; that is why I recycled. Practical and cheap (15€ bargain each time, used for SID too).

Link to comment
Share on other sites

i learned how to write 'OR' in C so I added support for indicating MIDI channel while in Program or CC mode. Two months I was waiting for this and it is the website of Arduino which learn it to me (nice free project this arduino !). Learned also && and !. Yeah. Still not understood how to make boolean var.

also edited the readme.txt and added a changelog into.

schematic not planned except if at least 3 midiboxers want to build it. Contact me. By default i can produce a map indicating the pins to connect :

J9 Core >> J1 DINX2 ...

D0 SR1 DIN >> scan matrix

etc ...

But ask if you want it. No job for nothing

8x8 KBD LED Enc v1.2.rar

8x8 KBD LED Enc v1.2.rar

8x8 KBD LED Enc v1.2.rar

8x8 KBD LED Enc v1.2.rar

Link to comment
Share on other sites

It sounds like you know C even better than you may be aware of.  You don't need to make a boolean variable.  What you are doing with &&, ||, and ! are boolean comparisons.  These boolean comparisons can be done with any type of variable (int, float, byte, char, long, pointers).  So yeah.. you are in good shape with the boolean comparisons.

Link to comment
Share on other sites

thanks for your explanations, but here is what i would like to do (maybe you can help me) :

i have a bool var : StateX. It can be 0 or 1 (true, false)

i have another var : StateY. 0 or 1

StateX is attached to ButtonA. When buttonA is pressed, StateX change from 0 to 1 or 1 to 0 (depending of the previous state). I have made a compromiss, using ++ and another condition sooner in the program : If StateX >2 ,then StateX=0.

And sometimes, during the use of the Voirinof, i have queries : "is StateX in 0 or 1 ?" then do something

And also "if StateX is false and StateY is true then ..."

Any help welcome. I don't know how to declare this, especially the "grammar" to use.

I noticed, studying clockbox, that thorsten uses State_t stuff. I tried the same but unsuccessful (i looked in the forum and the wiki), lots of error while compiling with the linker (i use PSPAd to code, no knowledge on IDE - i am a selfmade man)

I am also looking for a manner to isolate the "A" of 0x9A and put it in a integer in order to read it and display the midi channel. For the moment, i am using a sort of table with || (similar to an array), listing all the possibilities.

Ahh ! Arrays !, another thing i don't manage.

Cheers

Link to comment
Share on other sites

lots of questions there.

A lot of confusion can arise here over boolean operations because C++ added some new functionality that may or may not be implemented in the later C compiler we are using for the microcontrollers.  I'm not 100% sure what's implemented in the compiler you are using.

I use microsoft C++ every day and I can do the following to alternate the state of a variable that is being treated like a boolean:

char StateX = 0;

StateX = !StateX;

this works like the following psedocode:

if StateX is false then set StateX to be equal to true

else set StateX to be equal to false

I don't want to crack your brain while your doing so well with the booleans, but there are also bitwise operators that you can use.  That will result in all of the bits of your variable alternating states:

char StateX = 0;

StateX = ~StateX;

pseudocode for this:

if StateX == 0x00 then set StateX to 0xff

else set StateX to 0x00;

I'll have to dig into the code to see what you mean by the State_t stuff.  I assume that is some type that Thorsten uses for states.  Unfortunately I'm too busy to do that at the moment, so maybe someone else can comment more on that.

- Isolating the A of 0x9a:

char data = 0x9a;

char midichannel = (data & 0x0f)

after this, midichannel will be equal to 0x0a.  if data were set to another value, say 0x99, then data would be equal to 0x09.  The & 0x0f part is a bitwise AND operation.  Because 0x0f has the right side 4 bits set to 1, you are essentially extracting the rightmost 4 bits of the data variable.

Hope that helps.

Link to comment
Share on other sites

StateX = !StateX;
Is a comparator (a logical NOT) and might not work quite the way you're thinking. That's more for stuff like:
If (StateX != foo) then bar();
It's logical as in true/false. You might want an operator (a bitwise NOT, aka, one's complement) like this:
StateX = ~StateX;

Which inverts the bits of the variable given.

http://www.phim.unibe.ch/comp_doc/c_manual/C/CONCEPT/expressions.html Good summary. Check out the rest of the site.

http://www.midibox.org/forum/index.php?topic=6981.msg45080#msg45080 Nibbles thread of goodness. Check this out for grabbing one nibble of a byte (EG 0x94 broken into 0x90 or 0x04). I updated the cheat sheets tonight.

Link to comment
Share on other sites

typedef and union are actually two separate things, but TK is using them together. I'm guessing that you're looking at a bitfield. Here's an example, I'll break it down.

First we have typedef. It's used to define a variable type. You'll already know about types like 'unsigned char' which is 8bit, or 'signed int' which is 16b. Typedef allows you to create your own customised types.

You can do

typedef char MyType_t;
Which creates a type named MyType_t, and makes it a char (which will be unsigned by default). Now, you can create as many variables as you need, using this type:
unsigned char Example;
unsigned char Example1;

int Example2;

MyType_t MyVar;
MyType_t MyVar1;
MyType_t Foo;
Now your type can be just about anything you specify. For example we could create a struct:
struct MyStruct {
    unsigned char Foo;
    unsigned char Foo1;
    unsigned int Bah;
    unsigned int Black;
    unsigned char Sheep;
};
What this makes is a set of variables which you access like so:
MyStruct.Foo = 0x69;
MyStruct.Sheep = 0;
Now, you can also create bitfields with the struct keyword, by specifying the member name and how many bits it should have assigned to it:
  struct MyStatus {
    unsigned RUN:1;
    unsigned PAUSE:1;
    unsigned START_REQ:1;
    unsigned STOP_REQ:1;
    unsigned CONT_REQ:1;
  };
This creates a struct called MyStatus which is 5 bits in size, with one bit assigned to each member. So:
MyStatus.RUN = 1;
Sets a one-bit 'flag' that your app can use to tell if the Status is running. You can combine this with the typedef like so:
typedef struct {
    unsigned RUN:1;
    unsigned PAUSE:1;
    unsigned START_REQ:1;
    unsigned STOP_REQ:1;
    unsigned CONT_REQ:1;
  } MyStatus_t;
This creates a type called MyStatus_t, which you can then use to declare several variables as the same 5-bit bitfield:
MyStatus_t Status1;
MyStatus_t Status2;
So now, you have for example:
Status1.RUN = 1;
Status2.RUN = 0;
Status2.START_REQ = 1;
etc etc... Now, onto union... union instructs the compiler (SDCC) to assign the same memory address to two different variables. A simple example is:
union { 
unsigned char foo;
unsigned char bah;
} Example_u
Now if the two unsigned chars, foo and bah, share the same physical memory. That means that whatever you write to one, you also write to the other, so if you do:
Example_U = 0x10;
return bah;
Then this function will return the value of bah, which is 0x10. If the above declaration of the MyStatus type looked like this:
typedef union {

struct {
    unsigned ALL:5;
  } 

struct {
    unsigned RUN:1;
    unsigned PAUSE:1;
    unsigned START_REQ:1;
    unsigned STOP_REQ:1;
    unsigned CONT_REQ:1;
  } 

} MyStatus_t
Now we have created a type, which is a union, of two 5-bit bitfields. In order to make sure that the data is properly asigned with the 8-bit memory, it's best to make it 8-bit, so we do this:
// status of midi clock
typedef union {
  struct {
    unsigned ALL:8;
  };
  struct {
    unsigned RUN:1;
    unsigned PAUSE:1;
    unsigned START_REQ:1;
    unsigned STOP_REQ:1;
    unsigned CONT_REQ:1;
  };
} mclock_state_t;
(Look familiar?) ;) Notice that the 'ALL' member is now 8 bits wide. It is in a union with the 5-bit bitfield, so three bits are unused by the bitfield but still accessible by the ALL union member. Once this type is defined, then you use the type to declare the variable:
mclock_state_t mclock_state;
You could use this type as many times as you need:
mclock_state_t mclock1_state;

mclock_state_t mclock2_state;

mclock_state_t Some_Other_state;
Now, it is possible to address the individual flags like so:
mclock_state.RUN = 1;
Or you can access them all by making use of the union. For example, you can clear all the flags when you initialise the clock:
mclock_state.ALL = 0;

How's your head? It's 0130 here, I'm out!

PS Maybe this thread could be split off into the C programming forum?

Edit: BITFIELDS!!

(sorry, it's an in-joke between me and another forum member. couldn't help it)

Link to comment
Share on other sites

  • 1 month later...
  • 2 weeks later...

ok ok pics & colegram :

(i had no more battery on photo device so rather bad shoots)

as you can see, it indicates if it is note, cc or program change mode.

a function also print on the left of the lcd incoming midi message (software feedback idea)

find some videos at :

http://4colors.free.fr/midibox/demos/voirinof/voirinof%20mini%20demo.mov

some "chop chop" (like on MPC, each 1 of the 8 buttons is assigned to a sample, this sample is creating further by the slicing of a loop) with ableton, using midi learn (cmd+M) :

http://4colors.free.fr/midibox/demos/voirinof/chopchop_voirinof.mov

Guys having a monome can do the same thing without max/msp patches ...

Link to comment
Share on other sites

  • 3 years later...

huh, great.

that box is almost completely the thing i am looking for, because it can control other synths and samplers, with look and feel

of ableton live.

and here is the thing that would make my dreams totally come true :

this box..

with the ability sending a midi-signal that triggers a sample (eg. a loop from a connected sampler) BUT: not before the next bar is gained?

i hope you know what i mean. its like the starting of clips in ableton live's session-mode, where they start right in-time with the next bar.

so it will require a midi-clock to adjust the tempo (and able to send tempo to a slaved device) of course.

would it be hard to realize building a box like this?

if there a project that is similarly close to my visions, please let me know.

thanks a lot,

tibor

Link to comment
Share on other sites

  • 2 weeks later...

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