Skip to content

Commit

Permalink
Release 1.1.0a from Google Code.
Browse files Browse the repository at this point in the history
  • Loading branch information
trash80 committed Jul 26, 2015
1 parent 305299d commit 37f96b6
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 146 deletions.
46 changes: 26 additions & 20 deletions Arduinoboy/Arduinoboy.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,34 @@
***************************************************************************
***************************************************************************
* *
* Version: 1.0.5 *
* Date: Oct 28 2008 *
* Version: 1.1.0 *
* Date: Feb 7 2009 *
* Name: Timothy Lamb *
* Email: [email protected] *
* *
***************************************************************************
***************************************************************************
* *
* Notes: *
* Pins have changed from the original diagram, expect build *
* instructions to follow here soon: *
* http://code.google.com/p/arduinoboy/ *
* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE *
* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE *
* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE *
* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE *
* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE *
* *
* As of version 1.1.0 Gameboy Pins have changes from 5,6,7 to Analog in *
* pins 0,1,2 ... This allows direct port access which not interfearing *
* with serial communication. There are no more "delay" settings, and *
* everything seems much faster / better now. *
* *
* http://code.google.com/p/arduinoboy/ *
* *
* Arduino pin settings: (Layout is final) *
* - 6 LEDS on pins 8 to 13 *
* - Push button on pin 3 (for selecting mode) *
* - MIDI Opto-isolator power on pin 4 *
* - Gameboy Clock line on pin 5 *
* - Gameboy Serial Data input on 6 *
* - Serial Data from gameboy on pin 7 *
* - Gameboy Clock line on analog in pin 0 *
* - Gameboy Serial Data input on analog in pin 1 *
* - Serial Data from gameboy on analog in pin 2 *
* *
* Program Information: *
* LSDJ Slave Mode Midi Note Effects: *
Expand Down Expand Up @@ -87,17 +95,13 @@ int mode = 0; //0 to 4 - default mode for force mode
int numberOfModes = 5; //Right now there are 5 modes, Might be more in the future
boolean usbMode = false; //to use usb for serial communication as oppose to MIDI - sets baud rate to 38400

int gameboyBitPauseLOW = 5; //Bit pause for gbmidi mode .... 1 to 10 /// tested working value: 5=GBA/SP/DMG01 ---
int gameboyBitPauseHIGH = 1; //Bit pause for gbmidi mode .... 1 to 10 /// tested working value: 1=GBA/SP/DMG01 --- (note: roughly 4 microseconds off from Low do to code that writes to the serial line)
int gameboyBytePause= 10; //Byte pause for gbmidi mode .... 5 to 20 /// tested working value: 5=GBA/SP/GBC and 10=DMG

/***************************************************************************
* Lets Assign our Arduino Pins .....
***************************************************************************/

int pinGBClock = 5; // clock out to gameboy
int pinGBSerialOut = 6; // serial data to gameboy
int pinGBSerialIn = 7; // serial data from gameboy
int pinGBClock = 0; // Analog In 0 - clock out to gameboy
int pinGBSerialOut = 1; // Analog In 1 - serial data to gameboy
int pinGBSerialIn = 2; // Analog In 2 - serial data from gameboy

int pinMidiInputPower = 4; // power pin for midi input opto-isolator

Expand Down Expand Up @@ -218,17 +222,16 @@ void setup() {

pinMode(pinButtonMode,INPUT);

pinMode(pinGBClock,OUTPUT);
pinMode(pinGBSerialOut,OUTPUT);
pinMode(pinGBSerialIn,INPUT);

DDRC = B00111111; //Set analog in pins as outputs

/*
Set MIDI Serial Rate
*/
if(usbMode == true) {
Serial.begin(38400); //31250
} else {
pinMode(pinMidiInputPower,OUTPUT);
digitalWrite(pinMidiInputPower,HIGH); // turn on the optoisolator
Serial.begin(31250); //31250
}
/*
Expand Down Expand Up @@ -263,6 +266,9 @@ void setup() {
*/
if(!forceMode) mode = EEPROM.read(eepromMemoryByte);
lastMode = mode;

startupSequence();

showSelectedMode(); //Light up the LED that shows which mode we are in.
}

Expand Down
31 changes: 31 additions & 0 deletions Arduinoboy/Mode.ino
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,34 @@ void statusLedOn()
countStatusLedOn = 0; //Reset the timer
digitalWrite(pinStatusLed,HIGH); //Turn on the led
}

