Jump to content

Sauraen

Programmer
  • Posts

    460
  • Joined

  • Last visited

  • Days Won

    26

Everything posted by Sauraen

  1. Thanks for the recommendation, but that would be about $50 for me (two orders counting shipping), and considering the whole synth was only about $300, that's a bit too much. Also, they have those lines, and in order to get rid of them I'd have to get rid of the nice red too.
  2. So I have some more actual questions for anyone who might be interested in building one of these. How terrible would it be if Pitchbend, Sustain, and Mod Wheel controls were hard-coded instead of being routed in your .NGC file? Pitchbend is not a modulator, it just enters into the pitch calculations for a voice and adjusts it accordingly. There may be a global menu option for how far to bend, but this won't be modulatable. There are, however, tuning and transpose parameters that are modulatable. Sustain is also not a modulator, it affects what happens to voices when they get Note Offs--basically marks them for being released when the pedal is released. This would just permanently assign that to CC 64. Mod Wheel is a modulator (assignable time-varying data source), this decision would just make it permanently assigned to CC 01. There is also a modulator, VARI (variation), which I will keep as assignable to input from wherever in your .NGC, like so: EVENT_RECEIVER id=1 fwd_id=SENDER:1 type=CC chn=1 cc=2 EVENT_SENDER id=1 type=MBFM mbfm=ControlVari:0 EVENT_RECEIVER id=2 fwd_id=SENDER:2 type=CC chn=2 cc=2 EVENT_SENDER id=2 type=MBFM mbfm=ControlVari:1 # and so on for the other channels, or whatever you want to have control it How terrible would it be if all the CC-based controls for editing voice parameters--as if you were twiddling the knobs on the front panel--were hard-coded? I had to take memory away from the .NGC event pool to make room for the MBFM stuff, so my current config file, which has all the front panel stuff but no CCs for editing voice parameters, is about 70% full. I'm not sure if there's going to be room for a whole additional set of EVENT_RECEIVERS that perform similar actions--and if there is, there'll be almost no room left over for banking and other things you want your hardware to do. Leaving aside "special" CCs like 0 and 32 (bank), 100 and 101 (NRPN) (which will have to be hard-coded anyway), if I assign the rest of them permanently to other CCs, will this make trouble with anyone's DAW? Does anyone's DAW insist on sending the LSB version of parameters after the MSB version (e.g. CC 16 always is followed by CC 48)? I would not hard-code the assignments into the actual code, I would make them with preprocessor commands in your mios32_config.h file (which you're going to have to edit anyway to set up the hardware mapping of your OPL3 modules), so each user would still be able to edit them if necessary, just it would require a recompile. Also it would be significantly faster to process control changes if they were hard-coded, which matters if you're doing "smooth curves" with them in your DAW and sending hundreds of them per second on multiple channels. How do you want modulators to change the values of parameters? So you set a parameter, let's say you set Op Volume to 50. Now you assign an LFO to that parameter with depth 10. The LFO itself always outputs values (right now, this is the part I'm asking about!) in the range -127 to 127, so the synth engine scales this to -10 to 10 and adds the current modulator result value to the original value of 50 to get a range of 40 - 60. If you assign an EG, however, it outputs in the range 0-127, so instead of the 50 being the middle value, it's the low value, and it ranges 50 - 60. This came about because I think of EGs as being above the x-axis but LFOs as being symmetrical about it, but it's inconsistent and may be confusing to other people. Possible solutions: Make all modulators output 0-127, so the original value is always a minimum (this will make Velocity, Mod Wheel, and Vari go in with their original values) Make all modulators output -127 - 127, so the original value is always the middle (requiring those three passive modulators to be scaled by twice) Some combination that makes sense to people Switch to u8 and make all modulators output 0-255 (probably not a good solution) Make all modulators output -63 - 63 (preserve VEL/MOD/VARI values, probably not a good solution) By the way, when you have two modulation sources connected to the same destination, these delta values simply add.
  3. Just finished some more modifications to the MBNG framework, this time to allow for display of negative values properly with a negative sign, as well as blanking leading zeroes. Both are optional and triggered from your config file: # LED display digits # Using digit_signed=1 automatically enables digit_blankzero EVENT_LED_MATRIX id=8 led_matrix_pattern=Digit1 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=7 led_matrix_pattern=Digit2 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=6 led_matrix_pattern=Digit3 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=5 led_matrix_pattern=Digit4 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=4 led_matrix_pattern=Digit1 type=MBFM mbfm=DispVoice digit_blankzero=0 EVENT_LED_MATRIX id=3 led_matrix_pattern=Digit2 type=MBFM mbfm=DispVoice digit_blankzero=0
  4. From the album: MIDIbox FM V2.0 Prototype

    This is an animated GIF--please click on it to see all the digit possibilities! Just finished some more modifications to the MBNG framework, this time to allow for display of negative values properly with a negative sign, as well as blanking leading zeroes. Both are optional and triggered from your config file: # LED display digits # Using digit_signed=1 automatically enables digit_blankzero EVENT_LED_MATRIX id=8 led_matrix_pattern=Digit1 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=7 led_matrix_pattern=Digit2 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=6 led_matrix_pattern=Digit3 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=5 led_matrix_pattern=Digit4 type=MBFM mbfm=DispValue digit_signed=1 EVENT_LED_MATRIX id=4 led_matrix_pattern=Digit1 type=MBFM mbfm=DispVoice digit_blankzero=0 EVENT_LED_MATRIX id=3 led_matrix_pattern=Digit2 type=MBFM mbfm=DispVoice digit_blankzero=0
  5. Thanks! They're custom 3D printed--the whole order cost $20 including shipping. Note "improperly configured" in the title. :smile:
  6. Here's your demosong, m00dawg! One take, 32 voices allocated. I could have done it in half the number of voices if I had been willing to let the release trails of notes get cut off for other notes to replace them, but since I have two OPL3s, why not! The following features of MIDIbox FM V2.0 are being used in this video: Support for two OPL3 modules and up to 36 2-op voices or 12 4-op voices and 12 2-op voices Front panel button matrix, LED matrix, encoder array, and LED display digits Mode control, MIDI channel -> voice allocation, and basic voice editing DUPL voices (polyphonic copies that maintain similarity when parameters are changed) LINK voices (voices that are sounded together) Delay line (when combined with LINK, allows for delay/reverb effect) The following features are also working but were not used here: Portamento and Retrigger option Transpose and tuning control Drum channel MIDI mapping The following features are not done/working yet: Parameter modulation Saving/loading patches CC parameter controls OPL3 percussion mode (including editing) Wavetable editing The entire sequencer
  7. This demosong is dedicated to m00dawg, who has been chanting for it since November 27, 2013: https://soundcloud.com/sauraen/midibox-fm-v2-0-demosong-aemas (By the way, does anyone know how to embed the soundcloud player into posts?)
  8. You're welcome! I hope this is only the first of the times my code ends up in the repository, heh heh!
  9. Finally squished a couple of bugs (one in the vanilla MIDIbox NG, one in my modifications) and got the LED matrix working. You can see what the FM Widget is supposed to look like now (the colors are more obvious in person, red is modulator, green is carrier, blue is signal path, red on top is feedback). The voice "nodes" turn off when muted (though not when the volume is set to 0).
  10. From the album: MIDIbox FM V2.0 Prototype

    The widget shows the signal path for the FM synthesis. The colors are more visible in person: red is modulator, green is carrier, blue is signal path, red on top is feedback.
  11. Bug squashed! Here's the changes: In mbng_matrix.c, MBNG_MATRIX_DOUT_PinSet(): To make mirrored_row work right, right after int row, int column (your line 508), add: //Feature added by Sauraen if(m->flags.mirrored_row) column = (column&0xF8) | (7 - (column&7)); //Only swap lower 8 of column, as per spec To fix the second-shift-register-not-working bug, right after the switch(color) statement (your original line 515), add: //Bug fixed by Sauraen column &= 7; //Above, we picked a different sr if column >= 8, but then we wrote to that sr with column still >= 8 One other bug I discovered while tracing the program flow is in mbng_dout.c, MBNG_DOUT_NotifyReceivedValue(), line 96, I'm pretty sure it should be if( hw_id_ix < (m->led_emu_id_offset + (m->num_rows * row_size)) ) { //Bug? found by Sauraen As it was, m->led_emu_id_offset was being multiplied by m->num_rows, and that looked like it was going to generate a huge number. This might never actually lead to a visible problem, since even though it would pass events with indices too high, at MBNG_MATRIX_DOUT_PinSet() it checks again (at original line 503) to make sure the given pin is in range. But it would have executed a couple hundred extra lines of code per LED event with large index.
  12. I can confirm that both of these problems with led_emu_id_offset--mirrored_row doing nothing and only the first-defined shift register's worth of LEDs working in an 8x16 matrix--exist in the unmodified midibox_ng_v1 (i.e. are actual bugs). I checked out a new copy and tried it again, with the same results. The mapping tables I wrote above also appear to be the same. I'm now going to switch back to the modified copy (so I can have my LED digits working) and see if I can actually fix the bug.
  13. Hi TK, I thought I'd make this a separate topic. This is for a different DOUT_MATRIX (though same synth) than the one that has swap_rows_columns=1 (it doesn't even have that parameter at all). The first problem I noticed was that mirrored_row=1 didn't seem to do anything. That is, with writes to a bunch of LED ids, and then enabling the parameter, did not change which hardware LEDs lit up. But this is not a serious problem, it just means the assignment numbers will be different. The more serious problem is that the second shift register's worth of LEDs seem not to work (it's 8x16): # LED matrix DOUT_MATRIX n=2 rows=8 inverted_sel=1 sr_dout_sel1=1 \ inverted_row=0 mirrored_row=0 sr_dout_r1=3 sr_dout_r2=4 \ led_emu_id_offset=1001 I made a spreadsheet of how the offset IDs were being assigned to the elements of the matrix: 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1120 1119 1118 1117 1116 1115 1114 1113 1112 1111 1110 1109 1108 1107 1106 1105 1 1104 1103 1102 1101 1100 1099 1098 1097 1096 1095 1094 1093 1092 1091 1090 1089 2 1088 1087 1086 1085 1084 1083 1082 1081 1080 1079 1078 1077 1076 1075 1074 1073 3 1072 1071 1070 1069 1068 1067 1066 1065 1064 1063 1062 1061 1060 1059 1058 1057 4 1056 1055 1054 1053 1052 1051 1050 1049 1048 1047 1046 1045 1044 1043 1042 1041 5 1040 1039 1038 1037 1036 1035 1034 1033 1032 1031 1030 1029 1028 1027 1026 1025 6 1024 1023 1022 1021 1020 1019 1018 1017 1016 1015 1014 1013 1012 1011 1010 1009 7 1008 1007 1006 1005 1004 1003 1002 1001 1000 999 998 997 996 995 994 993 However, only the LEDs on the left shift register (the first 0-7) would light; I extrapolated the numbers for the right side, but couldn't actually confirm them because a statement like EVENT_LED id=1112 [etc.] would do nothing. (I didn't actually try all 64 on the side that were working, just a few here and there to establish the pattern, and at the beginning and end.) Swapping the shift registers in the DOUT_MATRIX definition as follows # LED matrix DOUT_MATRIX n=2 rows=8 inverted_sel=1 sr_dout_sel1=1 \ inverted_row=0 mirrored_row=0 sr_dout_r1=4 sr_dout_r2=3 \ led_emu_id_offset=1001 results in the mapping 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1136 1135 1134 1133 1132 1131 1130 1129 1128 1127 1126 1125 1124 1123 1122 1121 1 1120 1119 1118 1117 1116 1115 1114 1113 1112 1111 1110 1109 1108 1107 1106 1105 2 1104 1103 1102 1101 1100 1099 1098 1097 1096 1095 1094 1093 1092 1091 1090 1089 3 1088 1087 1086 1085 1084 1083 1082 1081 1080 1079 1078 1077 1076 1075 1074 1073 4 1072 1071 1070 1069 1068 1067 1066 1065 1064 1063 1062 1061 1060 1059 1058 1057 5 1056 1055 1054 1053 1052 1051 1050 1049 1048 1047 1046 1045 1044 1043 1042 1041 6 1040 1039 1038 1037 1036 1035 1034 1033 1032 1031 1030 1029 1028 1027 1026 1025 7 1024 1023 1022 1021 1020 1019 1018 1017 1016 1015 1014 1013 1012 1011 1010 1009 with now only the second shift register's worth of LEDs working and the first half not working. That is, the other 64 hardware LEDs now work but the first half don't (it's not a hardware problem). So in both cases only the first-defined shift register will accept LED input, but the mapping is defined across both. In both cases the mapping is not correct either: in the first case it extends below 1001 into the non-working shift register, and in the second case, above 1128 into the non-working shift register. If I can't find anything tonight, I'll try it with code from a new svn checkout just to make sure I didn't screw this up when I was fooling with mbng_matrix.c; but I'm pretty sure that all of the changes I made only executed additional code if swap_rows_columns=1 was active, and left the code untouched otherwise. Besides, I didn't change any code to do with the led_emu_offset_id mapping. Thanks, Sauraen
  14. It seems that the mirrored_row=1 parameter in a DOUT_MATRIX doesn't do anything at all when the matrix is assigned to individual LEDs with led_emu_id_offset=1001. From looking at MBNG_MATRIX_DOUT_PinSet, it doesn't look like there's code to handle this case (except in the MAX72xx portion). It's possible I accidentally removed this when I was messing with mbng_matrix.c, but it doesn't appear to be the case from looking at the revision history above. I tried adding a line to reverse the columns if this flag was set, but then no LEDs lit at all. Can someone else with a working DOUT_MATRIX that uses led_emu_id_offset try adding the mirrored_row=1 parameter to their config file and see if the matrix gets mirrored?
  15. I saw those videos a long time ago--I wish I had that kind of ability! Damn is he good! Also the ragtime style freshens up almost anything. The chiptune platform I'm most familiar with is the NES, and since I like music that pushes hardware limitations, the takes the cake for me. Koji Kondo was able to get a variety of sounds out of the two pulse wave oscillators by varying the pulse width and envelope and often by having them play similar parts, and the soundtrack featured a range of drums (I managed to sample at least 10) made with PCM in a fifth audio channel. The music for defeating the final boss includes tympani made on that channel and thus manages a brief moment of four-voice polyphony on a system which was barely designed to support three-voice polyphony.
  16. The buttons and LED pipes are custom 3D printed (whole order including shipping cost $20, the maker was avdwege2003_ebay@yahoo.com). I made the designs in Blender and exported them for printing as stl. They are pushing on standard 5mm tact switches. I had to dremel out a depression in the bottom of each button that had an LED, so the LED wouldn't hold the button cap against the front panel and keep it from being pressed. Thanks! :D
  17. Index: apps/controllers/midibox_ng_v1/src/mbng_matrix.c =================================================================== --- apps/controllers/midibox_ng_v1/src/mbng_matrix.c (revision 1912) +++ apps/controllers/midibox_ng_v1/src/mbng_matrix.c (working copy) @@ -505,6 +505,15 @@ int row = pin / row_size; int column = pin % row_size; + int temp; + + //Added by Sauraen + if(m->flags.swap_rows_columns){ + temp = row; + row = column; + column = temp; + //DEBUG_MSG("Swapped row (now %d) and column (now %d)", row, column); + } u8 sr; switch( color ) { @@ -573,6 +582,47 @@ return 0; } + u8 sr1, sr2; + switch( color ) { + case 1: sr1 = m->sr_dout_g1; sr2 = m->sr_dout_g2; break; + case 2: sr1 = m->sr_dout_b1; sr2 = m->sr_dout_b2; break; + default: sr1 = m->sr_dout_r1; sr2 = m->sr_dout_r2; break; + } + + //Added by Sauraen + if(m->flags.swap_rows_columns){ + u16 column = row; + u8 sr; + if(column && !sr1) return -2; + if(column >= 8 && !sr2) return -2; + + if(m->flags.mirrored_row){ + //Change column as if mirroring across 8 columns + column = (column & 0xFFF8) + (7 - (column & 8)); + } + + if(m->flags.inverted_row){ + matrix_pattern ^= 0xFFFF; + } + + if(column >= 8){ + sr = sr2; + column -= 8; + }else{ + sr = sr1; + } + sr -= 1; //Evidently, zero-indexed internally + + int i; + for(row=0; row<m->num_rows; row++){ + for(i=0; i<MIOS32_SRIO_NUM_DOUT_PAGES; i+=m->num_rows) { + MIOS32_DOUT_PagePinSet(row + i, 8*sr + column, matrix_pattern & 1); + } + matrix_pattern >>= 1; + } + //DEBUG_MSG("Just finished writing pattern at column %d sr %d out of %d rows", column, sr, m->num_rows); + return 0; + } + if( row >= m->num_rows ) return -2; // ignore @@ -581,19 +631,16 @@ matrix_pattern = ((u16)mios32_dout_reverse_tab[matrix_pattern >> 8] << 8) | (u16)mios32_dout_reverse_tab[matrix_pattern & 0xff]; } - u8 sr1, sr2; - switch( color ) { - case 1: sr1 = m->sr_dout_g1; sr2 = m->sr_dout_g2; break; - case 2: sr1 = m->sr_dout_b1; sr2 = m->sr_dout_b2; break; - default: sr1 = m->sr_dout_r1; sr2 = m->sr_dout_r2; break; - } + if( m->flags.inverted_row ) matrix_pattern ^= 0xffff; u8 sr1_value = matrix_pattern; u8 sr2_value = matrix_pattern >> 8; - + + + if( m->num_rows ) { if( sr1 ) { u8 sr_offset = sr1-1; @@ -791,8 +838,12 @@ int pin; u16 mask = (1 << 0); for(pin=0; pin<row_size; ++pin, mask <<= 1) - if( changed & mask ) - MBNG_MATRIX_NotifyToggle(matrix, (row * row_size) + pin, (button_row[matrix][row] & mask) ? 1 : 0); + //Modified by Sauraen + if( changed & mask ){ + MBNG_MATRIX_NotifyToggle(matrix, + (m->flags.swap_rows_columns) ? ((pin * m->num_rows) + row) : ((row * row_size) + pin), + (button_row[matrix][row] & mask) ? 1 : 0 ); + } } } Index: apps/controllers/midibox_ng_v1/src/mbng_file_c.c =================================================================== --- apps/controllers/midibox_ng_v1/src/mbng_file_c.c (revision 1912) +++ apps/controllers/midibox_ng_v1/src/mbng_file_c.c (working copy) @@ -1788,6 +1788,18 @@ flags.mirrored_row = value; + ////////////////////////////////////////////////////////////////////////////////////////////////Added by Sauraen + } else if( strcasecmp(parameter, "swap_rows_columns") == 0 ) { + int value; + if( (value=get_dec(value_str)) < 0 || value > 1 ) { +#if DEBUG_VERBOSE_LEVEL >= 1 + DEBUG_MSG("[MBNG_FILE_C:%d] ERROR invalid swap_rows_columns flag for %s n=%d ... %s=%s (only 0 or 1 allowed)\n", line, cmd, num, parameter, value_str); +#endif + return -1; // invalid parameter + } + + flags.swap_rows_columns = value; + //////////////////////////////////////////////////////////////////////////////////////////////// } else if( strcasecmp(parameter, "button_emu_id_offset") == 0 ) { if( (button_emu_id_offset=get_dec(value_str)) < 0 || button_emu_id_offset >= 4095 ) { @@ -1950,6 +1962,18 @@ flags.mirrored_row = value; //////////////////////////////////////////////////////////////////////////////////////////////// + } else if( strcasecmp(parameter, "swap_rows_columns") == 0 ) { + int value; + if( (value=get_dec(value_str)) < 0 || value > 1 ) { +#if DEBUG_VERBOSE_LEVEL >= 1 + DEBUG_MSG("[MBNG_FILE_C:%d] ERROR invalid swap_rows_columns flag for %s n=%d ... %s=%s (only 0 or 1 allowed)\n", line, cmd, num, parameter, value_str); +#endif + return -1; // invalid parameter + } + + flags.swap_rows_columns = value; + + //////////////////////////////////////////////////////////////////////////////////////////////// } else if( strcasecmp(parameter, "max72xx_enabled") == 0 ) { int value; if( (value=get_dec(value_str)) < 0 || value > 1 ) { Index: apps/controllers/midibox_ng_v1/src/mbng_patch.h =================================================================== --- apps/controllers/midibox_ng_v1/src/mbng_patch.h (revision 1912) +++ apps/controllers/midibox_ng_v1/src/mbng_patch.h (working copy) @@ -53,6 +53,7 @@ u8 inverted_row:1; u8 mirrored_row:1; u8 max72xx_enabled:1; + u8 swap_rows_columns:1; //Added by Sauraen }; } mbng_patch_matrix_flags_t; Just to be clear, this new swap_rows_columns does nothing to the MAX72xx driver, and I can't guarantee it supports all matrix sizes (though I see no reason it shouldn't, of course I could have missed something).
  18. An hour of coding later: It wasn't the easiest, as you said I had to consider a number of cases. I had to add an additional bit flag in mbng_patch.h : mbng_patch_matrix_flags_t, copy-and-paste to make parameter handlers for DIN_MATRIX and DOUT_MATRIX in mbng_file_c.c, and then in mbng_matrix.c, add a couple lines to MBNG_MATRIX_DOUT_PinSet and MBNG_MATRIX_ButtonHandler to do the swapping, and finally a separate handling section to Hlp_DOUT_PatternTransfer. I noticed the MAX72xx stuff but had no idea what that was, so I left it alone (i.e. the swapping would not work with those chips). My own matrices are 8x16 and 8x8 so I had to make sure those worked, and I considered the 16x16 case, but I'm not sure if the cases with 4 rows or columns will work. (That's why I wanted you to do it! :P) I don't think my code is good enough to add to the repository at this point, but as you said, if a couple more people ask here about the same thing, I'll send you what I changed, you can fix it up a bit and include it in the release.
  19. ...Except that I now have a partially-completed synth that I would have to make substantial hardware changes to in order to get to work, if I can't make a relatively simple software solution. I also think that adding one more optional parameter to a config file format that already supports hundreds of them is hardly "blowing up the complexity". I understand that you may see this as "n00b makes mistake and asks dev to change entire software package to cater to his special needs", but since the parameters for inverting the rows and columns and mirroring the columns were deemed useful enough to the general public to include them, and this seems to be a pretty similar thing, I would think it could be similarly useful. If it is that much of a problem I'll just add it to my own, but since this is a community, I'd really rather help to develop code that everyone can use, and allow what was originally my mistake to turn into more general hardware support for others in the future. Isn't that the point of MBNG being community-developed? TK finding out from other people building hardware what features would help make their lives easier?
  20. If anyone knows of any cheap (there are 40 above) smaller knob caps that are for 6mm flatted shaft (not knurled), let me know! I agree, they're ugly (and I really packed in the encoders, so there's not much space between them).
  21. If TK doesn't have time to work on it I will certainly try. But the above (fake) code is just the actual swapping, I don't know where in the entire MIOS32 architecture that function would be anyway, and it would require modification of the matrix definitions and .ngc parser (to understand the new keyword). More importantly, I was hoping it could be a permanent part of MBNG for everyone to use; if I add it myself, I can't commit to svn, so I would be the only one to be able to use it.
  22. It shouldn't be hard to test, if you have a Button/LED Matrix that's actually used as a matrix and not individually labeled buttons. If you invert the button matrix, the LED matrix should react to button presses as if it was mirrored across the diagonal; and if you invert the LED matrix, it should actually look mirrored across the diagonal. I was intending this would be inverted at a software level: the same shift registers would still be sending and receiving the same data, with the same row select signals and all, just when it is all written to or read from, the row and column numbers would be switched. Also, all the parameters you have already are absolutely necessary and generally well-documented (absolutely better documented than much commercial stuff, heh heh!). MBNG is a behemoth (200 Kb in flash?!) that I have barely scratched the surface of, and it's kind of magical that it automatically detects, configures, and runs things that I spent hours writing custom code for ASIDITY's front panel to do. So thanks again for providing it! Edit: To be clear, I want to be able to swap all the rows with all the columns, i.e. mirror the matrix across the diagonal, not swap individual rows with other rows or something. Just a single binary option for the whole matrix. You know, like: void DOUT_Matrix_SetLEDState(u8 column, u8 row, u8 state){ u8 temp; //add this part if(swap_rows_columns){ temp = row; row = column; column = temp; } //sample of already-existing code if(state) matrix_contents[row] |= 1 << column; else matrix_contents[row] &= ~(1 << column); }
  23. A slightly-buggy-hardware and improperly-MBNG-configured MIDIbox FM V2.0 prototype looks a bit like the control panel for an alien starship, does it not? ...But really, that's all we ever wanted from a synth. Right guys?
  24. From the album: MIDIbox FM V2.0 Prototype

    Looks a bit like a control panel from an alien starship, no?
×
×
  • Create New...