This is still work in progress. But I have marked in comments where the Arduino Uno and Arduino Leonardo differ. The libraries are simply the vanilla package from the Arduino website, no modifications or additional modules.
Using built-in specs.
Target: avr
Configured with: ../configure --prefix=/usr/local/AVRMacPack-20081213 --disable-dependency-tracking --disable-nls --disable-werror --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --with-dwarf2
Thread model: single
gcc version 4.3.2 (GCC)
/*
Button Box Controller w/ Keyboard Emulation
This controller tries to be a very accurate data logger (down to 1 ms)
for psychophysics research.
Since USB cannot give us that resolution, we need to communicate
the timestamps over the Virtual Serial (with the Leonardo controller)
The circuit:
TODO: Circuit ;-)
created 13 September 2012
modified 13 September 2012
by Evi Vanoost (vanooste@rcbi.rochester.edu)
This code is licensed by the GPL
*/
/* Developer refererence PortManipulation
PORTD maps to Arduino digital pins 0 to 7
DDRD - The Port D Data Direction Register - read/write
PORTD - The Port D Data Register - read/write
PIND - The Port D Input Pins Register - read only
PORTB maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable
DDRB - The Port B Data Direction Register - read/write
PORTB - The Port B Data Register - read/write
PINB - The Port B Input Pins Register - read only
PORTC maps to Arduino analog pins 0 to 5. Pins 6 & 7 are only accessible on the Arduino Mini
DDRC - The Port C Data Direction Register - read/write
PORTC - The Port C Data Register - read/write
PINC - The Port C Input Pins Register - read only
*/
// Global variables
byte analogConfig;
unsigned long analogConfigData;
boolean printTime = false;
union timekeeper {
unsigned long time;
unsigned char bytes[4];
} time;
void setup () {
// DDRD is pin 7 (MSB) - 0 (LSB)
// Pin 0 and 1 are Serial Port pins so leave those working by setting Pin0 to 0 and Pin1 to 1
// Set to 0 for input, 1 for output
DDRD = 0b00000010;
// DDRB is pin 13-8, the first two bits are unused, leave 0, pin 13 is LED
// Change pin SoftwareSerial code if you want to use it as an input.
DDRB = 0b00100000;
// DDRC is Analog Pin 0-5
DDRC = 0b00000000;
Serial.begin(115200);
// Turn the LED on just to show we are working
PORTB = 0b00100000;
}
/* Developer reference Bitwise operations - see http://www.arduino.cc/playground/Code/BitMath
char y = PIND; // Gets the whole Pin layout in a single byte (efficient)
boolean y = (PIND >> n) & 1; // n=0..7. stores nth bit of PIND in y. y becomes 0 or 1.
PORTD &= ~(1 << n); // forces nth bit of PORTD to be 0. all other bits left alone.
PORTD &= (1<<(n+1))-1; // leaves alone the lowest n bits of x; all higher bits set to 0.
PORTD |= (1 << n); // forces nth bit of x to be 1. all other bits left alone.
PORTD ^= (1 << n); // toggles nth bit of x. all other bits left alone.
PORTD = ~x; // toggles ALL the bits in x.
*/
void sendTime() {
// 32-bits is 4 bytes
// unrolled loop
time.time = micros();
Serial.write(time.bytes[3]);
Serial.write(time.bytes[2]);
Serial.write(time.bytes[1]);
Serial.write(time.bytes[0]);
}
void loop () {
if (printTime) {
sendTime();
//3 bytes for pins
Serial.write(PIND);
Serial.write(PINB);
if (analogConfig) {
// TODO: Handle analog config writes - this will extend the block many, many bytes
Serial.write(PINC);
}
else {
Serial.write(PINC);
}
//1 newline byte - this can be "\n" on Arduino Uno but will fail compile on Arduino Leonardo
Serial.write(10);
}
// SerialEvent gets invoked automatically on Arduino Uno but doesn't on Arduino Leonardo. Emulate the behavior (when there is Serial data)
if (Serial.available()) {
SerialEvent();
}
}
void SerialEvent () {
char inputChar = (char) Serial.read();
Serial.print(inputChar);
if (inputChar == 'T') {
// When T is sent, get current millis and return them to the host
// micros() are UNSIGNED long (32-bits, 4 bytes) - important for rollover
// time calculations
sendTime();
}
else if (inputChar == 'C') {
// When C is sent, configuration of the system follows in 5 bytes (so 6 bytes total)
// BITWISE:
// MSB
// 8 - Send back Analog value for Port3
// 7 - Send back Analog value for Port2
// 6 - Send back Analog value for Port1
// 5 - Send back Analog value for Port0
// 4 - Do threshold detection for Port3
// 3 - Do threshold detection for Port2
// 2 - Do threshold detection for Port1
// 1 - Do threshold detection for Port0
// LSB
//
// Next 4 bytes (32-bits) are threshold values 0...1023 * 4 - use bitconcat in MATLAB
// Port 3 Port 2 Port 1 Port 0
// 0000 0000 0000 0000 0000 0000 00 0000
//
// Notes: Analog port reads slow down and make it less accurate. Threshold detection even more.
// digital read is 1/16th of a microsecond,
// analog read is ~105 microseconds - all 4 analog inputs would take 420 microseconds, almost half a millisecond.
//
analogConfig = Serial.read();
// 32-bits need an unsigned long. Read the first 8 bits
for (int i=0;i<4;i++) {
// Shift 8 bits, the overflow overflows first time around.
analogConfigData = analogConfigData << 8;
// OR will simply fill in the 0's
analogConfigData |= Serial.read();
sendTime();
}
}
else if (inputChar == 'S') {
// Start or stop the operation
printTime = !printTime;
}
Serial.flush();
}