Omnimaga

General Discussion => Technology and Development => Other => Topic started by: ben_g on April 08, 2012, 04:35:10 pm

Title: calculator(84+) - arduino communication trough USB
Post by: ben_g on April 08, 2012, 04:35:10 pm
I wrote some communication routines to send bytes from an 84+ calculator to the arduino (not from arduino to calc).
Here is the example code:

z80:
Code: [Select]
.org $9D93
#define bcall(label) rst 28h \ .dw label

#include "ti83plus.inc"

.db t2ByteTok, tAsmCmp

  call USB_Init

  bcall(_GetKey)

  ;send 50
  ld b, 50
  call USB_SendByte

  ret

;------------------------------------------------
; calc-Arduino communication routines trough USB
;------------------------------------------------


USB_Init:
  ;initializes the USB connection

  ;turn the USB driver off so we can read and write manually
  bcall(810Eh) ;KillUSB

  ;put the D- line on low
  ld a, %00100000
  out ($4A), a

  ret


USB_SendByte:
  ;b = the byte to be send
  ld c, 0
  ;c = bitcounter

  call Wait

  ;set D- to high so the arduino knows we will send a byte
  ld a, %00011000
  out ($4A), a

  ;wait untill we can start sending the byte
  call Wait

SendLoop:
  ;put the bit we are going to send in carry
  rrc b

  jr c, sendOne

  ;send a 0
  ld a, %00100000
  out ($4A), a
  jr endBit

sendOne:
  ;send a 1
  ld a, %00011000
  out ($4A), a

endBit:
  ;increase the bit counter
  inc c

  ;stop sending if all 8 bits were sent
  ld a, c
  cp 8
  jr z, endSend

  call Wait
  jr sendLoop

endSend:
  ;set D- low so the arduino won't think we're trying to send an other byte
  ld a, %00100000
  out ($4A), a

  ret


;internally used routine(s)
;--------------------------

wait:
  ;waits untill you can send a bit

  ;if the clock is 0: wait untill it's 1
  in a, ($4D)
  bit 1, a
  jr z, Wait

waitLoop2:
  ;Wait untill the clock is 0, so we can begin writing
  in a, ($4D)
  bit 1, a
  jr nz, WaitLoop2

  ret

arduino
Code: [Select]

//Dp and Dm are the data kables of the USB
const int Dp = 5;
const int Dm = 6;
const int Delay = 1;

int RecievedByte = 0;
int Recieving = 0;
int RecievedBit = 0;
int Recieved = 0;
int ledOn = 0;

void setup(){
  pinMode(Dp, OUTPUT);
  pinMode(Dm, INPUT);
  pinMode(13, OUTPUT);
}


void loop(){
  digitalWrite(Dp, HIGH);
  //clock = 1 so we'll read a bit
  if(Recieving == 0){
    //if nothing is being sent, we have to check for a 1
    if(digitalRead(Dm) == HIGH){
      //1 was send, so we'll have to recieve a byte
      Recieving = 1;
      RecievedBit = 0;
      RecievedByte = 0;
    }
  } else {
    //save the received bit
    if(digitalRead(Dm) == HIGH){
      bitSet(RecievedByte, RecievedBit);
    } else{
      bitClear(RecievedByte, RecievedBit);
    }
    RecievedBit++;
    if(RecievedBit == 8){
      //if all 8 bits are sent, the byte is complete.
      Recieving = 0;
      Recieved = 1;
    }
  }
  delay(Delay);
  digitalWrite(Dp, LOW);
  if(Recieved){
    if(RecievedByte == 50){
      if(ledOn == 0){
        digitalWrite(13, HIGH);
        ledOn = 1;
      } else {
        digitalWrite(13, LOW);
        ledOn = 0;
      }
      RecievedByte = 0;
    }
    Recieved = 0;
  }
  delay(Delay);
}

HOW TO USE THE EXAMPLE PROGRAMS:
- BACKUP YOUR PROGRAMS AND OTHER IMPORTANT DATA ON YOUR CALC
- compile the z80 program (I used SPASM) and send it to your calc.
- send the programs to the arduino and the calc.
- if the arduino hasn't got an on-board LED, connect one (and a resistor!) to pin 13.
- cut a USB mini male end of a USB cable (make sure the wire attached to it is long enough, works with both A-type and B-type (both have been tested)).
- connect the white wire of the USB to pin 6, the green wire to pin 5 and the black wire to the GND.
- make sure the arduino is powered and insert the USB cable into the calc's USB port.
- run the assembly program with Asm( on the calc

When you run the program, press a key. The led should now turn on. When you run it and press a key again, the led should turn off. If your calc freezes, make sure the arduino is powered, the black wire is connected to the GND, runs the correct software and is connected to your calc.

What this does is: when you press a key on the calc, it sends a byte with a value of 50 to the arduino. The arduino notices a byte is send and checks if it's 50. If it's 50, pin 13 will toggle.

It may be very unoptimized (especially the arduino part, I learned the language two days ago), but it works. I hope this code can be usefull to anyone.

Also: thank you, Thepenguin77. Without your help, I wouldn't be able to control the USB port.
Title: Re: calculator(84+) - arduino communication trough USB
Post by: Keoni29 on April 13, 2012, 09:42:25 pm
So we are now able to control the USB port of the TI84+?
I like the idea of interfacing calculators with the outside world as you might have expected. (I have been working on my TI-Nterface for quite a while now)
Title: Re: calculator(84+) - arduino communication trough USB
Post by: ben_g on April 13, 2012, 10:04:58 pm
Only one wire can be controlled manually, but both can be read. If you need to recieve information too, it will be much more complicated, because you can't send and recieve bytes at the same time. But in many cases 1 way communication is enough. In my case, the calc is used as a controle panel for a scoreboard: the calc sends the values as binary numbers to the arduino, which relays the information as decimal numbers to a 7-segment display driver

If you need any help on getting it to work, just ask. I can even help you in Dutch if you want.

also: what's TI-Nterface and is it fot the 84+? (name makes me think it's for the nspire).
Title: Re: calculator(84+) - arduino communication trough USB
Post by: Keoni29 on April 21, 2012, 03:44:01 pm
It's the working name of the project. Just thought it was funny since TI makes up these weird names too. I wonder if syncing multiple calcs w/ the usb port is possible or even sending midi data from an arduino to em.