I'm building a controller and hope to make it compatible with monomeserial. I've been staring at this: http://wiki.monome.org/view/SerialProtocol But I'm still not sure exactly what strings to actually send over the wire. For instance to send a button press at 7,7, would my firmware just do: Serial.println("0 1 7 7"); or Serial.println("0177"); or Serial.println("0,1,7,7"); or does it need to be encoded in some way? Sorry if this is a dumb question but sometimes I need things spelled out for me. The docs describe what goes on between monomeserial and a host app but not so much what goes on between the monome and monomeserial. BTW: Thanks monome for all the wonderful work and for making this an open project - I'm learning so much my head is spinning.
on 06.09.2007 20:25
on 07.09.2007 01:58
you almost got it. it's separated by bit fields. learn your bit operators, you'll love them. a press down at 7,7 would send two bytes (everything in the 40h is two bytes): 1, 255 here's how it decodes: byte0 >> 4 = id = 0 = press byte0 & 1 = state = 1 = down byte1 & 0x0f = y = 7 byte1 >> 4 = y = 7 pretty, right? here's how to send an led on at 0,2: byte0 = (id<<4)+state = (2<<4)+1 = 33 byte1 = x<<4 + y = 0<<4 + 2 = 2 so send 33,2 pow!
on 07.09.2007 07:37
I've done bitwise operations on registers but I'm not following. id?
>>? <<? (I guess those last two are in/out pipe commands, what
language?) can you dumb it down a bit? are all those numbers hex?
on 07.09.2007 12:21
Bitwise operators:
* op1 & op2 -- The AND operator compares two bits and generates a
result of 1 if both bits are 1; otherwise, it returns 0.
* op1 | op2 -- The OR operator compares two bits and generates a
result of 1 if the bits are complementary; otherwise, it returns 0.
* op1^ op2 -- The EXCLUSIVE-OR operator compares two bits and
generates a result of 1 if either or both bits are 1; otherwise, it
returns 0.
* ~op1 -- The COMPLEMENT operator is used to invert all of the bits
of the operand.
* op1 >> op2 -- The SHIFT RIGHT operator moves the bits to the
right, discards the far right bit, and assigns the leftmost bit a value
of 0. Each move to the right effectively divides op1 in half.
* op1 << op2 -- The SHIFT LEFT operator moves the bits to the left,
discards the far left bit, and assigns the rightmost bit a value of 0.
Each move to the left effectively multiplies op1 by 2.
from: http://www.cs.cf.ac.uk/Dave/PERL/node36.html
***
I still don't entirely get it but:
... the idea is to fit EVERY message into only 2 bytes (16 bits) using
the binary 1's and 0's as "flags", encode the 2 binary strings into 2
integers, send them, then decode them on the other end.
... I think "id" correlates to "address" as shown on the protocol page,
e.g. 0 = output/press, 1 = output/adc_val, 2 = input/led etc
... byte0 and byte1 in tehn's explanation correlate to data0 and data1
on the diagram
... and shifting values << left or >> right has to do with creating the
correct binary values in the register to match the protocol diagram? I
think he is doing bitwise math here but I'm still trying to grasp that
concept.
Understanding is slowly dawning but I know I'm still not quite there.
This is helping me better understand the sample Arduino code I've been
cutting and pasting to make my LED driver firmware, as it uses the same
principles. This low-level stuff is pretty cool.
on 07.09.2007 18:33
still not getting it. this is embarrassing because I know this stuff for real, I'm a hardware guy but I've been coding low level like this on and off for 10 years. looking here http://wiki.monome.org/view/SerialProtocol you get two bytes, read in byte1 and byte 2 address_byte1 = (1111 0000 & byte1) data_byte1 = (0000 1111 & byte1) case address_byte1 2: %this is an led message, mask off the lower nibble of byte1 to get the state, the higher nibble of byte2 for x and lower nibble of byte2 for y% etc. I'm not going to write that much pseudocode today. likewise you build outgoing messages in the same way, construct a byte by logical ORing with 1 I just don't get tehn's notation...
on 07.09.2007 19:19
Makes me feel better that I'm not the only one who doesn't get it. I've found it useful to play with _serial_howto.mxb (comes with the base patches). By adding print objects all over the place I can watch the values go by in the Max window as I push buttons or light leds with the app. I wish I knew Max better but I'm learning. I need a bigger (or 2nd) monitor so I can view the Max reference manual at the same time as the app window. I'm still struggling for clarity, too. Once I figure it out I'll try to write it up in dummy-ese...
on 07.09.2007 21:41
you guys pretty much have everything right, it'll just take a bit to sink in. one way is to think of the two bytes as a string of bits. so each message is 16 bits. we want to cram more than two pieces of "data" in there, so we don't just use the byte division (8). we split it into more. mostly we split it into 4 chunks of 4 bits each. 4 bits give us 16 possible values. so say we want data "chunks" a,b,c,d each 4 bits. we're going to stuff them into byte0 and byte1 (sorry for the inconsistent notation, you're correct that on the wiki it's data0 and data1 or something). byte0 = (a << 4) + b byte1 = (c << 4) + d << 4 means shift 4 bit-positions to the left. so if we have bitmap of 4bit "a" (this is clunky notation): ....aaaa and we go (a << 4) we get: aaaa.... then if we + b we get aaaabbbb it's one byte with two "parts" real example: a = 3 = 0b0011 b = 2 = 0b0010 (a << 4) + b = 0b00110000 + 0b0010 = 0b00110010 = 50 that's encoding so let's decode (shown bitwise): input = abcdefgh the left four bits we need to be "x" and the right 4 "y" x = input >> 4 = abcdefgh >> 4 = ....abcd the left part is shifted to the right by 4. (the right four bits are "erased") now you can read x as is. y = input & 0b00001111 = input 0x0f = abcdefg & 0x0f = ....defg the left four bits are masked out (set to zero) and you're left with only the right bits. hopefully that helps a little. the serial protocol layout is modeled after those that you see in datasheets, like the max7221 datasheet. completely same idea. and yes, id = address
on 07.09.2007 22:50
makes sense, after I wrote my bit masking guess it occurred to me that you might be doing a similar thing with bit shifting, shifting in zeros to mask out data bits. which style makes sense in this context will make more sense once I try it myself. at work I always do bit masking, it's just what I'm used to. ultra has the right idea of sitting down and playing with the thing, seeing what data looks like. I'll be using max/msp, it does bit-wise operations and there are shift registers, it'll be interesting to see how that unfolds. actually it'll probably be a LOT easier than typing all the logic in. thanks tehn!!
on 07.09.2007 23:51
for the serial junk in max/msp, check out 40h_serial.mxb i do everything there like described above, and believe me, it's ugly in max. i'm pretty obsessed with bitops... http://machineproject.com/2007/02/10/computerbasics/
on 08.09.2007 01:58
That sounds like it was a cool machineproject event - any pics? I tried poking around in 40h_serial.mxb and I see there is an embedded patcher named "internal" which I assume has all the guts but it doesn't have the yellow stripes like other embedded patchers and double-clicking it doesn't open it up. How do I see what's in it? Forgive me if this is a noob Max question.
on 08.09.2007 02:55
"internal" should definitely open up. also check out serial_howto.mxb
on 08.09.2007 11:42
Okay nevermind I think I figured it out - I have to paste it into a text editor and remove "hidden" then paste it back in and then I can double-click the sub-patch and it shows up. Since I could only see the patch in un-locked mode I thought I was supposed to double-click it there. Max noob error. I see now it is pretty much the same stuff as in serial_howto.
on 08.09.2007 13:26
in edit mode, use apple (or ctrl on windows) then double click to open it up.
on 08.09.2007 15:37
Awesome - thanks.
on 10.09.2007 09:24
keep in mind I'm a max n00b. I messed with taking apart 40h_serial.mxb friday night, it started to make sense but I found myself hitting my learning curve, it helped me understand send and receive objects better but as I kept learning new stuff from the patch I wondered if there was a better place to spend my 40h/max learning hours. given that monomeserial is the standard monome interface app to break up the bytes and route them via the 'prefix' prefix, can someone post a straightforward 'hello world' max patch? I started looking at the 'lights out' patch that some user (sorry, forgot whom, but that was immpressive that you knocked that out so fast and it's FUN!) said was a good hello world app but I lost the old version, it was later on friday night and I didn't pick it up on sat or sun. I can spend some time figuring it out or copy the homework of those who've already been there. many thanks for any help, sooner or later I hope to post a usable patch in return. maybe a different thread is in order for this. good topic though. edit - wow, the word 'immpressive' hit the spam filter, sorry I didn't mean immpressive in THAT way, I hope your girlfriend/wife (or both) appreciate your immpressiveness. what a weird society, the things that are meant to keep me from such thoughts are suggesting them to me.
on 10.09.2007 11:00
Check out _serial_howto.mxb in the howto folder of the 0400 base patches- same functionality as 40h_serial but much more broken out - I just added print objects all over the place and patched them onto different things to see what strings show in the Max monitor window - this helped me understand a lot.
on 10.09.2007 12:40
for general getting started with max/msp, definitely check out cycling74's tutorials. they are outstanding, and bite-sized. also in the base patches howto folder, check out the OSC howto, since there's really no need to use serial in max/msp (monomeserial is superior).