Fixes to config and build tools.

- Added minimal arduino files needed to compile
- Build script will locate avr-gcc tools
- Z offset fix for MINI
master
Marcio Teixeira 7 years ago
parent ae6a79b0c9
commit 1932de77b4

@ -0,0 +1,266 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 03 August 2015 by Chuck Todd
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Arduino.h"
#include "Print.h"
// Public Methods //////////////////////////////////////////////////////////////
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
while (size--) {
if (write(*buffer++)) n++;
else break;
}
return n;
}
size_t Print::print(const __FlashStringHelper *ifsh)
{
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
size_t n = 0;
while (1) {
unsigned char c = pgm_read_byte(p++);
if (c == 0) break;
if (write(c)) n++;
else break;
}
return n;
}
size_t Print::print(const String &s)
{
return write(s.c_str(), s.length());
}
size_t Print::print(const char str[])
{
return write(str);
}
size_t Print::print(char c)
{
return write(c);
}
size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base);
}
size_t Print::print(int n, int base)
{
return print((long) n, base);
}
size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base);
}
size_t Print::print(long n, int base)
{
if (base == 0) {
return write(n);
} else if (base == 10) {
if (n < 0) {
int t = print('-');
n = -n;
return printNumber(n, 10) + t;
}
return printNumber(n, 10);
} else {
return printNumber(n, base);
}
}
size_t Print::print(unsigned long n, int base)
{
if (base == 0) return write(n);
else return printNumber(n, base);
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
}
size_t Print::println(const __FlashStringHelper *ifsh)
{
size_t n = print(ifsh);
n += println();
return n;
}
size_t Print::print(const Printable& x)
{
return x.printTo(*this);
}
size_t Print::println(void)
{
return write("\r\n");
}
size_t Print::println(const String &s)
{
size_t n = print(s);
n += println();
return n;
}
size_t Print::println(const char c[])
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(char c)
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base);
n += println();
return n;
}
size_t Print::println(int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
n += println();
return n;
}
size_t Print::println(const Printable& x)
{
size_t n = print(x);
n += println();
return n;
}
// Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if (base < 2) base = 10;
do {
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
return write(str);
}
size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0;
if (isnan(number)) return print("nan");
if (isinf(number)) return print("inf");
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
// Handle negative numbers
if (number < 0.0)
{
n += print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
n += print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
n += print('.');
}
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
unsigned int toPrint = (unsigned int)(remainder);
n += print(toPrint);
remainder -= toPrint;
}
return n;
}

@ -0,0 +1,619 @@
/* Tone.cpp
A Tone Generator Library
Written by Brett Hagman
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Version Modified By Date Comments
------- ----------- -------- --------
0001 B Hagman 09/08/02 Initial coding
0002 B Hagman 09/08/18 Multiple pins
0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
0004 B Hagman 09/09/26 Fixed problems with ATmega8
0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
09/11/25 Changed pin toggle method to XOR
09/11/25 Fixed timer0 from being excluded
0006 D Mellis 09/12/29 Replaced objects with functions
0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
0009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62)
0010 jipp 15/04/13 added additional define check #2923
*************************************************/
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "Arduino.h"
#include "pins_arduino.h"
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
#define TCCR2A TCCR2
#define TCCR2B TCCR2
#define COM2A1 COM21
#define COM2A0 COM20
#define OCR2A OCR2
#define TIMSK2 TIMSK
#define OCIE2A OCIE2
#define TIMER2_COMPA_vect TIMER2_COMP_vect
#define TIMSK1 TIMSK
#endif
// timerx_toggle_count:
// > 0 - duration specified
// = 0 - stopped
// < 0 - infinitely (until stop() method called, or new play() called)
#if !defined(__AVR_ATmega8__)
volatile long timer0_toggle_count;
volatile uint8_t *timer0_pin_port;
volatile uint8_t timer0_pin_mask;
#endif
volatile long timer1_toggle_count;
volatile uint8_t *timer1_pin_port;
volatile uint8_t timer1_pin_mask;
volatile long timer2_toggle_count;
volatile uint8_t *timer2_pin_port;
volatile uint8_t timer2_pin_mask;
#if defined(TIMSK3)
volatile long timer3_toggle_count;
volatile uint8_t *timer3_pin_port;
volatile uint8_t timer3_pin_mask;
#endif
#if defined(TIMSK4)
volatile long timer4_toggle_count;
volatile uint8_t *timer4_pin_port;
volatile uint8_t timer4_pin_mask;
#endif
#if defined(TIMSK5)
volatile long timer5_toggle_count;
volatile uint8_t *timer5_pin_port;
volatile uint8_t timer5_pin_mask;
#endif
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ };
#elif defined(__AVR_ATmega8__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
#elif defined(__AVR_ATmega32U4__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER3
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
#else
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
// Leave timer 0 to last.
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
#endif
static int8_t toneBegin(uint8_t _pin)
{
int8_t _timer = -1;
// if we're already using the pin, the timer should be configured.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
return pgm_read_byte(tone_pin_to_timer_PGM + i);
}
}
// search for an unused timer.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == 255) {
tone_pins[i] = _pin;
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
break;
}
}
if (_timer != -1)
{
// Set timer specific stuff
// All timers in CTC mode
// 8 bit timers will require changing prescalar values,
// whereas 16 bit timers are set to either ck/1 or ck/64 prescalar
switch (_timer)
{
#if defined(TCCR0A) && defined(TCCR0B) && defined(WGM01)
case 0:
// 8 bit timer
TCCR0A = 0;
TCCR0B = 0;
bitWrite(TCCR0A, WGM01, 1);
bitWrite(TCCR0B, CS00, 1);
timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer0_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12)
case 1:
// 16 bit timer
TCCR1A = 0;
TCCR1B = 0;
bitWrite(TCCR1B, WGM12, 1);
bitWrite(TCCR1B, CS10, 1);
timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer1_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR2A) && defined(TCCR2B)
case 2:
// 8 bit timer
TCCR2A = 0;
TCCR2B = 0;
bitWrite(TCCR2A, WGM21, 1);
bitWrite(TCCR2B, CS20, 1);
timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer2_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3)
case 3:
// 16 bit timer
TCCR3A = 0;
TCCR3B = 0;
bitWrite(TCCR3B, WGM32, 1);
bitWrite(TCCR3B, CS30, 1);
timer3_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer3_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4)
case 4:
// 16 bit timer
TCCR4A = 0;
TCCR4B = 0;
#if defined(WGM42)
bitWrite(TCCR4B, WGM42, 1);
#elif defined(CS43)
// TODO this may not be correct
// atmega32u4
bitWrite(TCCR4B, CS43, 1);
#endif
bitWrite(TCCR4B, CS40, 1);
timer4_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer4_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5)
case 5:
// 16 bit timer
TCCR5A = 0;
TCCR5B = 0;
bitWrite(TCCR5B, WGM52, 1);
bitWrite(TCCR5B, CS50, 1);
timer5_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer5_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
}
}
return _timer;
}
// frequency (in hertz) and duration (in milliseconds).
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
{
uint8_t prescalarbits = 0b001;
long toggle_count = 0;
uint32_t ocr = 0;
int8_t _timer;
_timer = toneBegin(_pin);
if (_timer >= 0)
{
// Set the pinMode as OUTPUT
pinMode(_pin, OUTPUT);
// if we are using an 8 bit timer, scan through prescalars to find the best fit
if (_timer == 0 || _timer == 2)
{
ocr = F_CPU / frequency / 2 - 1;
prescalarbits = 0b001; // ck/1: same for both timers
if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 8 - 1;
prescalarbits = 0b010; // ck/8: same for both timers
if (_timer == 2 && ocr > 255)
{
ocr = F_CPU / frequency / 2 / 32 - 1;
prescalarbits = 0b011;
}
if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 64 - 1;
prescalarbits = _timer == 0 ? 0b011 : 0b100;
if (_timer == 2 && ocr > 255)
{
ocr = F_CPU / frequency / 2 / 128 - 1;
prescalarbits = 0b101;
}
if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 256 - 1;
prescalarbits = _timer == 0 ? 0b100 : 0b110;
if (ocr > 255)
{
// can't do any better than /1024
ocr = F_CPU / frequency / 2 / 1024 - 1;
prescalarbits = _timer == 0 ? 0b101 : 0b111;
}
}
}
}
#if defined(TCCR0B)
if (_timer == 0)
{
TCCR0B = (TCCR0B & 0b11111000) | prescalarbits;
}
else
#endif
#if defined(TCCR2B)
{
TCCR2B = (TCCR2B & 0b11111000) | prescalarbits;
}
#else
{
// dummy place holder to make the above ifdefs work
}
#endif
}
else
{
// two choices for the 16 bit timers: ck/1 or ck/64
ocr = F_CPU / frequency / 2 - 1;
prescalarbits = 0b001;
if (ocr > 0xffff)
{
ocr = F_CPU / frequency / 2 / 64 - 1;
prescalarbits = 0b011;
}
if (_timer == 1)
{
#if defined(TCCR1B)
TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
#endif
}
#if defined(TCCR3B)
else if (_timer == 3)
TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR4B)
else if (_timer == 4)
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR5B)
else if (_timer == 5)
TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
#endif
}
// Calculate the toggle count
if (duration > 0)
{
toggle_count = 2 * frequency * duration / 1000;
}
else
{
toggle_count = -1;
}
// Set the OCR for the given timer,
// set the toggle count,
// then turn on the interrupts
switch (_timer)
{
#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A)
case 0:
OCR0A = ocr;
timer0_toggle_count = toggle_count;
bitWrite(TIMSK0, OCIE0A, 1);
break;
#endif
case 1:
#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A)
OCR1A = ocr;
timer1_toggle_count = toggle_count;
bitWrite(TIMSK1, OCIE1A, 1);
#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A)
// this combination is for at least the ATmega32
OCR1A = ocr;
timer1_toggle_count = toggle_count;
bitWrite(TIMSK, OCIE1A, 1);
#endif
break;
#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A)
case 2:
OCR2A = ocr;
timer2_toggle_count = toggle_count;
bitWrite(TIMSK2, OCIE2A, 1);
break;
#endif
#if defined(OCR3A) && defined(TIMSK3) && defined(OCIE3A)
case 3:
OCR3A = ocr;
timer3_toggle_count = toggle_count;
bitWrite(TIMSK3, OCIE3A, 1);
break;
#endif
#if defined(OCR4A) && defined(TIMSK4) && defined(OCIE4A)
case 4:
OCR4A = ocr;
timer4_toggle_count = toggle_count;
bitWrite(TIMSK4, OCIE4A, 1);
break;
#endif
#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A)
case 5:
OCR5A = ocr;
timer5_toggle_count = toggle_count;
bitWrite(TIMSK5, OCIE5A, 1);
break;
#endif
}
}
}
// XXX: this function only works properly for timer 2 (the only one we use
// currently). for the others, it should end the tone, but won't restore
// proper PWM functionality for the timer.
void disableTimer(uint8_t _timer)
{
switch (_timer)
{
case 0:
#if defined(TIMSK0)
TIMSK0 = 0;
#elif defined(TIMSK)
TIMSK = 0; // atmega32
#endif
break;
#if defined(TIMSK1) && defined(OCIE1A)
case 1:
bitWrite(TIMSK1, OCIE1A, 0);
break;
#endif
case 2:
#if defined(TIMSK2) && defined(OCIE2A)
bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt
#endif
#if defined(TCCR2A) && defined(WGM20)
TCCR2A = (1 << WGM20);
#endif
#if defined(TCCR2B) && defined(CS22)
TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22);
#endif
#if defined(OCR2A)
OCR2A = 0;
#endif
break;
#if defined(TIMSK3) && defined(OCIE3A)
case 3:
bitWrite(TIMSK3, OCIE3A, 0);
break;
#endif
#if defined(TIMSK4) && defined(OCIE4A)
case 4:
bitWrite(TIMSK4, OCIE4A, 0);
break;
#endif
#if defined(TIMSK5) && defined(OCIE5A)
case 5:
bitWrite(TIMSK5, OCIE5A, 0);
break;
#endif
}
}
void noTone(uint8_t _pin)
{
int8_t _timer = -1;
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
tone_pins[i] = 255;
break;
}
}
disableTimer(_timer);
digitalWrite(_pin, 0);
}
#ifdef USE_TIMER0
ISR(TIMER0_COMPA_vect)
{
if (timer0_toggle_count != 0)
{
// toggle the pin
*timer0_pin_port ^= timer0_pin_mask;
if (timer0_toggle_count > 0)
timer0_toggle_count--;
}
else
{
disableTimer(0);
*timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER1
ISR(TIMER1_COMPA_vect)
{
if (timer1_toggle_count != 0)
{
// toggle the pin
*timer1_pin_port ^= timer1_pin_mask;
if (timer1_toggle_count > 0)
timer1_toggle_count--;
}
else
{
disableTimer(1);
*timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER2
ISR(TIMER2_COMPA_vect)
{
if (timer2_toggle_count != 0)
{
// toggle the pin
*timer2_pin_port ^= timer2_pin_mask;
if (timer2_toggle_count > 0)
timer2_toggle_count--;
}
else
{
// need to call noTone() so that the tone_pins[] entry is reset, so the
// timer gets initialized next time we call tone().
// XXX: this assumes timer 2 is always the first one used.
noTone(tone_pins[0]);
// disableTimer(2);
// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER3
ISR(TIMER3_COMPA_vect)
{
if (timer3_toggle_count != 0)
{
// toggle the pin
*timer3_pin_port ^= timer3_pin_mask;
if (timer3_toggle_count > 0)
timer3_toggle_count--;
}
else
{
disableTimer(3);
*timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER4
ISR(TIMER4_COMPA_vect)
{
if (timer4_toggle_count != 0)
{
// toggle the pin
*timer4_pin_port ^= timer4_pin_mask;
if (timer4_toggle_count > 0)
timer4_toggle_count--;
}
else
{
disableTimer(4);
*timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER5
ISR(TIMER5_COMPA_vect)
{
if (timer5_toggle_count != 0)
{
// toggle the pin
*timer5_pin_port ^= timer5_pin_mask;
if (timer5_toggle_count > 0)
timer5_toggle_count--;
}
else
{
disableTimer(5);
*timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop
}
}
#endif

@ -0,0 +1,324 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.uniandes.edu.co
Copyright (c) 2004-05 Hernando Barragan
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
Modified 24 November 2006 by David A. Mellis
Modified 1 August 2010 by Mark Sproul
*/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "wiring_private.h"
static void nothing(void) {
}
static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
#if EXTERNAL_NUM_INTERRUPTS > 8
#warning There are more than 8 external interrupts. Some callbacks may not be initialized.
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 7
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 6
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 5
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 4
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 3
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 2
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 1
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 0
nothing,
#endif
};
// volatile static voidFuncPtr twiIntFunc;
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
intFunc[interruptNum] = userFunc;
// Configure the interrupt mode (trigger on low input, any change, rising
// edge, or falling edge). The mode constants were chosen to correspond
// to the configuration bits in the hardware register, so we simply shift
// the mode into place.
// Enable the interrupt.
switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
// I hate doing this, but the register assignment differs between the 1280/2560
// and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
// even present on the 32U4 this is the only way to distinguish between them.
case 0:
EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
EIMSK |= (1<<INT0);
break;
case 1:
EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
EIMSK |= (1<<INT1);
break;
case 2:
EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
EIMSK |= (1<<INT2);
break;
case 3:
EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
EIMSK |= (1<<INT3);
break;
case 4:
EICRB = (EICRB & ~((1<<ISC60) | (1<<ISC61))) | (mode << ISC60);
EIMSK |= (1<<INT6);
break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
break;
case 3:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
break;
case 4:
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
break;
case 5:
EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
EIMSK |= (1 << INT3);
break;
case 0:
EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
EIMSK |= (1 << INT4);
break;
case 1:
EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
EIMSK |= (1 << INT5);
break;
case 6:
EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
EIMSK |= (1 << INT6);
break;
case 7:
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
EIMSK |= (1 << INT7);
break;
#else
case 0:
#if defined(EICRA) && defined(ISC00) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
#elif defined(MCUCR) && defined(ISC00) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
GICR |= (1 << INT0);
#elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
GIMSK |= (1 << INT0);
#else
#error attachInterrupt not finished for this CPU (case 0)
#endif
break;
case 1:
#if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
#elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
GICR |= (1 << INT1);
#elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
GIMSK |= (1 << INT1);
#else
#warning attachInterrupt may need some more work for this cpu (case 1)
#endif
break;
case 2:
#if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
#elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
GICR |= (1 << INT2);
#elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
GIMSK |= (1 << INT2);
#endif
break;
#endif
}
}
}
void detachInterrupt(uint8_t interruptNum) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
// Disable the interrupt. (We can't assume that interruptNum is equal
// to the number of the EIMSK bit to clear, as this isn't true on the
// ATmega8. There, INT0 is 6 and INT1 is 7.)
switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
case 0:
EIMSK &= ~(1<<INT0);
break;
case 1:
EIMSK &= ~(1<<INT1);
break;
case 2:
EIMSK &= ~(1<<INT2);
break;
case 3:
EIMSK &= ~(1<<INT3);
break;
case 4:
EIMSK &= ~(1<<INT6);
break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EIMSK &= ~(1 << INT0);
break;
case 3:
EIMSK &= ~(1 << INT1);
break;
case 4:
EIMSK &= ~(1 << INT2);
break;
case 5:
EIMSK &= ~(1 << INT3);
break;
case 0:
EIMSK &= ~(1 << INT4);
break;
case 1:
EIMSK &= ~(1 << INT5);
break;
case 6:
EIMSK &= ~(1 << INT6);
break;
case 7:
EIMSK &= ~(1 << INT7);
break;
#else
case 0:
#if defined(EIMSK) && defined(INT0)
EIMSK &= ~(1 << INT0);
#elif defined(GICR) && defined(ISC00)
GICR &= ~(1 << INT0); // atmega32
#elif defined(GIMSK) && defined(INT0)
GIMSK &= ~(1 << INT0);
#else
#error detachInterrupt not finished for this cpu
#endif
break;
case 1:
#if defined(EIMSK) && defined(INT1)
EIMSK &= ~(1 << INT1);
#elif defined(GICR) && defined(INT1)
GICR &= ~(1 << INT1); // atmega32
#elif defined(GIMSK) && defined(INT1)
GIMSK &= ~(1 << INT1);
#else
#warning detachInterrupt may need some more work for this cpu (case 1)
#endif
break;
case 2:
#if defined(EIMSK) && defined(INT2)
EIMSK &= ~(1 << INT2);
#elif defined(GICR) && defined(INT2)
GICR &= ~(1 << INT2); // atmega32
#elif defined(GIMSK) && defined(INT2)
GIMSK &= ~(1 << INT2);
#elif defined(INT2)
#warning detachInterrupt may need some more work for this cpu (case 2)
#endif
break;
#endif
}
intFunc[interruptNum] = nothing;
}
}
/*
void attachInterruptTwi(void (*userFunc)(void) ) {
twiIntFunc = userFunc;
}
*/
#define IMPLEMENT_ISR(vect, interrupt) \
ISR(vect) { \
intFunc[interrupt](); \
}
#if defined(__AVR_ATmega32U4__)
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_3)
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_4)
#elif defined(EICRA) && defined(EICRB)
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_2)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_3)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_4)
IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_5)
IMPLEMENT_ISR(INT4_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT5_vect, EXTERNAL_INT_1)
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
#else
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
#if defined(EICRA) && defined(ISC20)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
#endif
#endif
/*
ISR(TWI_vect) {
if(twiIntFunc)
twiIntFunc();
}
*/

