/** * spi-peripheral-even.ino * Mithat Konar * GPL3 * * An SPI peripheral that returns even number(s). * Commands: * * '0': reset the number to 0 * * 'i': get most recent number, then increment the value by 2 * * 'r': get most recent number * * After you have made this device active by bringing pin SS/CS low, you * can send a transaction using one of these commands. * * On the controller, this would look like: * * byte rv = 0; // used to get responses from peripheral * * // reset the counter: * SPI.beginTransaction(SPISettings(400000, MSBFIRST, SPI_MODE0)); * digitalWrite(PERIPHERAL_CS, LOW); // make peripheral active * rv = SPI.transfer('r'); * digitalWrite(PERIPHERAL_CS, HIGH); // make peripheral inactive * SPI.endTransaction(); * * // get some numbers: * SPI.beginTransaction(SPISettings(400000, MSBFIRST, SPI_MODE0)); * digitalWrite(PERIPHERAL_CS, LOW); // make peripheral active * SPI.transfer('0'); // ALWAYS reset before using * rv = SPI.transfer('i'); // rv has 0, peripheral internal counter is 2 * rv = SPI.transfer('i'); // rv has 2, peripheral internal counter is 4 * rv = SPI.transfer('i'); // rv has 4, peripheral internal counter is 6 * digitalWrite(PERIPHERAL_CS, HIGH); // make peripheral inactive * SPI.endTransaction(); * * SPI.beginTransaction(SPISettings(400000, MSBFIRST, SPI_MODE0)); * digitalWrite(PERIPHERAL_CS, LOW); // make peripheral active * rv = SPI.transfer('r'); // rv has 6, peripheral internal counter is 6 * rv = SPI.transfer('i'); // rv has 6, peripheral internal counter is 8 * rv = SPI.transfer('r'); // rv has 8, peripheral internal counter is 8 * digitalWrite(PERIPHERAL_CS, HIGH); // make peripheral inactive * SPI.endTransaction(); * * Pinout (ATmega328P-based Arduinos): * SCK: 13 * PICO: 12 * POCI: 11 * CS: 10 */ #include #include volatile byte num = 0; // state variable used to hold count void setup (void) { // configure POCI as output pinMode(MISO, OUTPUT); // TODO: what happens when everyone is an output // all at once? SPCR |= bit(SPE); // turn on SPI in peripheral mode SPDR = 0; // initialize SPI data -- works on H/W reset but not // consistently on power up SPI.attachInterrupt(); } // SPI interrupt routine ISR (SPI_STC_vect) { // Before we got here, the old value in SPDR was already automagically // transferred back to the controller. byte cmd = SPDR; switch(cmd) { case '0': // reset num = 0; break; case 'i': // increment num += 2; break; case 'r': // do nothing -- also the default, so 'r' isn't necessary; break; // it makes for semantic code though. } SPDR = num; // set SPDR to num, ready to be transferred to the controller // on the next transfer. } void loop (void) { // nothing to do here :-) }