Jump to content





DH100 - MIDI Communication established

Posted by Pack007, 23 December 2017 · 200 views

DH100 DH-100 MIDI arduino
DH100 - MIDI Communication established

I was going to start writing my list of resolutions for 2018. Then I thought about writing about what I didn't accomplish in 2017.  Then I decided to just work on programing the interface and get the Atari to read and print the MIDI data stream through the joystick port.  I had high hopes of creating a midi monitor that would accept the data and print out the commands as they were received but all that extra code was getting in the way of finding errors.  I was happy when I got the Atari8 and Arduino to just reliably print the correct bytes.
 
A SIO cable was to be modified because the SIO2PC dead-ends the SIO chain.  I just attached jumper wires with female ends to the 4th and 8th pins on a standard cable.  Saved me a lot of plugging and unplugging.
 
Attached Image
 
Attached Image
 
I wasn't looking forward to programming the Arduino and Atari 8 because trouble shooting was going to be a painful endeavor.  Was it the interface hardware, the Arduino program or the Atari8 program that is the problem. Yes, I had problems with all three and even created more.
 
The Arduino Program.
 
The Arduino performs the following steps.
 
  1. Reads the midi data stream and puts it into a buffer. Continuously.
  2. Gets a bit from the buffer.  FIFO
  3. Sets control pins for the 8 joystick pins
  4. Sets trigger to signal that data is ready to be read
  5. Waits for Atari to signal it got the data
  6. Sets the trigger to signal data not ready
  7.  Waits for Atari to signal reset the process to step 2.
 
Its simple, when you remember that the logic from the Arduino is inverted.  When a pin on the Arduino is set high the transistor in the optocoupler turns on, shorting the pin to ground. Thus making the logic level, read by the Atari, LOW.
 
 
/* Midi data transfer test 12/2017
 * 
 *  This program reads midi data then ouputs
 * the data to the Atari Joystick ports.
 *
 * The use of the control lines to the Atari Trigger
 * and from the cassette motor control line on the SIO
 * port are used for data flow control.
 * 
 */
 
// Atari PORTA(54016) mapped to pins on arduino
int porta0 = 4;
int porta1 = 5;
int porta2 = 6;
int porta3 = 7;
int porta4 = 8;
int porta5 = 9;
int porta6 = 10;
int porta7 = 11;
int DSR = 3; //data set ready
int DTR = 12;//Atari ready
 
byte zero = 0;
byte tempX = 0;
int midiData = 0;
 
//Function to Send a byte to the atari and
void sendByte(byte byteToSend){
 
  setPorta(byteToSend);
  digitalWrite(DSR,LOW); //data ready-Trigger 0
  while(digitalRead(DTR) == LOW){} //Wait for Atari to get byte cmc goes low
  digitalWrite(DSR,HIGH); //data not ready-trigger 1
  while(digitalRead(DTR) == HIGH){} //wait for Atari to signal ok to get next byte
 
}
 
void setPorta(byte byteToMap){
  // Sets digital pins to transfer data to Atari joystick ports(PORTA)
  // When digital port high, joystick pin shorted to ground or logic 0
  if (byteToMap & B00000001){digitalWrite(porta0,LOW);}
    else {digitalWrite(porta0,HIGH);}
  if (byteToMap & B00000010){digitalWrite(porta1,LOW);}
    else {digitalWrite(porta1,HIGH);}
  if (byteToMap & B00000100){digitalWrite(porta2,LOW);}
    else {digitalWrite(porta2,HIGH);}
  if (byteToMap & B00001000){digitalWrite(porta3,LOW);}
    else {digitalWrite(porta3,HIGH);}
  if (byteToMap & B00010000){digitalWrite(porta4,LOW);}
    else {digitalWrite(porta4,HIGH);}
  if (byteToMap & B00100000){digitalWrite(porta5,LOW);}
    else {digitalWrite(porta5,HIGH);}
  if (byteToMap & B01000000){digitalWrite(porta6,LOW);}
    else {digitalWrite(porta6,HIGH);}
  if (byteToMap & B10000000){digitalWrite(porta7,LOW);}
    else {digitalWrite(porta7,HIGH);}
}
 
