If it were me, I would probably, update the input protocol between the two systems. Currently they are very very dependant on each other to get any performance. IE the host program must be ready to output the same command over and over again just to get it to walk. And it must do so at the exact point after it receives the request from the Atom Pro.
In particular the current main loop:
serout S_OUT,i9600,["Rd"] ; 'Ready' to recieve data now
serin S_OUT,i9600,100,NoData,[str DualShock(0)\7]
CheckSum = DualShock(1) ^ DualShock(2) ^ DualShock(3) ^ |
DualShock(4) ^ DualShock(5) ^ DualShock(6)
if CheckSum <> DualShock(0) then
DualShock(1) = $FF
DualShock(2) = $FF
for Index = 3 to 6
DualShock(Index) = $80
So what would I do different? I would probably try to make it where it could start walking at some speed and keep going that way until it gets another command. I would also try to build some form of failsafe in, such that if the communications is lost it would stop reasonably soon. There are many ways of doing this, but if it were me, I would probably try a hack I found when I had my TV brat be able to communicate with my VB app on a PC.
The outline of it would go something like:
The SIN/SOUT lines on the BAP is the IO line that can also be IRQ0, which is interesting. So I would set this up in my program. On the PC if you send a single byte of 0xff it forms one very nice simple pulse, which can be used to trigger the interrupt on the BAP. So here is how I would first try it out:
First I would setup the interrupt on the BAP:
; initialize PC communications, use an Int0
ONINTERRUPT IRQ0INT, HANDLE_S_IN_INT
; Initialize communications with PC
; lets setup to get interrupted if we get a rising edge on IRQ0.
PMR1.bit4 = 1 ; enable pin to IRQ0 interrupt instead of normal I/O
IEGR1.bit0 = 0 ; Interrupt IRQ0 on falling edge
ienr1.bit0 = 1
enable ; global enable interrupts to be processed
This would go in the init code. I would then have an interrupt handler that would respond with a serin to receive a new command. Here is a simple one from my test program that currently only receives one byte:
; We received an interrupt on IRQ0 so something is coming in on the S_IN/S_OUT line.
; disable our own interrupt.
PMR1.bit4 = 0 ; restore pin n to normal IO
enable ; Allow other interrupts to be processed
serin s_in, i9600, [bKeyboardCmd]
resume ; and return
In your case I would have it read in a new command into a different buffer than the one that is being processed.
I would then change the main loop, to check to see if a new valid command has been received. This could be done by having your interrupt handler setting a variable to some value. If there is a new valid command, move it into the current command and process it. If no new command continue with the old current command. Maybe increment some variable that says how many times this command has been processed, or decrement some variable. Maybe each command when processed sets what the maximum number of times a command can be repeated before a new command is received. IE maybe you only want to process the cross command once, but the walking or turning command can be repeated 1000 times...
Once the command has been moved into the curernt command, you would need to reneable the IRQ0 interrupt:
elseif (bKeyboardCmd <> 0)
serout S_OUT, i9600, [hex bKeyboardCmd, 13]
bKeyboardCmd = 0
PMR1.bit4 = 1 ; setup to interrupt again on IRQ0
Again that was from my test program, that currently is incomplete... but it does show setting up IRQ0 again (pmr1.bit4)
Of course the PC side would have to be changed to handle this. But it should be simple: Simply output one byte ff, wait a small amount of time to allow the BAP to get to the serin and then output the new command. Also with this I would expierment with checking to see if my new command is the same as the old command and if so don't output it again unless some time has elapsed.
Sorry I got to run. I hope this makes some sense.