/* cute startup sequence */
void startupSequence()
{
int ledFxA;
int ledFxB;

for(ledFxB=0;ledFxB<2;ledFxB++) {
for(ledFxA=0;ledFxA<numberOfModes;ledFxA++) {
digitalWrite(pinLeds[ledFxA], HIGH);
delay(50);
digitalWrite(pinLeds[ledFxA], LOW);
}
for(ledFxA=4;ledFxA>=0;ledFxA--) {
digitalWrite(pinLeds[ledFxA], HIGH);
delay(50);
digitalWrite(pinLeds[ledFxA], LOW);
}
}
delay(100);

for(ledFxA=0;ledFxA<numberOfModes;ledFxA++) digitalWrite(pinLeds[ledFxA], HIGH); // sets the LED on
delay(100);
for(ledFxA=0;ledFxA<numberOfModes;ledFxA++) digitalWrite(pinLeds[ledFxA], LOW); // sets the digital pin as output
delay(100);
for(ledFxA=0;ledFxA<numberOfModes;ledFxA++) digitalWrite(pinLeds[ledFxA], HIGH); // sets the LED on
delay(100);
for(ledFxA=0;ledFxA<numberOfModes;ledFxA++) digitalWrite(pinLeds[ledFxA], LOW); // sets the digital pin as output
delay(500);
}

97 changes: 39 additions & 58 deletions Arduinoboy/Mode_LSDJ_Keyboard.ino
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

void modeLSDJKeyboardSetup()
{
digitalWrite(pinMidiInputPower,HIGH); // turn on the optoisolator
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT); //make sure our gameboy Clock is set for OUTPUT mode
digitalWrite(pinGBClock,LOW); //Generally this should be HIGH ie: 1, on, whatever. but since we are emulating a pc keyboard it should be LOW/0/off
addGameboyByte(0); //Send 8bits of nothing. don't ask I dont know.
DDRC = B00111111; //Set analog in pins as outputs
PORTC = B00000010;

/* The stuff below makes sure the code is in the same state as LSDJ on reset / restart, mode switched, etc. */

for(int rst=0;rst<5;rst++) addGameboyByte(keyboardOctDn); //Return lsdj to the first octave
for(int rst=0;rst<41;rst++) addGameboyByte(keyboardInsDn); //Return lsdj to the first instrument
for(int rst=0;rst<5;rst++) sendKeyboardByteToGameboy(keyboardOctDn); //Return lsdj to the first octave
for(int rst=0;rst<41;rst++) sendKeyboardByteToGameboy(keyboardInsDn); //Return lsdj to the first instrument

keyboardCurrentOct = 0; //Set our current octave to 0.
keyboardLastOct = 0; //Set our last octave to 0.
Expand Down Expand Up @@ -100,7 +100,6 @@ void modeLSDJKeyboard()
}
}

updateGameboyByteFrame(); // Send out Bytes to LSDJ
updateStatusLed(); // Update our status blinker
setMode(); // Check if mode button was depressed
}
Expand All @@ -117,19 +116,19 @@ void changeLSDJInstrument(byte channel,byte message)
if(channel == keyboardInstrumentMidiChannel && keyboardCurrentIns != keyboardLastIns) {
//if its on our midi channel and the instrument isnt the same as our currrent
if(!keyboardCompatabilityMode) {
addGameboyByte(0x80 | message); // <- this is suppose to work but doesn't :/
sendKeyboardByteToGameboy(0x80 | message); // <- this is suppose to work but doesn't :/
} else {
//We will find out which is greater, the current instrument or the last instrument. then
//cycle up or down to that instrument
if(keyboardCurrentIns > keyboardLastIns) {
keyboardDiff = keyboardCurrentIns - keyboardLastIns;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++) {
addGameboyByte(keyboardInsUp); //send the instrument up command to go up to the requested instrument
sendKeyboardByteToGameboy(keyboardInsUp); //send the instrument up command to go up to the requested instrument
}
} else {
keyboardDiff = keyboardLastIns - keyboardCurrentIns;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++) {
addGameboyByte(keyboardInsDn); //send the instrument down command to down to the requested instrument
sendKeyboardByteToGameboy(keyboardInsDn); //send the instrument down command to down to the requested instrument
}
}
}
Expand All @@ -154,12 +153,12 @@ void playLSDJNote(byte channel,byte note, byte velocity)