void setup() {
  pinMode(porta0,OUTPUT);
  pinMode(porta1,OUTPUT);
  pinMode(porta2,OUTPUT);
  pinMode(porta3,OUTPUT);
  pinMode(porta4,OUTPUT);
  pinMode(porta5,OUTPUT);
  pinMode(porta6,OUTPUT);
  pinMode(porta7,OUTPUT);
  pinMode(DSR,OUTPUT);
  pinMode(DTR,INPUT);
  Serial.begin(31250);
  setPorta(zero);//
  digitalWrite(DSR,HIGH);
}
 
void loop() {
  if (Serial.available()>0){
  midiData = Serial.read(); //read MIDI stream
  tempX = byte(midiData);
  sendByte(tempX);         //Send to Atari 
  }
}
 
The Atari Program
  
When the Atari wants data it checks the trigger button to see if there is any to read. If not, this program simply waits for one to show up. 
 
10 GOSUB 29000:REM SET UP VARIABLES
15 POKE PACTL,CMCOFF:REM CAS.OFF
20 IF STRIG(0)=0 THEN GOTO 20:REM WAIT ARDUINO TO SIGNAL DATA READY
30 MIDIDATA=PEEK(PORTA):REM READ
35 ? MIDIDATA;" ";:SOUND 0,200,15,15:SOUND 0,0,0,0:REM SHOW DATA ON SCREEN
40 POKE PACTL,CMCON:REM GOT DATA
60 IF STRIG(0)=1 THEN GOTO 60:REM ARDUINO BUSY GETTING DATA
70 POKE PACTL,CMCOFF:REM TELL ARDUINO TO HOLD DATA UNTILL READY
80 GOTO 20:REM GO WAIT FOR NEXT BYTE TO BE READY
29000 PORTA=54016:REM STICK 0 AND 1
29020 PACTL=54018:REM PORTA CONTROL
29030 CMCON=52:REM CASSETTE MOTOR ON
29040 CMCOFF=60:REM CAS. MOTOR OFF
29050 REM POKE 559,0:REM TRUN OFF SCREEN
29100 RETURN
 
A Casio Keyboard was attached to the interface and data was sent to the Atari and dumped on the screen.  The following screen shot shows three 255s that were produced when the Arduino was turned on and the reset button was pushed twice.  Then anytime a key was pressed or released a NOTE ON command on channel 0 (144) was sent. You see the 144 then the MIDI key number and then the volume setting. If a volume setting was 0 the key was released.  The keyboard is not pressure sensitive so its volume defaults to 100. 
 
Attached Image
 
I didn't see any data being missed by the Atari but it was so slow. I mean, it make 300 baud seem fast. I mean, it was so slow that I tried to turn off the display.  I mean, it was soooooo slooooooow that I thought I would have to get out the M65 cartridge. 
 
Instead, the program was compiled using the MMG Compiler.  The speed improvement was remarkable.  I couldn't get the buffer to over flow even when a bunch of keys were pressed and released.  Since the digital horn is monophonic, its data output should be manageable even when it is transmitting the breath pressure(after touch) data.
 
I also took the time to load the compiled program onto a Max Flash cartridge.  Easily running these programs on computers with out a monitor and disk drive will simplify the hardware setup significantly. There was a problem when the Arduino was powered up, all the joystick pins were reading LOW.  This confused the Max Flash menu and the program didn't load when the return was pressed.  Pressing the Reset button on the Arduino resets the pins until they are turned off again by void Setup() function and hitting the return key on the Atari  before that happens will run the program.
 
Now on to writing the program that actually makes some noise and maybe a little music.






Maybe I should have tested this program out with the digital horn.  The horn puts out a lot more data that includes the after touch pressure.  I believe that it is over running the 127 byte buffer used for serial communication.

 

I think most of the data can be ignored or is redundant.  There may even be a way to combine data bytes.

 

Example: Scale the volume data to 0-15 and add it to the command code.  The first 4 bytes of the command are free when using channel 1.

 

The data points that is getting through are not totally random numbers so, I think the data transfer algorithm is sound.

  • Report

Latest Visitors