///////////////////////// Feb 2023 //////////////////////////////////////////////////////////////////////////////
// This is an example by dansfing.uk that uses the MIDI.h Library
// This should make it easier to add some other nice features like a MIDI through socket.
// Better realtime control of input on the front panel
// I have abandoned sample playback for the moment.
// Cheers Dan 9th Feb 2023
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Arduino YM2149 MIDI Synth
// by yukimizake
// video: https://youtu.be/hUPs2pv5d_g
// schematics: http://electronicfields.wordpress.com/?attachment_id=128 (Vcc/GND not shown)
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
#include
#include
#include
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
// Buttons on Analogue Pin A3
#define buttonPin A3 // analog input pin to use as a digital input
// Potentiometer Pin A0
#define potPin A0 // analog input pin to use as a 0 to 127 variable
int A3val=0;
int A0val=0;
MIDI_CREATE_DEFAULT_INSTANCE();
//Port settings
const int ad0 = 8;
const int ad1 = 9;
const int ad2 = 2;
const int ad3 = 3;
const int ad4 = 4;
const int ad5 = 5;
const int ad6 = 6;
const int ad7 = 7;
const int pinBC1 = 10;
const int pinBDIR = 11;
//BC2 to +5V
const int pinYMReset = 12;
//voicing
byte noteA = 0;
byte noteB = 0;
byte noteC = 0;
int periodA = 0;
int periodB = 0;
int periodC = 0;
//envelope
byte AmaxVolume = 0;
byte BmaxVolume = 0;
byte CmaxVolume = 0;
//unison detune
int detuneValue = 1;
//arpeggio settings
byte arpeggio[] = {0,7,12};
byte arpeggioLength = 3;
byte arpeggioCounter = 0;
boolean arpeggioFlipMe = false;
byte defaultLevel = 10;
//Fast pin switching macros
#define CLR(x,y) (x&=(~(1< 0)
{
periodB = tp[noteB + arpeggio[arpeggioCounter]];
byte LSB = ( periodB & 0x00FF);
byte MSB = ((periodB >> 8) & 0x000F);
send_data(0x02, LSB);
send_data(0x03, MSB);
arpeggioCounter++;
if (arpeggioCounter == arpeggioLength) arpeggioCounter = 0;
}
}
}
//Current Channel
int currentC=1;
//MIDI MUTES
int mm0=0;
int mm1=0;
int mm2=0;
int mm3=0;
int mm4=0;
int mm5=0;
int mm6=0;
int mm7=0;
//Button status - pressed or not
//MUTE Button
int muteP=0;
//STORE Button
int storeP=0;
//Button debounce timers
unsigned long startMillis; //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 175;
// MUTE debounce timer
unsigned long startMillisM; //some global variables available anywhere in the program
unsigned long currentMillisM;
const unsigned long periodM = 500; //the value is a number of milliseconds
void setup(){
startMillisM = millis(); //initial start time for MUTE debounce
//init pins
pinMode(ad0, OUTPUT);
pinMode(ad1, OUTPUT);
pinMode(ad2, OUTPUT);
pinMode(ad3, OUTPUT);
pinMode(ad4, OUTPUT);
pinMode(ad5, OUTPUT);
pinMode(ad6, OUTPUT);
pinMode(ad7, OUTPUT);
pinMode(pinBC1, OUTPUT);
pinMode(pinBDIR, OUTPUT);
pinMode(pinYMReset, OUTPUT);
pinMode(ledPin, OUTPUT);
__RGBLEDDDR__ |= ( 1 << __RLED__ | 1 << __GLED__ | 1 << __BLED__); //led pins as output
resetYM();
AmaxVolume = defaultLevel;
BmaxVolume = defaultLevel;
CmaxVolume = defaultLevel;
//serial init
//timer1 : sample player
cli();
TCCR1A = 0; //timer reset
TCCR1B = 0; //timer reset
OCR1A = 1450; //period for 11025 kHz at 16Mhz
TCCR1B |= (1 << WGM12); //CTC mode
TCCR1B |= (1 << CS10); // timer ticks = clock ticks
TIMSK1 |= (1 << OCIE1A); // enable compare
sei();
// Connect the handleNoteOn function to the library,
// so it is called upon reception of a NoteOn.
MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
// Do the same for NoteOffs
MIDI.setHandleNoteOff(handleNoteOff);
// Initiate MIDI communications, listen to all channels
MIDI.begin(MIDI_CHANNEL_OMNI);
////////read stored mutes from eeprom
//// If nothing is stored in eeprom we make it unmuted.
// byte mmS0b;
byte mmS0b = EEPROM.read(1); mm0 = int(mmS0b);
if ( mm0==0 || mm0==1 ) {} else {EEPROM.write(1, 0); mm0=0;}
byte mmS1b = EEPROM.read(2); mm1 = int(mmS1b);
if ( mm1==0 || mm1==1 ) {} else {EEPROM.write(2, 0); mm1=0;}
byte mmS2b = EEPROM.read(3); mm2 = int(mmS2b);
if ( mm2==0 || mm2==1 ) {} else {EEPROM.write(3, 0); mm2=0;}
byte mmS3b = EEPROM.read(4); mm3 = int(mmS3b);
if ( mm3==0 || mm3==1 ) {} else {EEPROM.write(4, 0); mm3=0;}
byte mmS4b = EEPROM.read(5); mm4 = int(mmS4b);
if ( mm4==0 || mm4==1 ) {} else {EEPROM.write(5, 0); mm4=0;}
byte mmS5b = EEPROM.read(6); mm5 = int(mmS5b);
if ( mm5==0 || mm5==1 ) {} else {EEPROM.write(6, 0); mm5=0;}
byte mmS6b = EEPROM.read(7); mm6 = int(mmS6b);
if ( mm6==0 || mm6==1 ) {} else {EEPROM.write(7, 0); mm6=0;}
byte mmS7b = EEPROM.read(8); mm7 = int(mmS7b);
if ( mm7==0 || mm7==1 ) {} else {EEPROM.write(8, 0); mm7=0;}
//say hello
playNote(60, 127, 5);
delay(40);
playNote(64, 127, 5);
delay(40);
playNote(67, 127, 5);
delay(40);
playNote(72, 127, 5);
delay(40);
stopNote(72, 5);
playDigidrum(52, 127);
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.drawString(4,0,"YM2149F");
u8x8.drawString(4,2,"MIDI.h");
u8x8.drawString(1,4,"v2.1b Feb 2023");
u8x8.drawString(3,6,"dansfing.uk");
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(potPin, INPUT);
delay(4000);
u8x8.clearDisplay();
showMutes();
}
void handleNoteOn(byte channel, byte pitch, byte velocity)
{
// Do whatever you want when a note is pressed.
if(channel!=10){ playNote(pitch, 127, channel);}
if(channel==1){ u8x8.setCursor(4,0); u8x8.print(pitch); u8x8.setCursor(7,0); u8x8.print("A"); }
if(channel==2){ u8x8.setCursor(4,1); u8x8.print(pitch); u8x8.setCursor(7,1); u8x8.print("B"); }
if(channel==3){ u8x8.setCursor(4,2); u8x8.print(pitch); u8x8.setCursor(7,2); u8x8.print("C"); }
if(channel==4){ u8x8.setCursor(4,3); u8x8.print(pitch); u8x8.setCursor(7,3); u8x8.print("AB");}
if(channel==5){ u8x8.setCursor(4,4); u8x8.print(pitch); u8x8.setCursor(7,4); u8x8.print("ABC");}
if(channel==6){ u8x8.setCursor(4,5); u8x8.print(pitch); u8x8.setCursor(7,5); u8x8.print("A");}
if(channel==7){ u8x8.setCursor(4,6); u8x8.print(pitch); u8x8.setCursor(7,6); u8x8.print("A");}
if(channel==8){ u8x8.setCursor(4,7); u8x8.print(pitch); u8x8.setCursor(7,7); u8x8.print("AB");}
// Sample playpack on channel 10
if(channel==10){ playDigidrum(pitch, 127); }
// Try to keep your callbacks short (no delays ect)
// otherwise it would slow down the loop() and have a bad impact
// on real-time performance.
}
void handleNoteOff(byte channel, byte pitch, byte velocity)
{
stopNote(pitch, channel);
// Do something when the note is released.
// Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
}
void showMutes(){
u8x8.setCursor(9,0); if(mm0==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(9,1); if(mm1==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(9,2); if(mm2==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(9,3); if(mm3==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(9,4); if(mm4==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(9,5); if(mm5==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(9,6); if(mm6==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(9,7); if(mm7==1){u8x8.print(" M");}else{u8x8.print(" _");}
u8x8.setCursor(0,0); u8x8.print("[1]");
u8x8.setCursor(0,1); u8x8.print("[2]");
u8x8.setCursor(0,2); u8x8.print("[3]");
u8x8.setCursor(0,3); u8x8.print("[4]");
u8x8.setCursor(0,4); u8x8.print("[5]");
u8x8.setCursor(0,5); u8x8.print("[6]");
u8x8.setCursor(0,6); u8x8.print("[7]");
u8x8.setCursor(0,7); u8x8.print("[8]");
u8x8.setCursor(13,7);
u8x8.print('(');
u8x8.print(currentC);
u8x8.print(')');
}
int CHs=0;
int detuneKnob=0;
int detuneKnobL=0;
int detune10=0;
void loop() {
currentMillisM = millis(); //get the current "time" for the MUTE debounce
// Call MIDI.read the fastest you can for real-time performance.
MIDI.read();
//////////////// TIMERS/////////////////////////////////////////////////////////////////////////
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //test whether the period has elapsed
{
CHs=0;
muteP=0;
storeP=0;
detuneKnob=analogRead(A0);
detune10=detuneKnob/8;
///Maybe alter detune with knob
if (detune10!=detuneKnobL){detuneKnobL=detune10;} else {
//detune10=detuneKnob/100;
u8x8.setCursor(13,5);
u8x8.print(" ");
u8x8.setCursor(13,5);
u8x8.print(detune10);
setChannelVolume(detune10 , currentC);
}
startMillis = currentMillis; //IMPORTANT reset timer for screen.
}
//Check CH Button
if (analogRead(A3)>=929 && analogRead(A3)<=936 && CHs==0 && currentMillisM - startMillisM >= periodM){
if(currentC>=8){
currentC=0;
} else { currentC++; CHs=1; u8x8.setCursor(13,7);
u8x8.print('(');
u8x8.print(currentC);
u8x8.print(')');
}
startMillisM = currentMillisM;
}
//Check Store Button
if (analogRead(A3)>=990 && analogRead(A3)<=996){ storeP=1; } else {storeP=0;}
//Check Mute Button
if (analogRead(A3)>=1011 && analogRead(A3)<=1016 && muteP==0){ muteP=1; } else {}
if(currentC==1 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm0==0){mm0=1; showMutes(); muteP=0; } else {mm0=0; showMutes(); muteP=0; }
startMillisM = currentMillisM;
}
if(currentC==2 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm1==0){mm1=1; showMutes(); } else {mm1=0; showMutes(); }
startMillisM = currentMillisM;
}
if(currentC==3 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm2==0){mm2=1; showMutes(); } else {mm2=0; showMutes();}
startMillisM = currentMillisM;
}
if(currentC==4 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm3==0){mm3=1; showMutes(); } else {mm3=0; showMutes(); }
startMillisM = currentMillisM;
}
if(currentC==5 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm4==0){mm4=1; showMutes(); } else {mm4=0; showMutes(); }
startMillisM = currentMillisM;
}
if(currentC==6 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm5==0){mm5=1; showMutes(); } else {mm5=0; showMutes(); }
startMillisM = currentMillisM;
}
if(currentC==7 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm6==0){mm6=1; showMutes(); } else {mm6=0; showMutes(); }
startMillisM = currentMillisM;
}
if(currentC==8 && muteP==1 && currentMillisM - startMillisM >= periodM){
if( mm7==0){mm7=1; showMutes(); } else {mm7=0; showMutes();}
startMillisM = currentMillisM;
}
if(currentC==1 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm0); startMillisM = currentMillisM; }
if(currentC==2 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm1); startMillisM = currentMillisM; }
if(currentC==3 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm2); startMillisM = currentMillisM; }
if(currentC==4 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm3); startMillisM = currentMillisM; }
if(currentC==5 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm4); startMillisM = currentMillisM; }
if(currentC==6 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm5); startMillisM = currentMillisM; }
if(currentC==7 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm6); startMillisM = currentMillisM; }
if(currentC==8 && storeP==1 && currentMillisM - startMillisM >= periodM){ EEPROM.write(currentC, mm7); startMillisM = currentMillisM; }
}
void setDetune(byte value)
{
detuneValue = (value >> 3) & 0x0F; //downscaling to 4 bits
}
void setChannelVolume(byte value, byte chan)
{
value = (value >> 3) & 0x0F; //downscaling to 4 bits
if (chan == 1)
{
AmaxVolume = value;
send_data(0x08, value);
}
else if (chan == 2)
{
BmaxVolume = value;
send_data(0x09, value);
}
else if (chan == 3)
{
CmaxVolume = value;
send_data(0x0A, value);
}
}
void playNote(byte note, byte velo, byte chan)
{
if (note < 24) return;
if (chan == 1 && mm0 == 0)
{
SET(__RGBLEDPORT__,__RLED__);
noteA = note;
periodA = tp[note];
byte LSB = ( periodA & 0x00FF);
byte MSB = ((periodA & 0x0F00) >> 8);
cli();
send_data(0x00, LSB);
send_data(0x01, MSB);
send_data(0x08, AmaxVolume); //can be set to 0 by envelope mode note off
sei();
}
else if (chan == 2 && mm1 == 0)
{
SET(__RGBLEDPORT__,__GLED__);
noteB = note;
periodB = tp[note];
byte LSB = ( periodB & 0x00FF);
byte MSB = ((periodB >> 8) & 0x000F);
cli();
arpeggioCounter = 0; //arpeggio reset
send_data(0x02, LSB);
send_data(0x03, MSB);
sei();
}
else if (chan == 3 && mm2 == 0)
{
SET(__RGBLEDPORT__,__BLED__);
noteC = note;
periodC = tp[note];
byte LSB = ( periodC & 0x00FF);
byte MSB = ((periodC >> 8) & 0x000F);
cli();
send_data(0x04, LSB);
send_data(0x05, MSB);
sei();
}
else if (chan == 4 && mm3 == 0)
{
SET(__RGBLEDPORT__,__RLED__);
SET(__RGBLEDPORT__,__GLED__);
noteA = note;
noteB = note;
periodA = tp[note];
periodB = tp[note] + detuneValue;
byte ALSB = ( periodA & 0x00FF);
byte AMSB = ((periodA >> 8) & 0x000F);
byte BLSB = ( periodB & 0x00FF);
byte BMSB = ((periodB >> 8) & 0x000F);
cli();
send_data(0x00, ALSB);
send_data(0x01, AMSB);
send_data(0x02, BLSB);
send_data(0x03, BMSB);
sei();
}
else if (chan == 5 && mm4 == 0)
{
SET(__RGBLEDPORT__,__RLED__);
SET(__RGBLEDPORT__,__GLED__);
SET(__RGBLEDPORT__,__BLED__);
noteA = note;
noteB = note;
noteC = note;
periodA = tp[note - 12];
periodB = tp[note] + detuneValue;
periodC = tp[note] - detuneValue;
byte ALSB = ( periodA & 0x00FF);
byte AMSB = ((periodA >> 8) & 0x000F);
byte BLSB = ( periodB & 0x00FF);
byte BMSB = ((periodB >> 8) & 0x000F);
byte CLSB = ( periodC & 0x00FF);
byte CMSB = ((periodC >> 8) & 0x000F);
cli();
send_data(0x00, ALSB);
send_data(0x01, AMSB);
send_data(0x02, BLSB);
send_data(0x03, BMSB);
send_data(0x04, CLSB);
send_data(0x05, CMSB);
sei();
}
else if (chan == 6 && mm5 == 0)
{
SET(__RGBLEDPORT__,__RLED__);
noteA = note;
periodA = envTp[note];
byte LSB = ( periodA & 0x00FF);
byte MSB = ((periodA >> 8) & 0x000F);
cli();
send_data(0x08, 0x10);
send_data(0x0B, LSB);
send_data(0x0C, MSB);
send_data(0x0D, 0b00001110);
sei();
}
else if (chan == 7 && mm6 == 0)
{
SET(__RGBLEDPORT__,__RLED__);
noteA = note;
periodA = envTp[note];
byte LSB = ( periodA & 0x00FF);
byte MSB = ((periodA >> 8) & 0x000F);
cli();
send_data(0x08, 0x10);
send_data(0x0B, LSB);
send_data(0x0C, MSB);
send_data(0x0D, 0b00001110);
sei();
}
else if (chan == 8 && mm7 == 0)
{
SET(__RGBLEDPORT__,__RLED__);
SET(__RGBLEDPORT__,__GLED__);
noteA = note;
noteB = note;
periodA = envTp[note];
periodB = (tp[note - 12] + detuneValue) << 1;
byte LSB = ( periodA & 0x00FF);
byte MSB = ((periodA >> 8) & 0x000F);
byte BLSB = ( periodB & 0x00FF);
byte BMSB = ((periodB >> 8) & 0x000F);
cli();
send_data(0x02, BLSB);
send_data(0x03, BMSB);
send_data(0x08, 0x10); //envelope mode on
send_data(0x0B, LSB);
send_data(0x0C, MSB);
send_data(0x0D, 0b00001000);
sei();
}
}
void stopNote(byte note, byte chan)
{
if (chan == 1 && note == noteA)
{
CLR(__RGBLEDPORT__,__RLED__);
noteA = periodA = 0;
cli();
send_data(0x00, 0);
send_data(0x01, 0);
sei();
}
else if (chan == 2 && note == noteB)
{
CLR(__RGBLEDPORT__,__GLED__);
noteB = periodB = 0;
cli();
send_data(0x02, 0);
send_data(0x03, 0);
sei();
}
else if (chan == 3 && note == noteC)
{
CLR(__RGBLEDPORT__,__BLED__);
noteC = periodC = 0;
cli();
send_data(0x04, 0);
send_data(0x05, 0);
sei();
}
else if (chan == 4 && note == noteA)
{
CLR(__RGBLEDPORT__,__RLED__);
CLR(__RGBLEDPORT__,__GLED__);
noteA = periodA = 0;
noteA = periodB = 0;
cli();
send_data(0x00, 0);
send_data(0x01, 0);
send_data(0x02, 0);
send_data(0x03, 0);
sei();
}
else if (chan == 5 && note == noteA)
{
CLR(__RGBLEDPORT__,__RLED__);
CLR(__RGBLEDPORT__,__GLED__);
CLR(__RGBLEDPORT__,__BLED__);
noteA = periodA = 0;
noteB = periodB = 0;
noteC = periodC = 0;
cli();
send_data(0x00, 0);
send_data(0x01, 0);
send_data(0x02, 0);
send_data(0x03, 0);
send_data(0x04, 0);
send_data(0x05, 0);
sei();
}
else if (chan == 6 && note == noteA)
{
CLR(__RGBLEDPORT__,__RLED__);
noteA = periodA = 0;
cli();
send_data(0x0D, 0);
send_data(0x08, AmaxVolume);
sei();
}
else if (chan == 7 && note == noteA)
{
CLR(__RGBLEDPORT__,__RLED__);
noteA = periodA = 0;
cli();
send_data(0x0D, 0);
send_data(0x08, AmaxVolume);
sei();
}
else if (chan == 8 && note == noteA)
{
CLR(__RGBLEDPORT__,__RLED__);
CLR(__RGBLEDPORT__,__GLED__);
noteA = periodA = 0;
noteB = periodB = 0;
cli();
send_data(0x02, 0);
send_data(0x03, 0);
send_data(0x0D, 0);
send_data(0x08, AmaxVolume);
sei();
}
}
void playDigidrum(byte index, byte velo)
{
if (index == 60)
{
cli();
SET(__RGBLEDPORT__,__BLED__);
sampleOffset = s0;
sampleLength = s0Length;
sampleCounter = 0;
sei();
}
else if (index == 62)
{
cli();
SET(__RGBLEDPORT__,__BLED__);
sampleOffset = s1;
sampleLength = s1Length;
sampleCounter = 0;
sei();
}
else if (index == 64)
{
cli();
SET(__RGBLEDPORT__,__BLED__);
sampleOffset = s2;
sampleLength = s2Length;
sampleCounter = 0;
sei();
}
else if (index == 65)
{
cli();
SET(__RGBLEDPORT__,__BLED__);
sampleOffset = s3;
sampleLength = s3Length;
sampleCounter = 0;
sei();
}
else if (index == 67)
{
cli();
SET(__RGBLEDPORT__,__BLED__);
sampleOffset = s4;
sampleLength = s4Length;
sampleCounter = 0;
sei();
}
}
void resetYM()
{
digitalWrite(pinYMReset, LOW);
digitalWrite(pinYMReset, HIGH);
delay(1);
send_data(0x07, 0b00111000);
for (byte i=0; i <= defaultLevel; i++)
{
send_data(0x08, i);
send_data(0x09, i);
send_data(0x0A, i);
delay(1);
}
}
void send_data(unsigned char address, unsigned char data)
{
SET(__LEDPORT__,__LED__);
boolean value[8];
//put address in a 8-bit array
for (int i; i < 8; i++)
{
value[i] = ((0x01 & address) == 1);
address = address >> 1;
}
//write address to pins
outputToYM(value);
//validate addess
__BCPORT__ |= (1 << __BDIR__) | (1 << __BC1__);
delayMicroseconds(1);
__BCPORT__ &= ~((1 << __BDIR__) | (1 << __BC1__));
//put data in a 8-bit array
for (int i; i < 8; i++)
{
value[i] = ((0x01 & data) == 1);
data = data >> 1;
}
//write data to pins
outputToYM(value);
//validate data
SET(__BCPORT__,__BDIR__);
delayMicroseconds(1);
CLR(__BCPORT__,__BDIR__);
CLR(__LEDPORT__,__LED__);
}
void outputToYM(boolean value[])
{
value[0] ? SET(PORTB, 0) : CLR(PORTB, 0);
value[1] ? SET(PORTB, 1) : CLR(PORTB, 1);
value[2] ? SET(PORTD, 2) : CLR(PORTD, 2);
value[3] ? SET(PORTD, 3) : CLR(PORTD, 3);
value[4] ? SET(PORTD, 4) : CLR(PORTD, 4);
value[5] ? SET(PORTD, 5) : CLR(PORTD, 5);
value[6] ? SET(PORTD, 6) : CLR(PORTD, 6);
value[7] ? SET(PORTD, 7) : CLR(PORTD, 7);
}
byte getSerialByte()
{
while(Serial.available() < 1) __asm__("nop\n\t");
return Serial.read();
}