@ -0,0 +1,58 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-06 Hernando Barragan
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
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
*/
extern "C" {
#include "stdlib.h"
}
void randomSeed(unsigned long seed)
{
if (seed != 0) {
srandom(seed);
}
}
long random(long howbig)
{
if (howbig == 0) {
return 0;
}
return random() % howbig;
}
long random(long howsmall, long howbig)
{
if (howsmall >= howbig) {
return howsmall;
}
long diff = howbig - howsmall;
return random(diff) + howsmall;
}
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
unsigned int makeWord(unsigned int w) { return w; }
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }

@ -0,0 +1,750 @@
/*
WString.cpp - String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.com
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "WString.h"
/*********************************************/
/* Constructors */
/*********************************************/
String::String(const char *cstr)
{
init();
if (cstr) copy(cstr, strlen(cstr));
}
String::String(const String &value)
{
init();
*this = value;
}
String::String(const __FlashStringHelper *pstr)
{
init();
*this = pstr;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String::String(String &&rval)
{
init();
move(rval);
}
String::String(StringSumHelper &&rval)
{
init();
move(rval);
}
#endif
String::String(char c)
{
init();
char buf[2];
buf[0] = c;
buf[1] = 0;
*this = buf;
}
String::String(unsigned char value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned char)];
utoa(value, buf, base);
*this = buf;
}
String::String(int value, unsigned char base)
{
init();
char buf[2 + 8 * sizeof(int)];
itoa(value, buf, base);
*this = buf;
}
String::String(unsigned int value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned int)];
utoa(value, buf, base);
*this = buf;
}
String::String(long value, unsigned char base)
{
init();
char buf[2 + 8 * sizeof(long)];
ltoa(value, buf, base);
*this = buf;
}
String::String(unsigned long value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned long)];
ultoa(value, buf, base);
*this = buf;
}
String::String(float value, unsigned char decimalPlaces)
{
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::String(double value, unsigned char decimalPlaces)
{
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::~String()
{
free(buffer);
}
/*********************************************/
/* Memory Management */
/*********************************************/
inline void String::init(void)
{
buffer = NULL;
capacity = 0;
len = 0;
}
void String::invalidate(void)
{
if (buffer) free(buffer);
buffer = NULL;
capacity = len = 0;
}
unsigned char String::reserve(unsigned int size)
{
if (buffer && capacity >= size) return 1;
if (changeBuffer(size)) {
if (len == 0) buffer[0] = 0;
return 1;
}
return 0;
}
unsigned char String::changeBuffer(unsigned int maxStrLen)
{
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
if (newbuffer) {
buffer = newbuffer;
capacity = maxStrLen;
return 1;
}
return 0;
}
/*********************************************/
/* Copy and Move */
/*********************************************/
String & String::copy(const char *cstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
strcpy(buffer, cstr);
return *this;
}
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
strcpy_P(buffer, (PGM_P)pstr);
return *this;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
void String::move(String &rhs)
{
if (buffer) {
if (rhs && capacity >= rhs.len) {
strcpy(buffer, rhs.buffer);
len = rhs.len;
rhs.len = 0;
return;
} else {
free(buffer);
}
}
buffer = rhs.buffer;
capacity = rhs.capacity;
len = rhs.len;
rhs.buffer = NULL;
rhs.capacity = 0;
rhs.len = 0;
}
#endif
String & String::operator = (const String &rhs)
{
if (this == &rhs) return *this;
if (rhs.buffer) copy(rhs.buffer, rhs.len);
else invalidate();
return *this;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String & String::operator = (String &&rval)
{
if (this != &rval) move(rval);
return *this;
}
String & String::operator = (StringSumHelper &&rval)
{
if (this != &rval) move(rval);
return *this;
}
#endif
String & String::operator = (const char *cstr)
{
if (cstr) copy(cstr, strlen(cstr));
else invalidate();
return *this;
}
String & String::operator = (const __FlashStringHelper *pstr)
{
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
else invalidate();
return *this;
}
/*********************************************/
/* concat */
/*********************************************/
unsigned char String::concat(const String &s)
{
return concat(s.buffer, s.len);
}
unsigned char String::concat(const char *cstr, unsigned int length)
{
unsigned int newlen = len + length;
if (!cstr) return 0;
if (length == 0) return 1;
if (!reserve(newlen)) return 0;
strcpy(buffer + len, cstr);
len = newlen;
return 1;
}
unsigned char String::concat(const char *cstr)
{
if (!cstr) return 0;
return concat(cstr, strlen(cstr));
}
unsigned char String::concat(char c)
{
char buf[2];
buf[0] = c;
buf[1] = 0;
return concat(buf, 1);
}
unsigned char String::concat(unsigned char num)
{
char buf[1 + 3 * sizeof(unsigned char)];
itoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(int num)
{
char buf[2 + 3 * sizeof(int)];
itoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned int num)
{
char buf[1 + 3 * sizeof(unsigned int)];
utoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(long num)
{
char buf[2 + 3 * sizeof(long)];
ltoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned long num)
{
char buf[1 + 3 * sizeof(unsigned long)];
ultoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(float num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(double num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(const __FlashStringHelper * str)
{
if (!str) return 0;
int length = strlen_P((const char *) str);
if (length == 0) return 1;
unsigned int newlen = len + length;
if (!reserve(newlen)) return 0;
strcpy_P(buffer + len, (const char *) str);
len = newlen;
return 1;
}
/*********************************************/
/* Concatenate */
/*********************************************/
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(c)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs)) a.invalidate();
return a;
}
/*********************************************/
/* Comparison */
/*********************************************/
int String::compareTo(const String &s) const
{
if (!buffer || !s.buffer) {
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
if (buffer && len > 0) return *(unsigned char *)buffer;
return 0;
}
return strcmp(buffer, s.buffer);
}
unsigned char String::equals(const String &s2) const
{
return (len == s2.len && compareTo(s2) == 0);
}
unsigned char String::equals(const char *cstr) const
{
if (len == 0) return (cstr == NULL || *cstr == 0);
if (cstr == NULL) return buffer[0] == 0;
return strcmp(buffer, cstr) == 0;
}
unsigned char String::operator<(const String &rhs) const
{
return compareTo(rhs) < 0;
}
unsigned char String::operator>(const String &rhs) const
{
return compareTo(rhs) > 0;
}
unsigned char String::operator<=(const String &rhs) const
{
return compareTo(rhs) <= 0;
}
unsigned char String::operator>=(const String &rhs) const
{
return compareTo(rhs) >= 0;
}
unsigned char String::equalsIgnoreCase( const String &s2 ) const
{
if (this == &s2) return 1;
if (len != s2.len) return 0;
if (len == 0) return 1;
const char *p1 = buffer;
const char *p2 = s2.buffer;
while (*p1) {
if (tolower(*p1++) != tolower(*p2++)) return 0;
}
return 1;
}
unsigned char String::startsWith( const String &s2 ) const
{
if (len < s2.len) return 0;
return startsWith(s2, 0);
}
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
{
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
}
unsigned char String::endsWith( const String &s2 ) const
{
if ( len < s2.len || !buffer || !s2.buffer) return 0;
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
}
/*********************************************/
/* Character Access */
/*********************************************/
char String::charAt(unsigned int loc) const
{
return operator[](loc);
}
void String::setCharAt(unsigned int loc, char c)
{
if (loc < len) buffer[loc] = c;
}
char & String::operator[](unsigned int index)
{
static char dummy_writable_char;
if (index >= len || !buffer) {
dummy_writable_char = 0;
return dummy_writable_char;
}
return buffer[index];
}
char String::operator[]( unsigned int index ) const
{
if (index >= len || !buffer) return 0;
return buffer[index];
}
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
{
if (!bufsize || !buf) return;
if (index >= len) {
buf[0] = 0;
return;
}
unsigned int n = bufsize - 1;
if (n > len - index) n = len - index;
strncpy((char *)buf, buffer + index, n);
buf[n] = 0;
}
/*********************************************/
/* Search */
/*********************************************/
int String::indexOf(char c) const
{
return indexOf(c, 0);
}
int String::indexOf( char ch, unsigned int fromIndex ) const
{
if (fromIndex >= len) return -1;
const char* temp = strchr(buffer + fromIndex, ch);
if (temp == NULL) return -1;
return temp - buffer;
}
int String::indexOf(const String &s2) const
{
return indexOf(s2, 0);
}
int String::indexOf(const String &s2, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
const char *found = strstr(buffer + fromIndex, s2.buffer);
if (found == NULL) return -1;
return found - buffer;
}
int String::lastIndexOf( char theChar ) const
{
return lastIndexOf(theChar, len - 1);
}
int String::lastIndexOf(char ch, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
char tempchar = buffer[fromIndex + 1];
buffer[fromIndex + 1] = '\0';
char* temp = strrchr( buffer, ch );
buffer[fromIndex + 1] = tempchar;
if (temp == NULL) return -1;
return temp - buffer;
}
int String::lastIndexOf(const String &s2) const
{
return lastIndexOf(s2, len - s2.len);
}
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
{
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
if (fromIndex >= len) fromIndex = len - 1;
int found = -1;
for (char *p = buffer; p <= buffer + fromIndex; p++) {
p = strstr(p, s2.buffer);
if (!p) break;
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
}
return found;
}
String String::substring(unsigned int left, unsigned int right) const
{
if (left > right) {
unsigned int temp = right;
right = left;
left = temp;
}
String out;
if (left >= len) return out;
if (right > len) right = len;
char temp = buffer[right]; // save the replaced character
buffer[right] = '\0';
out = buffer + left; // pointer arithmetic
buffer[right] = temp; //restore character
return out;
}
/*********************************************/
/* Modification */
/*********************************************/
void String::replace(char find, char replace)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
if (*p == find) *p = replace;
}
}
void String::replace(const String& find, const String& replace)
{
if (len == 0 || find.len == 0) return;
int diff = replace.len - find.len;
char *readFrom = buffer;
char *foundAt;
if (diff == 0) {
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
memcpy(foundAt, replace.buffer, replace.len);
readFrom = foundAt + replace.len;
}
} else if (diff < 0) {
char *writeTo = buffer;
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
unsigned int n = foundAt - readFrom;
memcpy(writeTo, readFrom, n);
writeTo += n;
memcpy(writeTo, replace.buffer, replace.len);
writeTo += replace.len;
readFrom = foundAt + find.len;
len += diff;
}
strcpy(writeTo, readFrom);
} else {
unsigned int size = len; // compute size needed for result
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
readFrom = foundAt + find.len;
size += diff;
}
if (size == len) return;
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
int index = len - 1;
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = buffer + index + find.len;
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
len += diff;
buffer[len] = 0;
memcpy(buffer + index, replace.buffer, replace.len);
index--;
}
}
}
void String::remove(unsigned int index){
// Pass the biggest integer as the count. The remove method
// below will take care of truncating it at the end of the
// string.
remove(index, (unsigned int)-1);
}
void String::remove(unsigned int index, unsigned int count){
if (index >= len) { return; }
if (count <= 0) { return; }
if (count > len - index) { count = len - index; }
char *writeTo = buffer + index;
len = len - count;
strncpy(writeTo, buffer + index + count,len - index);
buffer[len] = 0;
}
void String::toLowerCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = tolower(*p);
}
}
void String::toUpperCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = toupper(*p);
}
}
void String::trim(void)
{
if (!buffer || len == 0) return;
char *begin = buffer;
while (isspace(*begin)) begin++;
char *end = buffer + len - 1;
while (isspace(*end) && end >= begin) end--;
len = end + 1 - begin;
if (begin > buffer) memcpy(buffer, begin, len);
buffer[len] = 0;
}
/*********************************************/
/* Parsing / Conversion */
/*********************************************/
long String::toInt(void) const
{
if (buffer) return atol(buffer);
return 0;
}
float String::toFloat(void) const
{
return float(toDouble());
}
double String::toDouble(void) const
{
if (buffer) return atof(buffer);
return 0;
}

@ -0,0 +1,31 @@
/*
Copyright (c) 2012 Arduino. All right reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Empty yield() hook.
*
* This function is intended to be used by library writers to build
* libraries or sketches that supports cooperative threads.
*
* Its defined as a weak symbol and it can be redefined to implement a
* real cooperative scheduler.
*/
static void __empty() {
// Empty
}
void yield(void) __attribute__ ((weak, alias("__empty")));

