From 88d8326615d0f8e34062f94a528374bd8819b06f Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 3 Feb 2007 16:52:51 +0000 Subject: [PATCH] Splitting wiring.c into multiple files to get even smaller sketch sizes. --- targets/arduino/WInterrupts.c | 2 +- targets/arduino/pins_arduino.c | 2 +- targets/arduino/wiring.c | 397 +------------------------------ targets/arduino/wiring.h | 32 --- targets/arduino/wiring_analog.c | 109 +++++++++ targets/arduino/wiring_digital.c | 135 +++++++++++ targets/arduino/wiring_private.h | 83 +++++++ targets/arduino/wiring_pulse.c | 75 ++++++ targets/arduino/wiring_serial.c | 212 +++++++++++++++++ targets/arduino/wiring_shift.c | 39 +++ 10 files changed, 656 insertions(+), 430 deletions(-) create mode 100755 targets/arduino/wiring_analog.c create mode 100755 targets/arduino/wiring_digital.c create mode 100755 targets/arduino/wiring_private.h create mode 100755 targets/arduino/wiring_pulse.c create mode 100755 targets/arduino/wiring_serial.c create mode 100755 targets/arduino/wiring_shift.c diff --git a/targets/arduino/WInterrupts.c b/targets/arduino/WInterrupts.c index ff55c451f..38992ee35 100755 --- a/targets/arduino/WInterrupts.c +++ b/targets/arduino/WInterrupts.c @@ -31,7 +31,7 @@ #include #include "WConstants.h" - +#include "wiring_private.h" volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; // volatile static voidFuncPtr twiIntFunc; diff --git a/targets/arduino/pins_arduino.c b/targets/arduino/pins_arduino.c index b65b01777..5d4fcbc63 100755 --- a/targets/arduino/pins_arduino.c +++ b/targets/arduino/pins_arduino.c @@ -23,7 +23,7 @@ */ #include -#include "wiring.h" +#include "wiring_private.h" // On the Arduino board, digital pins are also used // for the analog output (software PWM). Analog input diff --git a/targets/arduino/wiring.c b/targets/arduino/wiring.c index e6a3fa5a4..3a20712b4 100755 --- a/targets/arduino/wiring.c +++ b/targets/arduino/wiring.c @@ -22,407 +22,12 @@ $Id$ */ -#include -#include -#include -#include -#include -#include - -#ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#endif -#ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) -#endif - -#include "wiring.h" - -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which rx_buffer_head is the index of the -// location to which to write the next incoming character and rx_buffer_tail -// is the index of the location from which to read. -#define RX_BUFFER_SIZE 128 - -unsigned char rx_buffer[RX_BUFFER_SIZE]; - -int rx_buffer_head = 0; -int rx_buffer_tail = 0; +#include "wiring_private.h" // The number of times timer 0 has overflowed since the program started. // Must be volatile or gcc will optimize away some uses of it. volatile unsigned long timer0_overflow_count; -// Get the hardware port of the given virtual pin number. This comes from -// the pins_*.c file for the active board configuration. -int digitalPinToPort(int pin) -{ - return digital_pin_to_port[pin].port; -} - -// Get the bit location within the hardware port of the given virtual pin. -// This comes from the pins_*.c file for the active board configuration. -int digitalPinToBit(int pin) -{ - return digital_pin_to_port[pin].bit; -} - -int analogOutPinToTimer(int pin) -{ - return analog_out_pin_to_timer[pin]; -} - -int analogInPinToBit(int pin) -{ - return analog_in_pin_to_port[pin].bit; -} - -void pinMode(int pin, int mode) -{ - if (digitalPinToPort(pin) != NOT_A_PIN) { - if (mode == INPUT) - cbi(_SFR_IO8(port_to_mode[digitalPinToPort(pin)]), - digitalPinToBit(pin)); - else - sbi(_SFR_IO8(port_to_mode[digitalPinToPort(pin)]), - digitalPinToBit(pin)); - } -} - -void digitalWrite(int pin, int val) -{ - if (digitalPinToPort(pin) != NOT_A_PIN) { - // If the pin that support PWM output, we need to turn it off - // before doing a digital write. - - if (analogOutPinToTimer(pin) == TIMER1A) - cbi(TCCR1A, COM1A1); - - if (analogOutPinToTimer(pin) == TIMER1B) - cbi(TCCR1A, COM1B1); - -#if defined(__AVR_ATmega168__) - if (analogOutPinToTimer(pin) == TIMER0A) - cbi(TCCR0A, COM0A1); - - if (analogOutPinToTimer(pin) == TIMER0B) - cbi(TCCR0A, COM0B1); - - if (analogOutPinToTimer(pin) == TIMER2A) - cbi(TCCR2A, COM2A1); - - if (analogOutPinToTimer(pin) == TIMER2B) - cbi(TCCR2A, COM2B1); -#else - if (analogOutPinToTimer(pin) == TIMER2) - cbi(TCCR2, COM21); -#endif - - if (val == LOW) - cbi(_SFR_IO8(port_to_output[digitalPinToPort(pin)]), - digitalPinToBit(pin)); - else - sbi(_SFR_IO8(port_to_output[digitalPinToPort(pin)]), - digitalPinToBit(pin)); - } -} - -int digitalRead(int pin) -{ - if (digitalPinToPort(pin) != NOT_A_PIN) { - // If the pin that support PWM output, we need to turn it off - // before getting a digital reading. - - if (analogOutPinToTimer(pin) == TIMER1A) - cbi(TCCR1A, COM1A1); - - if (analogOutPinToTimer(pin) == TIMER1B) - cbi(TCCR1A, COM1B1); - -#if defined(__AVR_ATmega168__) - if (analogOutPinToTimer(pin) == TIMER0A) - cbi(TCCR0A, COM0A1); - - if (analogOutPinToTimer(pin) == TIMER0B) - cbi(TCCR0A, COM0B1); - - if (analogOutPinToTimer(pin) == TIMER2A) - cbi(TCCR2A, COM2A1); - - if (analogOutPinToTimer(pin) == TIMER2B) - cbi(TCCR2A, COM2B1); -#else - if (analogOutPinToTimer(pin) == TIMER2) - cbi(TCCR2, COM21); -#endif - - return (_SFR_IO8(port_to_input[digitalPinToPort(pin)]) >> - digitalPinToBit(pin)) & 0x01; - } - - return LOW; -} - -int analogRead(int pin) -{ - unsigned int low, high, ch = analogInPinToBit(pin); - - // the low 4 bits of ADMUX select the ADC channel - ADMUX = (ADMUX & (unsigned int) 0xf0) | (ch & (unsigned int) 0x0f); - - // without a delay, we seem to read from the wrong channel - //delay(1); - - // start the conversion - sbi(ADCSRA, ADSC); - - // ADSC is cleared when the conversion finishes - while (bit_is_set(ADCSRA, ADSC)); - - // we have to read ADCL first; doing so locks both ADCL - // and ADCH until ADCH is read. reading ADCL second would - // cause the results of each conversion to be discarded, - // as ADCL and ADCH would be locked when it completed. - low = ADCL; - high = ADCH; - - // combine the two bytes - return (high << 8) | low; -} - -// Right now, PWM output only works on the pins with -// hardware support. These are defined in the appropriate -// pins_*.c file. For the rest of the pins, we default -// to digital output. -void analogWrite(int pin, int val) -{ - // We need to make sure the PWM output is enabled for those pins - // that support it, as we turn it off when digitally reading or - // writing with them. Also, make sure the pin is in output mode - // for consistenty with Wiring, which doesn't require a pinMode - // call for the analog output pins. - pinMode(pin, OUTPUT); - - if (analogOutPinToTimer(pin) == TIMER1A) { - // connect pwm to pin on timer 1, channel A - sbi(TCCR1A, COM1A1); - // set pwm duty - OCR1A = val; - } else if (analogOutPinToTimer(pin) == TIMER1B) { - // connect pwm to pin on timer 1, channel B - sbi(TCCR1A, COM1B1); - // set pwm duty - OCR1B = val; -#if defined(__AVR_ATmega168__) - } else if (analogOutPinToTimer(pin) == TIMER0A) { - // connect pwm to pin on timer 0, channel A - sbi(TCCR0A, COM0A1); - // set pwm duty - OCR0A = val; - } else if (analogOutPinToTimer(pin) == TIMER0B) { - // connect pwm to pin on timer 0, channel B - sbi(TCCR0A, COM0B1); - // set pwm duty - OCR0B = val; - } else if (analogOutPinToTimer(pin) == TIMER2A) { - // connect pwm to pin on timer 2, channel A - sbi(TCCR2A, COM2A1); - // set pwm duty - OCR2A = val; - } else if (analogOutPinToTimer(pin) == TIMER2B) { - // connect pwm to pin on timer 2, channel B - sbi(TCCR2A, COM2B1); - // set pwm duty - OCR2B = val; -#else - } else if (analogOutPinToTimer(pin) == TIMER2) { - // connect pwm to pin on timer 2, channel B - sbi(TCCR2, COM21); - // set pwm duty - OCR2 = val; -#endif - } else if (val < 128) - digitalWrite(pin, LOW); - else - digitalWrite(pin, HIGH); -} - -void beginSerial(long baud) -{ -#if defined(__AVR_ATmega168__) - UBRR0H = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8; - UBRR0L = ((F_CPU / 16 + baud / 2) / baud - 1); - - // enable rx and tx - sbi(UCSR0B, RXEN0); - sbi(UCSR0B, TXEN0); - - // enable interrupt on complete reception of a byte - sbi(UCSR0B, RXCIE0); -#else - UBRRH = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8; - UBRRL = ((F_CPU / 16 + baud / 2) / baud - 1); - - // enable rx and tx - sbi(UCSRB, RXEN); - sbi(UCSRB, TXEN); - - // enable interrupt on complete reception of a byte - sbi(UCSRB, RXCIE); -#endif - - // defaults to 8-bit, no parity, 1 stop bit -} - -void serialWrite(unsigned char c) -{ -#if defined(__AVR_ATmega168__) - while (!(UCSR0A & (1 << UDRE0))) - ; - - UDR0 = c; -#else - while (!(UCSRA & (1 << UDRE))) - ; - - UDR = c; -#endif -} - -int serialAvailable() -{ - return (RX_BUFFER_SIZE + rx_buffer_head - rx_buffer_tail) % RX_BUFFER_SIZE; -} - -int serialRead() -{ - // if the head isn't ahead of the tail, we don't have any characters - if (rx_buffer_head == rx_buffer_tail) { - return -1; - } else { - unsigned char c = rx_buffer[rx_buffer_tail]; - rx_buffer_tail = (rx_buffer_tail + 1) % RX_BUFFER_SIZE; - return c; - } -} - -void serialFlush() -{ - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // were full, not empty. - rx_buffer_head = rx_buffer_tail; -} - -#if defined(__AVR_ATmega168__) -SIGNAL(SIG_USART_RECV) -#else -SIGNAL(SIG_UART_RECV) -#endif -{ -#if defined(__AVR_ATmega168__) - unsigned char c = UDR0; -#else - unsigned char c = UDR; -#endif - - int i = (rx_buffer_head + 1) % RX_BUFFER_SIZE; - - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if (i != rx_buffer_tail) { - rx_buffer[rx_buffer_head] = c; - rx_buffer_head = i; - } -} - -void printMode(int mode) -{ - // do nothing, we only support serial printing, not lcd. -} - -void printByte(unsigned char c) -{ - serialWrite(c); -} - -void printNewline() -{ - printByte('\n'); -} - -void printString(char *s) -{ - while (*s) - printByte(*s++); -} - -void printIntegerInBase(unsigned long n, unsigned long base) -{ - unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. - unsigned long i = 0; - - if (n == 0) { - printByte('0'); - return; - } - - while (n > 0) { - buf[i++] = n % base; - n /= base; - } - - for (; i > 0; i--) - printByte(buf[i - 1] < 10 ? - '0' + buf[i - 1] : - 'A' + buf[i - 1] - 10); -} - -void printInteger(long n) -{ - if (n < 0) { - printByte('-'); - n = -n; - } - - printIntegerInBase(n, 10); -} - -void printHex(unsigned long n) -{ - printIntegerInBase(n, 16); -} - -void printOctal(unsigned long n) -{ - printIntegerInBase(n, 8); -} - -void printBinary(unsigned long n) -{ - printIntegerInBase(n, 2); -} - -/* Including print() adds approximately 1500 bytes to the binary size, - * so we replace it with the smaller and less-confusing printString(), - * printInteger(), etc. -void print(const char *format, ...) -{ - char buf[256]; - va_list ap; - - va_start(ap, format); - vsnprintf(buf, 256, format, ap); - va_end(ap); - - printString(buf); -} -*/ - SIGNAL(SIG_OVERFLOW0) { timer0_overflow_count++; diff --git a/targets/arduino/wiring.h b/targets/arduino/wiring.h index f97230324..05f671323 100755 --- a/targets/arduino/wiring.h +++ b/targets/arduino/wiring.h @@ -102,38 +102,6 @@ void detachInterrupt(uint8_t); void setup(void); void loop(void); -// XXX: internal definitions, should be moved to another header file -#define NOT_A_PIN 0 -#define NOT_A_PORT -1 - -#define NOT_ON_TIMER -1 -#define TIMER0A 0 -#define TIMER0B 1 -#define TIMER1A 2 -#define TIMER1B 3 -#define TIMER2 4 -#define TIMER2A 5 -#define TIMER2B 6 - -typedef struct { - int port; - int bit; -} pin_t; - -extern int port_to_mode[]; -extern int port_to_input[]; -extern int port_to_output[]; -extern pin_t *digital_pin_to_port; -extern pin_t *analog_in_pin_to_port; -extern int *analog_out_pin_to_timer; - -#define EXTERNAL_INT_0 0 -#define EXTERNAL_INT_1 1 - -#define EXTERNAL_NUM_INTERRUPTS 2 - -typedef void (*voidFuncPtr)(void); - #ifdef __cplusplus } // extern "C" #endif diff --git a/targets/arduino/wiring_analog.c b/targets/arduino/wiring_analog.c new file mode 100755 index 000000000..c01ec17df --- /dev/null +++ b/targets/arduino/wiring_analog.c @@ -0,0 +1,109 @@ +/* + wiring_analog.c - analog input and output + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +int analogRead(int pin) +{ + unsigned int low, high, ch = analogInPinToBit(pin); + + // the low 4 bits of ADMUX select the ADC channel + ADMUX = (ADMUX & (unsigned int) 0xf0) | (ch & (unsigned int) 0x0f); + + // without a delay, we seem to read from the wrong channel + //delay(1); + + // start the conversion + sbi(ADCSRA, ADSC); + + // ADSC is cleared when the conversion finishes + while (bit_is_set(ADCSRA, ADSC)); + + // we have to read ADCL first; doing so locks both ADCL + // and ADCH until ADCH is read. reading ADCL second would + // cause the results of each conversion to be discarded, + // as ADCL and ADCH would be locked when it completed. + low = ADCL; + high = ADCH; + + // combine the two bytes + return (high << 8) | low; +} + +// Right now, PWM output only works on the pins with +// hardware support. These are defined in the appropriate +// pins_*.c file. For the rest of the pins, we default +// to digital output. +void analogWrite(int pin, int val) +{ + // We need to make sure the PWM output is enabled for those pins + // that support it, as we turn it off when digitally reading or + // writing with them. Also, make sure the pin is in output mode + // for consistenty with Wiring, which doesn't require a pinMode + // call for the analog output pins. + pinMode(pin, OUTPUT); + + if (analogOutPinToTimer(pin) == TIMER1A) { + // connect pwm to pin on timer 1, channel A + sbi(TCCR1A, COM1A1); + // set pwm duty + OCR1A = val; + } else if (analogOutPinToTimer(pin) == TIMER1B) { + // connect pwm to pin on timer 1, channel B + sbi(TCCR1A, COM1B1); + // set pwm duty + OCR1B = val; +#if defined(__AVR_ATmega168__) + } else if (analogOutPinToTimer(pin) == TIMER0A) { + // connect pwm to pin on timer 0, channel A + sbi(TCCR0A, COM0A1); + // set pwm duty + OCR0A = val; + } else if (analogOutPinToTimer(pin) == TIMER0B) { + // connect pwm to pin on timer 0, channel B + sbi(TCCR0A, COM0B1); + // set pwm duty + OCR0B = val; + } else if (analogOutPinToTimer(pin) == TIMER2A) { + // connect pwm to pin on timer 2, channel A + sbi(TCCR2A, COM2A1); + // set pwm duty + OCR2A = val; + } else if (analogOutPinToTimer(pin) == TIMER2B) { + // connect pwm to pin on timer 2, channel B + sbi(TCCR2A, COM2B1); + // set pwm duty + OCR2B = val; +#else + } else if (analogOutPinToTimer(pin) == TIMER2) { + // connect pwm to pin on timer 2, channel B + sbi(TCCR2, COM21); + // set pwm duty + OCR2 = val; +#endif + } else if (val < 128) + digitalWrite(pin, LOW); + else + digitalWrite(pin, HIGH); +} diff --git a/targets/arduino/wiring_digital.c b/targets/arduino/wiring_digital.c new file mode 100755 index 000000000..564093fda --- /dev/null +++ b/targets/arduino/wiring_digital.c @@ -0,0 +1,135 @@ +/* + wiring_digital.c - digital input and output functions + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +// Get the hardware port of the given virtual pin number. This comes from +// the pins_*.c file for the active board configuration. +int digitalPinToPort(int pin) +{ + return digital_pin_to_port[pin].port; +} + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. +int digitalPinToBit(int pin) +{ + return digital_pin_to_port[pin].bit; +} + +int analogOutPinToTimer(int pin) +{ + return analog_out_pin_to_timer[pin]; +} + +int analogInPinToBit(int pin) +{ + return analog_in_pin_to_port[pin].bit; +} + +void pinMode(int pin, int mode) +{ + if (digitalPinToPort(pin) != NOT_A_PIN) { + if (mode == INPUT) + cbi(_SFR_IO8(port_to_mode[digitalPinToPort(pin)]), + digitalPinToBit(pin)); + else + sbi(_SFR_IO8(port_to_mode[digitalPinToPort(pin)]), + digitalPinToBit(pin)); + } +} + +void digitalWrite(int pin, int val) +{ + if (digitalPinToPort(pin) != NOT_A_PIN) { + // If the pin that support PWM output, we need to turn it off + // before doing a digital write. + + if (analogOutPinToTimer(pin) == TIMER1A) + cbi(TCCR1A, COM1A1); + + if (analogOutPinToTimer(pin) == TIMER1B) + cbi(TCCR1A, COM1B1); + +#if defined(__AVR_ATmega168__) + if (analogOutPinToTimer(pin) == TIMER0A) + cbi(TCCR0A, COM0A1); + + if (analogOutPinToTimer(pin) == TIMER0B) + cbi(TCCR0A, COM0B1); + + if (analogOutPinToTimer(pin) == TIMER2A) + cbi(TCCR2A, COM2A1); + + if (analogOutPinToTimer(pin) == TIMER2B) + cbi(TCCR2A, COM2B1); +#else + if (analogOutPinToTimer(pin) == TIMER2) + cbi(TCCR2, COM21); +#endif + + if (val == LOW) + cbi(_SFR_IO8(port_to_output[digitalPinToPort(pin)]), + digitalPinToBit(pin)); + else + sbi(_SFR_IO8(port_to_output[digitalPinToPort(pin)]), + digitalPinToBit(pin)); + } +} + +int digitalRead(int pin) +{ + if (digitalPinToPort(pin) != NOT_A_PIN) { + // If the pin that support PWM output, we need to turn it off + // before getting a digital reading. + + if (analogOutPinToTimer(pin) == TIMER1A) + cbi(TCCR1A, COM1A1); + + if (analogOutPinToTimer(pin) == TIMER1B) + cbi(TCCR1A, COM1B1); + +#if defined(__AVR_ATmega168__) + if (analogOutPinToTimer(pin) == TIMER0A) + cbi(TCCR0A, COM0A1); + + if (analogOutPinToTimer(pin) == TIMER0B) + cbi(TCCR0A, COM0B1); + + if (analogOutPinToTimer(pin) == TIMER2A) + cbi(TCCR2A, COM2A1); + + if (analogOutPinToTimer(pin) == TIMER2B) + cbi(TCCR2A, COM2B1); +#else + if (analogOutPinToTimer(pin) == TIMER2) + cbi(TCCR2, COM21); +#endif + + return (_SFR_IO8(port_to_input[digitalPinToPort(pin)]) >> + digitalPinToBit(pin)) & 0x01; + } + + return LOW; +} diff --git a/targets/arduino/wiring_private.h b/targets/arduino/wiring_private.h new file mode 100755 index 000000000..a83b17972 --- /dev/null +++ b/targets/arduino/wiring_private.h @@ -0,0 +1,83 @@ +/* + wiring_private.h - Internal header file. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ +*/ + +#ifndef WiringPrivate_h +#define WiringPrivate_h + +#include +#include +#include +#include +#include +#include + +#include "wiring.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#define NOT_A_PIN 0 +#define NOT_A_PORT -1 + +#define NOT_ON_TIMER -1 +#define TIMER0A 0 +#define TIMER0B 1 +#define TIMER1A 2 +#define TIMER1B 3 +#define TIMER2 4 +#define TIMER2A 5 +#define TIMER2B 6 + +typedef struct { + int port; + int bit; +} pin_t; + +extern int port_to_mode[]; +extern int port_to_input[]; +extern int port_to_output[]; +extern pin_t *digital_pin_to_port; +extern pin_t *analog_in_pin_to_port; +extern int *analog_out_pin_to_timer; + +#define EXTERNAL_INT_0 0 +#define EXTERNAL_INT_1 1 + +#define EXTERNAL_NUM_INTERRUPTS 2 + +typedef void (*voidFuncPtr)(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/targets/arduino/wiring_pulse.c b/targets/arduino/wiring_pulse.c new file mode 100755 index 000000000..a6e9a5e1b --- /dev/null +++ b/targets/arduino/wiring_pulse.c @@ -0,0 +1,75 @@ +/* + wiring_pulse.c - pulseIn() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +/* +unsigned long pulseIn(int pin, int state) +{ + unsigned long width = 0; + + while (digitalRead(pin) == !state) + ; + + while (digitalRead(pin) != !state) + width++; + + return width * 17 / 2; // convert to microseconds +} +*/ + +/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH + * or LOW, the type of pulse to measure. Works on pulses from 10 microseconds + * to 3 minutes in length, but must be called at least N microseconds before + * the start of the pulse. */ +unsigned long pulseIn(int pin, int state) +{ + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + int r = port_to_input[digitalPinToPort(pin)]; + int bit = digitalPinToBit(pin); + int mask = 1 << bit; + unsigned long width = 0; + + // compute the desired bit pattern for the port reading (e.g. set or + // clear the bit corresponding to the pin being read). the !!state + // ensures that the function treats any non-zero value of state as HIGH. + state = (!!state) << bit; + + // wait for the pulse to start + while ((_SFR_IO8(r) & mask) != state) + ; + + // wait for the pulse to stop + while ((_SFR_IO8(r) & mask) == state) + width++; + + // convert the reading to microseconds. the slower the CPU speed, the + // proportionally fewer iterations of the loop will occur (e.g. a + // 4 MHz clock will yield a width that is one-fourth of that read with + // a 16 MHz clock). each loop was empirically determined to take + // approximately 23/20 of a microsecond with a 16 MHz clock. + return width * (16000000UL / F_CPU) * 20 / 23; +} diff --git a/targets/arduino/wiring_serial.c b/targets/arduino/wiring_serial.c new file mode 100755 index 000000000..3654f4a33 --- /dev/null +++ b/targets/arduino/wiring_serial.c @@ -0,0 +1,212 @@ +/* + wiring_serial.c - serial functions. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which rx_buffer_head is the index of the +// location to which to write the next incoming character and rx_buffer_tail +// is the index of the location from which to read. +#define RX_BUFFER_SIZE 128 + +unsigned char rx_buffer[RX_BUFFER_SIZE]; + +int rx_buffer_head = 0; +int rx_buffer_tail = 0; + +void beginSerial(long baud) +{ +#if defined(__AVR_ATmega168__) + UBRR0H = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8; + UBRR0L = ((F_CPU / 16 + baud / 2) / baud - 1); + + // enable rx and tx + sbi(UCSR0B, RXEN0); + sbi(UCSR0B, TXEN0); + + // enable interrupt on complete reception of a byte + sbi(UCSR0B, RXCIE0); +#else + UBRRH = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8; + UBRRL = ((F_CPU / 16 + baud / 2) / baud - 1); + + // enable rx and tx + sbi(UCSRB, RXEN); + sbi(UCSRB, TXEN); + + // enable interrupt on complete reception of a byte + sbi(UCSRB, RXCIE); +#endif + + // defaults to 8-bit, no parity, 1 stop bit +} + +void serialWrite(unsigned char c) +{ +#if defined(__AVR_ATmega168__) + while (!(UCSR0A & (1 << UDRE0))) + ; + + UDR0 = c; +#else + while (!(UCSRA & (1 << UDRE))) + ; + + UDR = c; +#endif +} + +int serialAvailable() +{ + return (RX_BUFFER_SIZE + rx_buffer_head - rx_buffer_tail) % RX_BUFFER_SIZE; +} + +int serialRead() +{ + // if the head isn't ahead of the tail, we don't have any characters + if (rx_buffer_head == rx_buffer_tail) { + return -1; + } else { + unsigned char c = rx_buffer[rx_buffer_tail]; + rx_buffer_tail = (rx_buffer_tail + 1) % RX_BUFFER_SIZE; + return c; + } +} + +void serialFlush() +{ + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // were full, not empty. + rx_buffer_head = rx_buffer_tail; +} + +#if defined(__AVR_ATmega168__) +SIGNAL(SIG_USART_RECV) +#else +SIGNAL(SIG_UART_RECV) +#endif +{ +#if defined(__AVR_ATmega168__) + unsigned char c = UDR0; +#else + unsigned char c = UDR; +#endif + + int i = (rx_buffer_head + 1) % RX_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != rx_buffer_tail) { + rx_buffer[rx_buffer_head] = c; + rx_buffer_head = i; + } +} + +void printMode(int mode) +{ + // do nothing, we only support serial printing, not lcd. +} + +void printByte(unsigned char c) +{ + serialWrite(c); +} + +void printNewline() +{ + printByte('\n'); +} + +void printString(char *s) +{ + while (*s) + printByte(*s++); +} + +void printIntegerInBase(unsigned long n, unsigned long base) +{ + unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. + unsigned long i = 0; + + if (n == 0) { + printByte('0'); + return; + } + + while (n > 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) + printByte(buf[i - 1] < 10 ? + '0' + buf[i - 1] : + 'A' + buf[i - 1] - 10); +} + +void printInteger(long n) +{ + if (n < 0) { + printByte('-'); + n = -n; + } + + printIntegerInBase(n, 10); +} + +void printHex(unsigned long n) +{ + printIntegerInBase(n, 16); +} + +void printOctal(unsigned long n) +{ + printIntegerInBase(n, 8); +} + +void printBinary(unsigned long n) +{ + printIntegerInBase(n, 2); +} + +/* Including print() adds approximately 1500 bytes to the binary size, + * so we replace it with the smaller and less-confusing printString(), + * printInteger(), etc. +void print(const char *format, ...) +{ + char buf[256]; + va_list ap; + + va_start(ap, format); + vsnprintf(buf, 256, format, ap); + va_end(ap); + + printString(buf); +} +*/ diff --git a/targets/arduino/wiring_shift.c b/targets/arduino/wiring_shift.c new file mode 100755 index 000000000..c0fe7774a --- /dev/null +++ b/targets/arduino/wiring_shift.c @@ -0,0 +1,39 @@ +/* + wiring_shift.c - shiftOut() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +void shiftOut(int dataPin, int clockPin, int bitOrder, byte val) { + int i; + + for (i = 0; i < 8; i++) { + if (bitOrder == LSBFIRST) + digitalWrite(dataPin, !!(val & (1 << i))); + else + digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + + digitalWrite(clockPin, HIGH); + digitalWrite(clockPin, LOW); + } +}