if(note >= 0x3C) keyboardNoteOffset = 0x0C; //if the note really high we need to use the second row of keyboard keys
note = (note % 12) + keyboardNoteOffset; //get a 0 to 11 range of notes and add the offset
addGameboyByte(keyboardNotes[note]); // and finally send the note
sendKeyboardByteToGameboy(keyboardNotes[note]); // and finally send the note

} else if (note >= keyboardStartOctave) { //If we are at the octave below notes
keyboardDiff = note - keyboardStartOctave; //Get a value between 0 and 11
if(keyboardDiff < 8 && keyboardDiff > 3) addGameboyByte(0xE0); //if we are sending cursor values we have to send a 0xE0 byte for "extended" pc keyboard mode
addGameboyByte(keyboardCommands[note - keyboardStartOctave]); //send the byte corrisponding to the note number in the keyboard command array
if(keyboardDiff < 8 && keyboardDiff > 3) sendKeyboardByteToGameboy(0xE0); //if we are sending cursor values we have to send a 0xE0 byte for "extended" pc keyboard mode
sendKeyboardByteToGameboy(keyboardCommands[note - keyboardStartOctave]); //send the byte corrisponding to the note number in the keyboard command array
}
}
}
Expand All @@ -174,78 +173,60 @@ void changeLSDJOctave()
if(keyboardCurrentOct != keyboardLastOct) {
if(!keyboardCompatabilityMode) { // This new mode doesnt work yet. :/
keyboardCurrentOct = 0xB3 + keyboardCurrentOct;
addGameboyByte(keyboardCurrentOct);
sendKeyboardByteToGameboy(keyboardCurrentOct);
} else {
///We will find out which is greater, the current octave or the last. then
//cycle up or down to that octave
if(keyboardCurrentOct > keyboardLastOct) {
keyboardDiff = keyboardCurrentOct - keyboardLastOct;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++)
{
addGameboyByte(keyboardOctUp);
sendKeyboardByteToGameboy(keyboardOctUp);
}
} else {
keyboardDiff = keyboardLastOct - keyboardCurrentOct;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++)
{
addGameboyByte(keyboardOctDn);
sendKeyboardByteToGameboy(keyboardOctDn);
}
}
}
keyboardLastOct = keyboardCurrentOct;
}
}

/*
Reguardless how porely optimized my code is the real bottleneck is either LSDJ, gameboy, or the serial line,
Therefor a crude "buffer" is setup to capture the bytes we want to send and slowly output them to lsdj...
addGameboyByte put a byte into our output buffer
*/

void addGameboyByte(byte send_byte)
{
serialWriteBuffer[writePosition] = send_byte; //assign new byte
writePosition++; //increment the write position
writePosition = writePosition % 256; //make sure our write position is between 0 to 255 by using a mod of 256
}

/*
updateGameboyByteFrame is responcible responsibel resp.... job is to wait a period of time,
and then send a byte to the gameboy byte output function.
*/
void updateGameboyByteFrame()
{
if(readPosition != writePosition){ //if we have something to read out
waitClock++; //then increment our counter
if(waitClock > 40) { //if we've exceeded our wait time
waitClock=0; //reset the counter
statusLedOn(); //turn on the awesome visuals
sendByteToGameboy(serialWriteBuffer[readPosition]); //send the byte out
readPosition++; //increment our read position
readPosition = readPosition % 256; //wrap our reading range from 0 to 255
}
}
}

/*
sendByteToGameboy does what it says. yay magic
*/
void sendByteToGameboy(byte send_byte)
/*
sendKeyboardByteToGameboy
*/
void sendKeyboardByteToGameboy(byte send_byte)
{
PORTC = B00000000;
delayMicroseconds(50); //Delays are added to simulate PC keyboard rate
PORTC = B00000001;
delayMicroseconds(50);
for(countLSDJTicks=0;countLSDJTicks<8;countLSDJTicks++) { //we are going to send 8 bits, so do a loop 8 times
digitalWrite(pinGBClock,HIGH); //Set our clock output to 1
if(send_byte & 0x01) { //if the first bit is equal to 1
digitalWrite(pinGBSerialOut,HIGH); //then send a 1
PORTC = B00000010;
delayMicroseconds(50);
PORTC = B00000011;
delayMicroseconds(50);
} else {
digitalWrite(pinGBSerialOut,LOW); //send a 0
PORTC = B00000000;
delayMicroseconds(50);
PORTC = B00000001;
delayMicroseconds(50);
}
send_byte >>= 1; //bitshift right once for the next bit we are going to send
delayMicroseconds(gameboyBitPauseLOW); // firestARter : play around with this value, sometimes the gameboy needs more time between messages
digitalWrite(pinGBClock,LOW); //send a 0 to the clock, we finished sending the bit
delayMicroseconds(gameboyBitPauseHIGH); // firestARter : play around with this value, sometimes the gameboy needs more time between messages
}
digitalWrite(pinGBSerialOut,LOW); //make sure the serial state returns to 0 after its done sending the bits
delayMicroseconds(gameboyBitPauseLOW); // firestARter : play around with this value, sometimes the gameboy needs more time between messages

PORTC = B00000000;
delayMicroseconds(50);
PORTC = B00000001;
delayMicroseconds(50);
PORTC = B00000010;
delayMicroseconds(50);
PORTC = B00000011;
delay(4);
}