@ -0,0 +1,52 @@
/*
main.cpp - Main loop for Arduino sketches
Copyright (c) 2005-2013 Arduino Team. All right reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )()) { return 0; }
// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }
void setupUSB() __attribute__((weak));
void setupUSB() { }
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}

@ -0,0 +1,392 @@
/*
wiring.c - Partial implementation of the Wiring API for the ATmega8.
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
*/
#include "wiring_private.h"
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
unsigned long micros() {
unsigned long m;
uint8_t oldSREG = SREG, t;
cli();
m = timer0_overflow_count;
#if defined(TCNT0)
t = TCNT0;
#elif defined(TCNT0L)
t = TCNT0L;
#else
#error TIMER 0 not defined
#endif
#ifdef TIFR0
if ((TIFR0 & _BV(TOV0)) && (t < 255))
m++;
#else
if ((TIFR & _BV(TOV0)) && (t < 255))
m++;
#endif
SREG = oldSREG;
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}
void delay(unsigned long ms)
{
uint32_t start = micros();
while (ms > 0) {
yield();
while ( ms > 0 && (micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
void delayMicroseconds(unsigned int us)
{
// call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable)
// calling avrlib's delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
//delay_us(us);
#if F_CPU >= 24000000L
// for the 24 MHz clock for the aventurous ones, trying to overclock
// zero delay fix
if (!us) return; // = 3 cycles, (4 when true)
// the following loop takes a 1/6 of a microsecond (4 cycles)
// per iteration, so execute it six times for each microsecond of
// delay requested.
us *= 6; // x6 us, = 7 cycles
// account for the time taken in the preceeding commands.
// we just burned 22 (24) cycles above, remove 5, (5*4=20)
// us is at least 6 so we can substract 5
us -= 5; //=2 cycles
#elif F_CPU >= 20000000L
// for the 20 MHz clock on rare Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call takes 18 (20) cycles, which is 1us
__asm__ __volatile__ (
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop"); //just waiting 4 cycles
if (us <= 1) return; // = 3 cycles, (4 when true)
// the following loop takes a 1/5 of a microsecond (4 cycles)
// per iteration, so execute it five times for each microsecond of
// delay requested.
us = (us << 2) + us; // x5 us, = 7 cycles
// account for the time taken in the preceeding commands.
// we just burned 26 (28) cycles above, remove 7, (7*4=28)
// us is at least 10 so we can substract 7
us -= 7; // 2 cycles
#elif F_CPU >= 16000000L
// for the 16 MHz clock on most Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call takes 14 (16) cycles, which is 1us
if (us <= 1) return; // = 3 cycles, (4 when true)
// the following loop takes 1/4 of a microsecond (4 cycles)
// per iteration, so execute it four times for each microsecond of
// delay requested.
us <<= 2; // x4 us, = 4 cycles
// account for the time taken in the preceeding commands.
// we just burned 19 (21) cycles above, remove 5, (5*4=20)
// us is at least 8 so we can substract 5
us -= 5; // = 2 cycles,
#elif F_CPU >= 12000000L
// for the 12 MHz clock if somebody is working with USB
// for a 1 microsecond delay, simply return. the overhead
// of the function call takes 14 (16) cycles, which is 1.5us
if (us <= 1) return; // = 3 cycles, (4 when true)
// the following loop takes 1/3 of a microsecond (4 cycles)
// per iteration, so execute it three times for each microsecond of
// delay requested.
us = (us << 1) + us; // x3 us, = 5 cycles
// account for the time taken in the preceeding commands.
// we just burned 20 (22) cycles above, remove 5, (5*4=20)
// us is at least 6 so we can substract 5
us -= 5; //2 cycles
#elif F_CPU >= 8000000L
// for the 8 MHz internal clock
// for a 1 and 2 microsecond delay, simply return. the overhead
// of the function call takes 14 (16) cycles, which is 2us
if (us <= 2) return; // = 3 cycles, (4 when true)
// the following loop takes 1/2 of a microsecond (4 cycles)
// per iteration, so execute it twice for each microsecond of
// delay requested.
us <<= 1; //x2 us, = 2 cycles
// account for the time taken in the preceeding commands.
// we just burned 17 (19) cycles above, remove 4, (4*4=16)
// us is at least 6 so we can substract 4
us -= 4; // = 2 cycles
#else
// for the 1 MHz internal clock (default settings for common Atmega microcontrollers)
// the overhead of the function calls is 14 (16) cycles
if (us <= 16) return; //= 3 cycles, (4 when true)
if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22)
// compensate for the time taken by the preceeding and next commands (about 22 cycles)
us -= 22; // = 2 cycles
// the following loop takes 4 microseconds (4 cycles)
// per iteration, so execute it us/4 times
// us is at least 4, divided by 4 gives us 1 (no zero delay bug)
us >>= 2; // us div 4, = 4 cycles
#endif
// busy wait
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
);
// return = 4 cycles
}
void init()
{
// this needs to be called before setup() or some functions won't
// work there
sei();
// on the ATmega168, timer 0 is also used for fast hardware pwm
// (using phase-correct PWM would mean that timer 0 overflowed half as often
// resulting in different millis() behavior on the ATmega8 and ATmega168)
#if defined(TCCR0A) && defined(WGM01)
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
#endif
// set timer 0 prescale factor to 64
#if defined(__AVR_ATmega128__)
// CPU specific: different values for the ATmega128
sbi(TCCR0, CS02);
#elif defined(TCCR0) && defined(CS01) && defined(CS00)
// this combination is for the standard atmega8
sbi(TCCR0, CS01);
sbi(TCCR0, CS00);
#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
// this combination is for the standard 168/328/1280/2560
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
#elif defined(TCCR0A) && defined(CS01) && defined(CS00)
// this combination is for the __AVR_ATmega645__ series
sbi(TCCR0A, CS01);
sbi(TCCR0A, CS00);
#else
#error Timer 0 prescale factor 64 not set correctly
#endif
// enable timer 0 overflow interrupt
#if defined(TIMSK) && defined(TOIE0)
sbi(TIMSK, TOIE0);
#elif defined(TIMSK0) && defined(TOIE0)
sbi(TIMSK0, TOIE0);
#else
#error Timer 0 overflow interrupt not set correctly
#endif
// timers 1 and 2 are used for phase-correct hardware pwm
// this is better for motors as it ensures an even waveform
// note, however, that fast pwm mode can achieve a frequency of up
// 8 MHz (with a 16 MHz clock) at 50% duty cycle
#if defined(TCCR1B) && defined(CS11) && defined(CS10)
TCCR1B = 0;
// set timer 1 prescale factor to 64
sbi(TCCR1B, CS11);
#if F_CPU >= 8000000L
sbi(TCCR1B, CS10);
#endif
#elif defined(TCCR1) && defined(CS11) && defined(CS10)
sbi(TCCR1, CS11);
#if F_CPU >= 8000000L
sbi(TCCR1, CS10);
#endif
#endif
// put timer 1 in 8-bit phase correct pwm mode
#if defined(TCCR1A) && defined(WGM10)
sbi(TCCR1A, WGM10);
#endif
// set timer 2 prescale factor to 64
#if defined(TCCR2) && defined(CS22)
sbi(TCCR2, CS22);
#elif defined(TCCR2B) && defined(CS22)
sbi(TCCR2B, CS22);
//#else
// Timer 2 not finished (may not be present on this CPU)
#endif
// configure timer 2 for phase correct pwm (8-bit)
#if defined(TCCR2) && defined(WGM20)
sbi(TCCR2, WGM20);
#elif defined(TCCR2A) && defined(WGM20)
sbi(TCCR2A, WGM20);
//#else
// Timer 2 not finished (may not be present on this CPU)
#endif
#if defined(TCCR3B) && defined(CS31) && defined(WGM30)
sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64
sbi(TCCR3B, CS30);
sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode
#endif
#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
sbi(TCCR4B, CS41);
sbi(TCCR4B, CS40);
sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64
sbi(TCCR4B, CS40);
sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode
#endif
#endif /* end timer4 block for ATMEGA1280/2560 and similar */
#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64
sbi(TCCR5B, CS50);
sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode
#endif
#if defined(ADCSRA)
// set a2d prescaler so we are inside the desired 50-200 KHz range.
#if F_CPU >= 16000000 // 16 MHz / 128 = 125 KHz
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#elif F_CPU >= 8000000 // 8 MHz / 64 = 125 KHz
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
#elif F_CPU >= 4000000 // 4 MHz / 32 = 125 KHz
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#elif F_CPU >= 2000000 // 2 MHz / 16 = 125 KHz
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
#elif F_CPU >= 1000000 // 1 MHz / 8 = 125 KHz
cbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#else // 128 kHz / 2 = 64 KHz -> This is the closest you can get, the prescaler is 2
cbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#endif
// enable a2d conversions
sbi(ADCSRA, ADEN);
#endif
// the bootloader connects pins 0 and 1 to the USART; disconnect them
// here so they can be used as normal digital i/o; they will be
// reconnected in Serial.begin()
#if defined(UCSRB)
UCSRB = 0;
#elif defined(UCSR0B)
UCSR0B = 0;
#endif
}

@ -0,0 +1,294 @@
/*
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
Modified 28 September 2010 by Mark Sproul
*/
#include "wiring_private.h"
#include "pins_arduino.h"
uint8_t analog_reference = DEFAULT;
void analogReference(uint8_t mode)
{
// can't actually set the register here because the default setting
// will connect AVCC and the AREF pin, which would cause a short if
// there's something connected to AREF.
analog_reference = mode;
}
int analogRead(uint8_t pin)
{
uint8_t low, high;
#if defined(analogPinToChannel)
#if defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#endif
pin = analogPinToChannel(pin);
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif
#if defined(ADCSRB) && defined(MUX5)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
#if defined(ADMUX)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = (analog_reference << 4) | (pin & 0x07);
#else
ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif
#endif
// without a delay, we seem to read from the wrong channel
//delay(1);
#if defined(ADCSRA) && defined(ADCL)
// 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;
#else
// we dont have an ADC, return 0
low = 0;
high = 0;
#endif
// 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(uint8_t 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 (val == 0)
{
digitalWrite(pin, LOW);
}
else if (val == 255)
{
digitalWrite(pin, HIGH);
}
else
{
switch(digitalPinToTimer(pin))
{
// XXX fix needed for atmega8
#if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__)
case TIMER0A:
// connect pwm to pin on timer 0
sbi(TCCR0, COM00);
OCR0 = val; // set pwm duty
break;
#endif
#if defined(TCCR0A) && defined(COM0A1)
case TIMER0A:
// connect pwm to pin on timer 0, channel A
sbi(TCCR0A, COM0A1);
OCR0A = val; // set pwm duty
break;
#endif
#if defined(TCCR0A) && defined(COM0B1)
case TIMER0B:
// connect pwm to pin on timer 0, channel B
sbi(TCCR0A, COM0B1);
OCR0B = val; // set pwm duty
break;
#endif
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A:
// connect pwm to pin on timer 1, channel A
sbi(TCCR1A, COM1A1);
OCR1A = val; // set pwm duty
break;
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B:
// connect pwm to pin on timer 1, channel B
sbi(TCCR1A, COM1B1);
OCR1B = val; // set pwm duty
break;
#endif
#if defined(TCCR1A) && defined(COM1C1)
case TIMER1C:
// connect pwm to pin on timer 1, channel B
sbi(TCCR1A, COM1C1);
OCR1C = val; // set pwm duty
break;
#endif
#if defined(TCCR2) && defined(COM21)
case TIMER2:
// connect pwm to pin on timer 2
sbi(TCCR2, COM21);
OCR2 = val; // set pwm duty
break;
#endif
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A:
// connect pwm to pin on timer 2, channel A
sbi(TCCR2A, COM2A1);
OCR2A = val; // set pwm duty
break;
#endif
#if defined(TCCR2A) && defined(COM2B1)
case TIMER2B:
// connect pwm to pin on timer 2, channel B
sbi(TCCR2A, COM2B1);
OCR2B = val; // set pwm duty
break;
#endif
#if defined(TCCR3A) && defined(COM3A1)
case TIMER3A:
// connect pwm to pin on timer 3, channel A
sbi(TCCR3A, COM3A1);
OCR3A = val; // set pwm duty
break;
#endif
#if defined(TCCR3A) && defined(COM3B1)
case TIMER3B:
// connect pwm to pin on timer 3, channel B
sbi(TCCR3A, COM3B1);
OCR3B = val; // set pwm duty
break;
#endif
#if defined(TCCR3A) && defined(COM3C1)
case TIMER3C:
// connect pwm to pin on timer 3, channel C
sbi(TCCR3A, COM3C1);
OCR3C = val; // set pwm duty
break;
#endif
#if defined(TCCR4A)
case TIMER4A:
//connect pwm to pin on timer 4, channel A
sbi(TCCR4A, COM4A1);
#if defined(COM4A0) // only used on 32U4
cbi(TCCR4A, COM4A0);
#endif
OCR4A = val; // set pwm duty
break;
#endif
#if defined(TCCR4A) && defined(COM4B1)
case TIMER4B:
// connect pwm to pin on timer 4, channel B
sbi(TCCR4A, COM4B1);
OCR4B = val; // set pwm duty
break;
#endif
#if defined(TCCR4A) && defined(COM4C1)
case TIMER4C:
// connect pwm to pin on timer 4, channel C
sbi(TCCR4A, COM4C1);
OCR4C = val; // set pwm duty
break;
#endif
#if defined(TCCR4C) && defined(COM4D1)
case TIMER4D:
// connect pwm to pin on timer 4, channel D
sbi(TCCR4C, COM4D1);
#if defined(COM4D0) // only used on 32U4
cbi(TCCR4C, COM4D0);
#endif
OCR4D = val; // set pwm duty
break;
#endif
#if defined(TCCR5A) && defined(COM5A1)
case TIMER5A:
// connect pwm to pin on timer 5, channel A
sbi(TCCR5A, COM5A1);
OCR5A = val; // set pwm duty
break;
#endif
#if defined(TCCR5A) && defined(COM5B1)
case TIMER5B:
// connect pwm to pin on timer 5, channel B
sbi(TCCR5A, COM5B1);
OCR5B = val; // set pwm duty
break;
#endif
#if defined(TCCR5A) && defined(COM5C1)
case TIMER5C:
// connect pwm to pin on timer 5, channel C
sbi(TCCR5A, COM5C1);
OCR5C = val; // set pwm duty
break;
#endif
case NOT_ON_TIMER:
default:
if (val < 128) {
digitalWrite(pin, LOW);
} else {
digitalWrite(pin, HIGH);
}
}
}
}

@ -0,0 +1,179 @@
/*
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
Modified 28 September 2010 by Mark Sproul
*/
#define ARDUINO_MAIN
#include "wiring_private.h"
#include "pins_arduino.h"
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg, *out;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
out = portOutputRegister(port);
if (mode == INPUT) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out &= ~bit;
SREG = oldSREG;
} else if (mode == INPUT_PULLUP) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out |= bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
cli();
*reg |= bit;
SREG = oldSREG;
}
}
// Forcing this inline keeps the callers from having to push their own stuff
// on the stack. It is a good performance win and only takes 1 more byte per
// user than calling. (It will take more bytes on the 168.)
//
// But shouldn't this be moved into pinMode? Seems silly to check and do on
// each digitalread or write.
//
// Mark Sproul:
// - Removed inline. Save 170 bytes on atmega1280
// - changed to a switch statment; added 32 bytes but much easier to read and maintain.
// - Added more #ifdefs, now compiles for atmega645
//
//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
//static inline void turnOffPWM(uint8_t timer)
static void turnOffPWM(uint8_t timer)
{
switch (timer)
{
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A: cbi(TCCR1A, COM1A1); break;
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B: cbi(TCCR1A, COM1B1); break;
#endif
#if defined(TCCR1A) && defined(COM1C1)
case TIMER1C: cbi(TCCR1A, COM1C1); break;
#endif
#if defined(TCCR2) && defined(COM21)
case TIMER2: cbi(TCCR2, COM21); break;
#endif
#if defined(TCCR0A) && defined(COM0A1)
case TIMER0A: cbi(TCCR0A, COM0A1); break;
#endif
#if defined(TCCR0A) && defined(COM0B1)
case TIMER0B: cbi(TCCR0A, COM0B1); break;
#endif
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A: cbi(TCCR2A, COM2A1); break;
#endif
#if defined(TCCR2A) && defined(COM2B1)
case TIMER2B: cbi(TCCR2A, COM2B1); break;
#endif
#if defined(TCCR3A) && defined(COM3A1)
case TIMER3A: cbi(TCCR3A, COM3A1); break;
#endif
#if defined(TCCR3A) && defined(COM3B1)
case TIMER3B: cbi(TCCR3A, COM3B1); break;
#endif
#if defined(TCCR3A) && defined(COM3C1)
case TIMER3C: cbi(TCCR3A, COM3C1); break;
#endif
#if defined(TCCR4A) && defined(COM4A1)
case TIMER4A: cbi(TCCR4A, COM4A1); break;
#endif
#if defined(TCCR4A) && defined(COM4B1)
case TIMER4B: cbi(TCCR4A, COM4B1); break;
#endif
#if defined(TCCR4A) && defined(COM4C1)
case TIMER4C: cbi(TCCR4A, COM4C1); break;
#endif
#if defined(TCCR4C) && defined(COM4D1)
case TIMER4D: cbi(TCCR4C, COM4D1); break;
#endif
#if defined(TCCR5A)
case TIMER5A: cbi(TCCR5A, COM5A1); break;
case TIMER5B: cbi(TCCR5A, COM5B1); break;
case TIMER5C: cbi(TCCR5A, COM5C1); break;
#endif
}
}
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
}
int digitalRead(uint8_t pin)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return LOW;
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}

@ -0,0 +1,93 @@
/*
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
*/
#include "wiring_private.h"
#include "pins_arduino.h"
/* 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 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse.
*
* This function performs better with short pulses in noInterrupt() context
*/
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
// 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.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes approximately 16 clock cycles per iteration
unsigned long maxloops = microsecondsToClockCycles(timeout)/16;
unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops);
// prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out
if (width)
return clockCyclesToMicroseconds(width * 16 + 16);
else
return 0;
}
/* 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 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse.
*
* ATTENTION:
* this function relies on micros() so cannot be used in noInterrupt() context
*/
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)
{
// 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.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
unsigned long startMicros = micros();
// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
unsigned long start = micros();
// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
return micros() - start;
}

@ -0,0 +1,53 @@
/*
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
*/
#include "wiring_private.h"
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
digitalWrite(clockPin, HIGH);
if (bitOrder == LSBFIRST)
value |= digitalRead(dataPin) << i;
else
value |= digitalRead(dataPin) << (7 - i);
digitalWrite(clockPin, LOW);
}
return value;
}
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t 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);
}
}

@ -0,0 +1,201 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
* SPI Master library for arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#include "SPI.h"
SPIClass SPI;
uint8_t SPIClass::initialized = 0;
uint8_t SPIClass::interruptMode = 0;
uint8_t SPIClass::interruptMask = 0;
uint8_t SPIClass::interruptSave = 0;
#ifdef SPI_TRANSACTION_MISMATCH_LED
uint8_t SPIClass::inTransactionFlag = 0;
#endif
void SPIClass::begin()
{
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
if (!initialized) {
// Set SS to high so a connected chip will be "deselected" by default
uint8_t port = digitalPinToPort(SS);
uint8_t bit = digitalPinToBitMask(SS);
volatile uint8_t *reg = portModeRegister(port);
// if the SS pin is not already configured as an output
// then set it high (to enable the internal pull-up resistor)
if(!(*reg & bit)){
digitalWrite(SS, HIGH);
}
// When the SS pin is set as OUTPUT, it can be used as
// a general purpose output port (it doesn't influence
// SPI operations).
pinMode(SS, OUTPUT);
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
// automatically switches to Slave, so the data direction of
// the SS pin MUST be kept as OUTPUT.
SPCR |= _BV(MSTR);
SPCR |= _BV(SPE);
// Set direction register for SCK and MOSI pin.
// MISO pin automatically overrides to INPUT.
// By doing this AFTER enabling SPI, we avoid accidentally
// clocking in a single bit since the lines go directly
// from "input" to SPI control.
// http://code.google.com/p/arduino/issues/detail?id=888
pinMode(SCK, OUTPUT);
pinMode(MOSI, OUTPUT);
}
initialized++; // reference count
SREG = sreg;
}
void SPIClass::end() {
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
// Decrease the reference counter
if (initialized)
initialized--;
// If there are no more references disable SPI
if (!initialized) {
SPCR &= ~_BV(SPE);
interruptMode = 0;
#ifdef SPI_TRANSACTION_MISMATCH_LED
inTransactionFlag = 0;
#endif
}
SREG = sreg;
}
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
#if defined(__AVR_ATmega32U4__)
#define SPI_INT0_MASK (1<<INT0)
#define SPI_INT1_MASK (1<<INT1)
#define SPI_INT2_MASK (1<<INT2)
#define SPI_INT3_MASK (1<<INT3)
#define SPI_INT4_MASK (1<<INT6)
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#define SPI_INT0_MASK (1<<INT0)
#define SPI_INT1_MASK (1<<INT1)
#define SPI_INT2_MASK (1<<INT2)
#define SPI_INT3_MASK (1<<INT3)
#define SPI_INT4_MASK (1<<INT4)
#define SPI_INT5_MASK (1<<INT5)
#define SPI_INT6_MASK (1<<INT6)
#define SPI_INT7_MASK (1<<INT7)
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
#define SPI_INT0_MASK (1<<INT4)
#define SPI_INT1_MASK (1<<INT5)
#define SPI_INT2_MASK (1<<INT0)
#define SPI_INT3_MASK (1<<INT1)
#define SPI_INT4_MASK (1<<INT2)
#define SPI_INT5_MASK (1<<INT3)
#define SPI_INT6_MASK (1<<INT6)
#define SPI_INT7_MASK (1<<INT7)
#else
#ifdef INT0
#define SPI_INT0_MASK (1<<INT0)
#endif
#ifdef INT1
#define SPI_INT1_MASK (1<<INT1)
#endif
#ifdef INT2
#define SPI_INT2_MASK (1<<INT2)
#endif
#endif
void SPIClass::usingInterrupt(uint8_t interruptNumber)
{
uint8_t mask = 0;
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
switch (interruptNumber) {
#ifdef SPI_INT0_MASK
case 0: mask = SPI_INT0_MASK; break;
#endif
#ifdef SPI_INT1_MASK
case 1: mask = SPI_INT1_MASK; break;
#endif
#ifdef SPI_INT2_MASK
case 2: mask = SPI_INT2_MASK; break;
#endif
#ifdef SPI_INT3_MASK
case 3: mask = SPI_INT3_MASK; break;
#endif
#ifdef SPI_INT4_MASK
case 4: mask = SPI_INT4_MASK; break;
#endif
#ifdef SPI_INT5_MASK
case 5: mask = SPI_INT5_MASK; break;
#endif
#ifdef SPI_INT6_MASK
case 6: mask = SPI_INT6_MASK; break;
#endif
#ifdef SPI_INT7_MASK
case 7: mask = SPI_INT7_MASK; break;
#endif
default:
interruptMode = 2;
break;
}
interruptMask |= mask;
if (!interruptMode)
interruptMode = 1;
SREG = sreg;
}
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
{
// Once in mode 2 we can't go back to 0 without a proper reference count
if (interruptMode == 2)
return;
uint8_t mask = 0;
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
switch (interruptNumber) {
#ifdef SPI_INT0_MASK
case 0: mask = SPI_INT0_MASK; break;
#endif
#ifdef SPI_INT1_MASK
case 1: mask = SPI_INT1_MASK; break;
#endif
#ifdef SPI_INT2_MASK
case 2: mask = SPI_INT2_MASK; break;
#endif
#ifdef SPI_INT3_MASK
case 3: mask = SPI_INT3_MASK; break;
#endif
#ifdef SPI_INT4_MASK
case 4: mask = SPI_INT4_MASK; break;
#endif
#ifdef SPI_INT5_MASK
case 5: mask = SPI_INT5_MASK; break;
#endif
#ifdef SPI_INT6_MASK
case 6: mask = SPI_INT6_MASK; break;
#endif
#ifdef SPI_INT7_MASK
case 7: mask = SPI_INT7_MASK; break;
#endif
default:
break;
// this case can't be reached
}
interruptMask &= ~mask;
if (!interruptMask)
interruptMode = 0;
SREG = sreg;
}

