Obsługa protokołu SIO przez urządzenie peryferyjne
From Atariki
(Różnice między wersjami)
Wersja z dnia 14:22, 25 maj 2024 Mono (Dyskusja | wkład) (przeniesione z artykułu o sio) ← Previous diff |
Wersja z dnia 16:01, 25 maj 2024 Mono (Dyskusja | wkład) (→Kod dla mikrokontolera AVR (Arduino) - kosmetyka) Next diff → |
||
Linia 64: | Linia 64: | ||
/* Global Variable */ | /* Global Variable */ | ||
- | uint8_t RxBuffer [32+1]; | + | uint8_t RxBuffer[8+1]; |
- | + | uint8_t RxSum; | |
- | uint8_t RxSumData = 0; | + | |
- | uint8_t RxSumCmd = 0; | + | |
Linia 81: | Linia 79: | ||
{ | { | ||
//wait for COMMAND line is LOW | //wait for COMMAND line is LOW | ||
- | while (digitalRead(PIN_SIOCOMMAND) > 0) ; | + | while (digitalRead(PIN_SIOCOMMAND) != 0) ; |
//receive command frame and calculate checksum | //receive command frame and calculate checksum | ||
- | RxSumCmd = ReceiveData(RxBuffer, RxCmdSize+1); | + | RxSum = ReceiveData(RxBuffer, RxCmdSize+1); |
- | //wait for COMMAND line is LOW | + | //wait for COMMAND line is HIGH |
while (digitalRead(PIN_SIOCOMMAND) == 0) ; | while (digitalRead(PIN_SIOCOMMAND) == 0) ; | ||
Linia 93: | Linia 91: | ||
{ | { | ||
//check command checksum | //check command checksum | ||
- | if (RxSumCmd == RxBuffer[RxCmdSize]) | + | if (RxSum == RxBuffer[RxCmdSize]) |
{ | { | ||
//check command identifier | //check command identifier | ||
Linia 111: | Linia 109: | ||
//receive data frame | //receive data frame | ||
- | RxSumData = ReceiveData(RxBuffer, RxDataSize+1); | + | RxSum = ReceiveData(RxBuffer, RxDataSize+1); |
- | if (RxSumData == RxBuffer[RxDataSize]) | + | if (RxSum == RxBuffer[RxDataSize]) |
{ | { | ||
//send ACK | //send ACK |
Wersja z dnia 16:01, 25 maj 2024
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; }