10 changes: 6 additions & 4 deletions Arduinoboy/Mode_LSDJ_MasterSync.ino
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,23 @@

void modeLSDJMasterSyncSetup()
{

digitalWrite(pinMidiInputPower,LOW); // turn on the optoisolator
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,INPUT); //Set the gb clock as input, we will be reading from the clock
DDRC = B00000000; //Set analog in pins as inputs
countSyncTime=0;
modeLSDJMasterSync();
}

void modeLSDJMasterSync()
{
while(1){
readgbClockLine = digitalRead(pinGBClock); //Read gameboy's clock line
readgbClockLine = PINC & 0x01; //Read gameboy's clock line
if(readgbClockLine) { //If Gb's Clock is On
while(readgbClockLine) { //Loop untill its off
checkLSDJStopped(); //Check if LSDJ hit Stop
readgbClockLine = digitalRead(pinGBClock); //Read the clock again
bit = digitalRead(pinGBSerialIn); //Read the serial input for song position
readgbClockLine = PINC & 0x01; //Read the clock again
bit = (PINC & 0x04)>>2; //Read the serial input for song position
setMode();
updateStatusLight();
}
Expand Down
32 changes: 7 additions & 25 deletions Arduinoboy/Mode_LSDJ_SlaveSync.ino
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

void modeLSDJSlaveSyncSetup()
{
digitalWrite(pinMidiInputPower,HIGH); // turn on the optoisolator
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT); //Set the gb clock as output
digitalWrite(pinGBClock,HIGH); //Gameboy likes to get high
digitalWrite(pinGBSerialOut,LOW);//Nothing to send
DDRC = B00111111; //Set analog in pins as outputs
PORTC = B00000001;

modeLSDJSlaveSync();
}
Expand All @@ -34,7 +34,7 @@ void modeLSDJSlaveSync()
if(sequencerStarted && midiSyncEffectsTime && !countSyncTime //If the seq has started and our sync effect is on and at zero
|| sequencerStarted && !midiSyncEffectsTime) { //or seq is started and there is no sync effects
if(!countSyncPulse && midiDefaultStartOffset) { //if we received a note for start offset
sendByteReversed(midiDefaultStartOffset); //send the offset
//sendByteToGameboy(midiDefaultStartOffset); //send the offset
}
sendClockTickToLSDJ(); //send the clock tick
updateVisualSync();
Expand Down Expand Up @@ -75,37 +75,19 @@ void modeLSDJSlaveSync()
}
}

/*
Again its magic time, but this time its backweirds
We'll send a byte to the gameboy starting with big endian
From this point on I'm sick of writing comments
*/
void sendByteReversed(byte send_byte)
{
for(countLSDJTicks=0;countLSDJTicks<8;countLSDJTicks++) { //NEWS FLASH: there are 8 bits in a byte
digitalWrite(pinGBClock,LOW); //Set the clock to zero, wes about to send you somethin
if(send_byte & 0x80) { //Magic
digitalWrite(pinGBSerialOut,HIGH); //1
} else {
digitalWrite(pinGBSerialOut,LOW); //0
}
send_byte <<= 1; //More magic
digitalWrite(pinGBClock,HIGH); //Make the clock 1, so we can make a funky squarewave
}
digitalWrite(pinGBSerialOut,LOW); //We are done, turn the serial off
}

/*
sendClockTickToLSDJ is a lovely loving simple function I wish they where all this short
Technicallyly we are sending nothing but a 8bit clock pulse
*/
void sendClockTickToLSDJ()
{
for(countLSDJTicks=0;countLSDJTicks<8;countLSDJTicks++) {
digitalWrite(pinGBClock,LOW);digitalWrite(pinGBClock,HIGH);
PORTC = B00000000;
PORTC = B00000001;
}
}


/*
getSlaveSyncEffect receives a note, and assigns the propper effect of that note
*/
Expand Down
Loading

0 comments on commit 37f96b6

Please sign in to comment.