@ -0,0 +1,326 @@
#include "LiquidCrystal.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "Arduino.h"
// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
// DL = 1; 8-bit interface data
// N = 0; 1-line display
// F = 0; 5x8 dot character font
// 3. Display on/off control:
// D = 0; Display off
// C = 0; Cursor off
// B = 0; Blinking off
// 4. Entry mode set:
// I/D = 1; Increment by 1
// S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7);
}
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
init(0, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7);
}
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
{
init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
}
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
{
init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0);
}
void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
_rs_pin = rs;
_rw_pin = rw;
_enable_pin = enable;
_data_pins[0] = d0;
_data_pins[1] = d1;
_data_pins[2] = d2;
_data_pins[3] = d3;
_data_pins[4] = d4;
_data_pins[5] = d5;
_data_pins[6] = d6;
_data_pins[7] = d7;
if (fourbitmode)
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
else
_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin(16, 1);
}
void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = lines;
setRowOffsets(0x00, 0x40, 0x00 + cols, 0x40 + cols);
// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != LCD_5x8DOTS) && (lines == 1)) {
_displayfunction |= LCD_5x10DOTS;
}
pinMode(_rs_pin, OUTPUT);
// we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
if (_rw_pin != 255) {
pinMode(_rw_pin, OUTPUT);
}
pinMode(_enable_pin, OUTPUT);
// Do these once, instead of every time a character is drawn for speed reasons.
for (int i=0; i<((_displayfunction & LCD_8BITMODE) ? 8 : 4); ++i)
{
pinMode(_data_pins[i], OUTPUT);
}
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
delayMicroseconds(50000);
// Now we pull both RS and R/W low to begin commands
digitalWrite(_rs_pin, LOW);
digitalWrite(_enable_pin, LOW);
if (_rw_pin != 255) {
digitalWrite(_rw_pin, LOW);
}
//put the LCD into 4 bit or 8 bit mode
if (! (_displayfunction & LCD_8BITMODE)) {
// this is according to the hitachi HD44780 datasheet
// figure 24, pg 46
// we start in 8bit mode, try to set 4 bit mode
write4bits(0x03);
delayMicroseconds(4500); // wait min 4.1ms
// second try
write4bits(0x03);
delayMicroseconds(4500); // wait min 4.1ms
// third go!
write4bits(0x03);
delayMicroseconds(150);
// finally, set to 4-bit interface
write4bits(0x02);
} else {
// this is according to the hitachi HD44780 datasheet
// page 45 figure 23
// Send function set command sequence
command(LCD_FUNCTIONSET | _displayfunction);
delayMicroseconds(4500); // wait more than 4.1ms
// second try
command(LCD_FUNCTIONSET | _displayfunction);
delayMicroseconds(150);
// third go
command(LCD_FUNCTIONSET | _displayfunction);
}
// finally, set # lines, font size, etc.
command(LCD_FUNCTIONSET | _displayfunction);
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
display();
// clear it off
clear();
// Initialize to default text direction (for romance languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
// set the entry mode
command(LCD_ENTRYMODESET | _displaymode);
}
void LiquidCrystal::setRowOffsets(int row0, int row1, int row2, int row3)
{
_row_offsets[0] = row0;
_row_offsets[1] = row1;
_row_offsets[2] = row2;
_row_offsets[3] = row3;
}
/********** high level commands, for the user! */
void LiquidCrystal::clear()
{
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal::home()
{
command(LCD_RETURNHOME); // set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal::setCursor(uint8_t col, uint8_t row)
{
const size_t max_lines = sizeof(_row_offsets) / sizeof(*_row_offsets);
if ( row >= max_lines ) {
row = max_lines - 1; // we count rows starting w/0
}
if ( row >= _numlines ) {
row = _numlines - 1; // we count rows starting w/0
}
command(LCD_SETDDRAMADDR | (col + _row_offsets[row]));
}
// Turn the display on/off (quickly)
void LiquidCrystal::noDisplay() {
_displaycontrol &= ~LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal::display() {
_displaycontrol |= LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void LiquidCrystal::noCursor() {
_displaycontrol &= ~LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal::cursor() {
_displaycontrol |= LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void LiquidCrystal::noBlink() {
_displaycontrol &= ~LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal::blink() {
_displaycontrol |= LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void LiquidCrystal::scrollDisplayLeft(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void LiquidCrystal::scrollDisplayRight(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
// This is for text that flows Left to Right
void LiquidCrystal::leftToRight(void) {
_displaymode |= LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void LiquidCrystal::rightToLeft(void) {
_displaymode &= ~LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void LiquidCrystal::autoscroll(void) {
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void LiquidCrystal::noAutoscroll(void) {
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(charmap[i]);
}
}
/*********** mid level commands, for sending data/cmds */
inline void LiquidCrystal::command(uint8_t value) {
send(value, LOW);
}
inline size_t LiquidCrystal::write(uint8_t value) {
send(value, HIGH);
return 1; // assume sucess
}
/************ low level data pushing commands **********/
// write either command or data, with automatic 4/8-bit selection
void LiquidCrystal::send(uint8_t value, uint8_t mode) {
digitalWrite(_rs_pin, mode);
// if there is a RW pin indicated, set it low to Write
if (_rw_pin != 255) {
digitalWrite(_rw_pin, LOW);
}
if (_displayfunction & LCD_8BITMODE) {
write8bits(value);
} else {
write4bits(value>>4);
write4bits(value);
}
}
void LiquidCrystal::pulseEnable(void) {
digitalWrite(_enable_pin, LOW);
delayMicroseconds(1);
digitalWrite(_enable_pin, HIGH);
delayMicroseconds(1); // enable pulse must be >450ns
digitalWrite(_enable_pin, LOW);
delayMicroseconds(100); // commands need > 37us to settle
}
void LiquidCrystal::write4bits(uint8_t value) {
for (int i = 0; i < 4; i++) {
digitalWrite(_data_pins[i], (value >> i) & 0x01);
}
pulseEnable();
}
void LiquidCrystal::write8bits(uint8_t value) {
for (int i = 0; i < 8; i++) {
digitalWrite(_data_pins[i], (value >> i) & 0x01);
}
pulseEnable();
}

@ -0,0 +1,177 @@
/*
u8g_bitmap.c
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
void u8g_DrawHBitmap(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, const uint8_t *bitmap)
{
while( cnt > 0 )
{
u8g_Draw8Pixel(u8g, x, y, 0, *bitmap);
bitmap++;
cnt--;
x+=8;
}
}
void u8g_DrawBitmap(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, u8g_uint_t h, const uint8_t *bitmap)
{
if ( u8g_IsBBXIntersection(u8g, x, y, cnt*8, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHBitmap(u8g, x, y, cnt, bitmap);
bitmap += cnt;
y++;
h--;
}
}
void u8g_DrawHBitmapP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, const u8g_pgm_uint8_t *bitmap)
{
while( cnt > 0 )
{
u8g_Draw8Pixel(u8g, x, y, 0, u8g_pgm_read(bitmap));
bitmap++;
cnt--;
x+=8;
}
}
void u8g_DrawBitmapP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, u8g_uint_t h, const u8g_pgm_uint8_t *bitmap)
{
if ( u8g_IsBBXIntersection(u8g, x, y, cnt*8, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHBitmapP(u8g, x, y, cnt, bitmap);
bitmap += cnt;
y++;
h--;
}
}
/*=========================================================================*/
static void u8g_DrawHXBM(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, const uint8_t *bitmap)
{
uint8_t d;
x+=7;
while( w >= 8 )
{
u8g_Draw8Pixel(u8g, x, y, 2, *bitmap);
bitmap++;
w-= 8;
x+=8;
}
if ( w > 0 )
{
d = *bitmap;
x -= 7;
do
{
if ( d & 1 )
u8g_DrawPixel(u8g, x, y);
x++;
w--;
d >>= 1;
} while ( w > 0 );
}
}
void u8g_DrawXBM(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, const uint8_t *bitmap)
{
u8g_uint_t b;
b = w;
b += 7;
b >>= 3;
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHXBM(u8g, x, y, w, bitmap);
bitmap += b;
y++;
h--;
}
}
static void u8g_DrawHXBMP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, const u8g_pgm_uint8_t *bitmap)
{
uint8_t d;
x+=7;
while( w >= 8 )
{
u8g_Draw8Pixel(u8g, x, y, 2, u8g_pgm_read(bitmap));
bitmap++;
w-= 8;
x+=8;
}
if ( w > 0 )
{
d = u8g_pgm_read(bitmap);
x -= 7;
do
{
if ( d & 1 )
u8g_DrawPixel(u8g, x, y);
x++;
w--;
d >>= 1;
} while ( w > 0 );
}
}
void u8g_DrawXBMP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, const u8g_pgm_uint8_t *bitmap)
{
u8g_uint_t b;
b = w;
b += 7;
b >>= 3;
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHXBMP(u8g, x, y, w, bitmap);
bitmap += b;
y++;
h--;
}
}

@ -0,0 +1,156 @@
/*
u8g_clip.c
procedures for clipping
taken over from procs in u8g_pb.c
Universal 8bit Graphics Library
Copyright (c) 2012, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Notes
This is one of the most critical parts of u8glib. It must be fast, but still reliable.
Based on the intersection program (see tools folder), there is minimized version of
the condition for the intersaction test:
minimized version
---1----0 1 b1 <= a2 && b1 > b2
-----1--0 1 b2 >= a1 && b1 > b2
---1-1--- 1 b1 <= a2 && b2 >= a1
It includes the assumption, that a1 <= a2 is always true (correct, because
a1, a2 are the page dimensions.
The direct implementation of the above result is done in:
uint8_t u8g_is_intersection_boolean(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
However, this is slower than a decision tree version:
static uint8_t u8g_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
Also suprising is, that the macro implementation is slower than the inlined version.
The decision tree is based on the expansion of the truth table.
*/
#include "u8g.h"
#ifdef __GNUC__
#define U8G_ALWAYS_INLINE __inline__ __attribute__((always_inline))
#else
#define U8G_ALWAYS_INLINE
#endif
/*
intersection assumptions:
a1 <= a2 is always true
minimized version
---1----0 1 b1 <= a2 && b1 > b2
-----1--0 1 b2 >= a1 && b1 > b2
---1-1--- 1 b1 <= a2 && b2 >= a1
*/
#ifdef OLD_CODE_WHICH_IS_TOO_SLOW
static uint8_t u8g_is_intersection_boolean(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
{
uint8_t c1, c2, c3, tmp;
c1 = v0 <= a1;
c2 = v1 >= a0;
c3 = v0 > v1;
tmp = c1;
c1 &= c2;
c2 &= c3;
c3 &= tmp;
c1 |= c2;
c1 |= c3;
return c1 & 1;
}
#endif
#define U8G_IS_INTERSECTION_MACRO(a0,a1,v0,v1) ((uint8_t)( (v0) <= (a1) ) ? ( ( (v1) >= (a0) ) ? ( 1 ) : ( (v0) > (v1) ) ) : ( ( (v1) >= (a0) ) ? ( (v0) > (v1) ) : ( 0 ) ))
//static uint8_t u8g_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1) U8G_ALWAYS_INLINE;
static uint8_t U8G_ALWAYS_INLINE u8g_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
{
/* surprisingly the macro leads to larger code */
/* return U8G_IS_INTERSECTION_MACRO(a0,a1,v0,v1); */
if ( v0 <= a1 )
{
if ( v1 >= a0 )
{
return 1;
}
else
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
}
else
{
if ( v1 >= a0 )
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
uint8_t u8g_IsBBXIntersection(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
{
register u8g_uint_t tmp;
tmp = y;
tmp += h;
tmp--;
if ( u8g_is_intersection_decision_tree(u8g->current_page.y0, u8g->current_page.y1, y, tmp) == 0 )
return 0;
tmp = x;
tmp += w;
tmp--;
return u8g_is_intersection_decision_tree(u8g->current_page.x0, u8g->current_page.x1, x, tmp);
}

@ -0,0 +1,63 @@
/*
u8g_com_null.c
communication null device
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
uint8_t u8g_com_null_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
{
switch(msg)
{
case U8G_COM_MSG_INIT:
break;
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_CHIP_SELECT:
/* arg_val contains the chip number, which should be enabled */
break;
case U8G_COM_MSG_WRITE_BYTE:
break;
case U8G_COM_MSG_WRITE_SEQ:
break;
}
return 1;
}

@ -0,0 +1,240 @@
/*
u8g_delay.c
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
void u8g_Delay(uint16_t val) Delay by "val" milliseconds
void u8g_MicroDelay(void) Delay be one microsecond
void u8g_10MicroDelay(void) Delay by 10 microseconds
*/
#include "u8g.h"
/*==== Part 1: Derive suitable delay procedure ====*/
#if defined(ARDUINO)
# if ARDUINO < 100
# include <WProgram.h>
# else
# include <Arduino.h>
# endif
# if defined(__AVR__)
# define USE_AVR_DELAY
# elif defined(__PIC32MX)
# define USE_PIC32_DELAY
# elif defined(__arm__) /* Arduino Due */
# define USE_ARDUINO_DELAY
# else
# define USE_ARDUINO_DELAY
# endif
#elif defined(__AVR__)
# define USE_AVR_DELAY
#elif defined(__18CXX)
# define USE_PIC18_DELAY
#elif defined(__arm__)
/* do not define anything, all procedures are expected to be defined outside u8glib */
/*
void u8g_Delay(uint16_t val);
void u8g_MicroDelay(void);
void u8g_10MicroDelay(void);
*/
#else
# define USE_DUMMY_DELAY
#endif
/*==== Part 2: Definition of the delay procedures ====*/
/*== AVR Delay ==*/
#if defined(USE_AVR_DELAY)
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
/*
Delay by the provided number of milliseconds.
Thus, a 16 bit value will allow a delay of 0..65 seconds
Makes use of the _delay_loop_2
_delay_loop_2 will do a delay of n * 4 prozessor cycles.
with f = F_CPU cycles per second,
n = f / (1000 * 4 )
with f = 16000000 the result is 4000
with f = 1000000 the result is 250
the millisec loop, gcc requires the following overhead:
- movev 1
- subwi 2x2
- bne i 2
==> 7 cycles
==> must be devided by 4, rounded up 7/4 = 2
*/
void u8g_Delay(uint16_t val)
{
/* old version did a call to the arduino lib: delay(val); */
while( val != 0 )
{
_delay_loop_2( (F_CPU / 4000 ) -2);
val--;
}
}
/* delay by one micro second */
void u8g_MicroDelay(void)
{
#if (F_CPU / 4000000 ) > 0
_delay_loop_2( (F_CPU / 4000000 ) );
#endif
}
/* delay by 10 micro seconds */
void u8g_10MicroDelay(void)
{
#if (F_CPU / 400000 ) > 0
_delay_loop_2( (F_CPU / 400000 ) );
#endif
}
#endif
/*== Delay for PIC18 (not tested) ==*/
#if defined(USE_PIC18_DELAY)
#include <delays.h>
#define GetSystemClock() (64000000ul) // Hz
#define GetInstructionClock() (GetSystemClock()/4)
void u8g_Delay(uint16_t val)
{/*
unsigned int _iTemp = (val);
while(_iTemp--)
Delay1KTCYx((GetInstructionClock()+999999)/1000000);
*/
}
void u8g_MicroDelay(void)
{
/* not implemented */
}
void u8g_10MicroDelay(void)
{
/* not implemented */
}
#endif
/*== Arduino Delay ==*/
#if defined(USE_ARDUINO_DELAY)
void u8g_Delay(uint16_t val)
{
#if defined(__arm__)
delayMicroseconds((uint32_t)val*(uint32_t)1000);
#else
delay(val);
#endif
}
void u8g_MicroDelay(void)
{
delayMicroseconds(1);
}
void u8g_10MicroDelay(void)
{
delayMicroseconds(10);
}
#endif
#if defined(USE_PIC32_DELAY)
/*
Assume chipkit here with F_CPU correctly defined
The problem was, that u8g_Delay() is called within the constructor.
It seems that the chipkit is not fully setup at this time, so a
call to delay() will not work. So here is my own implementation.
*/
#define CPU_COUNTS_PER_SECOND (F_CPU/2UL)
#define TICKS_PER_MILLISECOND (CPU_COUNTS_PER_SECOND/1000UL)
#include "plib.h"
void u8g_Delay(uint16_t val)
{
uint32_t d;
uint32_t s;
d = val;
d *= TICKS_PER_MILLISECOND;
s = ReadCoreTimer();
while ( (uint32_t)(ReadCoreTimer() - s) < d )
;
}
void u8g_MicroDelay(void)
{
uint32_t d;
uint32_t s;
d = TICKS_PER_MILLISECOND/1000;
s = ReadCoreTimer();
while ( (uint32_t)(ReadCoreTimer() - s) < d )
;
}
void u8g_10MicroDelay(void)
{
uint32_t d;
uint32_t s;
d = TICKS_PER_MILLISECOND/100;
s = ReadCoreTimer();
while ( (uint32_t)(ReadCoreTimer() - s) < d )
;
}
#endif
/*== Any other systems: Dummy Delay ==*/
#if defined(USE_DUMMY_DELAY)
void u8g_Delay(uint16_t val)
{
/* do not know how to delay... */
}
void u8g_MicroDelay(void)
{
}
void u8g_10MicroDelay(void)
{
}
#endif

@ -0,0 +1,1501 @@
/*
u8g_font.c
U8G Font High Level Interface
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
/* font api */
/* pointer to the start adress of the glyph, points to progmem area */
typedef void * u8g_glyph_t;
/* size of the font data structure, there is no struct or class... */
#define U8G_FONT_DATA_STRUCT_SIZE 17
/*
... instead the fields of the font data structure are accessed directly by offset
font information
offset
0 font format
1 FONTBOUNDINGBOX width unsigned
2 FONTBOUNDINGBOX height unsigned
3 FONTBOUNDINGBOX x-offset signed
4 FONTBOUNDINGBOX y-offset signed
5 capital A height unsigned
6 start 'A'
8 start 'a'
10 encoding start
11 encoding end
12 descent 'g' negative: below baseline
13 font max ascent
14 font min decent negative: below baseline
15 font xascent
16 font xdecent negative: below baseline
*/
/* use case: What is the width and the height of the minimal box into which string s fints? */
void u8g_font_GetStrSize(const void *font, const char *s, u8g_uint_t *width, u8g_uint_t *height);
void u8g_font_GetStrSizeP(const void *font, const char *s, u8g_uint_t *width, u8g_uint_t *height);
/* use case: lower left edge of a minimal box is known, what is the correct x, y position for the string draw procedure */
void u8g_font_AdjustXYToDraw(const void *font, const char *s, u8g_uint_t *x, u8g_uint_t *y);
void u8g_font_AdjustXYToDrawP(const void *font, const char *s, u8g_uint_t *x, u8g_uint_t *y);
/* use case: Baseline origin known, return minimal box */
void u8g_font_GetStrMinBox(u8g_t *u8g, const void *font, const char *s, u8g_uint_t *x, u8g_uint_t *y, u8g_uint_t *width, u8g_uint_t *height);
/* procedures */
/*========================================================================*/
/* low level byte and word access */
/* removed NOINLINE, because it leads to smaller code, might also be faster */
//static uint8_t u8g_font_get_byte(const u8g_fntpgm_uint8_t *font, uint8_t offset) U8G_NOINLINE;
static uint8_t u8g_font_get_byte(const u8g_fntpgm_uint8_t *font, uint8_t offset)
{
font += offset;
return u8g_pgm_read( (u8g_pgm_uint8_t *)font );
}
static uint16_t u8g_font_get_word(const u8g_fntpgm_uint8_t *font, uint8_t offset) U8G_NOINLINE;
static uint16_t u8g_font_get_word(const u8g_fntpgm_uint8_t *font, uint8_t offset)
{
uint16_t pos;
font += offset;
pos = u8g_pgm_read( (u8g_pgm_uint8_t *)font );
font++;
pos <<= 8;
pos += u8g_pgm_read( (u8g_pgm_uint8_t *)font);
return pos;
}
/*========================================================================*/
/* direct access on the font */
static uint8_t u8g_font_GetFormat(const u8g_fntpgm_uint8_t *font) U8G_NOINLINE;
static uint8_t u8g_font_GetFormat(const u8g_fntpgm_uint8_t *font)
{
return u8g_font_get_byte(font, 0);
}
static uint8_t u8g_font_GetFontGlyphStructureSize(const u8g_fntpgm_uint8_t *font) U8G_NOINLINE;
static uint8_t u8g_font_GetFontGlyphStructureSize(const u8g_fntpgm_uint8_t *font)
{
switch(u8g_font_GetFormat(font))
{
case 0: return 6;
case 1: return 3;
case 2: return 6;
}
return 3;
}
static uint8_t u8g_font_GetBBXWidth(const void *font)
{
return u8g_font_get_byte(font, 1);
}
static uint8_t u8g_font_GetBBXHeight(const void *font)
{
return u8g_font_get_byte(font, 2);
}
static int8_t u8g_font_GetBBXOffX(const void *font)
{
return u8g_font_get_byte(font, 3);
}
static int8_t u8g_font_GetBBXOffY(const void *font)
{
return u8g_font_get_byte(font, 4);
}
uint8_t u8g_font_GetCapitalAHeight(const void *font)
{
return u8g_font_get_byte(font, 5);
}
uint16_t u8g_font_GetEncoding65Pos(const void *font) U8G_NOINLINE;
uint16_t u8g_font_GetEncoding65Pos(const void *font)
{
return u8g_font_get_word(font, 6);
}
uint16_t u8g_font_GetEncoding97Pos(const void *font) U8G_NOINLINE;
uint16_t u8g_font_GetEncoding97Pos(const void *font)
{
return u8g_font_get_word(font, 8);
}
uint8_t u8g_font_GetFontStartEncoding(const void *font)
{
return u8g_font_get_byte(font, 10);
}
uint8_t u8g_font_GetFontEndEncoding(const void *font)
{
return u8g_font_get_byte(font, 11);
}
int8_t u8g_font_GetLowerGDescent(const void *font)
{
return u8g_font_get_byte(font, 12);
}
int8_t u8g_font_GetFontAscent(const void *font)
{
return u8g_font_get_byte(font, 13);
}
int8_t u8g_font_GetFontDescent(const void *font)
{
return u8g_font_get_byte(font, 14);
}
int8_t u8g_font_GetFontXAscent(const void *font)
{
return u8g_font_get_byte(font, 15);
}
int8_t u8g_font_GetFontXDescent(const void *font)
{
return u8g_font_get_byte(font, 16);
}
/* return the data start for a font and the glyph pointer */
static uint8_t *u8g_font_GetGlyphDataStart(const void *font, u8g_glyph_t g)
{
return ((u8g_fntpgm_uint8_t *)g) + u8g_font_GetFontGlyphStructureSize(font);
}
/* calculate the overall length of the font, only used to create the picture for the google wiki */
size_t u8g_font_GetSize(const void *font)
{
uint8_t *p = (uint8_t *)(font);
uint8_t font_format = u8g_font_GetFormat(font);
uint8_t data_structure_size = u8g_font_GetFontGlyphStructureSize(font);
uint8_t start, end;
uint8_t i;
uint8_t mask = 255;
start = u8g_font_GetFontStartEncoding(font);
end = u8g_font_GetFontEndEncoding(font);
if ( font_format == 1 )
mask = 15;
p += U8G_FONT_DATA_STRUCT_SIZE; /* skip font general information */
i = start;
for(;;)
{
if ( u8g_pgm_read((u8g_pgm_uint8_t *)(p)) == 255 )
{
p += 1;
}
else
{
p += u8g_pgm_read( ((u8g_pgm_uint8_t *)(p)) + 2 ) & mask;
p += data_structure_size;
}
if ( i == end )
break;
i++;
}
return p - (uint8_t *)font;
}
/*========================================================================*/
/* u8g interface, font access */
uint8_t u8g_GetFontBBXWidth(u8g_t *u8g)
{
return u8g_font_GetBBXWidth(u8g->font);
}
uint8_t u8g_GetFontBBXHeight(u8g_t *u8g)
{
return u8g_font_GetBBXHeight(u8g->font);
}
int8_t u8g_GetFontBBXOffX(u8g_t *u8g) U8G_NOINLINE;
int8_t u8g_GetFontBBXOffX(u8g_t *u8g)
{
return u8g_font_GetBBXOffX(u8g->font);
}
int8_t u8g_GetFontBBXOffY(u8g_t *u8g) U8G_NOINLINE;
int8_t u8g_GetFontBBXOffY(u8g_t *u8g)
{
return u8g_font_GetBBXOffY(u8g->font);
}
uint8_t u8g_GetFontCapitalAHeight(u8g_t *u8g) U8G_NOINLINE;
uint8_t u8g_GetFontCapitalAHeight(u8g_t *u8g)
{
return u8g_font_GetCapitalAHeight(u8g->font);
}
/*========================================================================*/
/* glyph handling */
static void u8g_CopyGlyphDataToCache(u8g_t *u8g, u8g_glyph_t g)
{
uint8_t tmp;
switch( u8g_font_GetFormat(u8g->font) )
{
case 0:
case 2:
/*
format 0
glyph information
offset
0 BBX width unsigned
1 BBX height unsigned
2 data size unsigned (BBX width + 7)/8 * BBX height
3 DWIDTH signed
4 BBX xoffset signed
5 BBX yoffset signed
byte 0 == 255 indicates empty glyph
*/
u8g->glyph_width = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 0 );
u8g->glyph_height = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 1 );
u8g->glyph_dx = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 3 );
u8g->glyph_x = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 4 );
u8g->glyph_y = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 5 );
break;
case 1:
default:
/*
format 1
0 BBX xoffset signed --> upper 4 Bit
0 BBX yoffset signed --> lower 4 Bit
1 BBX width unsigned --> upper 4 Bit
1 BBX height unsigned --> lower 4 Bit
2 data size unsigned -(BBX width + 7)/8 * BBX height --> lower 4 Bit
2 DWIDTH signed --> upper 4 Bit
byte 0 == 255 indicates empty glyph
*/
tmp = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 0 );
u8g->glyph_y = tmp & 15;
u8g->glyph_y-=2;
tmp >>= 4;
u8g->glyph_x = tmp;
tmp = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 1 );
u8g->glyph_height = tmp & 15;
tmp >>= 4;
u8g->glyph_width = tmp;
tmp = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 2 );
tmp >>= 4;
u8g->glyph_dx = tmp;
break;
}
}
//void u8g_FillEmptyGlyphCache(u8g_t *u8g) U8G_NOINLINE;
static void u8g_FillEmptyGlyphCache(u8g_t *u8g)
{
u8g->glyph_dx = 0;
u8g->glyph_width = 0;
u8g->glyph_height = 0;
u8g->glyph_x = 0;
u8g->glyph_y = 0;
}
/*
Find (with some speed optimization) and return a pointer to the glyph data structure
Also uncompress (format 1) and copy the content of the data structure to the u8g structure
*/
u8g_glyph_t u8g_GetGlyph(u8g_t *u8g, uint8_t requested_encoding)
{
uint8_t *p = (uint8_t *)(u8g->font);
uint8_t font_format = u8g_font_GetFormat(u8g->font);
uint8_t data_structure_size = u8g_font_GetFontGlyphStructureSize(u8g->font);
uint8_t start, end;
uint16_t pos;
uint8_t i;
uint8_t mask = 255;
if ( font_format == 1 )
mask = 15;
start = u8g_font_GetFontStartEncoding(u8g->font);
end = u8g_font_GetFontEndEncoding(u8g->font);
pos = u8g_font_GetEncoding97Pos(u8g->font);
if ( requested_encoding >= 97 && pos > 0 )
{
p+= pos;
start = 97;
}
else
{
pos = u8g_font_GetEncoding65Pos(u8g->font);
if ( requested_encoding >= 65 && pos > 0 )
{
p+= pos;
start = 65;
}
else
p += U8G_FONT_DATA_STRUCT_SIZE; /* skip font general information */
}
if ( requested_encoding > end )
{
u8g_FillEmptyGlyphCache(u8g);
return NULL; /* not found */
}
i = start;
if ( i <= end )
{
for(;;)
{
if ( u8g_pgm_read((u8g_pgm_uint8_t *)(p)) == 255 )
{
p += 1;
}
else
{
if ( i == requested_encoding )
{
u8g_CopyGlyphDataToCache(u8g, p);
return p;
}
p += u8g_pgm_read( ((u8g_pgm_uint8_t *)(p)) + 2 ) & mask;
p += data_structure_size;
}
if ( i == end )
break;
i++;
}
}
u8g_FillEmptyGlyphCache(u8g);
return NULL;
}
uint8_t u8g_IsGlyph(u8g_t *u8g, uint8_t requested_encoding)
{
if ( u8g_GetGlyph(u8g, requested_encoding) != NULL )
return 1;
return 0;
}
int8_t u8g_GetGlyphDeltaX(u8g_t *u8g, uint8_t requested_encoding)
{
if ( u8g_GetGlyph(u8g, requested_encoding) == NULL )
return 0; /* should never happen, so return something */
return u8g->glyph_dx;
}
/*========================================================================*/
/* glyph drawing procedures */
#ifdef OBSOLETE
/*
Draw a glyph
x,y: left baseline position of the glyph
*/
int8_t u8g_DrawGlyphDir(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t encoding)
{
u8g_glyph_t g;
uint8_t w, h, i, j;
const u8g_pgm_uint8_t *data;
uint8_t bytes_per_line;
u8g_uint_t ix, iy;
g = u8g_GetGlyph(u8g, encoding);
if ( g == NULL )
return 0;
w = u8g->glyph_width;
h = u8g->glyph_height;
bytes_per_line = w;
bytes_per_line += 7;
bytes_per_line /= 8;
data = u8g_font_GetGlyphDataStart(u8g->font, g);
switch(dir)
{
case 0:
x += u8g->glyph_x;
y -= u8g->glyph_y;
y--;
//u8g_DrawFrame(u8g, x, y-h+1, w, h);
if ( u8g_IsBBXIntersection(u8g, x, y-h+1, w, h) == 0 )
return u8g->glyph_dx;
iy = y;
iy -= h;
iy++;
for( j = 0; j < h; j++ )
{
ix = x;
for( i = 0; i < bytes_per_line; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data));
data++;
ix+=8;
}
iy++;
}
break;
case 1:
x += u8g->glyph_y;
x++;
y += u8g->glyph_x;
//printf("enc %d, dir %d, x %d, y %d, w %d, h %d\n", encoding, dir, x, y, w, h);
//u8g_DrawFrame(u8g, x, y, h, w);
if ( u8g_IsBBXIntersection(u8g, x, y, h, w) == 0 )
return u8g->glyph_dx;
ix = x;
ix += h;
ix--;
for( j = 0; j < h; j++ )
{
iy = y;
for( i = 0; i < bytes_per_line; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data));
data++;
iy+=8;
}
ix--;
}
break;
case 2:
x -= u8g->glyph_x;
y += u8g->glyph_y;
y++;
if ( u8g_IsBBXIntersection(u8g, x-w-1, y, w, h) == 0 )
return u8g->glyph_dx;
iy = y;
iy += h;
iy--;
for( j = 0; j < h; j++ )
{
ix = x;
for( i = 0; i < bytes_per_line; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data));
data++;
ix-=8;
}
iy--;
}
break;
case 3:
x -= u8g->glyph_y;
x--;
y -= u8g->glyph_x;
if ( u8g_IsBBXIntersection(u8g, x-h-1, y-w-1, h, w) == 0 )
return u8g->glyph_dx;
ix = x;
ix -= h;
ix++;
for( j = 0; j < h; j++ )
{
iy = y;
for( i = 0; i < bytes_per_line; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data));
data++;
iy-=8;
}
ix++;
}
break;
}
return u8g->glyph_dx;
}
#endif
int8_t u8g_draw_glyph(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
const u8g_pgm_uint8_t *data;
uint8_t w, h;
uint8_t i, j;
u8g_uint_t ix, iy;
{
u8g_glyph_t g = u8g_GetGlyph(u8g, encoding);
if ( g == NULL )
return 0;
data = u8g_font_GetGlyphDataStart(u8g->font, g);
}
w = u8g->glyph_width;
h = u8g->glyph_height;
x += u8g->glyph_x;
y -= u8g->glyph_y;
y--;
if ( u8g_IsBBXIntersection(u8g, x, y-h+1, w, h) == 0 )
return u8g->glyph_dx;
/* now, w is reused as bytes per line */
w += 7;
w /= 8;
iy = y;
iy -= h;
iy++;
for( j = 0; j < h; j++ )
{
ix = x;
for( i = 0; i < w; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, 0, u8g_pgm_read(data));
data++;
ix+=8;
}
iy++;
}
return u8g->glyph_dx;
}
int8_t u8g_DrawGlyph(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
y += u8g->font_calc_vref(u8g);
return u8g_draw_glyph(u8g, x, y, encoding);
}
int8_t u8g_draw_glyph90(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
const u8g_pgm_uint8_t *data;
uint8_t w, h;
uint8_t i, j;
u8g_uint_t ix, iy;
{
u8g_glyph_t g = u8g_GetGlyph(u8g, encoding);
if ( g == NULL )
return 0;
data = u8g_font_GetGlyphDataStart(u8g->font, g);
}
w = u8g->glyph_width;
h = u8g->glyph_height;
x += u8g->glyph_y;
x++;
y += u8g->glyph_x;
if ( u8g_IsBBXIntersection(u8g, x, y, h, w) == 0 )
return u8g->glyph_dx;
/* now, w is reused as bytes per line */
w += 7;
w /= 8;
ix = x;
ix += h;
ix--;
for( j = 0; j < h; j++ )
{
iy = y;
for( i = 0; i < w; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, 1, u8g_pgm_read(data));
data++;
iy+=8;
}
ix--;
}
return u8g->glyph_dx;
}
int8_t u8g_DrawGlyph90(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
x -= u8g->font_calc_vref(u8g);
return u8g_draw_glyph90(u8g, x, y, encoding);
}
int8_t u8g_draw_glyph180(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
const u8g_pgm_uint8_t *data;
uint8_t w, h;
uint8_t i, j;
u8g_uint_t ix, iy;
{
u8g_glyph_t g = u8g_GetGlyph(u8g, encoding);
if ( g == NULL )
return 0;
data = u8g_font_GetGlyphDataStart(u8g->font, g);
}
w = u8g->glyph_width;
h = u8g->glyph_height;
x -= u8g->glyph_x;
y += u8g->glyph_y;
y++;
if ( u8g_IsBBXIntersection(u8g, x-(w-1), y, w, h) == 0 )
return u8g->glyph_dx;
/* now, w is reused as bytes per line */
w += 7;
w /= 8;
iy = y;
iy += h;
iy--;
for( j = 0; j < h; j++ )
{
ix = x;
for( i = 0; i < w; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, 2, u8g_pgm_read(data));
data++;
ix-=8;
}
iy--;
}
return u8g->glyph_dx;
}
int8_t u8g_DrawGlyph180(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
y -= u8g->font_calc_vref(u8g);
return u8g_draw_glyph180(u8g, x, y, encoding);
}
int8_t u8g_draw_glyph270(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
const u8g_pgm_uint8_t *data;
uint8_t w, h;
uint8_t i, j;
u8g_uint_t ix, iy;
{
u8g_glyph_t g = u8g_GetGlyph(u8g, encoding);
if ( g == NULL )
return 0;
data = u8g_font_GetGlyphDataStart(u8g->font, g);
}
w = u8g->glyph_width;
h = u8g->glyph_height;
x -= u8g->glyph_y;
x--;
y -= u8g->glyph_x;
if ( u8g_IsBBXIntersection(u8g, x-(h-1), y-(w-1), h, w) == 0 )
return u8g->glyph_dx;
/* now, w is reused as bytes per line */
w += 7;
w /= 8;
ix = x;
ix -= h;
ix++;
for( j = 0; j < h; j++ )
{
iy = y;
for( i = 0; i < w; i++ )
{
u8g_Draw8Pixel(u8g, ix, iy, 3, u8g_pgm_read(data));
data++;
iy-=8;
}
ix++;
}
return u8g->glyph_dx;
}
int8_t u8g_DrawGlyph270(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
x += u8g->font_calc_vref(u8g);
return u8g_draw_glyph270(u8g, x, y, encoding);
}
#ifdef OBSOLETE
/*
Draw a glyph
x,y: lower left corner of the font bounding box
*/
int8_t u8g_DrawGlyphFontBBX(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t encoding)
{
/* TODO: apply "dir" */
x -= u8g_GetFontBBXOffX(u8g);
y += u8g_GetFontBBXOffY(u8g);
return u8g_DrawGlyphDir(u8g, x, y, dir, encoding);
}
#endif
/*========================================================================*/
/* string drawing procedures */
u8g_uint_t u8g_DrawStr(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const char *s)
{
u8g_uint_t t = 0;
int8_t d;
//u8g_uint_t u8g_GetStrWidth(u8g, s);
//u8g_font_GetFontAscent(u8g->font)-u8g_font_GetFontDescent(u8g->font);
y += u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_draw_glyph(u8g, x, y, *s);
x += d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStr90(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const char *s)
{
u8g_uint_t t = 0;
int8_t d;
x -= u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_draw_glyph90(u8g, x, y, *s);
y += d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStr180(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const char *s)
{
u8g_uint_t t = 0;
int8_t d;
y -= u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_draw_glyph180(u8g, x, y, *s);
x -= d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStr270(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const char *s)
{
u8g_uint_t t = 0;
int8_t d;
x += u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_draw_glyph270(u8g, x, y, *s);
y -= d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStrDir(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, const char *s)
{
switch(dir)
{
case 0:
return u8g_DrawStr(u8g, x, y, s);
case 1:
return u8g_DrawStr90(u8g, x, y, s);
case 2:
return u8g_DrawStr180(u8g, x, y, s);
case 3:
return u8g_DrawStr270(u8g, x, y, s);
}
return 0;
}
u8g_uint_t u8g_DrawStrP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const u8g_pgm_uint8_t *s)
{
u8g_uint_t t = 0;
int8_t d;
uint8_t c;
y += u8g->font_calc_vref(u8g);
for(;;)
{
c = u8g_pgm_read(s);
if ( c == '\0' )
break;
d = u8g_draw_glyph(u8g, x, y, c);
x += d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStr90P(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const u8g_pgm_uint8_t *s)
{
u8g_uint_t t = 0;
int8_t d;
x -= u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_DrawGlyph90(u8g, x, y, u8g_pgm_read(s));
y += d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStr180P(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const u8g_pgm_uint8_t *s)
{
u8g_uint_t t = 0;
int8_t d;
y -= u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_DrawGlyph180(u8g, x, y, u8g_pgm_read(s));
x -= d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStr270P(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const u8g_pgm_uint8_t *s)
{
u8g_uint_t t = 0;
int8_t d;
x += u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_DrawGlyph270(u8g, x, y, u8g_pgm_read(s));
y -= d;
t += d;
s++;
}
return t;
}
u8g_uint_t u8g_DrawStrFontBBX(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, const char *s)
{
x -= u8g_GetFontBBXOffX(u8g);
y += u8g_GetFontBBXOffY(u8g);
return u8g_DrawStrDir(u8g, x, y, dir, s);
}
/* still used by picgen.c, dir argument is ignored */
int8_t u8g_DrawGlyphFontBBX(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t encoding)
{
x -= u8g_GetFontBBXOffX(u8g);
y += u8g_GetFontBBXOffY(u8g);
u8g_draw_glyph(u8g, x, y, encoding);
return 0;
}
/*========================================================================*/
/* set ascent/descent for reference point calculation */
void u8g_UpdateRefHeight(u8g_t *u8g)
{
uint16_t ls;
if ( u8g->font == NULL )
return;
if ( u8g->font_height_mode == U8G_FONT_HEIGHT_MODE_TEXT )
{
u8g->font_ref_ascent = u8g_font_GetCapitalAHeight(u8g->font);
u8g->font_ref_descent = u8g_font_GetLowerGDescent(u8g->font);
}
else if ( u8g->font_height_mode == U8G_FONT_HEIGHT_MODE_XTEXT )
{
u8g->font_ref_ascent = u8g_font_GetFontXAscent(u8g->font);
u8g->font_ref_descent = u8g_font_GetFontXDescent(u8g->font);
}
else
{
u8g->font_ref_ascent = u8g_font_GetFontAscent(u8g->font);
u8g->font_ref_descent = u8g_font_GetFontDescent(u8g->font);
}
ls = u8g->font_ref_ascent - u8g->font_ref_descent;
if ( u8g->font_line_spacing_factor != 64 )
{
ls &= 255;
ls *= u8g->font_line_spacing_factor;
ls >>= 6;
}
u8g->line_spacing = ls;
}
void u8g_SetFontRefHeightText(u8g_t *u8g)
{
u8g->font_height_mode = U8G_FONT_HEIGHT_MODE_TEXT;
u8g_UpdateRefHeight(u8g);
}
void u8g_SetFontRefHeightExtendedText(u8g_t *u8g)
{
u8g->font_height_mode = U8G_FONT_HEIGHT_MODE_XTEXT;
u8g_UpdateRefHeight(u8g);
}
void u8g_SetFontRefHeightAll(u8g_t *u8g)
{
u8g->font_height_mode = U8G_FONT_HEIGHT_MODE_ALL;
u8g_UpdateRefHeight(u8g);
}
/* factor = 64: linespaceing == ascent and descent */
void u8g_SetFontLineSpacingFactor(u8g_t *u8g, uint8_t factor)
{
u8g->font_line_spacing_factor = factor;
u8g_UpdateRefHeight(u8g);
}
/*========================================================================*/
/* callback procedures to correct the y position */
u8g_uint_t u8g_font_calc_vref_font(u8g_t *u8g)
{
return 0;
}
void u8g_SetFontPosBaseline(u8g_t *u8g)
{
u8g->font_calc_vref = u8g_font_calc_vref_font;
}
u8g_uint_t u8g_font_calc_vref_bottom(u8g_t *u8g)
{
/* y += (u8g_uint_t)(u8g_int_t)(u8g->font_ref_descent); */
return (u8g_uint_t)(u8g_int_t)(u8g->font_ref_descent);
}
void u8g_SetFontPosBottom(u8g_t *u8g)
{
u8g->font_calc_vref = u8g_font_calc_vref_bottom;
}
u8g_uint_t u8g_font_calc_vref_top(u8g_t *u8g)
{
u8g_uint_t tmp;
/* reference pos is one pixel above the upper edge of the reference glyph */
/*
y += (u8g_uint_t)(u8g_int_t)(u8g->font_ref_ascent);
y++;
*/
tmp = (u8g_uint_t)(u8g_int_t)(u8g->font_ref_ascent);
tmp++;
return tmp;
}
void u8g_SetFontPosTop(u8g_t *u8g)
{
u8g->font_calc_vref = u8g_font_calc_vref_top;
}
u8g_uint_t u8g_font_calc_vref_center(u8g_t *u8g)
{
int8_t tmp;
tmp = u8g->font_ref_ascent;
tmp -= u8g->font_ref_descent;
tmp /= 2;
tmp += u8g->font_ref_descent;
/* y += (u8g_uint_t)(u8g_int_t)(tmp); */
return tmp;
}
void u8g_SetFontPosCenter(u8g_t *u8g)
{
u8g->font_calc_vref = u8g_font_calc_vref_center;
}
/*========================================================================*/
/* string pixel width calculation */
char u8g_font_get_char(const void *s)
{
return *(const char *)(s);
}
char u8g_font_get_charP(const void *s)
{
return u8g_pgm_read(s);
}
typedef char (*u8g_font_get_char_fn)(const void *s);
u8g_uint_t u8g_font_calc_str_pixel_width(u8g_t *u8g, const char *s, u8g_font_get_char_fn get_char )
{
u8g_uint_t w;
uint8_t enc;
/* reset the total minimal width to zero, this will be expanded during calculation */
w = 0;
enc = get_char(s);
/* check for empty string, width is already 0 */
if ( enc == '\0' )
{
return w;
}
/* get the glyph information of the first char. This must be valid, because we already checked for the empty string */
/* if *s is not inside the font, then the cached parameters of the glyph are all zero */
u8g_GetGlyph(u8g, enc);
/* strlen(s) == 1: width = width(s[0]) */
/* strlen(s) == 2: width = - offx(s[0]) + deltax(s[0]) + offx(s[1]) + width(s[1]) */
/* strlen(s) == 3: width = - offx(s[0]) + deltax(s[0]) + deltax(s[1]) + offx(s[2]) + width(s[2]) */
/* assume that the string has size 2 or more, than start with negative offset-x */
/* for string with size 1, this will be nullified after the loop */
w = -u8g->glyph_x;
for(;;)
{
/* check and stop if the end of the string is reached */
s++;
if ( get_char(s) == '\0' )
break;
/* if there are still more characters, add the delta to the next glyph */
w += u8g->glyph_dx;
/* store the encoding in a local variable, used also after the for(;;) loop */
enc = get_char(s);
/* load the next glyph information */
u8g_GetGlyph(u8g, enc);
}
/* finally calculate the width of the last char */
/* here is another exception, if the last char is a black, use the dx value instead */
if ( enc != ' ' )
{
/* if g was not updated in the for loop (strlen() == 1), then the initial offset x gets removed */
w += u8g->glyph_width;
w += u8g->glyph_x;
}
else
{
w += u8g->glyph_dx;
}
return w;
}
u8g_uint_t u8g_GetStrPixelWidth(u8g_t *u8g, const char *s)
{
return u8g_font_calc_str_pixel_width(u8g, s, u8g_font_get_char);
}
u8g_uint_t u8g_GetStrPixelWidthP(u8g_t *u8g, const u8g_pgm_uint8_t *s)
{
return u8g_font_calc_str_pixel_width(u8g, (const char *)s, u8g_font_get_charP);
}
int8_t u8g_GetStrX(u8g_t *u8g, const char *s)
{
u8g_GetGlyph(u8g, *s);
return u8g->glyph_x;
}
int8_t u8g_GetStrXP(u8g_t *u8g, const u8g_pgm_uint8_t *s)
{
u8g_GetGlyph(u8g, u8g_pgm_read(s));
return u8g->glyph_x;
}
/*========================================================================*/
/* string width calculation */
u8g_uint_t u8g_GetStrWidth(u8g_t *u8g, const char *s)
{
u8g_uint_t w;
uint8_t encoding;
/* reset the total width to zero, this will be expanded during calculation */
w = 0;
for(;;)
{
encoding = *s;
if ( encoding == 0 )
break;
/* load glyph information */
u8g_GetGlyph(u8g, encoding);
w += u8g->glyph_dx;
/* goto next char */
s++;
}
return w;
}
u8g_uint_t u8g_GetStrWidthP(u8g_t *u8g, const u8g_pgm_uint8_t *s)
{
u8g_uint_t w;
uint8_t encoding;
/* reset the total width to zero, this will be expanded during calculation */
w = 0;
for(;;)
{
encoding = u8g_pgm_read(s);
if ( encoding == 0 )
break;
/* load glyph information */
u8g_GetGlyph(u8g, encoding);
w += u8g->glyph_dx;
/* goto next char */
s++;
}
return w;
}
/*========================================================================*/
/* calculation of font/glyph/string characteristics */
/*
Description:
Calculate parameter for the minimal bounding box on a given string
Output
buf->y_min extend of the lower left edge if the string below (y_min<0) or above (y_min>0) baseline (descent)
buf->y_max extend of the upper left edge if the string below (y_min<0) or above (y_min>0) baseline (ascent)
buf->w the width of the string
*/
struct u8g_str_size_struct
{
int8_t y_min; /* descent */
int8_t y_max; /* ascent */
int8_t x, y; /* the reference point of the font (negated!) */
u8g_uint_t w; /* width of the overall string */
};
typedef struct u8g_str_size_struct u8g_str_size_t;
static void u8g_font_calc_str_min_box(u8g_t *u8g, const char *s, u8g_str_size_t *buf)
{
/* u8g_glyph_t g; */
int8_t tmp;
/* reset the total minimal width to zero, this will be expanded during calculation */
buf->w = 0;
/* check for empty string, width is already 0, but also reset y_min and y_max to 0 */
if ( *s == '\0' )
{
buf->y_min = 0;
buf->y_max = 0;
buf->x = 0;
buf->y = 0;
return;
}
/* reset y_min to the largest possible value. Later we search for the smallest value */
/* y_min contains the position [pixel] of the lower left edge of the glyph above (y_min>0) or below (y_min<0) baseline */
buf->y_min = 127;
/* reset y_max to the smallest possible value. Later we search for the highest value */
/* y_max contains the position [pixel] of the upper left edge of the glyph above (y_max>0) or below (y_max<0) baseline */
buf->y_max = -128;
/* get the glyph information of the first char. This must be valid, because we already checked for the empty string */
u8g_GetGlyph(u8g, *s);
/* strlen(s) == 1: width = width(s[0]) */
/* strlen(s) == 2: width = - offx(s[0]) + deltax(s[0]) + offx(s[1]) + width(s[1]) */
/* strlen(s) == 3: width = - offx(s[0]) + deltax(s[0]) + deltax(s[1]) + offx(s[2]) + width(s[2]) */
/* assume that the string has size 2 or more, than start with negative offset-x */
/* for string with size 1, this will be nullified after the loop */
// buf->w = - u8g_font_GetGlyphBBXOffX(u8g->font, g);
buf->w = - u8g->glyph_x;
/* Also copy the position of the first glyph. This is the reference point of the string (negated) */
buf->x = u8g->glyph_x;
buf->y = u8g->glyph_y;
for(;;)
{
/* calculated y position of the upper left corner (y_max) and lower left corner (y_min) of the string */
/* relative to the base line */
tmp = u8g->glyph_y;
if ( buf->y_min > tmp )
buf->y_min = tmp;
tmp +=u8g->glyph_height;
if ( buf->y_max < tmp )
buf->y_max = tmp;
/* check and stop if the end of the string is reached */
s++;
if ( *s == '\0' )
break;
/* if there are still more characters, add the delta to the next glyph */
buf->w += u8g->glyph_dx;
/* load the next glyph information */
u8g_GetGlyph(u8g, *s);
}
/* finally calculate the width of the last char */
/* if g was not updated in the for loop (strlen() == 1), then the initial offset x gets removed */
buf->w += u8g->glyph_width;
// buf->w += u8g_font_GetGlyphBBXOffX(u8g->font, g);
buf->w += u8g->glyph_x;
}
/* calculate minimal box */
void u8g_font_box_min(u8g_t *u8g, const char *s, u8g_str_size_t *buf)
{
u8g_font_calc_str_min_box(u8g, s, buf);
}
/* calculate gA box, but do not calculate the overall width */
void u8g_font_box_left_gA(u8g_t *u8g, const char *s, u8g_str_size_t *buf)
{
}
/* calculate gA box, including overall width */
void u8g_font_box_all_gA(u8g_t *u8g, const char *s, u8g_str_size_t *buf)
{
}
static void u8g_font_get_str_box_fill_args(u8g_t *u8g, const char *s, u8g_str_size_t *buf, u8g_uint_t *x, u8g_uint_t *y, u8g_uint_t *width, u8g_uint_t *height)
{
/*
u8g_glyph_t g;
g =
*/
u8g_GetGlyph(u8g, *s);
*x += u8g->glyph_x;
*width = buf->w;
*y -= buf->y_max;
/* +1 because y_max is a height, this compensates the next step */
//*y += 1;
/* because the reference point is one below the string, this compensates the previous step */
//*y -= 1;
*height = buf->y_max;
*height -= buf->y_min;
}
void u8g_GetStrMinBox(u8g_t *u8g, const char *s, u8g_uint_t *x, u8g_uint_t *y, u8g_uint_t *width, u8g_uint_t *height)
{
u8g_str_size_t buf;
if ( *s == '\0' )
{
*width= 0;
*height = 0;
return;
}
u8g_font_calc_str_min_box(u8g, s, &buf);
u8g_font_get_str_box_fill_args(u8g, s, &buf, x, y, width, height);
}
void u8g_GetStrAMinBox(u8g_t *u8g, const char *s, u8g_uint_t *x, u8g_uint_t *y, u8g_uint_t *width, u8g_uint_t *height)
{
u8g_str_size_t buf;
uint8_t cap_a;
if ( *s == '\0' )
{
*width= 0;
*height = 0;
return;
}
cap_a = u8g_font_GetCapitalAHeight(u8g->font);
u8g_font_calc_str_min_box(u8g, s, &buf);
if ( buf.y_max < cap_a )
buf.y_max = cap_a;
u8g_font_get_str_box_fill_args(u8g, s, &buf, x, y, width, height);
}
void u8g_SetFont(u8g_t *u8g, const u8g_fntpgm_uint8_t *font)
{
if ( u8g->font != font )
{
u8g->font = font;
u8g_UpdateRefHeight(u8g);
u8g_SetFontPosBaseline(u8g);
}
}
/*========================================================================*/
/* anti aliasing fonts */
int8_t u8g_draw_aa_glyph(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
const u8g_pgm_uint8_t *data;
uint8_t w, h;
uint8_t i, j;
u8g_uint_t ix, iy;
{
u8g_glyph_t g = u8g_GetGlyph(u8g, encoding);
if ( g == NULL )
return 0;
data = u8g_font_GetGlyphDataStart(u8g->font, g);
}
w = u8g->glyph_width;
h = u8g->glyph_height;
x += u8g->glyph_x;
y -= u8g->glyph_y;
y--;
if ( u8g_IsBBXIntersection(u8g, x, y-h+1, w, h) == 0 )
return u8g->glyph_dx;
/* now, w is reused as bytes per line */
w += 3;
w /= 4;
iy = y;
iy -= h;
iy++;
for( j = 0; j < h; j++ )
{
ix = x;
for( i = 0; i < w; i++ )
{
u8g_Draw4TPixel(u8g, ix, iy, 0, u8g_pgm_read(data));
data++;
ix+=4;
}
iy++;
}
return u8g->glyph_dx;
}
int8_t u8g_DrawAAGlyph(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding)
{
y += u8g->font_calc_vref(u8g);
return u8g_draw_aa_glyph(u8g, x, y, encoding);
}
u8g_uint_t u8g_DrawAAStr(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const char *s)
{
u8g_uint_t t = 0;
int8_t d;
if ( u8g_font_GetFormat(u8g->font) != 2 )
return 0;
//u8g_uint_t u8g_GetStrWidth(u8g, s);
//u8g_font_GetFontAscent(u8g->font)-u8g_font_GetFontDescent(u8g->font);
y += u8g->font_calc_vref(u8g);
while( *s != '\0' )
{
d = u8g_draw_aa_glyph(u8g, x, y, *s);
x += d;
t += d;
s++;
}
return t;
}

@ -0,0 +1,573 @@
/*
u8g_ll_api.c
low level api
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stddef.h>
#include "u8g.h"
uint8_t u8g_call_dev_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg)
{
return dev->dev_fn(u8g, dev, msg, arg);
}
/*====================================================================*/
uint8_t u8g_InitLL(u8g_t *u8g, u8g_dev_t *dev)
{
uint8_t r;
u8g->state_cb(U8G_STATE_MSG_BACKUP_ENV);
r = u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_INIT, NULL);
u8g->state_cb(U8G_STATE_MSG_BACKUP_U8G);
u8g->state_cb(U8G_STATE_MSG_RESTORE_ENV);
return r;
}
void u8g_FirstPageLL(u8g_t *u8g, u8g_dev_t *dev)
{
u8g->state_cb(U8G_STATE_MSG_BACKUP_ENV);
u8g->state_cb(U8G_STATE_MSG_RESTORE_U8G);
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_PAGE_FIRST, NULL);
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_GET_PAGE_BOX, &(u8g->current_page));
u8g->state_cb(U8G_STATE_MSG_RESTORE_ENV);
}
uint8_t u8g_NextPageLL(u8g_t *u8g, u8g_dev_t *dev)
{
uint8_t r;
u8g->state_cb(U8G_STATE_MSG_BACKUP_ENV);
u8g->state_cb(U8G_STATE_MSG_RESTORE_U8G);
r = u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_PAGE_NEXT, NULL);
if ( r != 0 )
{
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_GET_PAGE_BOX, &(u8g->current_page));
}
u8g->state_cb(U8G_STATE_MSG_RESTORE_ENV);
return r;
}
uint8_t u8g_SetContrastLL(u8g_t *u8g, u8g_dev_t *dev, uint8_t contrast)
{
return u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_CONTRAST, &contrast);
}
void u8g_DrawPixelLL(u8g_t *u8g, u8g_dev_t *dev, u8g_uint_t x, u8g_uint_t y)
{
u8g_dev_arg_pixel_t *arg = &(u8g->arg_pixel);
arg->x = x;
arg->y = y;
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_SET_PIXEL, arg);
}
void u8g_Draw8PixelLL(u8g_t *u8g, u8g_dev_t *dev, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t pixel)
{
u8g_dev_arg_pixel_t *arg = &(u8g->arg_pixel);
arg->x = x;
arg->y = y;
arg->dir = dir;
arg->pixel = pixel;
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_SET_8PIXEL, arg);
}
void u8g_Draw4TPixelLL(u8g_t *u8g, u8g_dev_t *dev, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t pixel)
{
u8g_dev_arg_pixel_t *arg = &(u8g->arg_pixel);
arg->x = x;
arg->y = y;
arg->dir = dir;
arg->pixel = pixel;
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_SET_4TPIXEL, arg);
}
#ifdef U8G_DEV_MSG_IS_BBX_INTERSECTION
uint8_t u8g_IsBBXIntersectionLL(u8g_t *u8g, u8g_dev_t *dev, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
{
return u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_IS_BBX_INTERSECTION, &arg);
}
#endif
u8g_uint_t u8g_GetWidthLL(u8g_t *u8g, u8g_dev_t *dev)
{
u8g_uint_t r;
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_GET_WIDTH, &r);
return r;
}
u8g_uint_t u8g_GetHeightLL(u8g_t *u8g, u8g_dev_t *dev)
{
u8g_uint_t r;
u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_GET_HEIGHT, &r);
return r;
}
u8g_uint_t u8g_GetModeLL(u8g_t *u8g, u8g_dev_t *dev)
{
return u8g_call_dev_fn(u8g, dev, U8G_DEV_MSG_GET_MODE, NULL);
}
/*====================================================================*/
void u8g_UpdateDimension(u8g_t *u8g)
{
u8g->width = u8g_GetWidthLL(u8g, u8g->dev);
u8g->height = u8g_GetHeightLL(u8g, u8g->dev);
u8g->mode = u8g_GetModeLL(u8g, u8g->dev);
/* 9 Dec 2012: u8g_scale.c requires update of current page */
u8g_call_dev_fn(u8g, u8g->dev, U8G_DEV_MSG_GET_PAGE_BOX, &(u8g->current_page));
}
static void u8g_init_data(u8g_t *u8g)
{
u8g->font = NULL;
u8g->cursor_font = NULL;
u8g->cursor_bg_color = 0;
u8g->cursor_fg_color = 1;
u8g->cursor_encoding = 34;
u8g->cursor_fn = (u8g_draw_cursor_fn)0;
#if defined(U8G_WITH_PINLIST)
{
uint8_t i;
for( i = 0; i < U8G_PIN_LIST_LEN; i++ )
u8g->pin_list[i] = U8G_PIN_NONE;
}
#endif
u8g_SetColorIndex(u8g, 1);
u8g_SetFontPosBaseline(u8g);
u8g->font_height_mode = U8G_FONT_HEIGHT_MODE_XTEXT;
u8g->font_ref_ascent = 0;
u8g->font_ref_descent = 0;
u8g->font_line_spacing_factor = 64; /* 64 = 1.0, 77 = 1.2 line spacing factor */
u8g->line_spacing = 0;
u8g->state_cb = u8g_state_dummy_cb;
}
uint8_t u8g_Begin(u8g_t *u8g)
{
/* call and init low level driver and com device */
if ( u8g_InitLL(u8g, u8g->dev) == 0 )
return 0;
/* fetch width and height from the low level */
u8g_UpdateDimension(u8g);
return 1;
}
uint8_t u8g_Init(u8g_t *u8g, u8g_dev_t *dev)
{
u8g_init_data(u8g);
u8g->dev = dev;
/* On the Arduino Environment this will lead to two calls to u8g_Begin(), the following line will be called first (by U8glib constructors) */
/* if - in future releases - this is removed, then still call u8g_UpdateDimension() */
/* if Arduino call u8g_UpdateDimension else u8g_Begin */
/* issue 146 */
return u8g_Begin(u8g);
}
/* special init for pure ARM systems */
uint8_t u8g_InitComFn(u8g_t *u8g, u8g_dev_t *dev, u8g_com_fnptr com_fn)
{
u8g_init_data(u8g);
#if defined(U8G_WITH_PINLIST)
{
uint8_t i;
for( i = 0; i < U8G_PIN_LIST_LEN; i++ )
u8g->pin_list[i] = U8G_PIN_DUMMY;
}
#endif
u8g->dev = dev;
/* replace the device procedure with a custom communication procedure */
u8g->dev->com_fn = com_fn;
/* On the Arduino Environment this will lead to two calls to u8g_Begin(), the following line will be called first (by U8glib constructors) */
/* if - in future releases - this is removed, then still call u8g_UpdateDimension() */
/* if Arduino call u8g_UpdateDimension else u8g_Begin */
/* issue 146 */
return u8g_Begin(u8g);
}
#if defined(U8G_WITH_PINLIST)
uint8_t u8g_InitSPI(u8g_t *u8g, u8g_dev_t *dev, uint8_t sck, uint8_t mosi, uint8_t cs, uint8_t a0, uint8_t reset)
{
/* fill data structure with some suitable values */
u8g_init_data(u8g);
u8g->dev = dev;
/* assign user pins */
u8g->pin_list[U8G_PI_SCK] = sck;
u8g->pin_list[U8G_PI_MOSI] = mosi;
u8g->pin_list[U8G_PI_CS] = cs;
u8g->pin_list[U8G_PI_A0] = a0;
u8g->pin_list[U8G_PI_RESET] = reset;
/* On the Arduino Environment this will lead to two calls to u8g_Begin(), the following line will be called first (by U8glib constructors) */
/* if - in future releases - this is removed, then still call u8g_UpdateDimension() */
/* if Arduino call u8g_UpdateDimension else u8g_Begin */
/* issue 146 */
return u8g_Begin(u8g);
}
uint8_t u8g_InitHWSPI(u8g_t *u8g, u8g_dev_t *dev, uint8_t cs, uint8_t a0, uint8_t reset)
{
/* fill data structure with some suitable values */
u8g_init_data(u8g);
u8g->dev = dev;
/* assign user pins */
u8g->pin_list[U8G_PI_CS] = cs;
u8g->pin_list[U8G_PI_A0] = a0;
u8g->pin_list[U8G_PI_RESET] = reset;
return u8g_Begin(u8g);
}
uint8_t u8g_InitI2C(u8g_t *u8g, u8g_dev_t *dev, uint8_t options)
{
/* fill data structure with some suitable values */
u8g_init_data(u8g);
u8g->dev = dev;
u8g->pin_list[U8G_PI_I2C_OPTION] = options;
return u8g_Begin(u8g);
}
uint8_t u8g_Init8BitFixedPort(u8g_t *u8g, u8g_dev_t *dev, uint8_t en, uint8_t cs, uint8_t di, uint8_t rw, uint8_t reset)
{
/* fill data structure with some suitable values */
u8g_init_data(u8g);
u8g->dev = dev;
/* assign user pins */
u8g->pin_list[U8G_PI_EN] = en;
u8g->pin_list[U8G_PI_CS] = cs;
u8g->pin_list[U8G_PI_DI] = di;
u8g->pin_list[U8G_PI_RW] = rw;
u8g->pin_list[U8G_PI_RESET] = reset;
return u8g_Begin(u8g);
}
uint8_t u8g_Init8Bit(u8g_t *u8g, u8g_dev_t *dev, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
uint8_t en, uint8_t cs1, uint8_t cs2, uint8_t di, uint8_t rw, uint8_t reset)
{
/* fill data structure with some suitable values */
u8g_init_data(u8g);
u8g->dev = dev;
/* assign user pins */
u8g->pin_list[U8G_PI_D0] = d0;
u8g->pin_list[U8G_PI_D1] = d1;
u8g->pin_list[U8G_PI_D2] = d2;
u8g->pin_list[U8G_PI_D3] = d3;
u8g->pin_list[U8G_PI_D4] = d4;
u8g->pin_list[U8G_PI_D5] = d5;
u8g->pin_list[U8G_PI_D6] = d6;
u8g->pin_list[U8G_PI_D7] = d7;
u8g->pin_list[U8G_PI_EN] = en;
u8g->pin_list[U8G_PI_CS1] = cs1;
u8g->pin_list[U8G_PI_CS2] = cs2;
u8g->pin_list[U8G_PI_DI] = di;
u8g->pin_list[U8G_PI_RW] = rw;
u8g->pin_list[U8G_PI_RESET] = reset;
return u8g_Begin(u8g);
}
/*
PIN_D0 8
PIN_D1 9
PIN_D2 10
PIN_D3 11
PIN_D4 4
PIN_D5 5
PIN_D6 6
PIN_D7 7
PIN_CS 14
PIN_A0 15
PIN_RESET 16
PIN_WR 17
PIN_RD 18
u8g_InitRW8Bit(u8g, dev, d0, d1, d2, d3, d4, d5, d6, d7, cs, a0, wr, rd, reset)
u8g_InitRW8Bit(u8g, dev, 8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16)
*/
uint8_t u8g_InitRW8Bit(u8g_t *u8g, u8g_dev_t *dev, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
uint8_t cs, uint8_t a0, uint8_t wr, uint8_t rd, uint8_t reset)
{
/* fill data structure with some suitable values */
u8g_init_data(u8g);
u8g->dev = dev;
/* assign user pins */
u8g->pin_list[U8G_PI_D0] = d0;
u8g->pin_list[U8G_PI_D1] = d1;
u8g->pin_list[U8G_PI_D2] = d2;
u8g->pin_list[U8G_PI_D3] = d3;
u8g->pin_list[U8G_PI_D4] = d4;
u8g->pin_list[U8G_PI_D5] = d5;
u8g->pin_list[U8G_PI_D6] = d6;
u8g->pin_list[U8G_PI_D7] = d7;
u8g->pin_list[U8G_PI_CS] = cs;
u8g->pin_list[U8G_PI_A0] = a0;
u8g->pin_list[U8G_PI_WR] = wr;
u8g->pin_list[U8G_PI_RD] = rd;
u8g->pin_list[U8G_PI_RESET] = reset;
return u8g_Begin(u8g);
}
#endif /* defined(U8G_WITH_PINLIST) */
void u8g_FirstPage(u8g_t *u8g)
{
u8g_FirstPageLL(u8g, u8g->dev);
}
uint8_t u8g_NextPage(u8g_t *u8g)
{
if ( u8g->cursor_fn != (u8g_draw_cursor_fn)0 )
{
u8g->cursor_fn(u8g);
}
return u8g_NextPageLL(u8g, u8g->dev);
}
uint8_t u8g_SetContrast(u8g_t *u8g, uint8_t contrast)
{
return u8g_SetContrastLL(u8g, u8g->dev, contrast);
}
void u8g_SleepOn(u8g_t *u8g)
{
u8g_call_dev_fn(u8g, u8g->dev, U8G_DEV_MSG_SLEEP_ON, NULL);
}
void u8g_SleepOff(u8g_t *u8g)
{
u8g_call_dev_fn(u8g, u8g->dev, U8G_DEV_MSG_SLEEP_OFF, NULL);
}
void u8g_DrawPixel(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y)
{
u8g_DrawPixelLL(u8g, u8g->dev, x, y);
}
void u8g_Draw8Pixel(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t pixel)
{
u8g_Draw8PixelLL(u8g, u8g->dev, x, y, dir, pixel);
}
void u8g_Draw4TPixel(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t pixel)
{
u8g_Draw4TPixelLL(u8g, u8g->dev, x, y, dir, pixel);
}
/* u8g_IsBBXIntersection() has been moved to u8g_clip.c */
#ifdef OBSOLETE_CODE
uint8_t u8g_IsBBXIntersection(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
{
/* new code */
u8g_dev_arg_bbx_t arg;
arg.x = x;
arg.y = y;
arg.w = w;
arg.h = h;
return u8g_is_box_bbx_intersection(&(u8g->current_page), &arg);
/* old code */
//return u8g_IsBBXIntersectionLL(u8g, u8g->dev, x, y, w, h);
}
#endif
/*
idx: index for the palette entry (0..255)
r: value for red (0..255)
g: value for green (0..255)
b: value for blue (0..255)
*/
void u8g_SetColorEntry(u8g_t *u8g, uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
u8g_dev_arg_irgb_t irgb;
irgb.idx = idx;
irgb.r = r;
irgb.g = g;
irgb.b = b;
u8g_call_dev_fn(u8g, u8g->dev, U8G_DEV_MSG_SET_COLOR_ENTRY, &irgb);
}
void u8g_SetColorIndex(u8g_t *u8g, uint8_t idx)
{
u8g->arg_pixel.color = idx;
/*u8g->color_index = idx; */ /* must be removed */
}
void u8g_SetHiColor(u8g_t *u8g, uint16_t rgb)
{
u8g->arg_pixel.color = rgb&255;
u8g->arg_pixel.hi_color = rgb>>8;
/*u8g->color_index = idx; */ /* must be removed */
}
void u8g_SetHiColorByRGB(u8g_t *u8g, uint8_t r, uint8_t g, uint8_t b)
{
r &= ~7;
g >>= 2;
b >>= 3;
u8g->arg_pixel.color = b;
u8g->arg_pixel.color |= (g & 7) << 5;
u8g->arg_pixel.hi_color = r;
u8g->arg_pixel.hi_color |= (g>>3) & 7;
//u8g_SetHiColor(u8g, U8G_GET_HICOLOR_BY_RGB(r,g,b));
}
void u8g_SetRGB(u8g_t *u8g, uint8_t r, uint8_t g, uint8_t b)
{
if ( u8g->mode == U8G_MODE_R3G3B2 )
{
r &= 0x0e0;
g &= 0x0e0;
g >>= 3;
b >>= 6;
u8g->arg_pixel.color = r | g | b;
}
else if ( u8g->mode == U8G_MODE_HICOLOR )
{
u8g_SetHiColorByRGB(u8g, r,g,b);
}
else
{
u8g->arg_pixel.color = r;
u8g->arg_pixel.hi_color = g;
u8g->arg_pixel.blue = b;
}
}
uint8_t u8g_GetColorIndex(u8g_t *u8g)
{
return u8g->arg_pixel.color;
}
uint8_t u8g_GetDefaultForegroundColor(u8g_t *u8g)
{
uint8_t mode;
mode = u8g_GetMode(u8g);
if ( mode == U8G_MODE_R3G3B2 )
return 255; /* white */
else if ( u8g_GetMode(u8g) == U8G_MODE_GRAY2BIT )
return 3; /* max intensity */
else /* if ( u8g.getMode() == U8G_MODE_BW ) */
return 1; /* pixel on */
return 1;
}
void u8g_SetDefaultForegroundColor(u8g_t *u8g)
{
if ( u8g->mode == U8G_MODE_HICOLOR )
{
u8g->arg_pixel.color = 0x0ff;
u8g->arg_pixel.hi_color = 0x0ff;
}
else
{
u8g_SetColorIndex(u8g, u8g_GetDefaultForegroundColor(u8g));
}
}
uint8_t u8g_GetDefaultBackgroundColor(u8g_t *u8g)
{
return 0;
}
void u8g_SetDefaultBackgroundColor(u8g_t *u8g)
{
u8g_SetColorIndex(u8g, u8g_GetDefaultBackgroundColor(u8g)); /* pixel on / black */
}
uint8_t u8g_GetDefaultMidColor(u8g_t *u8g)
{
uint8_t mode;
mode = u8g_GetMode(u8g);
if ( mode == U8G_MODE_R3G3B2 )
return 0x06d; /* gray: 01101101 */
else if ( u8g_GetMode(u8g) == U8G_MODE_GRAY2BIT )
return 1; /* low mid intensity */
else /* if ( u8g.getMode() == U8G_MODE_BW ) */
return 1; /* pixel on */
return 1; /* default */
}
void u8g_SetDefaultMidColor(u8g_t *u8g)
{
u8g_SetColorIndex(u8g, u8g_GetDefaultMidColor(u8g));
}

@ -0,0 +1,81 @@
/*
u8g_page.c
page helper functions, only called by the dev handler.
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
/*
setup page count structure
conditions: page_height <= total_height
*/
void u8g_page_Init(u8g_page_t *p, u8g_uint_t page_height, u8g_uint_t total_height )
{
p->page_height = page_height;
p->total_height = total_height;
p->page = 0;
u8g_page_First(p);
}
void u8g_page_First(u8g_page_t *p)
{
p->page_y0 = 0;
p->page_y1 = p->page_height;
p->page_y1--;
p->page = 0;
}
uint8_t u8g_page_Next(u8g_page_t * p)
{
register u8g_uint_t y1;
p->page_y0 += p->page_height;
if ( p->page_y0 >= p->total_height )
return 0;
p->page++;
y1 = p->page_y1;
y1 += p->page_height;
if ( y1 >= p->total_height )
{
y1 = p->total_height;
y1--;
}
p->page_y1 = y1;
return 1;
}

@ -0,0 +1,191 @@
/*
u8g_pb.c
common procedures for the page buffer
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
void u8g_pb_Clear(u8g_pb_t *b)
{
uint8_t *ptr = (uint8_t *)b->buf;
uint8_t *end_ptr = ptr;
end_ptr += b->width;
do
{
*ptr++ = 0;
} while( ptr != end_ptr );
}
/* the following procedure does not work. why? Can be checked with descpic */
/*
void u8g_pb_Clear(u8g_pb_t *b)
{
uint8_t *ptr = (uint8_t *)b->buf;
uint8_t cnt = b->width;
do
{
*ptr++ = 0;
cnt--;
} while( cnt != 0 );
}
*/
/*
intersection assumptions:
a1 <= a2 is always true
*/
/*
minimized version
---1----0 1 b1 <= a2 && b1 > b2
-----1--0 1 b2 >= a1 && b1 > b2
---1-1--- 1 b1 <= a2 && b2 >= a1
*/
/*
uint8_t u8g_pb8v1_IsYIntersection___Old(u8g_pb_t *b, u8g_uint_t v0, u8g_uint_t v1)
{
uint8_t c0, c1, c;
c0 = v0 <= b->p.page_y1;
c1 = v1 >= b->p.page_y0;
c = v0 > v1;
if ( c0 && c1 ) return 1;
if ( c0 && c ) return 1;
if ( c1 && c ) return 1;
return 0;
}
*/
uint8_t u8g_pb_IsYIntersection(u8g_pb_t *pb, u8g_uint_t v0, u8g_uint_t v1)
{
uint8_t c1, c2, c3, tmp;
c1 = v0 <= pb->p.page_y1;
c2 = v1 >= pb->p.page_y0;
c3 = v0 > v1;
/*
if ( c1 && c2 )
return 1;
if ( c1 && c3 )
return 1;
if ( c2 && c3 )
return 1;
return 0;
*/
tmp = c1;
c1 &= c2;
c2 &= c3;
c3 &= tmp;
c1 |= c2;
c1 |= c3;
return c1 & 1;
}
uint8_t u8g_pb_IsXIntersection(u8g_pb_t *b, u8g_uint_t v0, u8g_uint_t v1)
{
uint8_t /*c0, c1, */ c2, c3;
/*
conditions: b->p.page_y0 < b->p.page_y1
there are no restriction on v0 and v1. If v0 > v1, then warp around unsigned is assumed
*/
/*
c0 = v0 < 0;
c1 = v1 < 0;
*/
c2 = v0 > b->width;
c3 = v1 > b->width;
/*if ( c0 && c1 ) return 0;*/
if ( c2 && c3 ) return 0;
/*if ( c1 && c2 ) return 0;*/
return 1;
}
uint8_t u8g_pb_IsIntersection(u8g_pb_t *pb, u8g_dev_arg_bbx_t *bbx)
{
u8g_uint_t tmp;
tmp = bbx->y;
tmp += bbx->h;
tmp--;
if ( u8g_pb_IsYIntersection(pb, bbx->y, tmp) == 0 )
return 0;
/* maybe this one can be skiped... probability is very high to have an intersection, so it would be ok to always return 1 */
tmp = bbx->x;
tmp += bbx->w;
tmp--;
return u8g_pb_IsXIntersection(pb, bbx->x, tmp);
}
void u8g_pb_GetPageBox(u8g_pb_t *pb, u8g_box_t *box)
{
box->x0 = 0;
box->y0 = pb->p.page_y0;
box->x1 = pb->width;
box->x1--;
box->y1 = pb->p.page_y1;
}
uint8_t u8g_pb_Is8PixelVisible(u8g_pb_t *b, u8g_dev_arg_pixel_t *arg_pixel)
{
u8g_uint_t v0, v1;
v0 = arg_pixel->y;
v1 = v0;
switch( arg_pixel->dir )
{
case 0:
break;
case 1:
v1 += 8; /* this is independent from the page height */
break;
case 2:
break;
case 3:
v0 -= 8;
break;
}
return u8g_pb_IsYIntersection(b, v0, v1);
}
uint8_t u8g_pb_WriteBuffer(u8g_pb_t *b, u8g_t *u8g, u8g_dev_t *dev)
{
return u8g_WriteSequence(u8g, dev, b->width, b->buf);
}

@ -0,0 +1,213 @@
/*
u8g_pb16h1.c
2x 8bit height monochrom (1 bit) page buffer
byte has horizontal orientation
Universal 8bit Graphics Library
Copyright (c) 2012, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
total buffer size is limited to 2*256 bytes because of the calculation inside the set pixel procedure
*/
#include "u8g.h"
#include <string.h>
void u8g_pb16h1_Init(u8g_pb_t *b, void *buf, u8g_uint_t width) U8G_NOINLINE;
void u8g_pb16h1_set_pixel(u8g_pb_t *b, u8g_uint_t x, u8g_uint_t y, uint8_t color_index) U8G_NOINLINE;
void u8g_pb16h1_SetPixel(u8g_pb_t *b, const u8g_dev_arg_pixel_t * const arg_pixel) U8G_NOINLINE ;
void u8g_pb16h1_Set8PixelStd(u8g_pb_t *b, u8g_dev_arg_pixel_t *arg_pixel) U8G_NOINLINE;
uint8_t u8g_dev_pb8h1_base_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg);
void u8g_pb16h1_Clear(u8g_pb_t *b)
{
uint8_t *ptr = (uint8_t *)b->buf;
uint8_t *end_ptr = ptr;
end_ptr += b->width*2;
do
{
*ptr++ = 0;
} while( ptr != end_ptr );
}
void u8g_pb16h1_Init(u8g_pb_t *b, void *buf, u8g_uint_t width)
{
b->buf = buf;
b->width = width;
u8g_pb16h1_Clear(b);
}
/* limitation: total buffer must not exceed 2*256 bytes */
void u8g_pb16h1_set_pixel(u8g_pb_t *b, u8g_uint_t x, u8g_uint_t y, uint8_t color_index)
{
register uint8_t mask;
u8g_uint_t tmp;
uint8_t *ptr = b->buf;
y -= b->p.page_y0;
if ( y >= 8 )
{
ptr += b->width;
y &= 0x07;
}
tmp = b->width;
tmp >>= 3;
tmp *= (uint8_t)y;
ptr += tmp;
mask = 0x080;
mask >>= x & 7;
x >>= 3;
ptr += x;
if ( color_index )
{
*ptr |= mask;
}
else
{
mask ^=0xff;
*ptr &= mask;
}
}
void u8g_pb16h1_SetPixel(u8g_pb_t *b, const u8g_dev_arg_pixel_t * const arg_pixel)
{
if ( arg_pixel->y < b->p.page_y0 )
return;
if ( arg_pixel->y > b->p.page_y1 )
return;
if ( arg_pixel->x >= b->width )
return;
u8g_pb16h1_set_pixel(b, arg_pixel->x, arg_pixel->y, arg_pixel->color);
}
void u8g_pb16h1_Set8PixelStd(u8g_pb_t *b, u8g_dev_arg_pixel_t *arg_pixel)
{
register uint8_t pixel = arg_pixel->pixel;
do
{
if ( pixel & 128 )
{
u8g_pb16h1_SetPixel(b, arg_pixel);
}
switch( arg_pixel->dir )
{
case 0: arg_pixel->x++; break;
case 1: arg_pixel->y++; break;
case 2: arg_pixel->x--; break;
case 3: arg_pixel->y--; break;
}
pixel <<= 1;
} while( pixel != 0 );
}
void u8g_pb16h1_Set8PixelOpt2(u8g_pb_t *b, u8g_dev_arg_pixel_t *arg_pixel)
{
register uint8_t pixel = arg_pixel->pixel;
u8g_uint_t dx = 0;
u8g_uint_t dy = 0;
switch( arg_pixel->dir )
{
case 0: dx++; break;
case 1: dy++; break;
case 2: dx--; break;
case 3: dy--; break;
}
do
{
if ( pixel & 128 )
u8g_pb16h1_SetPixel(b, arg_pixel);
arg_pixel->x += dx;
arg_pixel->y += dy;
pixel <<= 1;
} while( pixel != 0 );
}
uint8_t u8g_dev_pb16h1_base_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg)
{
u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
switch(msg)
{
case U8G_DEV_MSG_SET_8PIXEL:
if ( u8g_pb_Is8PixelVisible(pb, (u8g_dev_arg_pixel_t *)arg) )
u8g_pb16h1_Set8PixelOpt2(pb, (u8g_dev_arg_pixel_t *)arg);
break;
case U8G_DEV_MSG_SET_PIXEL:
u8g_pb16h1_SetPixel(pb, (u8g_dev_arg_pixel_t *)arg);
break;
case U8G_DEV_MSG_INIT:
break;
case U8G_DEV_MSG_STOP:
break;
case U8G_DEV_MSG_PAGE_FIRST:
u8g_pb16h1_Clear(pb);
u8g_page_First(&(pb->p));
break;
case U8G_DEV_MSG_PAGE_NEXT:
if ( u8g_page_Next(&(pb->p)) == 0 )
return 0;
u8g_pb16h1_Clear(pb);
break;
#ifdef U8G_DEV_MSG_IS_BBX_INTERSECTION
case U8G_DEV_MSG_IS_BBX_INTERSECTION:
return u8g_pb_IsIntersection(pb, (u8g_dev_arg_bbx_t *)arg);
#endif
case U8G_DEV_MSG_GET_PAGE_BOX:
u8g_pb_GetPageBox(pb, (u8g_box_t *)arg);
break;
case U8G_DEV_MSG_GET_WIDTH:
*((u8g_uint_t *)arg) = pb->width;
break;
case U8G_DEV_MSG_GET_HEIGHT:
*((u8g_uint_t *)arg) = pb->p.total_height;
break;
case U8G_DEV_MSG_SET_COLOR_ENTRY:
break;
case U8G_DEV_MSG_SET_XY_CB:
break;
case U8G_DEV_MSG_GET_MODE:
return U8G_MODE_BW;
}
return 1;
}

