Move master branch from from mios git repo
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Andrew Smallbone <andrew@rocketnumbernine.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ds1305.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
unsigned char ds1305_transfer(unsigned char address, unsigned char data)
|
||||
{
|
||||
select_ds1305();
|
||||
send_spi(address);
|
||||
unsigned char out = send_spi(data);
|
||||
deselect_ds1305();
|
||||
return out;
|
||||
}
|
||||
|
||||
void ds1305_write_block(unsigned char address, unsigned char *data, int length)
|
||||
{
|
||||
select_ds1305();
|
||||
send_spi(address+DS1305_WRITE);
|
||||
int i;
|
||||
for (i=0; i<length; i++) {
|
||||
send_spi(*data++);
|
||||
}
|
||||
deselect_ds1305();
|
||||
}
|
||||
|
||||
void ds1305_read_block(unsigned char address, unsigned char *data, int length)
|
||||
{
|
||||
select_ds1305();
|
||||
send_spi(address);
|
||||
int i;
|
||||
for (i=0; i<length; i++) {
|
||||
*(data+i) = send_spi(0xFF);
|
||||
}
|
||||
deselect_ds1305();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Andrew Smallbone <andrew@rocketnumbernine.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef _ds1305_h__
|
||||
#define _ds1305_h__
|
||||
|
||||
#include <spi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
// these should be defined to the operation used to select/deselect the DS1305
|
||||
void select_ds1305(void);
|
||||
void deselect_ds1305(void);
|
||||
|
||||
#define DS1305_WRITE 0x80
|
||||
#define DS1305_TIME 0x00
|
||||
#define DS1305_ALARM0 0x07
|
||||
#define DS1305_ALARM1 0x0B
|
||||
#define DS1305_CONTROL 0x0F
|
||||
#define DS1305_STATUS 0x010
|
||||
#define DS1305_CHARGER 0x11
|
||||
#define DS1305_USERRAM 0x20
|
||||
|
||||
#define DS1305_ALARM_SET 0x80
|
||||
|
||||
// send the address and a byte and returns the byte returned by the DS1305
|
||||
unsigned char ds1305_transfer(unsigned char address, unsigned char data);
|
||||
// write a block of bytes - will add 0x80 to the address
|
||||
void ds1305_write_block(unsigned char address, unsigned char *data, int length);
|
||||
// read a block of bytes
|
||||
void ds1305_read_block(unsigned char address, unsigned char *data, int length);
|
||||
|
||||
typedef struct _DS1305_DATETIME
|
||||
{
|
||||
unsigned char seconds;
|
||||
unsigned char minutes;
|
||||
unsigned char hours;
|
||||
unsigned char dayofweek;
|
||||
unsigned char date;
|
||||
unsigned char month;
|
||||
unsigned char year;
|
||||
} DS1305_DATETIME;
|
||||
|
||||
/* set/get the current time/date passed the address of a DS1305_DATETIME struct
|
||||
To set the current time/date to "20:11:32 Sunday 29/07/2009"
|
||||
DS1305_DATETIME current = {0x32, 0x11, 0x20, 0x01, 0x29, 0x05, 0x09};
|
||||
set_time(¤t);
|
||||
*/
|
||||
#define set_time(datetime) ds1305_write_block(DS1305_TIME, (unsigned char *)datetime, 7)
|
||||
#define get_time(datetime) ds1305_read_block(DS1305_TIME, (unsigned char *)datetime, 7)
|
||||
|
||||
/* set/get the time of alarm0/alarm1 passed the address of a DS1305_DATETIME struct,
|
||||
although only the seconds/minutes/hours/dayofweek are sent/received
|
||||
*/
|
||||
#define set_alarm0(time) ds1305_write_block(DS1305_ALARM0, (unsigned char *)time, 4)
|
||||
#define get_alarm0(time) ds1305_read_block(DS1305_ALARM0, (unsigned char *)time, 4)
|
||||
#define set_alarm1(time) ds1305_write_block(DS1305_ALARM1, (unsigned char *)time, 4)
|
||||
#define get_alarm1(time) ds1305_read_block(DS1305_ALARM1, (unsigned char *)time, 4)
|
||||
|
||||
// flags used in set_control/get_control
|
||||
#define DS1305_EOSC 0x80 // enable oscillator, note this is inverse of ^EOSC bit value on chip
|
||||
#define DS1305_WP 0x40 // write protect
|
||||
#define DS1305_INTCN 0x04 // enable interrupts
|
||||
#define DS1305_AIE1 0x02 // alarm0 interrupt enable
|
||||
#define DS1305_AIE0 0x01 // alarm1 interrupt enable
|
||||
|
||||
/* get/set the control register. To enable the oscillator, turn on write protection
|
||||
and enable all interrupts the following would be used:
|
||||
set_control(DS1305_EOSC | DS1305_WP | DS1305_INTCN | DS1305_AIE1 | DS1305_AIE0);
|
||||
*/
|
||||
#define set_control(data) ds1305_transfer(DS1305_CONTROL+DS1305_WRITE, (data) ^ DS1305_EOSC)
|
||||
#define get_control(data) (ds1305_transfer(DS1305_CONTROL, 0xFF) ^ DS1305_EOSC)
|
||||
|
||||
// flags used in get_status
|
||||
#define DS1305_IRQF0 0x01 // interrupt 0 request flag - current time has matched alarm 0
|
||||
#define DS1305_IRQF1 0x02 // interrupt 1 request flag - current time has matched alarm 1
|
||||
#define get_status(data) ds1305_transfer(DS1305_STATUS, 0xFF)
|
||||
|
||||
// flags used in set_charger/get_charger
|
||||
#define DS1305_CHARGER_OFF 0x5C // no charge - don't combine with other values
|
||||
#define DS1305_CHARGER_1D2K 0xA5 // 1 diode 2K resistor
|
||||
#define DS1305_CHARGER_1D4K 0xA6 // 1 diode 4K resistor
|
||||
#define DS1305_CHARGER_1D8K 0xA7 // 1 diode 8K resistor
|
||||
#define DS1305_CHARGER_2D2K 0xA1 // 2 diode 2K resistor
|
||||
#define DS1305_CHARGER_2D4K 0xA2 // 2 diode 4K resistor
|
||||
#define DS1305_CHARGER_2D8K 0xA3 // 2 diode 8K resistor
|
||||
/* get/set the charger register */
|
||||
#define set_charger(data) ds1305_transfer(DS1305_CHARGE+DS1305_WRITE, data)
|
||||
#define get_charger(data) ds1305_transfer(DS1305_CHARGE, 0xFF)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For SPI
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
DS1305_DATETIME KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
select_ds1305 KEYWORD2
|
||||
deselect_ds1305 KEYWORD2
|
||||
set_time KEYWORD2
|
||||
get_time KEYWORD2
|
||||
set_control KEYWORD2
|
||||
get_control KEYWORD2
|
||||
set_charger KEYWORD2
|
||||
get_charger KEYWORD2
|
||||
get_alarm0 KEYWORD2
|
||||
set_alarm1 KEYWORD2
|
||||
get_alarm1 KEYWORD2
|
||||
get_status KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants KEYWORD2
|
||||
#######################################
|
||||
DS1305_WRITE LITERAL1
|
||||
DS1305_TIME LITERAL1
|
||||
DS1305_ALARM0 LITERAL1
|
||||
DS1305_ALARM1 LITERAL1
|
||||
DS1305_CONTROL LITERAL1
|
||||
DS1305_STATUS LITERAL1
|
||||
DS1305_CHARGER LITERAL1
|
||||
DS1305_USERRAM LITERAL1
|
||||
DS1305_ALARM_SET LITERAL1
|
||||
DS1305_EOSC LITERAL1
|
||||
DS1305_WP LITERAL1
|
||||
DS1305_INTCN LITERAL1
|
||||
DS1305_AIE1 LITERAL1
|
||||
DS1305_AIE0 LITERAL1
|
||||
DS1305_IRQF0 LITERAL1
|
||||
DS1305_IRQF1 LITERAL1
|
||||
DS1305_CHARGER_OFF LITERAL1
|
||||
DS1305_CHARGER_1D2K LITERAL1
|
||||
DS1305_CHARGER_1D4K LITERAL1
|
||||
DS1305_CHARGER_1D8K LITERAL1
|
||||
DS1305_CHARGER_2D2K LITERAL1
|
||||
DS1305_CHARGER_2D4K LITERAL1
|
||||
DS1305_CHARGER_2D8K LITERAL1
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <spi.h>
|
||||
#include <ds1305.h>
|
||||
|
||||
#define DS1305_PIN 4
|
||||
#define LED_PIN 3
|
||||
|
||||
// following two methods required by DS1305 library to select/deselect device
|
||||
void select_ds1305(void)
|
||||
{
|
||||
digitalWrite(DS1305_PIN, HIGH);
|
||||
}
|
||||
|
||||
void deselect_ds1305(void)
|
||||
{
|
||||
digitalWrite(DS1305_PIN, LOW);
|
||||
}
|
||||
|
||||
// flash led that's connected to pin 3
|
||||
void flash_led(void)
|
||||
{
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
for (int i=0; i<10; i++) {
|
||||
digitalWrite(LED_PIN, i%2==0);
|
||||
delay(50);
|
||||
}
|
||||
}
|
||||
|
||||
// called when pin INT0 goes from 1 to 0
|
||||
ISR(INT0_vect)
|
||||
{
|
||||
// get alarm value to clear alarm interrupt flag on DS1305
|
||||
DS1305_DATETIME alarm;
|
||||
get_alarm0(&alarm);
|
||||
flash_led();
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
// flash LED at start to indicate were about to start
|
||||
flash_led();
|
||||
flash_led();
|
||||
|
||||
// pin used to enable DS1305
|
||||
pinMode(DS1305_PIN, OUTPUT);
|
||||
|
||||
// Make sure ADC is unselected and setup spi
|
||||
deselect_ds1305();
|
||||
setup_spi(SPI_MODE_1, SPI_MSB, SPI_NO_INTERRUPT, SPI_MSTR_CLK16);
|
||||
set_control(0);
|
||||
|
||||
// set current date/time to Thursday 06/05/09 20:32:30
|
||||
DS1305_DATETIME current = {0x30, 0x32, 0x20, 0x05, 0x06, 0x05, 0x09};
|
||||
set_time(¤t);
|
||||
|
||||
// change the value of alarm to the required time/granularity:
|
||||
// raise alarm every day (at 20:32:00):
|
||||
// DS1305_DATETIME alarm = {0x00, 0x32, 0x20, 0x00 | DS1305_ALARM_SET};
|
||||
// raise alarm every minute (when seconds = 00):
|
||||
// DS1305_DATETIME alarm = {0x00, 0x32 | DS1305_ALARM_SET,
|
||||
// 0x20 | DS1305_ALARM_SET, 0x05 | DS1305_ALARM_SET};
|
||||
// raise alarm every second:
|
||||
DS1305_DATETIME alarm = {0x55 | DS1305_ALARM_SET, 0x32 | DS1305_ALARM_SET,
|
||||
0x20 | DS1305_ALARM_SET, 0x05 | DS1305_ALARM_SET};
|
||||
set_alarm0(&alarm);
|
||||
// turn on timer and make alarm0 lower INT0 pin when alarm is triggered
|
||||
set_control(DS1305_EOSC | DS1305_INTCN | DS1305_AIE0);
|
||||
|
||||
// raise interrupt when INT0 pin falls (pin PD0 at AT90usbXXX, pin PD2 on ATmegaXXX (arduino pin 2))
|
||||
// the code in ISR(INT0_vect) above will be called
|
||||
EICRA = (1<<ISC01) | (0<<ISC00);
|
||||
// enable interrupts
|
||||
EIMSK = (1<<INT0);
|
||||
sei();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// do nothing - all action happens in interrupt
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <spi.h>
|
||||
|
||||
// MAX6675 connected to pin D9
|
||||
#define MAX6675_SELECT_PIN 8
|
||||
#define DESELECT_MAX6675 digitalWrite(MAX6675_SELECT_PIN, HIGH)
|
||||
#define SELECT_MAX6675 digitalWrite(MAX6675_SELECT_PIN, LOW)
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(MAX6675_SELECT_PIN, OUTPUT);
|
||||
DESELECT_MAX6675;
|
||||
setup_spi(SPI_MODE_1, SPI_MSB, SPI_NO_INTERRUPT, SPI_MSTR_CLK8);
|
||||
Serial.begin(19200);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(500);
|
||||
|
||||
// select the device, wait > 100nS, read two bytes, deselect
|
||||
SELECT_MAX6675;
|
||||
delayMicroseconds(1);
|
||||
unsigned char highByte = send_spi(0);
|
||||
unsigned char lowByte = send_spi(0);
|
||||
DESELECT_MAX6675;
|
||||
|
||||
// if bit 3 is high thermocouple is unconnected
|
||||
if (lowByte & (1<<2)) {
|
||||
Serial.print("Not connected ");
|
||||
Serial.print(highByte, HEX); Serial.print(" ");
|
||||
Serial.println(lowByte, HEX);
|
||||
} else {
|
||||
// temperature value is in bits 6-0 of highByte and 7-2 of lowByte
|
||||
short value = (highByte << 5 | lowByte>>3);
|
||||
// 1 bit is 0.25 degree 'divide' by 4 to show degrees
|
||||
Serial.print(value/4); Serial.print("."); Serial.println(value%4 *25);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <spi.h>
|
||||
|
||||
#define SELECT_ADC digitalWrite(8, LOW);
|
||||
#define DESELECT_ADC digitalWrite(8, HIGH);
|
||||
|
||||
unsigned short read_adc(void)
|
||||
{
|
||||
// select ADC wait 100microseconds then read two bytes
|
||||
SELECT_ADC;
|
||||
unsigned char one = send_spi(0xFF);
|
||||
unsigned char two = send_spi(0xFF);
|
||||
DESELECT_ADC;
|
||||
// 12 bits of ADC value is bottom 5 bits of first
|
||||
// byte and top 7 bits of second, move into 16 bit int
|
||||
return ((0x1F & one) << 7) | (two >> 1);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(8, OUTPUT);
|
||||
Serial.begin(19200);
|
||||
// make sure ADC is not selected and setup spi
|
||||
DESELECT_ADC;
|
||||
setup_spi(SPI_MODE_0, SPI_MSB, SPI_NO_INTERRUPT, SPI_MSTR_CLK16);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
unsigned short num = read_adc();
|
||||
Serial.println(num);
|
||||
delay(1000);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#include <spi.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#define BUTTON_PIN 2
|
||||
#define LED_PIN 3
|
||||
#define FLASH_LED_COMMAND 0x01
|
||||
|
||||
#define OTHER_SELECT_PIN 7
|
||||
#define SELECT_OTHER digitalWrite(OTHER_SELECT_PIN, LOW);
|
||||
#define DESELECT_OTHER digitalWrite(OTHER_SELECT_PIN, HIGH);
|
||||
|
||||
#define BUFSIZE 20
|
||||
volatile unsigned char incoming[BUFSIZE];
|
||||
volatile short int received=0;
|
||||
|
||||
// flash led that's connected to pin PD7
|
||||
void flash_led(int count)
|
||||
{
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
for (int i=0; i<count*2; i++) {
|
||||
digitalWrite(LED_PIN, i%2==0);
|
||||
_delay_ms(75);
|
||||
}
|
||||
}
|
||||
|
||||
// send a SPI message to the other device - 3 bytes then go back into
|
||||
// slave mode
|
||||
void send_message()
|
||||
{
|
||||
setup_spi(SPI_MODE_1, SPI_MSB, SPI_NO_INTERRUPT, SPI_MSTR_CLK8);
|
||||
if (SPCR & (1<<MSTR)) { // if we are still in master mode
|
||||
SELECT_OTHER; // tell other device to flash LED twice
|
||||
send_spi(FLASH_LED_COMMAND); send_spi(0x02); send_spi(0x00);
|
||||
DESELECT_OTHER;
|
||||
}
|
||||
setup_spi(SPI_MODE_1, SPI_MSB, SPI_INTERRUPT, SPI_SLAVE);
|
||||
}
|
||||
|
||||
|
||||
// called when button pushed and pin INT0 goes from 1 to 0
|
||||
void button_pressed()
|
||||
{
|
||||
send_message();
|
||||
_delay_ms(500); // 'debounce'
|
||||
}
|
||||
|
||||
// parse the data received from the other device
|
||||
// currently just knows about the FLASH_LED_COMMAND
|
||||
void parse_message()
|
||||
{
|
||||
switch(incoming[0]) {
|
||||
case FLASH_LED_COMMAND:
|
||||
flash_led(incoming[1]);
|
||||
break;
|
||||
default:
|
||||
flash_led(20);
|
||||
}
|
||||
}
|
||||
|
||||
// called by the SPI system when there is data ready.
|
||||
// Just store the incoming data in a buffer, when we receive a
|
||||
// terminating byte (0x00) call parse_message to process the data received
|
||||
ISR(SPI_STC_vect)
|
||||
{
|
||||
incoming[received++] = received_from_spi(0x00);
|
||||
if (received == BUFSIZE || incoming[received-1] == 0x00) {
|
||||
parse_message();
|
||||
received = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
// make sure other device is unselected (pin is HIGH) and setup spi
|
||||
DESELECT_OTHER;
|
||||
pinMode(OTHER_SELECT_PIN, OUTPUT);
|
||||
setup_spi(SPI_MODE_1, SPI_MSB, SPI_INTERRUPT, SPI_SLAVE);
|
||||
|
||||
// raise interrupt when INT0 pin falls (arduino pin 2))
|
||||
// the function button_pressed will be called
|
||||
attachInterrupt(0, button_pressed, FALLING);
|
||||
|
||||
// flash LED at start to indicate were ready
|
||||
flash_led(1);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* First stab at a test suite for spi lib.
|
||||
*/
|
||||
#include <spi.h>
|
||||
|
||||
void reportError(int line, char *message, uint8_t expected, uint8_t actual)
|
||||
{
|
||||
Serial.print("Test "); Serial.print(message);
|
||||
Serial.print(" failed at line "); Serial.print(line-3);
|
||||
Serial.print(", expected="); Serial.print(expected, BIN);
|
||||
Serial.print(", actual="); Serial.println(actual, BIN);
|
||||
}
|
||||
|
||||
#define assertEquals(message, expected, actual) \
|
||||
if (expected != actual) { reportError(__LINE__, message, expected, actual); return; }
|
||||
|
||||
|
||||
#define test_setup_spi(message, eSPCR, eSPSR, mode, dord, interrupt, clock) \
|
||||
setup_spi(mode, dord, interrupt, clock); \
|
||||
assertEquals(message, eSPCR, SPCR); \
|
||||
assertEquals(message, eSPSR, SPSR & 0x01);
|
||||
|
||||
|
||||
void test_registers()
|
||||
{
|
||||
// top 4 bits of SPCR - enabled, interrupt, lsb/msb, master/slave
|
||||
disable_spi();
|
||||
assertEquals("0", 0x00, SPCR);
|
||||
|
||||
test_setup_spi("1", 0xE0, 0x00, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_SLAVE);
|
||||
test_setup_spi("2", 0x60, 0x00, SPI_MODE_0, SPI_LSB, SPI_NO_INTERRUPT, SPI_SLAVE);
|
||||
test_setup_spi("3", 0x40, 0x00, SPI_MODE_0, SPI_MSB, SPI_NO_INTERRUPT, SPI_SLAVE);
|
||||
|
||||
// CPOL/CPHA bits - timing mode
|
||||
test_setup_spi("4", 0x40, 0x00, SPI_MODE_0, SPI_MSB, SPI_NO_INTERRUPT, SPI_SLAVE);
|
||||
test_setup_spi("5", 0x44, 0x00, SPI_MODE_1, SPI_MSB, SPI_NO_INTERRUPT, SPI_SLAVE);
|
||||
test_setup_spi("6", 0x48, 0x00, SPI_MODE_2, SPI_MSB, SPI_NO_INTERRUPT, SPI_SLAVE);
|
||||
test_setup_spi("7", 0x4C, 0x00, SPI_MODE_3, SPI_MSB, SPI_NO_INTERRUPT, SPI_SLAVE);
|
||||
|
||||
// clock
|
||||
test_setup_spi("9", 0xE0, 1, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_MSTR_CLK2);
|
||||
test_setup_spi("10", 0xE0, 0, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_MSTR_CLK4);
|
||||
test_setup_spi("11", 0xE1, 1, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_MSTR_CLK8);
|
||||
test_setup_spi("12", 0xE1, 0, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_MSTR_CLK16);
|
||||
test_setup_spi("13", 0xE2, 1, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_MSTR_CLK32);
|
||||
test_setup_spi("14", 0xE2, 0, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_MSTR_CLK64);
|
||||
test_setup_spi("15", 0xE3, 0, SPI_MODE_0, SPI_LSB, SPI_INTERRUPT, SPI_MSTR_CLK128);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(19200);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(5000);
|
||||
Serial.println("Running tests");
|
||||
test_registers();
|
||||
Serial.println("Run tests");
|
||||
while(true);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For SPI
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
setup_spi KEYWORD2
|
||||
disable_spi KEYWORD2
|
||||
send_spi KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
SPI_SS_PIN LITERAL1
|
||||
SPI_SCK_PIN LITERAL1
|
||||
SPI_MOSI_PIN LITERAL1
|
||||
SPI_MISO_PIN LITERAL1
|
||||
SPI_MODE_0 LITERAL1
|
||||
SPI_MODE_1 LITERAL1
|
||||
SPI_MODE_2 LITERAL1
|
||||
SPI_MODE_3 LITERAL1
|
||||
SPI_LSB LITERAL1
|
||||
SPI_MSB LITERAL1
|
||||
SPI_NO_INTERRUPT LITERAL1
|
||||
SPI_INTERRUPT LITERAL1
|
||||
SPI_SLAVE LITERAL1
|
||||
SPI_MSTR_CLK2 LITERAL1
|
||||
SPI_MSTR_CLK4 LITERAL1
|
||||
SPI_MSTR_CLK8 LITERAL1
|
||||
SPI_MSTR_CLK16 LITERAL1
|
||||
SPI_MSTR_CLK32 LITERAL1
|
||||
SPI_MSTR_CLK64 LITERAL1
|
||||
SPI_MSTR_CLK128 LITERAL1
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Andrew Smallbone <andrew@rocketnumbernine.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <spi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#ifdef __ARDUINO__
|
||||
#include <wiring.h>
|
||||
#endif
|
||||
|
||||
void setup_spi(uint8_t mode, int dord, int interrupt, uint8_t clock)
|
||||
{
|
||||
// specify pin directions for SPI pins on port B
|
||||
if (clock == SPI_SLAVE) { // if slave SS and SCK is input
|
||||
DDRB &= ~(1<<SPI_MOSI_PIN); // input
|
||||
DDRB |= (1<<SPI_MISO_PIN); // output
|
||||
DDRB &= ~(1<<SPI_SS_PIN); // input
|
||||
DDRB &= ~(1<<SPI_SCK_PIN);// input
|
||||
} else {
|
||||
DDRB |= (1<<SPI_MOSI_PIN); // output
|
||||
DDRB &= ~(1<<SPI_MISO_PIN); // input
|
||||
DDRB |= (1<<SPI_SCK_PIN);// output
|
||||
DDRB |= (1<<SPI_SS_PIN);// output
|
||||
}
|
||||
SPCR = ((interrupt ? 1 : 0)<<SPIE) // interrupt enabled
|
||||
| (1<<SPE) // enable SPI
|
||||
| (dord<<DORD) // LSB or MSB
|
||||
| (((clock != SPI_SLAVE) ? 1 : 0) <<MSTR) // Slave or Master
|
||||
| (((mode & 0x02) == 2) << CPOL) // clock timing mode CPOL
|
||||
| (((mode & 0x01)) << CPHA) // clock timing mode CPHA
|
||||
| (((clock & 0x02) == 2) << SPR1) // cpu clock divisor SPR1
|
||||
| ((clock & 0x01) << SPR0); // cpu clock divisor SPR0
|
||||
SPSR = (((clock & 0x04) == 4) << SPI2X); // clock divisor SPI2X
|
||||
}
|
||||
|
||||
void disable_spi()
|
||||
{
|
||||
SPCR = 0;
|
||||
}
|
||||
|
||||
uint8_t send_spi(uint8_t out)
|
||||
{
|
||||
SPDR = out;
|
||||
while (!(SPSR & (1<<SPIF)));
|
||||
return SPDR;
|
||||
}
|
||||
|
||||
uint8_t received_from_spi(uint8_t data)
|
||||
{
|
||||
SPDR = data;
|
||||
return SPDR;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Andrew Smallbone <andrew@rocketnumbernine.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef _spi_h__
|
||||
#define _spi_h__
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
// create alias for the different SPI chip pins - code assumes all on port B
|
||||
#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__))
|
||||
#define SPI_SS_PIN PORTB0
|
||||
#define SPI_SCK_PIN PORTB1
|
||||
#define SPI_MOSI_PIN PORTB2
|
||||
#define SPI_MISO_PIN PORTB3
|
||||
#elif (defined(__AVR_ATmega48__) || defined(_AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__))
|
||||
#define SPI_SS_PIN PORTB2
|
||||
#define SPI_SCK_PIN PORTB5
|
||||
#define SPI_MOSI_PIN PORTB3
|
||||
#define SPI_MISO_PIN PORTB4
|
||||
#else
|
||||
#error unknown processor - add to spi.h
|
||||
#endif
|
||||
|
||||
// SPI clock modes
|
||||
#define SPI_MODE_0 0x00 /* Sample (Rising) Setup (Falling) CPOL=0, CPHA=0 */
|
||||
#define SPI_MODE_1 0x01 /* Setup (Rising) Sample (Falling) CPOL=0, CPHA=1 */
|
||||
#define SPI_MODE_2 0x02 /* Sample (Falling) Setup (Rising) CPOL=1, CPHA=0 */
|
||||
#define SPI_MODE_3 0x03 /* Setup (Falling) Sample (Rising) CPOL=1, CPHA=1 */
|
||||
|
||||
// data direction
|
||||
#define SPI_LSB 1 /* send least significant bit (bit 0) first */
|
||||
#define SPI_MSB 0 /* send most significant bit (bit 7) first */
|
||||
|
||||
// whether to raise interrupt when data received (SPIF bit received)
|
||||
#define SPI_NO_INTERRUPT 0
|
||||
#define SPI_INTERRUPT 1
|
||||
|
||||
// slave or master with clock diviser
|
||||
#define SPI_SLAVE 0xF0
|
||||
#define SPI_MSTR_CLK4 0x00 /* chip clock/4 */
|
||||
#define SPI_MSTR_CLK16 0x01 /* chip clock/16 */
|
||||
#define SPI_MSTR_CLK64 0x02 /* chip clock/64 */
|
||||
#define SPI_MSTR_CLK128 0x03 /* chip clock/128 */
|
||||
#define SPI_MSTR_CLK2 0x04 /* chip clock/2 */
|
||||
#define SPI_MSTR_CLK8 0x05 /* chip clock/8 */
|
||||
#define SPI_MSTR_CLK32 0x06 /* chip clock/32 */
|
||||
|
||||
|
||||
|
||||
// setup spi
|
||||
void setup_spi(uint8_t mode, // timing mode SPI_MODE[0-4]
|
||||
int dord, // data direction SPI_LSB|SPI_MSB
|
||||
int interrupt, // whether to raise interrupt on recieve
|
||||
uint8_t clock); // clock diviser
|
||||
|
||||
// disable spi
|
||||
void disable_spi(void);
|
||||
|
||||
// send and receive a byte of data (master mode)
|
||||
uint8_t send_spi(uint8_t out);
|
||||
|
||||
// receive the byte of data waiting on the SPI buffer and
|
||||
// set the next byte to transfer - for use in slave mode
|
||||
// when interrupts are enabled.
|
||||
uint8_t received_from_spi(uint8_t out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user