Watchdog ISR in assembly language

It's still a work in progess and a bit rough

//
// Acts as an SPI master
// Receives 3 bytes, CMD, ADDR_LO, ADDR_HI
// performs an action based on the CMD
// returns the results as a fourth byte
//
// Still very rough, a work in progress.
//

//#define RUNNING_ON_328
#define RUNNING_ON_2560

//#define  VERSION_ASM
#define  VERSION_C


#ifdef RUNNING_ON_328
#define ATMON_PORT_PIN_MOSI  3
#define ATMON_PORT_PIN_MISO  4
#define ATMON_PORT_PIN_SCK   5

#define ATMON_ARD_PIN_MOSI  11
#define ATMON_ARD_PIN_MISO  12
#define ATMON_ARD_PIN_SCK   13
#define ATMON_ARD_PIN_DEBUG 8
#endif

#ifdef RUNNING_ON_2560
#define ATMON_PORT_PIN_MOSI  2
#define ATMON_PORT_PIN_MISO  3
#define ATMON_PORT_PIN_SCK   1

#define ATMON_ARD_PIN_MOSI  51
#define ATMON_ARD_PIN_MISO  50
#define ATMON_ARD_PIN_SCK   52
#define ATMON_ARD_PIN_DEBUG 53
#endif

#define    CMD_POLL  1
#define    CMD_RD    2
#define    CMD_WR    3

#define  ACK    6
#define  NAK    15

// known location to read from
byte  test_byte = 0x23;


#ifdef VERSION_ASM
ISR (WDT_vect, ISR_NAKED) {
  #include "d:\work\atmon\atmon\atmon_isr.s"
}
#endif

#ifdef VERSION_C
ISR (WDT_vect) {
  volatile byte cmd = 0;
  volatile byte addr_hi = 0;
  volatile byte addr_lo = 0;
  byte response;
  byte *address;
  int i;

  asm ("wdr");
  
  
  // get the command byte from other Arduino
 for (i = 0; i < 8; i++) {
    cmd <<= 1;
    PORTB |= (1 << ATMON_PORT_PIN_SCK);     
    if (PINB & 1 << ATMON_PORT_PIN_MISO) {
      cmd |= 1;
    }
    PORTB &= ~(1 << ATMON_PORT_PIN_SCK); 
  }
  delayMicroseconds (5); // needed to allow the other Arduino some time to load another byte
  
  // get the low address byte from other Arduino
  for (i = 0; i < 8; i++) {
    addr_lo <<= 1;
    PORTB |= (1 << ATMON_PORT_PIN_SCK); 
    if (PINB & 1 << ATMON_PORT_PIN_MISO) {
      addr_lo |= 1;
    }
    PORTB &= ~(1 << ATMON_PORT_PIN_SCK); 
  } 
  delayMicroseconds (5);
  
  // get the high address byte from other Arduino
  for (i = 0; i < 8; i++) {
    addr_hi <<= 1;
    PORTB |= (1 << ATMON_PORT_PIN_SCK); 
    if (PINB & 1 << ATMON_PORT_PIN_MISO) {
      addr_hi |= 1;
    }
    PORTB &= ~(1 << ATMON_PORT_PIN_SCK); 
  }
  
  address = (byte*)((addr_hi << 8) + addr_lo);
  
  // action the command
  switch (cmd) {
    case  CMD_POLL:
      response = ACK;
      break;
 
    case  CMD_RD:
      response = *address;
      break;
 
    case  CMD_WR:
      response = ACK; // not implemented yet
      break;  
      
    default:
      response = NAK;
      break;  
  }

   // send response byte to other Arduino  
   for (i = 0; i < 8; i++) {
     if ((response & 0x80) == 0) 
        PORTB &= ~(1 << ATMON_PORT_PIN_MOSI); 
     else
        PORTB |= (1 << ATMON_PORT_PIN_MOSI); 
  
    PORTB |= (1 << ATMON_PORT_PIN_SCK); 
    response <<= 1;
    PORTB &= ~(1 << ATMON_PORT_PIN_SCK); 
  }
}
#endif

void setup () {
 
  WDTCSR = (1<<WDIE);
  
  Serial.begin (115200);
  
  pinMode(ATMON_ARD_PIN_MOSI, OUTPUT);
  pinMode(ATMON_ARD_PIN_MISO, INPUT);
  pinMode(ATMON_ARD_PIN_SCK, OUTPUT);
  pinMode(ATMON_ARD_PIN_DEBUG,OUTPUT);
  
};

void loop () {
  // pulse to allow measuring of the timeout from main code
   PORTB |= (1); 
   PORTB &= ~(1); 
};

I cleaned it up a bit, hopefully I didn't break anything while doing so.


Rob