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

From Atariki

Jump to: navigation, search

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:
RxBuffer[0]		- SIO device identifier and unit number
RxBuffer[1]		- COMMAND
RxBuffer[2]		- DAUX1
RxBuffer[3]		- DAUX2
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