@ -0,0 +1,232 @@
/*
u8g_rect.c
U8G high level interface for horizontal and vertical things
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
void u8g_draw_hline(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w)
{
uint8_t pixel = 0x0ff;
while( w >= 8 )
{
u8g_Draw8Pixel(u8g, x, y, 0, pixel);
w-=8;
x+=8;
}
if ( w != 0 )
{
w ^=7;
w++;
pixel <<= w&7;
u8g_Draw8Pixel(u8g, x, y, 0, pixel);
}
}
void u8g_draw_vline(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t h)
{
uint8_t pixel = 0x0ff;
while( h >= 8 )
{
u8g_Draw8Pixel(u8g, x, y, 1, pixel);
h-=8;
y+=8;
}
if ( h != 0 )
{
h ^=7;
h++;
pixel <<= h&7;
u8g_Draw8Pixel(u8g, x, y, 1, pixel);
}
}
void u8g_DrawHLine(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w)
{
if ( u8g_IsBBXIntersection(u8g, x, y, w, 1) == 0 )
return;
u8g_draw_hline(u8g, x, y, w);
}
void u8g_DrawVLine(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w)
{
if ( u8g_IsBBXIntersection(u8g, x, y, 1, w) == 0 )
return;
u8g_draw_vline(u8g, x, y, w);
}
/* restrictions: w > 0 && h > 0 */
void u8g_DrawFrame(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
{
u8g_uint_t xtmp = x;
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
u8g_draw_hline(u8g, x, y, w);
u8g_draw_vline(u8g, x, y, h);
x+=w;
x--;
u8g_draw_vline(u8g, x, y, h);
y+=h;
y--;
u8g_draw_hline(u8g, xtmp, y, w);
}
void u8g_draw_box(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
{
do
{
u8g_draw_hline(u8g, x, y, w);
y++;
h--;
} while( h != 0 );
}
/* restrictions: h > 0 */
void u8g_DrawBox(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
{
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
u8g_draw_box(u8g, x, y, w, h);
}
void u8g_DrawRFrame(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, u8g_uint_t r)
{
u8g_uint_t xl, yu;
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
xl = x;
xl += r;
yu = y;
yu += r;
{
u8g_uint_t yl, xr;
xr = x;
xr += w;
xr -= r;
xr -= 1;
yl = y;
yl += h;
yl -= r;
yl -= 1;
u8g_draw_circle(u8g, xl, yu, r, U8G_DRAW_UPPER_LEFT);
u8g_draw_circle(u8g, xr, yu, r, U8G_DRAW_UPPER_RIGHT);
u8g_draw_circle(u8g, xl, yl, r, U8G_DRAW_LOWER_LEFT);
u8g_draw_circle(u8g, xr, yl, r, U8G_DRAW_LOWER_RIGHT);
}
{
u8g_uint_t ww, hh;
ww = w;
ww -= r;
ww -= r;
ww -= 2;
hh = h;
hh -= r;
hh -= r;
hh -= 2;
xl++;
yu++;
h--;
w--;
u8g_draw_hline(u8g, xl, y, ww);
u8g_draw_hline(u8g, xl, y+h, ww);
u8g_draw_vline(u8g, x, yu, hh);
u8g_draw_vline(u8g, x+w, yu, hh);
}
}
void u8g_DrawRBox(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, u8g_uint_t r)
{
u8g_uint_t xl, yu;
u8g_uint_t yl, xr;
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
xl = x;
xl += r;
yu = y;
yu += r;
xr = x;
xr += w;
xr -= r;
xr -= 1;
yl = y;
yl += h;
yl -= r;
yl -= 1;
u8g_draw_disc(u8g, xl, yu, r, U8G_DRAW_UPPER_LEFT);
u8g_draw_disc(u8g, xr, yu, r, U8G_DRAW_UPPER_RIGHT);
u8g_draw_disc(u8g, xl, yl, r, U8G_DRAW_LOWER_LEFT);
u8g_draw_disc(u8g, xr, yl, r, U8G_DRAW_LOWER_RIGHT);
{
u8g_uint_t ww, hh;
ww = w;
ww -= r;
ww -= r;
ww -= 2;
hh = h;
hh -= r;
hh -= r;
hh -= 2;
xl++;
yu++;
h--;
u8g_draw_box(u8g, xl, y, ww, r+1);
u8g_draw_box(u8g, xl, yl, ww, r+1);
//u8g_draw_hline(u8g, xl, y+h, ww);
u8g_draw_box(u8g, x, yu, w, hh);
//u8g_draw_vline(u8g, x+w, yu, hh);
}
}

@ -0,0 +1,150 @@
/*
u8g_state.c
backup and restore hardware state
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
state callback: backup env U8G_STATE_MSG_BACKUP_ENV
device callback: DEV_MSG_INIT
state callback: backup u8g U8G_STATE_MSG_BACKUP_U8G
state callback: restore env U8G_STATE_MSG_RESTORE_ENV
state callback: backup env U8G_STATE_MSG_BACKUP_ENV
state callback: retore u8g U8G_STATE_MSG_RESTORE_U8G
DEV_MSG_PAGE_FIRST or DEV_MSG_PAGE_NEXT
state callback: restore env U8G_STATE_MSG_RESTORE_ENV
*/
#include <stddef.h>
#include "u8g.h"
void u8g_state_dummy_cb(uint8_t msg)
{
/* the dummy procedure does nothing */
}
void u8g_SetHardwareBackup(u8g_t *u8g, u8g_state_cb backup_cb)
{
u8g->state_cb = backup_cb;
/* in most cases the init message was already sent, so this will backup the */
/* current u8g state */
backup_cb(U8G_STATE_MSG_BACKUP_U8G);
}
/*===============================================================*/
/* register variable for restoring interrupt state */
#if defined(__AVR__)
uint8_t global_SREG_backup;
#endif
/*===============================================================*/
/* AVR */
#if defined(__AVR__)
#define U8G_ATMEGA_HW_SPI
/* remove the definition for attiny */
#if __AVR_ARCH__ == 2
#undef U8G_ATMEGA_HW_SPI
#endif
#if __AVR_ARCH__ == 25
#undef U8G_ATMEGA_HW_SPI
#endif
#endif
#if defined(U8G_ATMEGA_HW_SPI)
#include <avr/interrupt.h>
static uint8_t u8g_state_avr_spi_memory[2];
void u8g_backup_spi(uint8_t msg)
{
if ( U8G_STATE_MSG_IS_BACKUP(msg) )
{
u8g_state_avr_spi_memory[U8G_STATE_MSG_GET_IDX(msg)] = SPCR;
}
else
{
uint8_t tmp = SREG;
cli();
SPCR = 0;
SPCR = u8g_state_avr_spi_memory[U8G_STATE_MSG_GET_IDX(msg)];
SREG = tmp;
}
}
#elif defined(ARDUINO) && defined(__arm__) // Arduino Due, maybe we should better check for __SAM3X8E__
#include "sam.h"
struct sam_backup_struct
{
uint32_t mr;
uint32_t sr;
uint32_t csr[4];
} sam_backup[2];
void u8g_backup_spi(uint8_t msg)
{
uint8_t idx = U8G_STATE_MSG_GET_IDX(msg);
if ( U8G_STATE_MSG_IS_BACKUP(msg) )
{
sam_backup[idx].mr = SPI0->SPI_MR;
sam_backup[idx].sr = SPI0->SPI_SR;
sam_backup[idx].csr[0] = SPI0->SPI_CSR[0];
sam_backup[idx].csr[1] = SPI0->SPI_CSR[1];
sam_backup[idx].csr[2] = SPI0->SPI_CSR[2];
sam_backup[idx].csr[3] = SPI0->SPI_CSR[3];
}
else
{
SPI0->SPI_MR = sam_backup[idx].mr;
SPI0->SPI_CSR[0] = sam_backup[idx].csr[0];
SPI0->SPI_CSR[1] = sam_backup[idx].csr[1];
SPI0->SPI_CSR[2] = sam_backup[idx].csr[2];
SPI0->SPI_CSR[3] = sam_backup[idx].csr[3];
}
}
#else
void u8g_backup_spi(uint8_t msg)
{
}
#endif

@ -62,7 +62,7 @@
#error Angelfish_Aero // Titan AERO (Angelfish)
#endif
#define LULZBOT_FW_VERSION ".15"
#define LULZBOT_FW_VERSION ".16"
// Select options based on printer model
@ -74,7 +74,7 @@
#if defined(LULZBOT_Huerfano_Mini)
// Prototype Mini w/ Z-Belt
#define LULZBOT_CUSTOM_MACHINE_NAME "Mini Z-Belt"
#define LULZBOT_CUSTOM_MACHINE_NAME "Mini 2"
#define LULZBOT_IS_MINI
#define LULZBOT_MINI_BED
#endif
@ -88,7 +88,7 @@
#if defined(LULZBOT_Huerfano_GLCD)
// Prototype Mini w/ Z-Belt
#define LULZBOT_CUSTOM_MACHINE_NAME "Mini GLCD Z-Belt"
#define LULZBOT_CUSTOM_MACHINE_NAME "Mini 2 GLCD"
#define LULZBOT_IS_MINI
#define LULZBOT_MINI_BED
#define LULZBOT_USE_LCD_DISPLAY
@ -274,7 +274,6 @@
#define LULZBOT_PROBE_DOUBLE_TOUCH
#define LULZBOT_X_PROBE_OFFSET_FROM_EXTRUDER 0
#define LULZBOT_Y_PROBE_OFFSET_FROM_EXTRUDER 0
#define LULZBOT_Z_PROBE_OFFSET_FROM_EXTRUDER -1.5
#define LULZBOT_Z_PROBE_OFFSET_RANGE_MIN -2
#define LULZBOT_Z_PROBE_OFFSET_RANGE_MAX 5
#define LULZBOT_XY_PROBE_SPEED 6000
@ -580,6 +579,8 @@
#define LULZBOT_Z_MAX_POS 160
#define LULZBOT_Z_MIN_POS 0
#define LULZBOT_Z_PROBE_OFFSET_FROM_EXTRUDER -1.43
#elif defined(LULZBOT_IS_TAZ)
#define DIGIPOT_MOTOR_CURRENT_XY 175
#define LULZBOT_XY_STEPS 100.5
@ -590,7 +591,9 @@
#define LULZBOT_DEFAULT_ACCELERATION 500
#endif
#define LULZBOT_DEFAULT_TRAVEL_ACCELERATION 3000
#define LULZBOT_Z_MIN_POS 0
#define LULZBOT_Z_MIN_POS 0
#define LULZBOT_Z_PROBE_OFFSET_FROM_EXTRUDER -1.5
#endif
#if defined(LULZBOT_Gladiola_Mini) || defined(LULZBOT_Gladiola_GLCD)

@ -1,15 +1,94 @@
#!/bin/sh
# Copyright (C) 2017 AlephObjects, Inc.
#
#
# The bash script in this page is free software: you can
# redistribute it and/or modify it under the terms of the GNU Affero
# General Public License (GNU AGPL) as published by the Free Software
# Foundation, either version 3 of the License, or (at your option)
# any later version. The code is distributed WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
#
####
# build_firmware <printer> <toolhead>
#
# Compiles firmware for the specified printer and toolhead
#
build_firmware() {
printer=$1
toolhead=$2
echo
echo Building for ${printer} and ${toolhead}
echo
(cd Marlin; make clean; make $MAKEOPTS MODEL=${printer} TOOLHEAD=${toolhead}) || exit
(cd Marlin; make clean; make $MAKEOPTS AVR_TOOLS_PATH=${AVR_TOOLS_PATH}/ MODEL=${printer} TOOLHEAD=${toolhead}) || exit
mv Marlin/applet/*.hex build
}
####
# check_tool <exec_name>
#
# Checks whether a tool exists in the AVR_TOOLS_PATH
#
check_tool() {
if [ ! -x "$AVR_TOOLS_PATH/$1" ]; then
echo Cannot locate $1 in $AVR_TOOLS_PATH.
exit 1
fi
}
####
# locate_avr_tools
#
# Attempts to locate the avr tools, otherwise prompts
# the user for a location.
#
locate_avr_tools() {
AVR_OBJCOPY=`which avr-objcopy`
if [ $? -eq 0 ]; then
AVR_TOOLS_PATH=`dirname $AVR_OBJCOPY`
fi
while [ ! -x $AVR_TOOLS_PATH/avr-gcc ]
do
echo
echo avr-gcc tools not found!
echo
read -p "Type path to avr-gcc tools: " AVR_TOOLS_PATH
if [ -z $AVR_TOOLS_PATH ]; then
echo Aborting.
exit
fi
done
}
####
# check_avr_tools
#
# Verify that all the AVR tools we need exist in the located
# directory.
#
check_avr_tools() {
echo
echo Using $AVR_TOOLS_PATH for avr-gcc tools.
echo
check_tool avr-gcc
check_tool avr-objcopy
check_tool avr-g++
check_tool avr-objdump
check_tool avr-ar
check_tool avr-size
}
############################################
# MAIN SCRIPT
############################################
locate_avr_tools
check_avr_tools
rm -rf build
mkdir build

Loading…
Cancel
Save