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;
}
