Obsługa protokołu SIO przez urządzenie peryferyjne

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
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;
}

Zobacz też

Personal tools