Obsługa protokołu SIO przez urządzenie peryferyjne
From Atariki
Dane jest urządzenie peryferyjne o identyfikatorze $40 obsługujące rozkaz 'W' ($57), dla którego odbiera 8 bajtów danych i realizuje jakąś operację.
Kod dla Atari
lda #$40 sta DDEVIC ;$300 lda #$01 sta DUNIT ;$301 lda #'W' sta DCMND ;$302 lda #$80 sta DSTATS ;$303 lda #<buffer sta DBUFA ;$304 lda #>buffer sta DBUFA+1 lda #$07 sta DTIMLO ;$306 lda #<8 sta DBUFL ;$308 lda #>8 sta DBUFL+1 lda #$00 sta DAUX1 ;$30A lda #$00 sta DAUX2 ;$30B jsr SIOV ;$E459 bmi ?error
Kod dla mikrokontolera AVR (Arduino)
/* SIO CMD structure: Byte: RxBuffer[0] - SIO device identifier and unit number RxBuffer[1] - COMMAND, for future use, RxBuffer[2] - DAUX1, for future use, RxBuffer[3] - DAUX2, for future use, RxBuffer[4] - checksum. SIO DATA structure: RxBuffer[0] - data, RxBuffer[1] - data, ... ... RxBuffer[RxDataSize-1] - data, RxBuffer[RxDataSize] - checksum. */ /* Arduino hardware settings */ #define PIN_SIOCOMMAND 2 // ATARI SIO-COMMAND Pin #define SIO Serial1 // ATARI SIO-Serial interface // ---------------------------------------- /* Global define */ #define RxCmdSize 4 // size of command frame (w/o checksum byte) #define RxDataSize 8 // size of data frame (w/o checksum byte) #define DEVICE_ID 0x40 // SIO device identifier and unit number #define COMMAND_ID 'W' // SIO operation command /* Global Variable */ uint8_t RxBuffer[8+1]; uint8_t RxSum; void setup() { pinMode(PIN_SIOCOMMAND, INPUT_PULLUP); SIO.begin(19200); } void loop() { while (1) { //wait for COMMAND line is LOW while (digitalRead(PIN_SIOCOMMAND) != 0) ; //receive command frame and calculate checksum RxSum = ReceiveData(RxBuffer, RxCmdSize+1); //wait for COMMAND line is HIGH while (digitalRead(PIN_SIOCOMMAND) == 0) ; //verify device identifier if (RxBuffer[0] == DEVICE_ID) { //check command checksum if (RxSum == RxBuffer[RxCmdSize]) { //check command identifier if (RxBuffer[1] == COMMAND_ID) { //-- check or process auxiliary bytes RxBuffer[2] and RxBuffer[3] when needed //... //... //-- end of aux data processing ---------------------------------------- //send ACK and continue receive data delayMicroseconds(1000); SIO.write('A'); SIO.flush(); //receive data frame RxSum = ReceiveData(RxBuffer, RxDataSize+1); if (RxSum == RxBuffer[RxDataSize]) { //send ACK delayMicroseconds(1000); SIO.write('A'); SIO.flush(); //-- start operation according to received command and data //... //... //-- end of operation ---------------------------------------- //then send operation COMPLETE delayMicroseconds(250); SIO.write('C'); SIO.flush(); } else { //send NAK because of wrong data frame checksum delayMicroseconds(1000); SIO.write('N'); SIO.flush(); //then send operation ERROR delayMicroseconds(250); SIO.write('E'); SIO.flush(); } } else { //send NAK because of not supported command delayMicroseconds(1000); SIO.write('N'); SIO.flush(); } } else { //send NAK because of wrong command frame checksum delayMicroseconds(1000); SIO.write('N'); SIO.flush(); } } } } //functions uint8_t ReceiveData(uint8_t *buffer, uint8_t length) { u8 cnt = 0; int sum = 0; cnt = SIO.readBytes(buffer,length); if (cnt == length) { for (cnt = 0; cnt < length-1; cnt++) { sum += buffer[cnt]; if (sum >= 256) { sum = (sum - 256) + 1; // add carry into sum } } } return sum; }