From 23ba8f6e7c9390df2a38aac348e4598858ff44fe Mon Sep 17 00:00:00 2001 From: Nigel Vander Houwen Date: Sat, 20 Jun 2015 13:37:48 -0700 Subject: [PATCH] Initial commit of HamShield library and example sketches. Probably not fully functional. --- examples/APRS-Beacon/1200.wav | Bin 0 -> 178 bytes examples/APRS-Beacon/2200.wav | Bin 0 -> 174 bytes examples/ChromeHAMShield/background.js | 8 + examples/ChromeHAMShield/manifest.json | 10 + examples/ChromeHAMShield/project.ps | 1 + examples/ChromeHAMShield/styles.css | 1 + examples/ChromeHAMShield/window.html | 13 + examples/FMBeacon/FMBeacon.ino | 53 + examples/FixMe/DTMFDecoder/DTMFDecoder.ino | 283 ++++ examples/FoxHunt/FoxHunt.ino | 37 + examples/Gauges/Gauges.ino | 99 ++ examples/HAMBot/HAMBot.ino | 32 + examples/Identifier/Identifier.ino | 80 + examples/Parrot/Parrot.ino | 111 ++ examples/SSTV/SSTV.ino | 45 + .../SerialTransceiver/SerialTransceiver.ino | 203 +++ examples/SignalTest/SignalTest.ino | 140 ++ examples/SignalTest/Sounds/0.wav | Bin 0 -> 4204 bytes examples/SignalTest/Sounds/1.wav | Bin 0 -> 2196 bytes examples/SignalTest/Sounds/2.wav | Bin 0 -> 2794 bytes examples/SignalTest/Sounds/3.wav | Bin 0 -> 3244 bytes examples/SignalTest/Sounds/4.wav | Bin 0 -> 2850 bytes examples/SignalTest/Sounds/5.wav | Bin 0 -> 3294 bytes examples/SignalTest/Sounds/6.wav | Bin 0 -> 2348 bytes examples/SignalTest/Sounds/7.wav | Bin 0 -> 2956 bytes examples/SignalTest/Sounds/8.wav | Bin 0 -> 2106 bytes examples/SignalTest/Sounds/9.wav | Bin 0 -> 3910 bytes examples/SignalTest/Sounds/dbm.wav | Bin 0 -> 6316 bytes examples/SignalTest/Sounds/minus.wav | Bin 0 -> 4790 bytes keywords.txt | 30 + src/HamShield.cpp | 1362 +++++++++++++++ src/HamShield.h | 554 +++++++ src/I2Cdev_rda.cpp | 1458 +++++++++++++++++ src/I2Cdev_rda.h | 269 +++ 34 files changed, 4789 insertions(+) create mode 100755 examples/APRS-Beacon/1200.wav create mode 100755 examples/APRS-Beacon/2200.wav create mode 100755 examples/ChromeHAMShield/background.js create mode 100755 examples/ChromeHAMShield/manifest.json create mode 100755 examples/ChromeHAMShield/project.ps create mode 100755 examples/ChromeHAMShield/styles.css create mode 100755 examples/ChromeHAMShield/window.html create mode 100644 examples/FMBeacon/FMBeacon.ino create mode 100755 examples/FixMe/DTMFDecoder/DTMFDecoder.ino create mode 100755 examples/FoxHunt/FoxHunt.ino create mode 100755 examples/Gauges/Gauges.ino create mode 100755 examples/HAMBot/HAMBot.ino create mode 100755 examples/Identifier/Identifier.ino create mode 100755 examples/Parrot/Parrot.ino create mode 100755 examples/SSTV/SSTV.ino create mode 100755 examples/SerialTransceiver/SerialTransceiver.ino create mode 100755 examples/SignalTest/SignalTest.ino create mode 100755 examples/SignalTest/Sounds/0.wav create mode 100755 examples/SignalTest/Sounds/1.wav create mode 100755 examples/SignalTest/Sounds/2.wav create mode 100755 examples/SignalTest/Sounds/3.wav create mode 100755 examples/SignalTest/Sounds/4.wav create mode 100755 examples/SignalTest/Sounds/5.wav create mode 100755 examples/SignalTest/Sounds/6.wav create mode 100755 examples/SignalTest/Sounds/7.wav create mode 100755 examples/SignalTest/Sounds/8.wav create mode 100755 examples/SignalTest/Sounds/9.wav create mode 100755 examples/SignalTest/Sounds/dbm.wav create mode 100755 examples/SignalTest/Sounds/minus.wav create mode 100644 keywords.txt create mode 100644 src/HamShield.cpp create mode 100644 src/HamShield.h create mode 100644 src/I2Cdev_rda.cpp create mode 100644 src/I2Cdev_rda.h diff --git a/examples/APRS-Beacon/1200.wav b/examples/APRS-Beacon/1200.wav new file mode 100755 index 0000000000000000000000000000000000000000..de711939e6387e8f172a98a90dea9bcd2f695fdc GIT binary patch literal 178 zcmV;j08Rf=Nk&Gh00012K~_a(ZFC?I000010096%9{>P=J^%m$01yCVVRT`J0001C z3I|bLV(K1l#0;5H#4I1wVQ^Ak0Me}Lo)+M3JTqonJUQUFo)WDQ0LxNrVWA(-!=9PP z!>}J#Vd+xr|30mRo_63BJcDKvJbB=Lo=C0V|M^lwVZ|S>!?~HW!@VC-VdPTz|0=Da go=@OMJVa(+JRjidp2n#if^o$9$McY5)KL literal 0 HcmV?d00001 diff --git a/examples/APRS-Beacon/2200.wav b/examples/APRS-Beacon/2200.wav new file mode 100755 index 0000000000000000000000000000000000000000..2c7d9a0fe365d7ddeaf9ab5212db0c1e09f5f17e GIT binary patch literal 174 zcmV;f08#%^Nk&Gd00012K~_a(ZFC?I000010096%9{>P=J^%m$01yCVVRT`F0002( z6t7_4;^3mkJpe~;u36A_Vh9g_nl=v_V&%}St@}raJb|Q$;0k330OgvFA7ERe!_Bvy zQoJr)o;&a;W;XC?o~SOiQm(hg!#Z2GAHA9^0PJL*;C7^kJPAmTtrpSLVU!OCnw}59 cVKmWYtwKmUJlmug;GAVc|Mi;=9* + + + + +
+ Power +
+
+ +
+ + \ No newline at end of file diff --git a/examples/FMBeacon/FMBeacon.ino b/examples/FMBeacon/FMBeacon.ino new file mode 100644 index 0000000..7c00a29 --- /dev/null +++ b/examples/FMBeacon/FMBeacon.ino @@ -0,0 +1,53 @@ +/* + +Morse Code Beacon + +Test beacon will transmit and wait 30 seconds. +Beacon will check to see if the channel is clear before it will transmit. + + +*/ + +#include +#include + +HAMShield radio; + +void setup() { + Serial.begin(9600); + Serial.println("starting up.."); + Wire.begin(); + + pinMode(11, OUTPUT); + + //testing + //Wire.beginTransmission(42); + //Wire.write('T'); + //Wire.write('e'); + //Wire.write('s'); + //Wire.write('t'); + //Wire.endTransmission(); + + + Serial.print("Radio status: "); + int result = radio.testConnection(); + Serial.println(result,DEC); + radio.initialize(); // setup radio + radio.setFrequency(446000); // set to 70 cm call frequency + Serial.println("Done with radio beacon setup."); +} + +void loop() { + //while(1){} + //if(radio.waitForChannel(30000,2000)) { // wait up to 30 seconds for a clear channel, and then 2 seconds of empty channel + Serial.println("Signal is clear -- Transmitting"); + radio.setModeTransmit(); // turn on the transmitter + radio.morseOut("1ZZ9ZZ/B CN87 ARDUINO HAMSHIELD"); + radio.setModeReceive(); // turn off the transmitter (receive mode) + Serial.print("TX Off"); + //delay(30000); + //} else { Serial.println("The channel was busy. Waiting 10 seconds."); delay(10000); } + delay(10000); +} + + diff --git a/examples/FixMe/DTMFDecoder/DTMFDecoder.ino b/examples/FixMe/DTMFDecoder/DTMFDecoder.ino new file mode 100755 index 0000000..adfa21c --- /dev/null +++ b/examples/FixMe/DTMFDecoder/DTMFDecoder.ino @@ -0,0 +1,283 @@ + +// BlueHAM Proto01 Connection Guide +/********************** +** +** BlueHAM Proto01 <--> Arduino +** ADC_SCL A5 +** ADC_DIO A4 +** GND GND +** PWM_RF_CTL D9 +** +** Setting Connections +** MODE -> GND +** SENB -> GND +** PDN -> 3.3V +** AVDD -> 5V (note this should be a beefy supply, could draw up to 4As) +** +** +** +** Pinout information for RadioPeripheral01 Prototype board +** GPIO0 - +** GPIO1 - +** GPIO2 - VHF_SEL +** GPIO3 - UHF_SEL +** GPIO4 - RX_EN +** GPIO5 - TX_EN +** GPIO6 - +** GPIO7 - +**************************/ + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#include "Wire.h" +#include "HAMShield.h" + +#include + +//typedef enum { +#define MAIN_S 0 +#define RX_S 1 +#define TX_S 2 +#define FREQ_S 3 +#define UHF_S 4 +#define VHF_S 5 +#define PWR_S 6 +#define GPIO_S 7 +//} menu_view; + +int state; + +/* goertzel routines */ + +int sensorPin = A0; +int led = 13; +const float TARGET_FREQUENCY = 2200; +const int N = 100; +const float THRESHOLD = 4000; +const float SAMPLING_FREQUENCY = 8900; +Goertzel goertzel = Goertzel(TARGET_FREQUENCY, N, SAMPLING_FREQUENCY); + +// create object for RDA +HAMShield radio; + + +#define LED_PIN 13 +bool blinkState = false; + +void setup() { + // initialize serial communication + Serial.begin(115200); + Serial.println("beginning radio setup"); + + // join I2C bus (I2Cdev library doesn't do this automatically) + Wire.begin(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(radio.testConnection() ? "RDA radio connection successful" : "RDA radio connection failed"); + + // initialize device + Serial.println("Initializing I2C devices..."); + radio.initialize(); // initializes automatically for UHF 12.5kHz channel + + Serial.println("setting default Radio configuration"); + + + // set frequency + Serial.println("changing frequency"); + + + radio.setFrequency(446000); // in kHz + radio.setModeReceive(); + + // configure Arduino LED for + pinMode(LED_PIN, OUTPUT); + + state = MAIN_S; + print_menu(); +} + +void loop() { + goertzel.sample(sensorPin); + float magnitude = goertzel.detect(); + if(magnitude>THRESHOLD) digitalWrite(led, HIGH); //if found, enable led + else digitalWrite(led, LOW); + while (Serial.available()) { + if (state == FREQ_S) { + char freq_khz[6]; + int i = 0; + while(i < 6) { + if (Serial.available()) { + freq_khz[i] = Serial.read(); + i++; + } + } + + // interpret frequency + uint32_t freq = 0; + i = 0; + while (i < 6) { + uint32_t temp = freq_khz[i] - '0'; + for (int k = 5-i; k > 0; k--) { + temp = temp * 10; + } + freq += temp; + i++; + } + Serial.print("setting frequency to: "); + Serial.println(freq); + radio.setFrequency(freq); + state = MAIN_S; + + } else if (state == PWR_S) { + uint8_t pwr_raw[3]; + int i = 0; + while(i < 3) { + if (Serial.available()) { + pwr_raw[i] = Serial.read(); + i++; + } + } + + // interpret power + uint8_t pwr = 0; + i = 0; + while (i < 3) { + uint8_t temp = pwr_raw[i] - '0'; + for (int k = 2-i; k > 0; k--) { + temp = temp * 10; + } + pwr += temp; + i++; + } + + Serial.print("Setting power to: "); + Serial.println(pwr); + radio.setRfPower(pwr); + state = MAIN_S; + + } else if (state == GPIO_S) { + uint8_t gpio_raw[2]; + int i = 0; + while(i < 2) { + if (Serial.available()) { + gpio_raw[i] = Serial.read(); + i++; + } + } + uint16_t gpio_pin = gpio_raw[0] - 48; // '0'; + uint16_t gpio_mode = gpio_raw[1] - 48; + + radio.setGpioMode(gpio_pin, gpio_mode); + state = MAIN_S; + + } else { + char action = Serial.read(); + if (action == 'r') { // get current state + state = RX_S; + } else if (action == 't') { + state = TX_S; + } else if (action == 'f') { + state = FREQ_S; + } else if (action == 'u') { + state = UHF_S; + } else if (action == 'v') { + state = VHF_S; + } else if (action == '1') { + turn_on(state); + state = MAIN_S; + } else if (action == '0') { + turn_off(state); + state = MAIN_S; + } else if (action == 'p') { + state = PWR_S; + } else if (action == 'g') { + state = GPIO_S; + } else if (action == 's') { + int16_t rssi = radio.readRSSI(); + Serial.print("rssi: "); + Serial.println(rssi); + } else if (action == 'i') { + int16_t vssi = radio.readVSSI(); + Serial.print("vssi: "); + Serial.println(vssi); + } + + Serial.println(action); + } + Serial.flush(); + print_menu(); + } +} + +void turn_off(int dev) { + switch (dev) { + case RX_S: + radio.setRX(0); + break; + case TX_S: + radio.setTX(0); + break; + case UHF_S: + radio.setGpioMode(3, 3); // set GPIO3 high (uhf is active low) + break; + case VHF_S: + radio.setGpioMode(2, 3); // set GPIO2 high (vhf is active low) + break; + default: + break; + } +} + +void turn_on(int dev) { + switch (dev) { + case RX_S: + radio.setRX(1); + break; + case TX_S: + radio.setTX(1); + break; + case UHF_S: + radio.setGpioMode(3, 2); // set GPIO3 low (uhf is active low) + break; + case VHF_S: + radio.setGpioMode(2, 2); // set GPIO2 low (uhf is active low) + break; + default: + break; + } +} + +void print_menu() { + Serial.println("MENU"); + switch (state) { + case MAIN_S: + Serial.println("select step: [r]x, [t]x, [f]req, [u]hf, [v]hf, [p]wr, [g]pio control, r[s]si, vss[i] ..."); + break; + case RX_S: + Serial.println("enter 1 to turn on rx, 0 to turn off rx"); + break; + case TX_S: + Serial.println("enter 1 to turn on tx, 0 to turn off tx"); + break; + case FREQ_S: + Serial.println("enter frequency in kHz (ffffff)"); + break; + case UHF_S: + Serial.println("enter 1 to turn on uhf, 0 to turn off uhf"); + break; + case VHF_S: + Serial.println("enter 1 to turn on vhf, 0 to turn off vhf"); + break; + case PWR_S: + Serial.println("enter power (raw) (ppp)"); + break; + case GPIO_S: + Serial.println("enter GPIO pin and control (no spaces, eg pin 1 mode 3 is 13"); + Serial.println("modes 0 - HiZ, 1 - FCN, 2 - Low, 3 - Hi"); + break; + default: + state = MAIN_S; + break; + } +} diff --git a/examples/FoxHunt/FoxHunt.ino b/examples/FoxHunt/FoxHunt.ino new file mode 100755 index 0000000..d71aab8 --- /dev/null +++ b/examples/FoxHunt/FoxHunt.ino @@ -0,0 +1,37 @@ +/* Fox Hunt */ + +#include +#include + +// transmit for 1 minute, every 10 minutes + +#define TRANSMITLENGTH 1 +#define INTERVAL 10 +#define RANDOMCHANCE 3 + +HAMShield radio; + +void setup() { + Wire.begin(); + radio.initialize(); + radio.setFrequency(145510); + radio.setModeReceive(); +} + +void loop() { + waitMinute(INTERVAL + random(0,RANDOMCHANCE)); // wait before transmitting, randomly up to 3 minutes later + if(radio.waitForChannel(30000,2000)) { // wait for a clear channel, abort after 30 seconds, wait 2 seconds of dead air for breakers + radio.setModeTransmit(); // turn on transmit mode + tone(1000,11,TRANSMITLENGTH * 60 * 1000); // play a long solid tone + radio.morseOut("1ZZ9ZZ/B FOXHUNT"); // identify the fox hunt transmitter + radio.setModeReceive(); // turn off the transmit mode + } +} + +// a function so we can wait by minutes + +void waitMinute(int period) { + delay(period * 60 * 1000); +} + + diff --git a/examples/Gauges/Gauges.ino b/examples/Gauges/Gauges.ino new file mode 100755 index 0000000..10c3c20 --- /dev/null +++ b/examples/Gauges/Gauges.ino @@ -0,0 +1,99 @@ +/* + +Gauges + +Simple gauges for the radio receiver. + + +*/ + +#include +#include + +HAMShield radio; + +void clr() { +/* Serial.write(27); + Serial.print("[2J"); // cursor to home command */ + Serial.write(27); + Serial.print("[H"); // cursor to home command +} + +void setup() { + analogReference(DEFAULT); + Serial.begin(115200); + Wire.begin(); + Serial.print("Radio status: "); + int result = radio.testConnection(); + Serial.println(result,DEC); + radio.initialize(); + radio.setFrequency(446000); + Serial.println("Entering gauges..."); + tone(9,1000); + delay(2000); +} + +int gauge; +int x = 0; +int y = 0; +int peak = 0; +int a = 0; +int mini = 0; +int vpeak = 0; +int txc = 0; +int mode = 0; + +void loop() { + clr(); + int16_t rssi = radio.readRSSI(); + gauge = map(rssi,-123,-50,0,8); + Serial.print("["); + for(x = 0; x < gauge; x++) { + Serial.print("."); + } + Serial.print("|"); + for(y = x; y < 8; y++) { + Serial.print("."); + } + Serial.print("] "); + Serial.print(rssi); + Serial.println(" "); + Serial.println("Signal \n"); + + // radio.setModeTransmit(); + int16_t vssi = radio.readVSSI(); + // radio.setModeReceive(); + if(vssi > vpeak) { vpeak = vssi; } + gauge = map(vssi,-50,-150,0,8); + Serial.print("["); + for(x = 0; x < gauge; x++) { + Serial.print("."); + } + Serial.print("|"); + for(y = x; y < 8; y++) { + Serial.print("."); + } + Serial.print("] "); + Serial.print(vpeak); + Serial.println(" "); + Serial.println("Audio In\n"); + + a = analogRead(0); + if(a > peak) { peak = a; } + if(a < mini) { mini = a; } + gauge = map(a,400,1023,0,8); + Serial.print("["); + for(x = 0; x < gauge; x++) { + Serial.print("."); + } + Serial.print("|"); + for(y = x; y < 8; y++) { + Serial.print("."); + } + Serial.print("] "); + Serial.print(a,DEC); + Serial.print(" ("); Serial.print(peak,DEC); Serial.println(") "); + Serial.println("Audio RX ADC Peak\n"); +} + + diff --git a/examples/HAMBot/HAMBot.ino b/examples/HAMBot/HAMBot.ino new file mode 100755 index 0000000..54d5bf5 --- /dev/null +++ b/examples/HAMBot/HAMBot.ino @@ -0,0 +1,32 @@ +/* Simple DTMF controlled HAM Radio Robot */ + +#include // include the robot library +#include +#include +#include + +HAMShield radio; + +void setup() { + Robot.begin(); + Wire.begin(); + radio.initialize(); + radio.setFrequency(145510); +} + +void loop() { + if(radio.waitForDTMF()) { // wait for a received DTMF tone + uint8_t command = radio.getLastDTMFDigit(); // get the last DTMF tone sent + if(command == '4') { Robot.turn(-90); } // turn robot left + if(command == '6') { Robot.turn(90); } // turn robot right + if(command == '2') { Robot.motorsWrite(-255,-255); delay(500); Robot.motorsWrite(255, 255); } // move robot forward + if(command == '5') { // tell robot to send morse code identity + if(radio.waitForChannel()) { // wait for the user to release the transmit button + radio.setModeTransmit(); // turn on transmit mode + radio.morseOut("1ZZ9ZZ I AM HAMRADIO ROBOT"); // send morse code + radio.setModeReceive(); // go back to receive mode on radio + } + } + } +} + diff --git a/examples/Identifier/Identifier.ino b/examples/Identifier/Identifier.ino new file mode 100755 index 0000000..94f73c9 --- /dev/null +++ b/examples/Identifier/Identifier.ino @@ -0,0 +1,80 @@ +/* + +Indentifier + +Arduino audio overlay example + +*/ + +#include +#include + +#define DOT 100 + +HAMShield radio; + +const char *bascii = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?'!/()&:;=+-_\"$@", + *bitu[] = { ".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",".-.-.-","--..--","..--..",".----.","-.-.--","-..-.","-.--.","-.--.-",".-...","---...","-.-.-.","-...-",".-.-.","-....-","..--.-",".-..-.","...-..-",".--.-." + }; + +const char *callsign = {"1ZZ9ZZ/B"} ; + +char morsebuffer[8]; + +void setup() { + Serial.begin(9600); + Serial.println("starting up.."); + Wire.begin(); + Serial.print("Radio status: "); + int result = radio.testConnection(); + Serial.println(result,DEC); + radio.initialize(); + radio.setFrequency(446000); + radio.setVolume1(0xF); + radio.setVolume2(0xF); + radio.setModeReceive(); + radio.setTxSourceMic(); + radio.setSQLoThresh(80); + radio.setSQOn(); + Serial.println("Done with radio beacon setup. Press and hold a key to transmit."); +} + +int state = 0; +long timer = 0; +int morseletter = 0; +int morsesymbol = 0; +long keyer = 0; +char symbol; + +void loop() { + if(Serial.available() > 0) { + if(state == 0) { + state = 10; + radio.setModeTransmit(); + timer = millis(); + keyer = millis(); + } + if(state == 10) { + timer = millis(); + } + } + if(millis() > (timer + 500)) { radio.setModeReceive(); morseletter = 0; morsesymbol = 0; state = 0; } + if(state == 10) { + if(millis() > (keyer + (DOT * 3))) { + keyer = millis(); + symbol = lookup(callsign[morseletter],morsesymbol); + if(symbol == '-') { tone(9,1000,DOT*3); } + if(symbol == '.') { tone(9,1000,DOT); } + if(symbol == 0) { morsesymbol = 0; morseletter++; } + if(callsign[morseletter] == 0) { morsesymbol = 0; morseletter = 0; } + } + } +} + +char lookup(char letter, int morsesymbol) { + for(int x = 0; x < 54; x++) { + if(letter == bascii[x]) { + return bitu[x][morsesymbol]; + } + } +} diff --git a/examples/Parrot/Parrot.ino b/examples/Parrot/Parrot.ino new file mode 100755 index 0000000..18e1c91 --- /dev/null +++ b/examples/Parrot/Parrot.ino @@ -0,0 +1,111 @@ +/* + +Record sound and then plays it back a few times. +Very low sound quality @ 2KHz 0.75 seconds +A bit robotic and weird + +*/ + +#include +#include + +#define RATE 500 +#define SIZE 1500 + +HAMShield radio; + +char sound[SIZE]; +unsigned int sample1; +int x = -1; +int16_t rssi; +byte mode = 8; + +void setup() { + Wire.begin(); + // int result = radio.testConnection(); + radio.initialize(); + radio.setFrequency(446000); + setPwmFrequency(9, 1); +} + + + +void loop() { + rssi = radio.readRSSI(); + if(rssi > -100) { + if(x == -1) { + for(x = 0; x < SIZE; x++) { + if(mode == 4) { + sample1 = analogRead(0); + sound[x] = sample1 >> 4; + delayMicroseconds(RATE); x++; + sample1 = analogRead(0); + sound[x] = (sample1 & 0xF0) | sound[x]; + delayMicroseconds(RATE); + } else { + sound[x] = analogRead(0); + delayMicroseconds(RATE); x++; + sound[x] = analogRead(0); + delayMicroseconds(RATE); + } + } + } + } + if(rssi < -100) { + if(x == 1500) { + radio.setModeTransmit(); + delay(500); + tone(9,1000,500); delay(750); + for(int r = 0; r < 10; r++) { + for(x = 0; x < SIZE; x++) { + if(mode == 4) { + + analogWrite(9,sound[x] << 4); + delayMicroseconds(RATE); x++; + analogWrite(9,sound[x] & 0xF); + delayMicroseconds(RATE); } else { + + analogWrite(9,sound[x]); + delayMicroseconds(RATE); x++; + analogWrite(9,sound[x]); + delayMicroseconds(RATE); + } + } } + tone(9,1000,500); delay(750); + radio.setModeReceive(); + x = -1; + } + } +} + +void setPwmFrequency(int pin, int divisor) { + byte mode; + if(pin == 5 || pin == 6 || pin == 9 || pin == 10) { + switch(divisor) { + case 1: mode = 0x01; break; + case 8: mode = 0x02; break; + case 64: mode = 0x03; break; + case 256: mode = 0x04; break; + case 1024: mode = 0x05; break; + default: return; + } + if(pin == 5 || pin == 6) { + TCCR0B = TCCR0B & 0b11111000 | mode; + } else { + TCCR1B = TCCR1B & 0b11111000 | mode; + } + } else if(pin == 3 || pin == 11) { + switch(divisor) { + case 1: mode = 0x01; break; + case 8: mode = 0x02; break; + case 32: mode = 0x03; break; + case 64: mode = 0x04; break; + case 128: mode = 0x05; break; + case 256: mode = 0x06; break; + case 1024: mode = 0x7; break; + default: return; + } + TCCR2B = TCCR2B & 0b11111000 | mode; + } +} + diff --git a/examples/SSTV/SSTV.ino b/examples/SSTV/SSTV.ino new file mode 100755 index 0000000..e4787c0 --- /dev/null +++ b/examples/SSTV/SSTV.ino @@ -0,0 +1,45 @@ +/* + +Sends an SSTV test pattern + +*/ + +#define DOT 100 +#define CALLSIGN "1ZZ9ZZ/B" + +/* Standard libraries and variable init */ + +#include +#include + +HAMShield radio; +int16_t rssi; + +/* get our radio ready */ + +void setup() { + Wire.begin(); + Serial.begin(9600); + Serial.print("Radio status: "); + int result = radio.testConnection(); + Serial.println(result); + radio.initialize(); + radio.setFrequency(446000); + radio.setModeReceive(); +} + +/* main program loop */ + + +void loop() { + if(radio.waitForChannel(1000,2000)) { // Wait forever for calling frequency to open, then wait 2 seconds for breakers + radio.setModeTransmit(); // Turn on the transmitter + delay(250); // Wait a moment + radio.SSTVTestPattern(MARTIN1); // send a MARTIN1 test pattern + delay(250); + radio.setModeReceive(); // Turn off the transmitter + } else { delay(30000); } // someone broke in fast after prior transmission, was it an emergency? wait 30 secs. + + delay(60000); // Wait a minute +} + diff --git a/examples/SerialTransceiver/SerialTransceiver.ino b/examples/SerialTransceiver/SerialTransceiver.ino new file mode 100755 index 0000000..3733302 --- /dev/null +++ b/examples/SerialTransceiver/SerialTransceiver.ino @@ -0,0 +1,203 @@ +/* + +SerialTransceiver is TTL Serial port "glue" to allow desktop or laptop control of the HAMShield + +Commands: + +Mode ASCII Description Implemented +-------------- ----------- -------------------------------------------------------------------------------------------------------------------------------------------- ----------------- +Transmit space Space must be received at least every 500 mS Yes +Receive not space If space is not received and/or 500 mS timeout of space occurs, unit will go into receive mode Yes +CTCSS In A; must be a numerical ascii value with decimal point indicating CTCSS receive tone required to unsquelch No +CTCSS Out B; must be a numerical ascii value with decimal point indicating CTCSS transmit tone No +CTCSS Enable C; Turns on CTCSS mode (analog tone) with 1, off with 0. No +CDCSS Enable D; Turns on CDCSS mode (digital tone) with 1, off with 0. No +Bandwidth E; for 12.5KHz mode is 0, for 25KHz, mode is 1 No +Frequency F; Set the receive frequency in KHz, if offset is disabled, this is the transmit frequency No +CDCSS In G; must be a valid CDCSS code No +CDCSS Out H; must be a valid CDCSS code No +Print tones I Prints out all configured tones and codes, coma delimited in format: CTCSS In, CTCSS Out, CDCSS In, CDCSS Out No +Power level P; Set the power amp level, 0 = lowest, 255 = highest No +Enable Offset R; 1 turns on repeater offset mode, 0 turns off repeater offset mode No +Squelch S; Set the squelch level No +TX Offset T; The absolute frequency of the repeater offset to transmit on in KHz No +Volume V; Set the volume level of the receiver No +Reset X Reset all settings to default No +Sleep Z Sleep radio No +Filters @; Set bit to enable, clear bit to disable: 0 = pre/de-emphasis, 1 = high pass filter, 2 = low pass filter (default: ascii 7, all enabled) No +Vox mode $; 0 = vox off, >= 1 audio sensitivity. lower value more sensitive No +Mic Channel *; Set the voice channel. 0 = signal from mic or arduino, 1 = internal tone generator No +RSSI ? Respond with the current receive level in - dBm (no sign provided on numerical response) No +Tone Gen % (notes) To send a tone, use the following format: Single tone: %1,,; Dual tone: %2,,,; DTMF: %3,,; No +Voice Level ^ Respond with the current voice level (VSSI) + + +Responses: + +Condition ASCII Description +------------ ---------- ----------------------------------------------------------------- +Startup *; Startup and shield connection status +Success !; Generic success message for command that returns no value +Error X; Indicates an error code. The numerical value is the type of error +Value :; In response to a query +Status #; Unsolicited status message +Debug Msg @; 32 character debug message + +*/ + +#include "Wire.h" +#include "HAMShield.h" + +int state; +int txcount = 0; +long timer = 0; +long freq = 144390; +long tx = 0; +char cmdbuff[32] = ""; +int temp = 0; +int repeater = 0; +float ctcssin = 0; +float ctcssout = 0; +int cdcssin = 0; +int cdcssout = 0; + + +HAMShield radio; + + + +void setup() { + Serial.begin(115200); + Serial.print(";;;;;;;;;;;;;;;;;;;;;;;;;;"); + Wire.begin(); + int result = radio.testConnection(); + Serial.print("*"); + Serial.print(result,DEC); + Serial.print(";"); + radio.initialize(); // initializes automatically for UHF 12.5kHz channel + Serial.print("*START;"); + radio.frequency(freq); + radio.setVolume1(0xF); + radio.setVolume2(0xF); + radio.setModeReceive(); + radio.setTxSourceMic(); + radio.setRfPower(255); // 30 is 0.5V, which corresponds to 29 dBm out (see RF6886 datasheet) + radio.setSQLoThresh(80); + radio.setSQOn(); +} + +void loop() { + + if(Serial.available()) { + + int text = Serial.read(); + + switch (state) { + + case 10: + if(text == 32) { timer = millis();} + break; + + case 0: + switch(text) { + + case 32: // space - transmit + if(repeater == 1) { radio.frequency(tx); } + radio.setRX(0); + radio.setTX(1); + state = 10; + Serial.print("#TX,ON;"); + timer = millis(); + break; + + case 63: // ? - RSSI + Serial.print(":"); + Serial.print(radio.readRSSI(),DEC); + Serial.print(";"); + break; + + case 65: // A - CTCSS In + getValue(); + ctcssin = atof(cmdbuff); + radio.setCtcss(ctcssin); + break; + + case 66: // B - CTCSS Out + break; + + case 67: // C - CTCSS Enable + break; + + case 68: // D - CDCSS Enable + break; + + case 70: // F - frequency + getValue(); + freq = atol(cmdbuff); + if(radio.frequency(freq) == true) { Serial.print("@"); Serial.print(freq,DEC); Serial.print(";!;"); } else { Serial.print("X1;"); } + break; + + case 80: // P - power level + getValue(); + temp = atol(cmdbuff); + radio.setRfPower(temp); + break; + + case 82: // R - repeater offset mode + getValue(); + temp = atol(cmdbuff); + if(temp == 0) { repeater = 0; } + if(temp == 1) { repeater = 1; } + break; + + case 83: // S - squelch + getValue(); + temp = atol(cmdbuff); + radio.setSQLoThresh(temp); + break; + + case 84: // T - transmit offset + getValue(); + tx = atol(cmdbuff); + break; + + + case 94: // ^ - VSSI (voice) level + Serial.print(":"); + Serial.print(radio.readVSSI(),DEC); + Serial.print(";"); + } + break; + } + + } + if(state == 10) { + if(millis() > (timer + 500)) { Serial.print("#TX,OFF;");radio.setRX(1); radio.setTX(0); if(repeater == 1) { radio.frequency(freq); } state = 0; txcount = 0; } + } +} + +void getValue() { + int p = 0; + char temp; + for(;;) { + if(Serial.available()) { + temp = Serial.read(); + if(temp == 59) { cmdbuff[p] = 0; Serial.print("@"); + for(int x = 0; x < 32; x++) { Serial.print(cmdbuff[x]); } + return; + } + cmdbuff[p] = temp; + p++; + if(p == 32) { + Serial.print("@"); + for(int x = 0; x < 32; x++) { + Serial.print(cmdbuff[x]); + } + + cmdbuff[0] = 0; + + Serial.print("X0;"); return; } // some sort of alignment issue? lets not feed junk into whatever takes this string in + } + } +} + diff --git a/examples/SignalTest/SignalTest.ino b/examples/SignalTest/SignalTest.ino new file mode 100755 index 0000000..11bb298 --- /dev/null +++ b/examples/SignalTest/SignalTest.ino @@ -0,0 +1,140 @@ +/* + +Plays back the current signal strength level and morses out it's call sign at the end. + + +*/ + +#define DOT 100 +#define CALLSIGN "1ZZ9ZZ/B" + +/* Standard libraries and variable init */ + +#include +#include +#include + +HAMShield radio; +int16_t rssi; +int peak = -150; +char sig[8]; + + +/* Audio samples */ + +const unsigned char minus[] PROGMEM = { +130, 130, 130, 132, 134, 134, 135, 139, 141, 140, 141, 143, 141, 139, 139, 138, 135, 131, 129, 126, 122, 119, 117, 114, 111, 110, 110, 108, 107, 107, 107, 107, 108, 109, 110, 111, 113, 115, 116, 119, 121, 124, 126, 128, 129, 131, 133, 135, 135, 137, 138, 138, 137, 137, 137, 135, 134, 135, 134, 128, 126, 127, 124, 119, 120, 119, 113, 113, 120, 119, 117, 123, 129, 128, 131, 140, 143, 145, 153, 158, 158, 163, 168, 169, 168, 170, 168, 164, 161, 157, 149, 142, 136, 128, 121, 116, 109, 103, 100, 97, 92, 91, 92, 93, 93, 95, 99, 102, 105, 107, 110, 113, 117, 119, 120, 122, 125, 126, 128, 127, 126, 130, 131, 125, 123, 129, 126, 118, 117, 120, 113, 112, 117, 112, 101, 103, 108, 102, 98, 102, 102, 105, 121, 129, 128, 137, 160, 171, 172, 178, 185, 186, 189, 194, 192, 190, 192, 190, 181, 175, 167, 157, 148, 141, 130, 119, 112, 106, 99, 95, 91, 86, 84, 84, 85, 86, 89, 92, 95, 100, 106, 111, 116, 121, 126, 130, 134, 137, 139, 139, 139, 137, 134, 131, 125, 120, 115, 108, 101, 95, 90, 84, 80, 78, 75, 73, 75, 77, 77, 80, 83, 87, 91, 97, 100, 103, 112, 119, 118, 119, 125, 127, 123, 129, 135, 135, 142, 152, 153, 151, 165, 175, 179, 185, 194, 192, 193, 199, 199, 197, 197, 194, 183, 176, 167, 158, 151, 147, 138, 128, 119, 110, 102, 99, 97, 94, 93, 92, 87, 87, 91, 95, 104, 111, 115, 118, 122, 127, 133, 142, 149, 152, 156, 157, 159, 159, 161, 161, 161, 158, 151, 144, 139, 131, 124, 119, 111, 103, 94, 86, 78, 74, 71, 69, 69, 68, 66, 66, 69, 73, 77, 83, 86, 91, 96, 101, 104, 110, 109, 108, 107, 117, 118, 127, 144, 144, 143, 151, 171, 172, 186, 198, 205, 201, 205, 203, 198, 196, 192, 183, 169, 159, 143, 137, 129, 125, 115, 111, 100, 91, 85, 83, 80, 78, 79, 79, 80, 81, 85, 89, 95, 100, 109, 111, 116, 112, 109, 101, 108, 115, 146, 200, 224, 235, 230, 216, 180, 145, 125, 112, 112, 118, 118, 119, 118, 123, 133, 150, 166, 164, 161, 144, 126, 112, 108, 113, 119, 128, 130, 124, 124, 123, 126, 132, 137, 135, 129, 125, 118, 120, 126, 132, 139, 143, 141, 138, 135, 134, 132, 131, 130, 128, 128, 128, 130, 130, 129, 126, 123, 118, 115, 114, 115, 113, 113, 111, 109, 107, 107, 109, 109, 108, 108, 111, 115, 118, 114, 114, 107, 107, 106, 110, 115, 116, 114, 115, 109, 101, 89, 96, 105, 136, 201, 230, 247, 212, 159, 97, 62, 74, 112, 173, 199, 202, 174, 134, 107, 102, 119, 141, 153, 149, 129, 117, 112, 124, 140, 148, 146, 131, 116, 103, 103, 110, 117, 124, 128, 131, 135, 141, 146, 144, 139, 127, 119, 116, 119, 130, 139, 144, 142, 136, 131, 129, 130, 130, 130, 125, 120, 116, 117, 119, 121, 121, 117, 113, 109, 109, 110, 113, 111, 113, 111, 113, 113, 113, 113, 116, 116, 115, 110, 104, 101, 105, 114, 121, 123, 117, 110, 85, 83, 84, 115, 139, 206, 250, 241, 211, 132, 83, 50, 90, 143, 201, 219, 185, 148, 112, 108, 121, 143, 147, 139, 131, 124, 129, 136, 135, 131, 123, 124, 128, 135, 129, 118, 103, 97, 105, 123, 141, 149, 149, 140, 131, 124, 121, 119, 123, 128, 136, 143, 148, 145, 138, 131, 127, 128, 132, 133, 131, 127, 120, 116, 115, 118, 121, 125, 126, 121, 115, 112, 108, 107, 109, 112, 111, 109, 109, 111, 114, 115, 110, 109, 111, 115, 116, 112, 108, 97, 100, 101, 109, 110, 116, 108, 177, 255, 236, 180, 111, 87, 86, 142, 174, 166, 152, 148, 155, 156, 154, 121, 104, 119, 142, 148, 142, 131, 117, 120, 135, 136, 131, 128, 123, 116, 119, 115, 110, 112, 120, 129, 138, 146, 142, 135, 128, 125, 126, 128, 129, 132, 139, 144, 143, 137, 132, 133, 137, 137, 131, 123, 119, 116, 114, 113, 115, 120, 123, 120, 112, 106, 104, 106, 107, 104, 102, 105, 109, 113, 111, 110, 109, 109, 107, 108, 112, 114, 108, 100, 101, 99, 105, 97, 113, 129, 201, 246, 201, 165, 163, 175, 139, 120, 115, 134, 156, 154, 140, 147, 171, 161, 140, 131, 131, 130, 127, 114, 112, 127, 136, 125, 121, 130, 136, 129, 120, 117, 120, 120, 111, 107, 118, 136, 139, 138, 145, 152, 152, 145, 136, 132, 131, 130, 127, 130, 136, 134, 127, 125, 126, 122, 115, 110, 109, 110, 110, 106, 105, 106, 105, 102, 102, 101, 98, 100, 104, 103, 104, 108, 105, 104, 105, 106, 105, 108, 109, 109, 109, 110, 110, 107, 107, 117, 134, 145, 148, 155, 173, 178, 179, 182, 186, 186, 186, 184, 177, 176, 173, 168, 159, 151, 141, 137, 132, 124, 118, 119, 120, 117, 114, 112, 113, 112, 112, 110, 111, 112, 112, 113, 114, 116, 120, 126, 130, 131, 134, 138, 142, 144, 147, 148, 149, 148, 147, 145, 142, 138, 134, 129, 124, 119, 115, 110, 105, 100, 96, 93, 91, 88, 88, 89, 88, 87, 87, 87, 88, 90, 90, 92, 93, 95, 95, 97, 98, 100, 100, 101, 105, 116, 132, 136, 143, 158, 175, 177, 183, 193, 198, 200, 201, 197, 187, 184, 178, 167, 158, 151, 140, 133, 128, 120, 115, 119, 119, 116, 117, 116, 113, 112, 110, 108, 110, 110, 112, 115, 123, 129, 134, 142, 148, 154, 155, 154, 151, 151, 144, 137, 132, 127, 123, 118, 114, 111, 114, 111, 109, 107, 104, 101, 97, 91, 90, 89, 82, 72, 75, 77, 75, 71, 73, 78, 81, 83, 82, 94, 92, 97, 120, 166, 182, 182, 195, 217, 220, 196, 185, 177, 178, 159, 143, 133, 141, 145, 143, 142, 144, 149, 147, 144, 140, 145, 140, 132, 126, 126, 124, 119, 113, 111, 115, 115, 114, 117, 126, 134, 141, 146, 153, 160, 158, 155, 153, 149, 143, 137, 131, 127, 124, 118, 114, 114, 113, 108, 108, 109, 107, 104, 102, 96, 93, 89, 85, 81, 74, 74, 70, 69, 70, 75, 74, 76, 81, 86, 100, 130, 157, 160, 183, 207, 205, 187, 184, 182, 173, 167, 154, 147, 150, 150, 140, 139, 142, 145, 143, 140, 138, 140, 138, 132, 132, 131, 130, 129, 128, 124, 125, 127, 127, 126, 126, 127, 132, 134, 131, 134, 137, 141, 143, 144, 144, 146, 145, 137, 129, 121, 114, 109, 101, 93, 90, 88, 85, 80, 76, 75, 79, 79, 77, 72, 73, 69, 67, 64, 73, 86, 119, 156, 166, 185, 201, 210, 196, 193, 178, 171, 169, 161, 157, 152, 154, 148, 148, 137, 139, 140, 134, 128, 129, 126, 127, 130, 125, 128, 130, 132, 129, 128, 124, 126, 132, 126, 123, 127, 131, 133, 136, 139, 140, 143, 139, 135, 132, 127, 122, 115, 112, 106, 100, 97, 91, 85, 80, 79, 79, 78, 72, 72, 67, 70, 67, 66, 71, 92, 133, 162, 178, 173, 188, 196, 195, 179, 165, 158, 158, 166, 154, 142, 136, 150, 153, 148, 139, 139, 142, 141, 137, 134, 138, 139, 143, 141, 136, 132, 132, 129, 124, 120, 122, 124, 127, 133, 134, 137, 140, 140, 138, 136, 131, 126, 122, 117, 109, 101, 93, 89, 87, 84, 80, 79, 79, 77, 74, 68, 68, 69, 65, 67, 103, 141, 150, 151, 162, 173, 179, 175, 157, 156, 165, 173, 168, 165, 153, 159, 168, 160, 151, 149, 150, 147, 148, 142, 138, 140, 148, 142, 135, 131, 131, 127, 125, 122, 120, 121, 121, 122, 121, 122, 125, 129, 125, 123, 122, 121, 116, 110, 104, 101, 100, 95, 92, 91, 90, 88, 85, 82, 83, 84, 82, 81, 101, 129, 136, 132, 136, 144, 149, 151, 147, 148, 159, 166, 162, 158, 155, 158, 163, 162, 153, 152, 157, 158, 154, 152, 148, 148, 146, 136, 130, 129, 128, 121, 120, 119, 120, 121, 120, 118, 119, 121, 120, 118, 118, 121, 122, 119, 114, 110, 110, 112, 108, 108, 105, 104, 104, 103, 100, 102, 102, 98, 98, 98, 97, 101, 119, 129, 130, 131, 138, 141, 146, 146, 145, 148, 154, 156, 155, 154, 151, 151, 150, 148, 145, 146, 144, 144, 141, 141, 138, 137, 135, 132, 130, 129, 128, 124, 123, 120, 121, 120, 120, 118, 121, 121, 120, 124, 120, 119, 119, 120, 119, 117, 114, 114, 116, 117, 115, 117, 114, 120, 115, 115, 111, 116, 120, 118, 122, 118, 122, 123, 125, 121, 125, 125, 129, 129, 133, 130, 137, 134, 138, 138, 139, 142, 141, 144, 138, 141, 138, 141, 137, 137, 135, 137, 136, 134, 131, 131, 132, 131, 129, 128, 127, 129, 124, 125, 125, 124, 126, 122, 126, 121, 125, 117, 123, 123, 122, 125, 124, 125, 120, 123, 120, 122, 120, 123, 126, 126, 126, 124, 129, 129, 127, 126, 131, 129, 130, 126, 127, 131, 127, 130, 125, 129, 127, 125, 127, 130, 128, 126, 130, 131, 130, 126, 129, 127, 131, 126, 126, 129, 130, 130, 126, 130, 124, 132, 130, 130, 132, 126, 131, 125, 128, 126, 126, 129, 126, 129, 126, 131, 128, 127, 127, 128, 127, 128, 129, 127, 124, 129, 126, 127, 130, 129, 130, 129, 126, 128, 128, 127, 130, 122, 132, 121, 130, 125, 131, 125, 128, 129, 128, 130, 122, 131, 122, 133, 125, 129, 123, 130, 125, 130, 122, 127, 129, 125, 132, 124, 129, 129, 130, 125, 128, 127, 132, 127, 129, 125, 130, 128, 126, 128, 125, 129, 126, 129, 127, 129, 128, 127, 128, 124, 130, 128, 127, 128, 128, 130, 127, 130, 123, 132, 122, 132, 123, 126, 128, 124, 134, 120, 134, 118, 138, 124, 127, 125, 125, 132, 125, 129, 122, 134, 126, 132, 123, 130, 126, 131, 127, 127, 124, 130, 128, 128, 124, 126, 129, 127, 129, 125, 128, 125, 131, 123, 130, 123, 134, 127, 129, 126, 126, 130, 126, 126, 126, 128, 126, 130, 127, 127, 129, 129, 127, 130, 125, 131, 126, 130, 127, 127, 127, 128, 128, 126, 129, 124, 131, 124, 132, 125, 129, 127, 129, 128, 126, 130, 124, 134, 124, 130, 128, 129, 129, 126, 128, 128, 129, 130, 125, 126, 131, 126, 128, 125, 127, 129, 128, 129, 125, 128, 132, 123, 130, 125, 129, 126, 126, 126, 128, 127, 127, 124, 126, 129, 125, 129, 123, 132, 123, 129, 125, 128, 126, 127, 126, 125, 129, 123, 131, 125, 128, 126, 125, 129, 126, 129, 129, 126, 131, 125, 133, 124, 131, 126, 127, 129, 125, 130, 125, 134, 121, 134, 120, 134, 123, 129, 130, 123, 135, 121, 132, 123, 132, 124, 130, 126, 128, 131, 126, 128, 126, 127, 128, 129, 127, 127, 128, 131, 123, 131, 124, 132, 127, 124, 132, 121, 134, 125, 127, 129, 126, 128, 128, 129, 125, 127, 126, 128, 127, 126, 128, 128, 128, 125, 128, 128, 127, 128, 127, 129, 127, 130, 125, 126, 128, 126, 131, 123, 130, 127, 128, 129, 123, 129, 127, 129, 126, 128, 127, 127, 130, 125, 128, 129, 125, 129, 122, 127, 130, 124, 129, 125, 127, 130, 125, 127, 127, 126, 129, 126, 127, 129, 128, 126, 129, 124, 131, 126, 126, 131, 123, 129, 129, 125, 131, 125, 130, 127, 126, 129, 125, 130, 125, 130, 128, 127, 127, 128, 124, 129, 125, 132, 126, 128, 128, 125, 127, 128, 127, 127, 132, 123, 132, 125, 128, 127, 126, 129, 127, 125, 129, 126, 132, 126, 130, 126, 132, 125, 129, 130, 127, 133, 123, 131, 124, 132, 126, 134, 124, 131, 128, 127, 129, 122, 136, 124, 129, 127, 124, 127, 128, 128, 125, 133, 125, 129, 128, 124, 131, 123, 132, 124, 127, 129, 126, 131, 125, 130, 127, 131, 125, 129, 129, 128, 129, 125, 130, 127, 128, 126, 132, 127, 129, 128, 127, 129, 129, 126, 128, 126, 131, 129, 125, 127, 131, 128, 126, 129, 122, 136, 121, 131, 124, 129, 130, 121, 133, 124, 133, 124, 129, 125, 130, 127, 127, 134, 121, 132, 123, 133, 127, 125, 125, 133, 127, 123, 129, 130, 131, 123, 130, 125, 137, 116, 135, 120, 133, 129, 119, 136, 121, 138, 114, 131, 129, 129, 127, 126, 134, 119, 134, 120, 130, 128, 126, 122, 131, 126, 126, 129, 123, 140, 120, 136, 116, 135, 128, 124, 127, 127, 129, 131, 121, 131, 129, 125, 133, 120, 138, 116, 141, 112, 137, 126, 126, 124, 132, 126, 125, 126, 127, 136, 120, 136, 114, 143, 113, 133, 122, 130, 127, 128, 122, 124, 140, 118, 128, 127, 134, 124, 131, 120, 136, 129, 125, 122, 131, 131, 128, 121, 129, 134, 128, 124, 125, 139, 120, 134, 124, 127, 134, 124, 125, 124, 138, 124, 115, 145, 113, 131, 137, 116, 128, 126, 140, 103, 133, 133, 108, 138, 124, 114, 124, 139, 116, 122, 145, 124, 124, 146, 117, 134, 145, 120, 128, 132, 148, 116, 137, 135, 133, 132, 125, 140, 133, 135, 127, 147, 114, 136, 138, 114, 130, 125, 133, 107, 131, 130, 98, 135, 115, 113, 117, 107, 114, 104, 113, +}; + +const unsigned char zero[] PROGMEM = { +123, 124, 123, 121, 122, 122, 121, 119, 117, 117, 117, 117, 114, 111, 112, 113, 112, 111, 111, 112, 116, 123, 134, 146, 154, 164, 176, 184, 189, 192, 194, 196, 197, 195, 189, 183, 175, 167, 156, 144, 132, 122, 113, 103, 95, 88, 86, 86, 86, 88, 88, 90, 92, 93, 93, 94, 96, 97, 98, 99, 98, 101, 98, 97, 99, 96, 93, 89, 88, 83, 80, 75, 75, 77, 80, 98, 113, 114, 128, 148, 165, 180, 192, 199, 213, 228, 228, 229, 229, 226, 224, 215, 197, 183, 174, 161, 144, 129, 116, 109, 105, 97, 92, 94, 99, 104, 108, 111, 120, 129, 134, 137, 138, 140, 141, 138, 131, 127, 125, 125, 118, 112, 107, 108, 105, 97, 99, 95, 101, 95, 97, 90, 92, 92, 83, 80, 73, 72, 67, 68, 60, 62, 59, 65, 70, 88, 104, 107, 123, 142, 162, 178, 193, 204, 222, 238, 241, 240, 240, 235, 230, 222, 206, 190, 177, 162, 145, 128, 115, 102, 101, 94, 93, 90, 95, 95, 105, 107, 115, 122, 131, 135, 136, 142, 141, 145, 138, 139, 131, 135, 123, 128, 112, 121, 103, 110, 100, 104, 101, 98, 101, 89, 100, 81, 93, 73, 87, 65, 82, 57, 74, 62, 60, 69, 54, 74, 74, 94, 97, 119, 128, 158, 166, 190, 196, 218, 231, 239, 240, 242, 241, 236, 230, 211, 198, 181, 167, 147, 136, 120, 114, 106, 100, 95, 93, 96, 102, 105, 116, 115, 127, 125, 132, 130, 133, 130, 131, 129, 125, 127, 122, 125, 117, 122, 113, 115, 106, 111, 102, 104, 98, 93, 90, 93, 83, 85, 85, 79, 86, 75, 83, 81, 81, 85, 79, 85, 94, 83, 98, 101, 126, 126, 140, 148, 157, 173, 183, 187, 192, 212, 210, 216, 204, 207, 200, 201, 182, 175, 166, 162, 147, 144, 133, 128, 129, 120, 118, 113, 121, 109, 123, 114, 123, 121, 122, 121, 122, 121, 124, 122, 125, 122, 119, 127, 115, 120, 115, 115, 116, 115, 105, 112, 101, 108, 100, 95, 101, 100, 101, 101, 95, 102, 102, 97, 89, 98, 103, 98, 106, 100, 107, 97, 110, 93, 113, 122, 129, 125, 140, 144, 151, 162, 158, 173, 173, 194, 172, 193, 182, 189, 186, 178, 165, 175, 165, 149, 149, 139, 146, 135, 129, 116, 130, 121, 130, 111, 125, 129, 128, 131, 117, 126, 135, 122, 130, 117, 117, 132, 119, 116, 108, 122, 121, 128, 93, 120, 114, 128, 100, 96, 124, 108, 107, 94, 91, 113, 109, 81, 108, 90, 114, 87, 104, 79, 109, 80, 97, 76, 87, 97, 63, 122, 61, 118, 59, 141, 104, 121, 135, 139, 177, 159, 188, 159, 233, 193, 208, 208, 228, 199, 208, 201, 173, 196, 166, 150, 148, 149, 120, 135, 120, 124, 120, 124, 127, 121, 145, 125, 143, 146, 149, 140, 149, 143, 137, 130, 113, 124, 82, 117, 67, 94, 83, 50, 103, 56, 72, 56, 72, 68, 34, 83, 28, 40, 53, 19, 35, 34, 116, 65, 110, 144, 156, 195, 184, 226, 220, 255, 233, 240, 250, 223, 228, 198, 189, 168, 153, 146, 112, 127, 111, 107, 109, 111, 116, 111, 130, 129, 145, 148, 159, 161, 165, 157, 167, 160, 132, 139, 129, 108, 102, 84, 68, 76, 57, 53, 49, 41, 58, 47, 29, 41, 54, 22, 0, 24, 33, 44, 68, 57, 101, 174, 130, 141, 231, 235, 207, 241, 255, 250, 239, 232, 221, 211, 190, 151, 145, 143, 114, 92, 107, 106, 91, 105, 119, 135, 149, 162, 181, 206, 218, 204, 205, 223, 199, 167, 163, 138, 106, 80, 51, 33, 8, 5, 6, 0, 0, 4, 0, 0, 0, 4, 32, 130, 98, 45, 217, 246, 142, 178, 255, 255, 209, 217, 220, 218, 201, 149, 134, 163, 137, 79, 91, 122, 111, 90, 107, 145, 164, 161, 181, 214, 218, 220, 222, 207, 192, 187, 160, 126, 110, 84, 51, 26, 23, 5, 0, 0, 0, 0, 0, 0, 0, 73, 149, 129, 108, 211, 255, 232, 216, 221, 244, 233, 203, 169, 141, 135, 131, 90, 62, 73, 86, 97, 90, 112, 166, 188, 192, 216, 237, 232, 226, 215, 190, 156, 139, 127, 91, 50, 34, 19, 0, 0, 0, 0, 0, 0, 0, 9, 152, 182, 81, 138, 255, 255, 209, 196, 251, 246, 183, 181, 152, 83, 94, 119, 76, 40, 75, 122, 122, 128, 184, 208, 191, 226, 255, 233, 186, 183, 187, 148, 93, 74, 66, 39, 23, 11, 0, 0, 9, 10, 0, 0, 12, 132, 196, 137, 129, 223, 255, 255, 208, 197, 205, 192, 185, 160, 87, 46, 88, 119, 81, 58, 102, 143, 156, 192, 224, 210, 203, 237, 249, 197, 151, 149, 132, 98, 77, 65, 42, 13, 19, 30, 8, 0, 0, 6, 3, 22, 94, 161, 171, 167, 194, 235, 252, 241, 226, 208, 175, 156, 163, 139, 88, 63, 68, 86, 96, 103, 138, 174, 184, 193, 227, 255, 241, 200, 168, 145, 122, 101, 88, 65, 23, 7, 19, 19, 10, 0, 0, 0, 15, 90, 191, 204, 158, 163, 215, 255, 252, 223, 204, 167, 139, 151, 139, 89, 64, 69, 79, 88, 114, 159, 181, 182, 204, 228, 229, 212, 191, 174, 133, 91, 87, 84, 63, 40, 23, 20, 14, 1, 0, 0, 0, 33, 144, 208, 190, 174, 199, 225, 224, 225, 228, 192, 139, 126, 132, 113, 87, 78, 88, 102, 116, 147, 181, 200, 210, 214, 214, 199, 171, 150, 129, 106, 81, 50, 33, 35, 33, 26, 17, 4, 0, 0, 23, 117, 198, 212, 194, 189, 201, 209, 212, 220, 201, 151, 118, 121, 120, 100, 88, 100, 120, 129, 143, 172, 199, 212, 213, 206, 196, 170, 138, 118, 104, 85, 62, 40, 24, 6, 0, 0, 7, 9, 3, 37, 125, 196, 208, 206, 219, 220, 205, 204, 221, 207, 156, 119, 109, 99, 91, 101, 122, 136, 147, 166, 193, 212, 212, 201, 194, 173, 138, 110, 89, 62, 36, 19, 8, 0, 0, 0, 0, 0, 22, 106, 187, 216, 219, 221, 227, 215, 193, 203, 209, 172, 130, 113, 108, 96, 93, 121, 146, 154, 167, 191, 206, 203, 198, 195, 173, 134, 105, 81, 53, 28, 15, 13, 3, 0, 0, 0, 0, 37, 145, 218, 222, 210, 213, 220, 211, 207, 218, 203, 155, 119, 111, 107, 99, 106, 130, 152, 168, 187, 205, 206, 191, 184, 178, 150, 111, 78, 52, 29, 14, 8, 3, 0, 0, 0, 0, 32, 137, 215, 233, 222, 210, 211, 209, 210, 218, 200, 155, 119, 104, 101, 103, 111, 129, 156, 177, 189, 200, 206, 198, 181, 167, 148, 113, 76, 45, 28, 22, 15, 6, 0, 0, 0, 0, 52, 167, 228, 224, 216, 216, 210, 201, 207, 216, 189, 136, 108, 101, 96, 97, 116, 147, 171, 187, 202, 209, 203, 191, 180, 161, 126, 89, 52, 19, 5, 3, 1, 0, 0, 0, 0, 41, 166, 248, 255, 238, 221, 203, 189, 192, 205, 186, 132, 101, 100, 96, 101, 134, 170, 185, 192, 206, 207, 182, 164, 160, 141, 106, 77, 41, 2, 0, 5, 13, 6, 0, 0, 0, 59, 201, 255, 255, 244, 218, 179, 156, 175, 192, 160, 122, 116, 104, 89, 121, 166, 184, 198, 219, 222, 194, 166, 155, 132, 107, 95, 68, 23, 0, 0, 7, 7, 8, 4, 0, 0, 121, 235, 255, 255, 240, 189, 150, 160, 190, 171, 133, 131, 118, 92, 118, 166, 182, 194, 218, 217, 190, 166, 152, 130, 110, 107, 73, 23, 8, 6, 5, 15, 24, 9, 0, 0, 110, 214, 247, 255, 243, 173, 146, 162, 180, 172, 155, 143, 112, 91, 120, 149, 169, 205, 221, 209, 195, 172, 144, 121, 115, 110, 83, 55, 34, 9, 1, 25, 24, 3, 0, 0, 40, 166, 233, 255, 255, 202, 157, 143, 153, 166, 164, 165, 140, 107, 114, 129, 146, 180, 212, 216, 200, 179, 154, 130, 116, 108, 94, 79, 58, 38, 23, 18, 20, 12, 2, 0, 5, 93, 169, 229, 255, 245, 193, 155, 135, 137, 151, 179, 167, 140, 140, 122, 130, 159, 181, 209, 210, 196, 176, 136, 120, 105, 91, 89, 74, 61, 40, 22, 20, 10, 11, 15, 0, 26, 108, 163, 230, 255, 240, 192, 160, 138, 131, 157, 180, 172, 162, 143, 127, 132, 151, 171, 196, 206, 195, 173, 149, 126, 100, 86, 71, 61, 51, 42, 37, 29, 33, 24, 18, 1, 0, 83, 139, 201, 255, 255, 232, 194, 163, 123, 137, 153, 157, 167, 157, 140, 121, 142, 152, 174, 199, 195, 186, 170, 143, 113, 105, 84, 77, 67, 58, 53, 42, 36, 17, 15, 10, 0, 11, 75, 131, 197, 253, 255, 232, 193, 154, 128, 146, 161, 169, 170, 156, 137, 131, 142, 152, 174, 190, 191, 185, 170, 146, 132, 112, 84, 71, 53, 44, 46, 48, 45, 40, 26, 0, 0, 3, 65, 124, 202, 252, 255, 239, 200, 154, 127, 136, 143, 165, 175, 167, 155, 147, 141, 144, 158, 168, 175, 181, 176, 166, 150, 131, 108, 84, 56, 41, 45, 48, 59, 52, 46, 18, 1, 0, 2, 66, 116, 200, 241, 255, 236, 204, 162, 137, 139, 137, 163, 165, 166, 163, 155, 147, 143, 157, 153, 168, 176, 168, 174, 164, 149, 126, 99, 64, 41, 34, 28, 46, 51, 60, 55, 42, 11, 0, 34, 56, 130, 195, 236, 255, 241, 211, 157, 147, 127, 136, 157, 159, 166, 167, 155, 147, 156, 154, 157, 170, 166, 164, 161, 150, 140, 124, 106, 79, 59, 38, 28, 36, 45, 52, 54, 54, 37, 21, 33, 56, 99, 158, 211, 240, 249, 232, 200, 174, 147, 135, 133, 139, 143, 152, 156, 158, 163, 164, 164, 163, 160, 153, 147, 138, 133, 123, 115, 102, 80, 62, 42, 34, 29, 35, 40, 47, 41, 29, 49, 58, 97, 147, 192, 223, 244, 239, 212, 200, 163, 151, 139, 129, 128, 128, 133, 132, 150, 150, 166, 173, 174, 173, 162, 155, 139, 133, 117, 113, 98, 83, 70, 51, 42, 34, 35, 34, 43, 46, 44, 55, 71, 89, 124, 163, 194, 224, 235, 228, 213, 191, 166, 147, 134, 125, 125, 126, 131, 142, 150, 161, 167, 166, 161, 152, 139, 129, 124, 119, 118, 120, 115, 110, 96, 80, 63, 45, 34, 26, 31, 35, 46, 48, 65, 82, 99, 135, 161, 192, 211, 224, 215, 207, 192, 166, 155, 138, 132, 130, 132, 133, 139, 146, 146, 154, 158, 158, 160, 157, 151, 146, 141, 130, 123, 113, 101, 94, 88, 82, 80, 76, 72, 68, 63, 55, 50, 53, 51, 60, 68, 91, 113, 138, 168, 189, 211, 215, 219, 205, 192, 174, 158, 146, 135, 134, 129, 132, 134, 141, 148, 153, 156, 159, 158, 151, 143, 132, 121, 111, 104, 99, 101, 104, 111, 118, 120, 121, 113, 103, 88, 76, 61, 54, 52, 48, 52, 50, 46, 47, 52, 53, 71, 92, 120, 154, 188, 213, 232, 247, 244, 243, 229, 211, 190, 167, 146, 126, 115, 106, 107, 111, 119, 129, 138, 146, 150, 155, 153, 151, 146, 137, 131, 123, 115, 109, 109, 108, 113, 118, 122, 125, 123, 119, 111, 100, 87, 79, 69, 64, 61, 64, 65, 67, 66, 59, 52, 47, 53, 53, 70, 91, 118, 153, 185, 210, 229, 242, 240, 237, 224, 206, 187, 166, 148, 132, 124, 118, 119, 123, 129, 138, 145, 151, 156, 157, 154, 150, 142, 134, 128, 123, 119, 119, 120, +}; + +const unsigned char one[] PROGMEM = { +168, 161, 152, 142, 132, 126, 122, 121, 123, 125, 125, 124, 119, 112, 104, 97, 88, 78, 69, 56, 42, 32, 22, 15, 16, 20, 22, 25, 33, 53, 69, 84, 112, 138, 160, 182, 194, 201, 203, 200, 194, 189, 182, 174, 172, 169, 167, 165, 164, 167, 170, 172, 174, 173, 169, 162, 154, 144, 135, 129, 124, 123, 123, 124, 124, 123, 120, 115, 109, 101, 91, 82, 71, 59, 47, 35, 26, 23, 23, 24, 25, 25, 25, 38, 56, 72, 98, 127, 153, 177, 195, 205, 206, 203, 195, 185, 176, 167, 163, 162, 164, 166, 168, 169, 171, 174, 177, 177, 177, 174, 167, 159, 149, 138, 131, 125, 123, 123, 124, 123, 119, 113, 104, 94, 82, 72, 60, 46, 31, 16, 3, 0, 0, 0, 0, 0, 0, 0, 31, 63, 107, 161, 197, 221, 234, 228, 211, 201, 192, 186, 186, 184, 181, 179, 177, 172, 168, 176, 184, 196, 208, 207, 201, 186, 165, 144, 129, 121, 119, 122, 123, 119, 112, 102, 90, 81, 73, 60, 49, 33, 9, 0, 0, 0, 0, 0, 0, 0, 0, 15, 50, 96, 161, 210, 232, 246, 241, 219, 206, 196, 195, 194, 192, 188, 177, 170, 162, 159, 174, 193, 210, 226, 223, 209, 190, 164, 140, 125, 121, 123, 126, 125, 118, 106, 94, 85, 81, 75, 58, 33, 4, 0, 0, 0, 0, 0, 0, 0, 0, 34, 64, 97, 165, 214, 232, 241, 236, 204, 185, 181, 181, 187, 192, 190, 181, 171, 160, 152, 172, 198, 219, 235, 233, 213, 181, 156, 132, 121, 126, 128, 130, 124, 109, 104, 99, 97, 94, 73, 42, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 143, 235, 255, 255, 216, 185, 150, 147, 183, 212, 225, 204, 176, 146, 126, 132, 160, 206, 233, 249, 242, 216, 181, 151, 142, 137, 135, 136, 133, 126, 114, 111, 112, 108, 98, 75, 45, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 167, 226, 255, 244, 178, 143, 170, 186, 211, 245, 222, 171, 132, 123, 144, 183, 194, 189, 193, 186, 195, 206, 208, 200, 170, 150, 131, 125, 132, 130, 128, 117, 112, 105, 105, 102, 75, 39, 2, 0, 7, 12, 6, 0, 0, 0, 0, 0, 4, 156, 163, 174, 199, 195, 193, 211, 238, 209, 191, 190, 164, 172, 172, 162, 168, 169, 172, 191, 200, 204, 220, 211, 191, 182, 172, 156, 144, 135, 131, 130, 127, 117, 104, 98, 98, 85, 57, 34, 15, 10, 16, 5, 0, 0, 0, 0, 0, 0, 0, 135, 171, 135, 177, 178, 173, 211, 223, 227, 216, 210, 216, 195, 190, 176, 145, 161, 170, 172, 202, 196, 188, 209, 211, 200, 186, 162, 147, 144, 145, 142, 131, 124, 122, 113, 100, 88, 65, 36, 26, 23, 3, 0, 0, 0, 0, 0, 0, 0, 0, 27, 176, 111, 66, 185, 218, 219, 253, 208, 196, 238, 241, 222, 180, 154, 167, 180, 189, 178, 161, 172, 185, 192, 200, 198, 181, 173, 175, 160, 142, 139, 138, 134, 127, 119, 114, 108, 94, 78, 60, 34, 32, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 149, 67, 59, 171, 202, 167, 179, 197, 204, 213, 210, 206, 194, 184, 202, 208, 188, 180, 187, 186, 180, 180, 182, 180, 176, 173, 165, 155, 149, 146, 143, 138, 134, 132, 127, 118, 110, 100, 85, 69, 52, 33, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 18, 47, 105, 134, 143, 156, 172, 192, 209, 214, 219, 230, 235, 236, 235, 222, 208, 203, 197, 186, 180, 179, 173, 171, 169, 164, 158, 154, 150, 146, 143, 139, 136, 133, 129, 123, 118, 109, 97, 88, 72, 59, 47, 32, 15, 0, 0, 0, 0, 0, 0, 0, 0, 4, 27, 23, 55, 117, 138, 136, 162, 177, 184, 202, 225, 226, 230, 239, 245, 245, 226, 206, 204, 196, 177, 172, 171, 165, 166, 171, 157, 148, 153, 149, 142, 140, 139, 134, 133, 131, 125, 124, 114, 104, 100, 83, 69, 61, 52, 27, 5, 0, 0, 0, 0, 0, 0, 0, 0, 21, 28, 44, 86, 122, 133, 149, 174, 192, 205, 222, 234, 235, 238, 243, 240, 226, 211, 204, 199, 187, 177, 173, 169, 168, 166, 159, 153, 153, 148, 144, 143, 139, 136, 134, 128, 125, 119, 110, 103, 96, 80, 67, 57, 47, 38, 29, 18, 10, 2, 0, 0, 0, 0, 0, 0, 12, 8, 31, 83, 100, 118, 148, 169, 179, 203, 227, 242, 240, 254, 244, 255, 253, 191, 214, 198, 198, 184, 177, 177, 164, 163, 156, 159, 144, 149, 145, 142, 136, 136, 132, 129, 122, 118, 112, 104, 95, 83, 74, 67, 54, 41, 39, 27, 12, 1, 0, 0, 0, 0, 0, 3, 15, 22, 51, 98, 107, 128, 159, 177, 191, 222, 241, 240, 250, 255, 255, 250, 243, 228, 217, 210, 199, 193, 186, 177, 170, 169, 167, 157, 153, 155, 149, 144, 140, 138, 136, 131, 127, 123, 118, 114, 109, 103, 98, 92, 87, 81, 76, 72, 67, 64, 60, 57, 53, 52, 48, 49, 50, 49, 47, 55, 65, 70, 78, 88, 98, 107, 118, 119, 126, 132, 137, 140, 142, 150, 151, 151, 149, 153, 158, 159, 157, 157, 160, 161, 160, 158, 155, 156, 157, 156, 152, 148, 149, 149, 145, 141, 138, 136, 134, 133, 131, 130, 128, 127, 126, 124, 122, 122, 120, 118, 116, 115, 115, 115, +}; + +const unsigned char two[] PROGMEM = { +104, 107, 113, 113, 115, 120, 120, 121, 125, 127, 122, 122, 130, 134, 129, 126, 129, 130, 126, 126, 130, 131, 130, 132, 135, 137, 139, 137, 133, 134, 137, 135, 132, 129, 130, 132, 131, 128, 125, 127, 128, 130, 129, 130, 132, 135, 133, 130, 131, 133, 133, 134, 134, 136, 135, 135, 134, 134, 131, 127, 127, 128, 126, 123, 125, 127, 129, 126, 125, 125, 129, 125, 126, 125, 128, 125, 128, 125, 127, 125, 126, 124, 124, 126, 126, 132, 126, 129, 123, 133, 126, 140, 128, 147, 114, 212, 212, 75, 161, 113, 146, 186, 160, 119, 144, 85, 110, 149, 82, 148, 106, 186, 140, 114, 84, 101, 84, 83, 103, 91, 141, 84, 133, 112, 100, 118, 141, 82, 188, 62, 166, 108, 72, 207, 32, 229, 46, 189, 109, 120, 167, 99, 184, 16, 131, 37, 118, 50, 148, 63, 111, 134, 76, 197, 56, 236, 72, 214, 97, 148, 161, 86, 186, 58, 213, 16, 194, 48, 122, 119, 41, 198, 46, 205, 53, 204, 111, 140, 171, 76, 209, 107, 181, 101, 191, 96, 142, 122, 108, 172, 54, 178, 80, 171, 101, 167, 130, 82, 191, 85, 177, 122, 150, 128, 124, 125, 103, 167, 76, 141, 139, 109, 141, 87, 156, 144, 100, 121, 126, 115, 181, 59, 115, 192, 117, 111, 148, 173, 104, 162, 77, 141, 115, 120, 125, 92, 165, 104, 108, 134, 116, 139, 146, 111, 131, 147, 135, 80, 161, 142, 140, 139, 77, 173, 121, 85, 120, 136, 150, 120, 115, 131, 126, 84, 132, 144, 128, 74, 151, 144, 89, 169, 133, 143, 104, 177, 97, 118, 144, 79, 161, 98, 114, 129, 128, 118, 111, 153, 130, 152, 152, 123, 155, 110, 141, 123, 104, 133, 138, 126, 96, 128, 116, 106, 106, 117, 136, 128, 105, 147, 175, 108, 108, 184, 153, 97, 127, 161, 130, 112, 106, 139, 167, 109, 104, 138, 156, 104, 105, 150, 142, 130, 107, 150, 176, 117, 125, 138, 135, 85, 110, 135, 64, 127, 112, 108, 96, 90, 137, 127, 121, 96, 158, 154, 97, 123, 161, 158, 123, 113, 185, 184, 118, 118, 148, 158, 107, 104, 109, 151, 150, 92, 120, 161, 150, 110, 133, 148, 145, 134, 95, 129, 154, 119, 101, 142, 155, 140, 132, 126, 176, 167, 119, 144, 180, 157, 132, 137, 132, 126, 113, 90, 108, 109, 82, 61, 60, 76, 56, 44, 52, 65, 57, 35, 40, 78, 62, 11, 29, 83, 59, 4, 13, 48, 73, 55, 61, 101, 164, 176, 179, 232, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 239, 197, 205, 195, 156, 126, 119, 127, 112, 81, 71, 92, 93, 67, 55, 72, 85, 63, 43, 47, 58, 45, 13, 0, 13, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 36, 103, 195, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 212, 188, 188, 180, 166, 155, 151, 159, 161, 158, 153, 159, 161, 152, 144, 138, 131, 115, 96, 78, 55, 32, 15, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 83, 164, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 222, 206, 183, 157, 137, 138, 141, 145, 157, 166, 173, 176, 185, 191, 187, 186, 185, 180, 165, 146, 126, 89, 42, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 103, 117, 114, 180, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 176, 155, 141, 134, 123, 122, 129, 143, 157, 165, 172, 174, 186, 193, 193, 190, 189, 184, 173, 151, 122, 83, 46, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 67, 113, 154, 222, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 237, 205, 172, 142, 113, 103, 110, 116, 116, 122, 132, 141, 154, 167, 175, 179, 185, 191, 192, 190, 183, 164, 132, 95, 59, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 78, 112, 173, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 237, 204, 183, 163, 130, 102, 91, 95, 104, 111, 120, 126, 131, 139, 153, 169, 177, 178, 179, 184, 184, 178, 164, 139, 102, 63, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 82, 149, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 206, 179, 151, 122, 98, 90, 95, 101, 107, 114, 121, 133, 147, 157, 167, 178, 180, 183, 184, 183, 177, 158, 127, 86, 46, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 70, 141, 196, 254, 255, 255, 255, 255, 255, 255, 255, 255, 250, 210, 180, 154, 124, 97, 85, 86, 92, 97, 104, 109, 119, 133, 145, 156, 165, 174, 180, 185, 188, 189, 185, 166, 137, 104, 65, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 68, 137, 199, 255, 255, 255, 255, 255, 255, 255, 255, 255, 217, 189, 169, 140, 99, 80, 84, 93, 103, 108, 114, 126, 146, 158, 170, 177, 182, 192, 196, 194, 191, 185, 155, 114, 77, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 67, 115, 175, 236, 255, 255, 255, 255, 255, 255, 255, 255, 233, 189, 151, 133, 111, 83, 70, 82, 96, 117, 133, 143, 160, 176, 187, 194, 195, 192, 190, 191, 185, 178, 166, 141, 110, 78, 42, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 138, 150, 185, 236, 255, 255, 255, 255, 255, 255, 255, 228, 194, 178, 160, 148, 146, 130, 112, 116, 145, 165, 171, 170, 173, 189, 198, 194, 182, 172, 171, 173, 168, 153, 138, 131, 110, 79, 62, 44, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 108, 148, 146, 156, 186, 233, 255, 240, 216, 216, 245, 253, 228, 190, 179, 186, 186, 176, 161, 152, 155, 180, 193, 183, 179, 186, 192, 188, 175, 164, 160, 160, 150, 137, 127, 122, 114, 100, 92, 86, 75, 62, 53, 52, 46, 36, 24, 20, 20, 28, 30, 23, 15, 38, 56, 38, 19, 22, 50, 68, 70, 72, 101, 126, 138, 147, 161, 189, 207, 214, 217, 227, 248, 255, 240, 228, 226, 230, 225, 208, 190, 191, 200, 197, 186, 176, 177, 179, 170, 163, 157, 158, 155, 141, 133, 128, 124, 114, 107, 97, 86, 89, 84, 67, 58, 58, 60, 51, 43, 49, 65, 73, 75, 74, 75, 101, 118, 114, 114, 137, 149, 153, 149, 152, 171, 174, 177, 181, 180, 171, 174, 177, 178, 169, 161, 163, 170, 172, 156, 140, 137, 151, 148, 126, 111, 115, 118, 110, 91, 95, 92, 87, 105, 96, 89, 95, 107, 98, 99, 98, 107, 115, 88, 95, 134, 127, 106, 111, 118, 140, 144, 130, 126, 122, 137, 158, 149, 130, 141, 151, 165, 174, 146, 140, 148, 164, 163, 140, 131, 135, 147, 154, 132, 115, 118, 131, 141, 122, 103, 112, 134, 137, 119, 105, 116, 123, 123, 119, 107, 110, 127, 123, 114, 119, 122, 130, 122, 117, 128, 126, 121, 127, 133, 126, 126, +}; + +const unsigned char three[] PROGMEM = { +131, 129, 126, 130, 123, 128, 128, 127, 124, 130, 128, 129, 134, 124, 130, 127, 125, 127, 127, 128, 129, 125, 128, 127, 127, 127, 126, 128, 124, 130, 126, 127, 127, 129, 127, 127, 127, 127, 126, 125, 128, 126, 125, 128, 129, 127, 126, 124, 129, 127, 128, 128, 127, 128, 130, 125, 129, 128, 128, 129, 128, 127, 123, 130, 123, 124, 134, 133, 120, 131, 128, 125, 124, 126, 127, 127, 130, 124, 130, 129, 130, 125, 128, 131, 131, 129, 131, 127, 127, 132, 124, 127, 126, 126, 130, 124, 126, 131, 128, 124, 125, 130, 133, 128, 123, 122, 130, 129, 123, 120, 129, 131, 124, 128, 128, 129, 127, 135, 128, 119, 114, 119, 130, 115, 127, 127, 122, 136, 128, 123, 115, 129, 124, 129, 124, 124, 130, 131, 132, 115, 124, 132, 135, 126, 142, 131, 134, 137, 159, 128, 114, 135, 133, 118, 111, 126, 106, 133, 126, 123, 111, 144, 145, 138, 135, 141, 140, 125, 128, 114, 123, 107, 133, 115, 113, 120, 131, 114, 120, 136, 128, 137, 131, 136, 123, 153, 134, 120, 123, 131, 126, 119, 123, 125, 129, 120, 132, 120, 126, 133, 149, 130, 128, 134, 125, 121, 125, 119, 116, 131, 126, 138, 127, 138, 125, 132, 122, 117, 130, 124, 127, 127, 130, 120, 138, 123, 137, 131, 116, 128, 136, 125, 120, 129, 123, 136, 126, 121, 127, 139, 128, 124, 125, 126, 129, 125, 132, 128, 133, 131, 137, 129, 116, 135, 116, 120, 125, 118, 117, 122, 132, 117, 130, 129, 131, 130, 134, 123, 120, 144, 133, 130, 125, 144, 141, 133, 133, 134, 139, 125, 143, 138, 140, 140, 140, 141, 128, 135, 129, 138, 132, 125, 129, 124, 125, 118, 111, 122, 116, 118, 99, 103, 133, 110, 98, 107, 104, 92, 105, 115, 91, 84, 105, 107, 98, 83, 104, 122, 120, 118, 119, 151, 157, 153, 164, 172, 172, 176, 173, 174, 173, 163, 162, 165, 159, 147, 143, 144, 140, 135, 130, 132, 131, 127, 126, 124, 123, 119, 117, 116, 113, 108, 108, 104, 98, 97, 92, 89, 94, 95, 91, 91, 96, 95, 87, 87, 97, 91, 76, 76, 102, 130, 136, 133, 131, 147, 163, 171, 175, 171, 177, 183, 180, 174, 163, 157, 156, 148, 142, 134, 134, 133, 128, 128, 131, 133, 135, 134, 132, 134, 135, 132, 131, 131, 133, 131, 133, 135, 136, 136, 135, 135, 136, 138, 137, 132, 129, 127, 124, 120, 111, 107, 100, 94, 90, 89, 88, 80, 72, 67, 64, 59, 54, 49, 59, 83, 111, 129, 137, 140, 141, 149, 164, 181, 194, 202, 202, 195, 184, 172, 161, 154, 150, 146, 138, 126, 114, 110, 113, 121, 126, 129, 129, 128, 126, 127, 131, 138, 143, 146, 148, 149, 147, 145, 143, 141, 141, 140, 138, 132, 124, 117, 110, 104, 99, 94, 89, 83, 74, 66, 58, 51, 42, 30, 27, 38, 67, 105, 136, 148, 145, 141, 148, 171, 198, 216, 220, 212, 201, 186, 172, 159, 153, 147, 136, 118, 99, 91, 95, 106, 113, 116, 119, 125, 135, 145, 153, 159, 162, 165, 165, 163, 159, 148, 136, 128, 128, 134, 137, 132, 120, 108, 98, 93, 91, 90, 85, 70, 53, 43, 39, 30, 15, 21, 60, 120, 159, 151, 128, 129, 174, 222, 238, 218, 190, 182, 187, 188, 174, 154, 137, 119, 103, 94, 97, 107, 110, 107, 107, 119, 136, 150, 155, 154, 157, 166, 175, 176, 164, 147, 134, 131, 132, 131, 127, 120, 116, 116, 121, 118, 105, 91, 82, 79, 75, 66, 52, 33, 14, 1, 19, 70, 127, 150, 123, 109, 143, 214, 253, 225, 181, 173, 210, 228, 195, 148, 126, 131, 130, 112, 97, 91, 95, 100, 107, 118, 128, 134, 141, 151, 160, 164, 164, 167, 165, 156, 148, 147, 144, 129, 113, 116, 132, 133, 119, 112, 122, 123, 111, 101, 107, 105, 84, 67, 68, 61, 38, 8, 38, 116, 111, 64, 76, 179, 214, 144, 128, 199, 255, 196, 150, 184, 210, 178, 127, 127, 134, 116, 95, 90, 101, 102, 104, 112, 125, 141, 148, 157, 162, 166, 169, 164, 162, 159, 154, 139, 127, 129, 126, 121, 115, 120, 121, 118, 116, 112, 106, 100, 99, 94, 82, 72, 58, 46, 27, 32, 103, 95, 53, 82, 172, 192, 120, 142, 213, 229, 178, 175, 220, 200, 160, 150, 157, 140, 110, 105, 103, 100, 95, 100, 110, 118, 130, 138, 147, 154, 161, 163, 160, 162, 161, 154, 144, 138, 136, 130, 126, 124, 126, 121, 117, 114, 110, 103, 101, 96, 84, 76, 73, 56, 45, 27, 55, 110, 59, 66, 138, 162, 119, 133, 211, 194, 169, 190, 218, 194, 166, 179, 177, 151, 131, 130, 128, 110, 101, 106, 108, 105, 107, 120, 123, 131, 140, 145, 149, 157, 163, 160, 161, 161, 155, 144, 143, 141, 132, 127, 127, 121, 116, 104, 102, 96, 89, 86, 80, 77, 74, 58, 58, 42, 56, 114, 48, 79, 151, 126, 106, 162, 194, 148, 180, 200, 201, 180, 183, 198, 170, 154, 153, 149, 123, 115, 120, 110, 103, 107, 115, 111, 121, 134, 136, 144, 153, 158, 159, 165, 160, 156, 152, 146, 139, 135, 131, 123, 118, 109, 107, 100, 85, 95, 85, 77, 74, 71, 67, 55, 44, 55, 110, 60, 65, 146, 131, 104, 151, 188, 152, 173, 198, 198, 181, 184, 199, 175, 157, 164, 158, 126, 128, 129, 113, 104, 114, 116, 111, 121, 133, 135, 141, 155, 157, 155, 162, 162, 148, 150, 145, 136, 130, 127, 115, 109, 102, 95, 86, 83, 79, 70, 69, 68, 60, 54, 48, 53, 112, 56, 77, 149, 111, 112, 164, 175, 141, 187, 198, 189, 182, 199, 200, 173, 169, 177, 158, 131, 145, 134, 112, 116, 123, 108, 112, 128, 129, 128, 149, 154, 149, 156, 163, 151, 147, 151, 144, 129, 130, 128, 109, 101, 98, 86, 76, 76, 66, 66, 59, 61, 52, 51, 39, 92, 81, 52, 137, 125, 106, 151, 178, 142, 176, 199, 185, 188, 195, 199, 179, 179, 174, 168, 144, 146, 141, 120, 118, 127, 113, 111, 124, 127, 129, 138, 148, 150, 151, 156, 160, 147, 151, 153, 137, 130, 141, 117, 108, 109, 97, 79, 84, 74, 65, 61, 61, 54, 49, 48, 45, 101, 55, 82, 135, 107, 112, 167, 157, 142, 191, 188, 183, 185, 205, 186, 181, 178, 177, 157, 147, 151, 130, 122, 126, 124, 114, 125, 130, 133, 140, 151, 154, 151, 157, 163, 152, 153, 156, 138, 135, 135, 119, 105, 104, 92, 77, 76, 70, 59, 53, 61, 47, 47, 40, 84, 78, 49, 128, 118, 96, 144, 165, 139, 167, 195, 176, 185, 198, 193, 181, 180, 178, 165, 149, 154, 143, 121, 128, 129, 110, 119, 133, 128, 132, 151, 148, 146, 161, 160, 151, 154, 156, 139, 135, 135, 113, 103, 103, 87, 76, 73, 69, 56, 54, 57, 51, 40, 69, 90, 57, 99, 130, 102, 125, 165, 146, 150, 189, 181, 170, 190, 192, 174, 176, 174, 168, 152, 147, 150, 131, 123, 134, 134, 121, 133, 146, 140, 143, 155, 156, 149, 153, 159, 147, 139, 146, 133, 118, 113, 104, 90, 80, 72, 69, 63, 57, 58, 59, 54, 56, 54, 85, 104, 71, 112, 148, 121, 123, 170, 164, 150, 184, 193, 181, 178, 186, 185, 171, 161, 174, 156, 141, 146, 143, 133, 126, 143, 138, 137, 151, 152, 149, 153, 157, 147, 142, 146, 135, 124, 128, 113, 102, 101, 90, 87, 81, 75, 74, 72, 67, 66, 68, 63, 66, 64, 79, 109, 89, 97, 140, 137, 121, 148, 169, 150, 156, 175, 171, 163, 167, 166, 161, 156, 152, 146, 141, 141, 136, 137, 136, 137, 136, 135, 139, 141, 139, 134, 133, 132, 135, 127, 124, 126, 121, 122, 124, 125, 123, 123, 122, 122, 125, 128, 127, 123, 124, 128, 126, 126, 127, 126, 128, 128, 127, 129, 128, 129, 126, 126, 130, 132, 126, 126, 129, 124, 129, 128, 129, 126, 126, 128, 127, 130, 126, 125, 127, 129, 128, 125, 125, 127, 129, 127, 128, 126, 125, 128, 124, 128, 129, 125, 126, 126, 125, 129, 129, 127, 129, 129, 128, 127, 127, 128, 129, 125, 127, 128, 128, 129, 129, 127, 127, 128, 130, 129, 125, 127, 130, 129, 126, 128, 128, 126, 129, 127, 124, 127, 129, 128, 127, 127, 129, 129, 125, 128, 132, 126, 127, 129, 126, 129, 127, 126, 130, 126, 129, 130, 126, 130, 129, 125, 129, 130, 128, 128, 125, 126, 130, 132, 125, 127, 130, 127, 128, 127, 126, +}; + +const unsigned char four[] PROGMEM = { +125, 128, 125, 128, 127, 128, 130, 130, 124, 124, 129, 130, 130, 127, 127, 130, 125, 126, 129, 129, 130, 128, 129, 127, 129, 125, 125, 130, 129, 127, 125, 127, 126, 125, 128, 130, 130, 126, 125, 133, 123, 126, 127, 126, 129, 128, 132, 125, 132, 122, 126, 132, 122, 131, 126, 122, 132, 125, 121, 130, 122, 135, 127, 123, 131, 128, 127, 125, 129, 133, 123, 123, 130, 132, 128, 122, 131, 126, 128, 128, 124, 130, 132, 124, 127, 126, 127, 134, 130, 126, 124, 126, 135, 134, 124, 124, 123, 132, 130, 120, 128, 132, 122, 126, 127, 125, 128, 124, 122, 129, 131, 122, 123, 126, 127, 129, 129, 128, 128, 128, 130, 129, 132, 128, 129, 129, 126, 125, 127, 129, 122, 122, 129, 126, 127, 128, 127, 133, 124, 128, 129, 129, 135, 128, 125, 133, 134, 131, 128, 124, 121, 125, 129, 129, 132, 127, 128, 128, 129, 128, 129, 129, 132, 129, 128, 130, 126, 125, 127, 130, 124, 119, 128, 128, 127, 130, 126, 132, 127, 127, 130, 128, 134, 130, 125, 130, 134, 132, 129, 126, 122, 124, 128, 128, 132, 131, 122, 123, 128, 121, 126, 135, 128, 125, 127, 127, 128, 122, 131, 133, 130, 132, 129, 127, 122, 118, 122, 136, 130, 116, 133, 131, 127, 130, 118, 126, 126, 124, 128, 132, 129, 129, 125, 125, 127, 129, 130, 123, 132, 135, 127, 121, 133, 123, 125, 130, 122, 128, 132, 138, 132, 130, 114, 117, 130, 129, 129, 140, 131, 115, 123, 127, 134, 123, 119, 122, 123, 128, 138, 133, 131, 128, 114, 121, 119, 133, 139, 136, 127, 125, 132, 121, 126, 128, 136, 144, 159, 155, 127, 112, 113, 123, 135, 143, 137, 131, 129, 127, 119, 115, 118, 123, 124, 121, 120, 120, 124, 121, 116, 127, 131, 110, 91, 82, 80, 77, 77, 83, 88, 88, 90, 93, 98, 111, 131, 157, 184, 199, 204, 203, 194, 181, 169, 156, 146, 138, 135, 133, 129, 123, 117, 112, 107, 109, 113, 123, 136, 152, 164, 169, 177, 179, 174, 170, 164, 152, 140, 129, 117, 109, 105, 106, 105, 106, 108, 108, 108, 105, 101, 93, 90, 84, 77, 68, 62, 61, 57, 52, 46, 46, 57, 76, 101, 139, 176, 207, 219, 223, 219, 204, 183, 161, 144, 131, 125, 123, 124, 124, 123, 119, 115, 112, 115, 121, 133, 148, 166, 178, 183, 185, 181, 171, 158, 147, 134, 123, 116, 113, 112, 112, 113, 116, 116, 118, 119, 117, 113, 109, 102, 94, 87, 81, 77, 71, 63, 55, 47, 44, 45, 56, 78, 109, 147, 184, 217, 230, 231, 223, 205, 182, 158, 138, 123, 117, 116, 117, 119, 120, 117, 114, 111, 114, 119, 131, 145, 162, 176, 183, 185, 181, 172, 159, 146, 134, 124, 117, 114, 113, 114, 115, 117, 118, 119, 120, 119, 117, 112, 106, 98, 91, 85, 80, 75, 67, 60, 51, 45, 44, 48, 66, 93, 132, 169, 206, 229, 234, 230, 214, 192, 166, 143, 124, 114, 111, 111, 113, 116, 115, 113, 111, 111, 116, 126, 141, 158, 174, 186, 190, 185, 173, 156, 137, 121, 110, 105, 105, 108, 113, 120, 125, 131, 136, 138, 137, 136, 133, 129, 122, 115, 106, 95, 85, 75, 66, 58, 51, 45, 40, 39, 48, 67, 94, 129, 171, 210, 235, 245, 243, 227, 199, 168, 142, 121, 108, 104, 105, 108, 110, 110, 109, 108, 110, 115, 125, 140, 159, 176, 187, 190, 184, 172, 157, 141, 126, 112, 104, 101, 102, 107, 115, 124, 130, 134, 137, 138, 136, 131, 126, 119, 110, 99, 88, 78, 70, 62, 54, 47, 38, 33, 44, 65, 96, 134, 178, 219, 242, 246, 238, 217, 186, 155, 131, 114, 106, 104, 107, 111, 110, 110, 107, 104, 105, 114, 131, 151, 172, 189, 198, 195, 183, 165, 147, 129, 116, 108, 106, 105, 108, 112, 117, 121, 125, 128, 131, 134, 136, 138, 134, 127, 115, 103, 89, 77, 65, 55, 48, 41, 33, 31, 46, 72, 109, 150, 194, 232, 249, 248, 233, 208, 175, 144, 122, 109, 104, 104, 107, 108, 104, 101, 98, 100, 106, 122, 147, 172, 193, 203, 201, 186, 162, 140, 124, 116, 115, 118, 123, 122, 119, 114, 112, 114, 120, 129, 137, 144, 146, 144, 134, 121, 104, 86, 68, 54, 47, 47, 48, 48, 46, 52, 70, 98, 138, 180, 221, 243, 245, 231, 205, 172, 139, 119, 108, 107, 108, 109, 106, 98, 90, 88, 98, 119, 146, 175, 198, 210, 205, 188, 161, 134, 115, 109, 113, 122, 132, 138, 131, 117, 105, 102, 109, 123, 141, 157, 161, 155, 140, 121, 99, 80, 71, 68, 70, 70, 70, 62, 45, 30, 33, 58, 101, 155, 208, 248, 255, 239, 202, 163, 132, 114, 117, 128, 135, 129, 113, 93, 76, 72, 86, 119, 157, 187, 203, 202, 185, 162, 142, 132, 129, 129, 130, 128, 123, 115, 109, 109, 115, 125, 136, 146, 155, 158, 156, 151, 141, 126, 110, 95, 83, 76, 74, 76, 77, 77, 71, 64, 54, 45, 46, 65, 112, 162, 204, 221, 218, 200, 171, 153, 149, 156, 158, 146, 125, 101, 81, 80, 98, 128, 152, 163, 163, 158, 155, 157, 165, 172, 169, 154, 133, 114, 104, 107, 122, 135, 137, 129, 123, 122, 130, 145, 163, 170, 161, 145, 130, 119, 110, 102, 92, 81, 69, 65, 69, 76, 79, 74, 66, 54, 45, 49, 72, 122, 176, 210, 212, 193, 174, 161, 161, 168, 166, 150, 123, 100, 93, 98, 113, 129, 140, 141, 140, 146, 159, 174, 180, 175, 161, 143, 130, 124, 123, 120, 117, 118, 124, 130, 138, 147, 153, 153, 153, 156, 156, 149, 136, 123, 108, 96, 90, 85, 78, 71, 71, 75, 81, 83, 81, 74, 65, 58, 57, 69, 104, 147, 176, 181, 176, 180, 177, 175, 173, 163, 149, 138, 136, 132, 122, 119, 123, 130, 139, 148, 153, 154, 158, 164, 165, 159, 150, 143, 139, 137, 136, 137, 135, 133, 130, 131, 135, 139, 144, 147, 144, 138, 129, 120, 111, 107, 104, 96, 86, 82, 86, 85, 81, 83, 86, 87, 87, 86, 79, 74, 76, 76, 63, 54, 91, 137, 156, 155, 162, 176, 181, 188, 187, 170, 158, 164, 169, 156, 137, 128, 127, 132, 137, 141, 142, 148, 159, 162, 159, 155, 154, 155, 152, 148, 142, 140, 140, 137, 134, 132, 131, 131, 131, 128, 127, 128, 130, 126, 119, 111, 102, 92, 85, 90, 98, 98, 92, 90, 88, 88, 90, 89, 84, 83, 85, 84, 82, 86, 83, 91, 117, 139, 142, 144, 156, 163, 168, 170, 166, 160, 160, 159, 153, 145, 143, 142, 144, 149, 148, 145, 144, 146, 145, 145, 144, 142, 141, 138, 136, 134, 132, 132, 133, 133, 129, 125, 123, 125, 127, 127, 129, 130, 129, 129, 126, 125, 123, 121, 119, 117, 118, 120, 121, 124, 125, 127, 128, 130, 129, 127, 128, 125, 125, 124, 121, 124, 125, 124, 125, 123, 121, 121, 124, 124, 126, 129, 127, 126, 128, 125, 124, 123, 121, 124, 125, 123, 124, 124, 121, 121, 124, 124, 125, 128, 125, 127, 129, 126, 126, 125, 124, 125, 127, 127, 128, 129, 129, 131, 134, 134, 133, 134, 135, 139, 140, 140, 142, 140, 139, 139, 140, 138, 138, 139, 137, 134, 131, 129, 127, 127, 127, 126, 124, 123, 124, 122, 120, 121, 121, 121, 122, 121, 119, 117, 117, 117, +}; + +const unsigned char five[] PROGMEM = { +130, 126, 127, 130, 130, 125, 128, 129, 129, 130, 128, 128, 127, 123, 126, 124, 123, 129, 126, 127, 130, 131, 128, 131, 132, 130, 126, 127, 128, 126, 128, 123, 127, 128, 127, 130, 128, 129, 130, 129, 127, 132, 131, 129, 127, 127, 128, 127, 120, 121, 124, 120, 124, 127, 129, 127, 132, 133, 130, 129, 132, 135, 131, 126, 125, 124, 125, 125, 129, 129, 124, 129, 128, 133, 133, 128, 129, 129, 130, 127, 125, 127, 125, 127, 124, 120, 123, 121, 120, 127, 132, 132, 134, 137, 138, 132, 129, 129, 121, 119, 117, 116, 123, 124, 127, 128, 130, 139, 134, 134, 139, 136, 134, 129, 125, 127, 128, 122, 120, 122, 116, 115, 115, 118, 124, 132, 140, 139, 140, 136, 131, 132, 126, 124, 121, 121, 116, 112, 117, 118, 117, 122, 135, 144, 148, 145, 136, 122, 115, 112, 115, 119, 126, 130, 128, 129, 133, 139, 143, 145, 141, 130, 122, 122, 126, 130, 137, 141, 140, 140, 140, 138, 137, 136, 135, 133, 133, 132, 131, 131, 133, 134, 133, 133, 134, 133, 129, 124, 118, 108, 103, 102, 101, 99, 100, 99, 95, 92, 89, 86, 81, 80, 86, 87, 109, 168, 220, 240, 225, 189, 126, 75, 69, 85, 110, 133, 155, 147, 142, 151, 162, 165, 162, 150, 119, 99, 98, 110, 124, 140, 150, 145, 139, 136, 132, 128, 127, 125, 123, 123, 128, 132, 135, 137, 134, 129, 126, 124, 124, 125, 127, 125, 121, 117, 115, 113, 112, 113, 115, 115, 112, 105, 91, 76, 67, 63, 71, 89, 122, 194, 250, 255, 219, 157, 87, 45, 53, 87, 128, 157, 169, 160, 154, 156, 154, 145, 130, 112, 97, 99, 117, 141, 155, 159, 150, 137, 127, 122, 121, 122, 124, 126, 129, 134, 138, 137, 133, 128, 123, 120, 121, 125, 128, 129, 130, 128, 123, 121, 119, 115, 112, 113, 112, 110, 103, 93, 81, 75, 72, 76, 85, 122, 192, 238, 238, 193, 129, 65, 49, 76, 121, 160, 177, 169, 147, 141, 140, 140, 134, 124, 109, 104, 117, 137, 154, 159, 151, 135, 123, 119, 120, 122, 125, 128, 131, 133, 135, 135, 133, 130, 126, 123, 122, 125, 128, 130, 130, 128, 125, 120, 120, 122, 122, 119, 117, 116, 111, 102, 88, 74, 66, 65, 75, 93, 127, 195, 239, 230, 181, 116, 60, 50, 89, 133, 165, 175, 164, 145, 142, 143, 140, 133, 123, 110, 107, 121, 139, 153, 157, 148, 131, 121, 117, 120, 125, 129, 130, 132, 133, 133, 133, 131, 128, 126, 127, 129, 131, 131, 126, 120, 116, 116, 121, 124, 125, 125, 118, 109, 106, 98, 88, 79, 76, 74, 81, 92, 111, 174, 226, 228, 187, 127, 68, 55, 91, 135, 168, 177, 163, 142, 138, 134, 133, 133, 129, 120, 120, 129, 139, 146, 146, 140, 132, 127, 124, 127, 129, 131, 130, 129, 129, 129, 130, 131, 130, 128, 126, 127, 128, 128, 128, 126, 122, 120, 118, 118, 115, 115, 116, 112, 108, 97, 86, 74, 71, 71, 83, 99, 138, 195, 218, 200, 155, 106, 72, 87, 123, 158, 172, 164, 145, 133, 134, 133, 133, 132, 132, 129, 131, 136, 140, 143, 140, 132, 128, 129, 129, 131, 133, 130, 127, 127, 127, 128, 129, 130, 130, 132, 132, 130, 127, 125, 124, 123, 123, 120, 112, 104, 103, 110, 120, 118, 103, 88, 74, 68, 66, 82, 94, 140, 211, 233, 206, 151, 92, 57, 86, 129, 166, 179, 168, 145, 134, 133, 132, 134, 131, 129, 129, 137, 139, 140, 138, 135, 130, 131, 135, 133, 133, 129, 126, 124, 127, 128, 130, 131, 132, 131, 129, 128, 127, 127, 127, 126, 123, 118, 109, 107, 108, 109, 111, 112, 103, 93, 84, 81, 76, 78, 86, 103, 172, 226, 223, 177, 120, 69, 66, 110, 153, 172, 169, 156, 138, 137, 138, 135, 128, 128, 130, 138, 144, 143, 139, 136, 132, 131, 135, 136, 132, 126, 124, 123, 126, 130, 132, 131, 130, 129, 128, 127, 126, 126, 124, 122, 121, 117, 114, 113, 109, 108, 110, 108, 98, 87, 81, 80, 81, 89, 101, 128, 183, 220, 206, 158, 102, 66, 76, 119, 157, 171, 169, 157, 142, 136, 134, 129, 128, 132, 134, 137, 140, 138, 136, 136, 135, 135, 136, 135, 130, 126, 124, 125, 128, 130, 130, 129, 130, 133, 133, 129, 122, 118, 118, 121, 121, 115, 108, 107, 107, 110, 105, 94, 88, 80, 73, 71, 86, 103, 150, 212, 229, 190, 134, 94, 77, 99, 130, 148, 151, 155, 154, 151, 146, 134, 125, 123, 129, 134, 137, 138, 139, 139, 140, 138, 136, 134, 132, 129, 125, 124, 124, 126, 129, 130, 130, 129, 127, 128, 131, 132, 125, 117, 112, 105, 103, 110, 115, 113, 110, 103, 95, 85, 79, 74, 75, 93, 127, 186, 223, 208, 161, 117, 92, 94, 114, 129, 142, 157, 169, 165, 153, 135, 121, 121, 129, 135, 137, 138, 137, 139, 141, 139, 134, 132, 131, 129, 128, 127, 127, 127, 127, 127, 128, 130, 130, 130, 127, 121, 116, 114, 111, 106, 104, 103, 101, 99, 95, 91, 89, 87, 85, 87, 107, 153, 187, 179, 158, 149, 139, 125, 117, 111, 118, 141, 163, 163, 155, 147, 140, 138, 138, 130, 125, 132, 142, 145, 141, 139, 137, 137, 134, 131, 127, 126, 128, 127, 126, 128, 130, 131, 132, 130, 125, 121, 120, 114, 112, 111, 107, 101, 104, 109, 101, 85, 80, 82, 84, 85, 89, 104, 133, 183, 210, 192, 154, 131, 120, 112, 109, 113, 128, 156, 174, 166, 153, 144, 140, 134, 130, 126, 128, 135, 140, 142, 142, 141, 140, 137, 133, 130, 128, 128, 128, 128, 128, 128, 129, 132, 131, 128, 125, 123, 118, 112, 105, 102, 100, 99, 98, 98, 92, 83, 78, 81, 82, 81, 94, 126, 171, 188, 182, 168, 155, 141, 125, 109, 105, 123, 143, 155, 155, 158, 160, 159, 150, 136, 127, 129, 130, 130, 133, 139, 143, 143, 140, 136, 135, 132, 128, 126, 127, 126, 126, 127, 128, 128, 128, 125, 118, 115, 115, 111, 103, 98, 93, 94, 97, 84, 64, 74, 87, 77, 81, 112, 157, 188, 194, 179, 170, 159, 135, 106, 98, 113, 132, 141, 144, 154, 164, 166, 154, 143, 141, 140, 133, 127, 127, 135, 137, 134, 136, 139, 140, 134, 130, 130, 132, 131, 127, 124, 125, 127, 124, 120, 119, 118, 117, 111, 104, 100, 95, 91, 81, 76, 77, 78, 75, 76, 94, 120, 154, 175, 182, 180, 175, 159, 135, 119, 112, 117, 123, 129, 136, 147, 157, 162, 158, 155, 151, 146, 137, 128, 126, 130, 129, 127, 132, 137, 137, 135, 135, 135, 136, 132, 128, 126, 126, 124, 121, 117, 115, 114, 112, 104, 99, 100, 99, 96, 88, 75, 67, 70, 65, 71, 87, 132, 182, 194, 183, 190, 196, 169, 140, 116, 114, 119, 118, 110, 120, 138, 149, 155, 161, 173, 181, 176, 157, 146, 140, 133, 119, 116, 120, 130, 137, 135, 138, 148, 151, 141, 137, 134, 122, 111, 106, 97, 91, 94, 93, 91, 93, 97, 90, 82, 73, 71, 70, 70, 76, 98, 150, 177, 175, 178, 195, 191, 169, 144, 126, 130, 129, 116, 108, 124, 138, 143, 148, 157, 166, 173, 168, 152, 146, 147, 140, 125, 119, 122, 127, 129, 128, 131, 142, 147, 145, 142, 134, 126, 115, 100, 90, 90, 87, 80, 78, 82, 83, 77, 69, 69, 69, 78, 88, 113, 153, 175, 177, 178, 190, 185, 172, 154, 139, 134, 136, 124, 113, 119, 129, 134, 137, 145, 151, 162, 162, 158, 158, 160, 154, 144, 137, 132, 131, 129, 126, 123, 126, 127, 127, 121, 117, 114, 111, 105, 101, 99, 96, 97, 97, 92, 84, 76, 72, 68, 67, 73, 96, 136, 151, 154, 162, 181, 186, 182, 170, 155, 158, 156, 145, 125, 120, 120, 122, 121, 118, 121, 133, 148, 151, 152, 156, 161, 162, 159, 150, 142, 141, 140, 132, 121, 117, 114, 112, 109, 105, 105, 108, 109, 108, 108, 109, 111, 110, 106, 100, 95, 92, 90, 89, 91, 104, 120, 126, 129, 135, 143, 147, 151, 151, 149, 150, 151, 149, 145, 141, 136, 135, 138, 138, 137, 138, 140, 140, 141, 140, 140, 140, 138, 135, 134, 133, 129, 125, 123, 123, 123, 124, 122, 121, 122, 123, 124, 122, 120, 119, 119, 119, 119, 119, 119, 120, 121, 123, 123, 124, 124, 125, 127, 127, 127, 128, 128, 127, 127, 128, 128, 127, 130, 131, 132, 134, 134, 134, 135, 136, 134, 135, 134, 134, 135, 134, 132, 131, 132, 131, 132, 130, 131, 132, 130, 130, 131, 130, 127, 125, 125, 126, 124, 122, 121, 122, 121, 122, 123, 122, 122, 123, 125, +}; + +const unsigned char six[] PROGMEM = { +116, 134, 134, 134, 121, 137, 127, 135, 128, 132, 119, 131, 122, 113, 125, 114, 131, 123, 120, 126, 133, 137, 128, 138, 139, 136, 154, 117, 143, 134, 128, 130, 112, 116, 112, 118, 104, 122, 125, 140, 117, 137, 136, 133, 142, 126, 141, 118, 132, 112, 122, 123, 102, 120, 128, 130, 142, 129, 135, 151, 138, 133, 137, 145, 138, 122, 111, 123, 121, 123, 106, 122, 119, 151, 132, 130, 151, 153, 144, 124, 133, 122, 136, 110, 109, 98, 121, 101, 96, 108, 135, 128, 130, 133, 145, 154, 131, 126, 114, 134, 106, 104, 96, 107, 111, 109, 111, 135, 141, 162, 163, 169, 184, 186, 176, 165, 163, 159, 150, 125, 135, 124, 133, 127, 135, 136, 143, 137, 137, 142, 132, 128, 114, 84, 76, 64, 35, 33, 31, 24, 2, 7, 9, 12, 11, 0, 99, 221, 166, 148, 240, 255, 247, 240, 211, 221, 255, 205, 128, 155, 166, 110, 83, 88, 84, 121, 139, 103, 123, 192, 205, 181, 212, 221, 224, 218, 197, 162, 157, 137, 88, 79, 83, 64, 56, 57, 49, 55, 53, 36, 58, 59, 35, 18, 18, 2, 0, 0, 0, 150, 171, 75, 125, 255, 255, 215, 217, 211, 255, 233, 148, 106, 162, 138, 59, 43, 91, 112, 133, 125, 138, 203, 231, 205, 195, 228, 213, 183, 164, 160, 141, 126, 98, 96, 107, 104, 98, 117, 133, 141, 134, 138, 138, 114, 91, 84, 76, 43, 17, 0, 0, 0, 0, 0, 110, 186, 89, 121, 255, 255, 193, 230, 253, 242, 187, 148, 120, 130, 105, 32, 44, 101, 97, 86, 141, 175, 199, 208, 214, 225, 225, 197, 175, 185, 164, 114, 106, 110, 86, 73, 96, 107, 107, 117, 123, 129, 133, 118, 107, 106, 101, 62, 43, 39, 1, 0, 0, 49, 112, 69, 89, 202, 228, 174, 199, 255, 238, 193, 201, 199, 166, 134, 116, 101, 92, 82, 87, 104, 117, 135, 157, 175, 184, 190, 198, 206, 197, 176, 165, 149, 124, 103, 94, 93, 83, 87, 98, 108, 105, 109, 117, 119, 115, 116, 110, 100, 81, 63, 63, 48, 29, 47, 102, 93, 71, 113, 170, 151, 137, 187, 208, 181, 176, 199, 188, 155, 148, 152, 132, 118, 119, 121, 123, 130, 137, 144, 151, 159, 161, 158, 162, 162, 147, 143, 138, 127, 114, 111, 112, 106, 106, 109, 113, 115, 121, 122, 122, 123, 123, 120, 119, 114, 110, 106, 103, 102, 100, 102, 103, 108, 110, 114, 118, 119, 127, 130, 129, 129, 134, 136, 131, 134, 134, 136, 135, 136, 139, 138, 139, 137, 140, 141, 142, 142, 141, 141, 140, 135, 134, 134, 132, 129, 129, 126, 124, 124, 124, 125, 125, 124, 124, 127, 127, 125, 127, 127, 125, 124, 124, 123, 124, 123, 123, 124, 124, 125, 126, 129, 129, 130, 129, 130, 130, 130, 129, 128, 127, 126, 126, 125, 127, 127, 127, 128, 128, 128, 129, 129, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 128, 128, 128, 129, 128, 129, 128, 128, 128, 127, 127, 127, 126, 126, 126, 126, 126, 126, 127, 127, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 126, 127, 127, 127, 127, 128, 128, 129, 129, 129, 129, 129, 129, 128, 128, 128, 127, 127, 127, 126, 127, 127, 127, 128, 128, 128, 128, 129, 129, 128, 128, 128, 128, 126, 126, 127, 127, 126, 126, 127, 127, 127, 127, 128, 129, 129, 129, 128, 128, 128, 127, 127, 126, 125, 126, 126, 126, 126, 127, 128, 129, 128, 127, 129, 129, 128, 129, 127, 125, 125, 126, 128, 126, 125, 130, 131, 125, 123, 127, 134, 135, 120, 124, 150, 148, 121, 105, 122, 141, 134, 115, 113, 130, 135, 122, 118, 126, 133, 131, 126, 127, 136, 133, 127, 136, 132, 118, 110, 122, 131, 127, 112, 118, 135, 138, 126, 129, 142, 146, 141, 122, 117, 125, 134, 119, 113, 117, 124, 129, 122, 114, 133, 139, 120, 132, 132, 141, 131, 117, 132, 131, 130, 117, 124, 122, 123, 123, 121, 137, 121, 125, 135, 131, 128, 122, 132, 132, 140, 120, 132, 124, 135, 142, 110, 127, 118, 152, 119, 129, 112, 145, 139, 117, 125, 113, 150, 128, 126, 112, 126, 141, 133, 112, 122, 130, 151, 115, 119, 129, 144, 129, 116, 125, 136, 137, 114, 131, 119, 146, 120, 125, 127, 125, 139, 113, 123, 139, 137, 118, 116, 133, 133, 127, 113, 122, 146, 127, 122, 111, 135, 153, 108, 118, 124, 150, 131, 111, 118, 138, 143, 118, 115, 127, 150, 116, 126, 121, 132, 136, 120, 126, 126, 138, 130, 121, 121, 129, 129, 118, 130, 128, 137, 125, 126, 134, 132, 131, 109, 136, 135, 126, 122, 123, 131, 131, 126, 119, 130, 132, 125, 128, 123, 128, 126, 130, 126, 127, 123, 130, 134, 123, 124, 130, 134, 127, 126, 123, 137, 120, 128, 132, 130, 126, 129, 129, 122, 132, 128, 123, 136, 118, 128, 141, 118, 126, 128, 136, 124, 130, 127, 129, 116, 143, 110, 136, 130, 115, 144, 114, 131, 121, 132, 128, 129, 121, 144, 106, 145, 117, 127, 133, 123, 138, 116, 142, 112, 140, 107, 146, 121, 121, 142, 116, 138, 119, 140, 118, 126, 137, 121, 140, 107, 144, 121, 122, 133, 123, 129, 136, 121, 131, 129, 122, 141, 112, 143, 113, 143, 113, 145, 109, 131, 134, 107, 147, 116, 136, 117, 139, 115, 131, 138, 108, 152, 97, 153, 117, 130, 130, 117, 141, 110, 160, 86, 171, 90, 165, 92, 159, 108, 138, 130, 112, 148, 90, 175, 69, 185, 78, 170, 95, 152, 110, 138, 127, 116, 147, 108, 159, 91, 159, 101, 142, 119, 127, 131, 124, 131, 130, 125, 137, 114, 143, 108, 148, 111, 129, 138, 110, 154, 101, 147, 114, 135, 126, 127, 129, 125, 134, 115, 136, 119, 136, 126, 124, 132, 119, 139, 117, 144, 111, 146, 116, 129, 135, +}; + +const unsigned char seven[] PROGMEM = { +134, 123, 132, 124, 127, 126, 123, 125, 124, 134, 123, 133, 124, 135, 125, 127, 126, 124, 132, 123, 130, 128, 134, 127, 131, 125, 125, 125, 129, 125, 127, 129, 128, 128, 128, 131, 130, 135, 126, 132, 127, 130, 119, 129, 121, 125, 127, 123, 132, 120, 134, 123, 130, 124, 130, 127, 128, 132, 126, 130, 126, 128, 123, 128, 125, 126, 129, 128, 130, 129, 128, 133, 132, 129, 130, 131, 128, 126, 123, 123, 126, 124, 123, 128, 131, 129, 128, 133, 136, 132, 134, 124, 125, 126, 124, 121, 117, 125, 123, 124, 124, 129, 134, 135, 129, 130, 130, 128, 123, 117, 118, 119, 126, 119, 111, 113, 119, 116, 118, 121, 125, 136, 138, 134, 136, 147, 145, 142, 137, 133, 134, 130, 126, 126, 135, 134, 131, 137, 143, 148, 147, 147, 146, 149, 145, 135, 129, 130, 132, 127, 120, 119, 126, 128, 121, 112, 115, 118, 114, 102, 96, 92, 90, 77, 59, 52, 60, 58, 49, 46, 55, 64, 59, 49, 52, 117, 170, 215, 229, 218, 223, 231, 209, 156, 137, 121, 127, 123, 111, 106, 124, 153, 162, 163, 169, 184, 184, 170, 144, 126, 119, 110, 93, 92, 102, 122, 134, 132, 133, 140, 143, 133, 120, 116, 129, 133, 137, 140, 143, 146, 146, 144, 137, 139, 140, 133, 121, 118, 114, 110, 100, 90, 85, 84, 75, 59, 52, 58, 63, 54, 51, 57, 67, 61, 52, 50, 101, 161, 211, 233, 220, 223, 230, 214, 161, 136, 120, 126, 123, 110, 104, 118, 150, 160, 161, 167, 181, 183, 173, 146, 125, 118, 111, 92, 92, 101, 121, 138, 137, 136, 141, 145, 133, 118, 109, 115, 121, 133, 146, 151, 153, 159, 159, 154, 152, 146, 139, 126, 116, 109, 104, 95, 87, 84, 78, 74, 72, 77, 77, 74, 71, 68, 60, 52, 48, 47, 44, 51, 97, 179, 241, 239, 226, 220, 212, 187, 147, 109, 97, 116, 131, 131, 130, 153, 176, 190, 183, 172, 161, 140, 122, 103, 99, 108, 118, 121, 133, 152, 167, 173, 164, 155, 140, 123, 98, 85, 88, 99, 125, 140, 160, 181, 188, 182, 172, 161, 143, 133, 125, 115, 108, 103, 96, 94, 92, 84, 78, 78, 73, 68, 66, 67, 57, 49, 51, 42, 42, 43, 54, 93, 181, 255, 241, 201, 194, 202, 180, 137, 99, 86, 112, 141, 137, 125, 143, 181, 196, 183, 159, 145, 144, 139, 118, 102, 109, 123, 128, 129, 135, 143, 156, 160, 146, 128, 116, 106, 98, 97, 109, 128, 152, 171, 178, 175, 167, 160, 151, 139, 126, 119, 117, 112, 106, 102, 95, 85, 79, 76, 79, 82, 81, 73, 66, 62, 53, 47, 49, 55, 76, 126, 195, 237, 233, 216, 201, 187, 167, 138, 104, 89, 108, 132, 139, 137, 146, 162, 177, 181, 167, 143, 134, 139, 136, 119, 107, 111, 125, 138, 143, 139, 135, 137, 139, 137, 129, 122, 120, 132, 148, 155, 151, 145, 147, 150, 144, 134, 126, 123, 122, 122, 117, 110, 103, 97, 93, 84, 73, 65, 67, 71, 72, 73, 73, 71, 73, 73, 65, 73, 120, 184, 216, 212, 200, 191, 182, 172, 157, 134, 116, 119, 131, 135, 132, 134, 139, 146, 156, 164, 158, 144, 139, 138, 136, 135, 130, 124, 124, 131, 135, 128, 118, 116, 117, 117, 116, 119, 132, 142, 143, 140, 138, 140, 141, 141, 137, 135, 135, 133, 127, 120, 116, 114, 110, 110, 109, 104, 99, 97, 97, 98, 102, 101, 100, 95, 90, 89, 93, 98, 106, 120, 132, 140, 145, 154, 158, 159, 161, 161, 159, 156, 154, 152, 146, 142, 139, 135, 132, 129, 127, 125, 127, 130, 133, 136, 141, 145, 144, 138, 133, 129, 126, 120, 115, 112, 115, 122, 125, 125, 125, 130, 135, 138, 140, 140, 140, 136, 131, 129, 128, 126, 123, 118, 116, 115, 114, 113, 113, 111, 108, 108, 107, 108, 108, 105, 99, 94, 90, 92, 103, 112, 119, 124, 128, 130, 134, 144, 153, 154, 153, 151, 153, 150, 152, 152, 147, 143, 142, 143, 139, 137, 136, 137, 138, 135, 131, 128, 129, 130, 128, 126, 124, 125, 124, 123, 124, 124, 124, 122, 122, 120, 126, 131, 130, 129, 130, 135, 136, 134, 138, 135, 126, 126, 130, 128, 122, 117, 113, 114, 114, 115, 116, 115, 113, 112, 114, 115, 108, 102, 101, 99, 93, 105, 122, 124, 125, 125, 131, 130, 134, 145, 146, 146, 148, 150, 144, 141, 146, 144, 139, 140, 144, 139, 133, 135, 134, 133, 134, 134, 131, 130, 134, 135, 132, 130, 133, 133, 131, 132, 130, 126, 124, 127, 127, 128, 127, 124, 123, 123, 126, 131, 130, 130, 130, 125, 125, 126, 125, 120, 113, 112, 112, 114, 118, 116, 115, 115, 114, 110, 108, 106, 101, 97, 101, 116, 120, 122, 126, 131, 134, 138, 147, 146, 146, 151, 151, 147, 146, 148, 145, 140, 138, 135, 131, 133, 135, 127, 124, 129, 135, 139, 138, 139, 143, 150, 154, 148, 142, 141, 142, 139, 133, 128, 121, 118, 119, 121, 123, 120, 125, 121, 117, 117, 114, 110, 108, 103, 96, 92, 93, 94, 89, 88, 87, 81, 76, 72, 64, 56, 62, 100, 126, 146, 167, 178, 189, 192, 206, 201, 186, 178, 174, 168, 151, 142, 132, 123, 122, 120, 118, 113, 120, 131, 140, 149, 154, 159, 159, 173, 185, 177, 162, 152, 150, 137, 126, 116, 108, 106, 111, 118, 114, 114, 116, 119, 122, 121, 118, 109, 109, 105, 92, 77, 71, 69, 65, 61, 57, 48, 41, 40, 45, 41, 45, 94, 140, 170, 181, 195, 215, 223, 225, 203, 176, 165, 168, 158, 131, 120, 116, 118, 124, 128, 129, 134, 152, 159, 159, 159, 164, 167, 160, 155, 154, 162, 156, 140, 132, 130, 133, 124, 122, 123, 127, 137, 140, 141, 138, 140, 136, 127, 118, 108, 93, 75, 63, 52, 46, 43, 39, 32, 29, 36, 38, 33, 28, 36, 93, 138, 154, 162, 190, 229, 228, 214, 199, 202, 202, 180, 157, 145, 152, 147, 136, 133, 144, 159, 154, 146, 147, 159, 162, 152, 144, 143, 146, 134, 126, 132, 132, 129, 130, 131, 131, 131, 133, 130, 134, 145, 147, 145, 144, 142, 137, 127, 113, 99, 86, 74, 65, 53, 45, 43, 38, 30, 29, 35, 34, 33, 32, 59, 110, 120, 122, 158, 201, 202, 193, 208, 216, 210, 194, 183, 183, 183, 169, 151, 154, 164, 157, 146, 148, 158, 159, 154, 149, 153, 158, 149, 134, 135, 141, 127, 119, 126, 128, 123, 123, 127, 132, 135, 136, 140, 144, 141, 139, 137, 131, 123, 113, 101, 89, 77, 61, 53, 48, 42, 36, 32, 31, 38, 35, 28, 32, 67, 107, 114, 131, 170, 199, 196, 200, 217, 223, 212, 199, 199, 200, 183, 165, 165, 164, 154, 145, 142, 140, 139, 137, 137, 144, 148, 140, 139, 140, 133, 127, 127, 125, 128, 128, 125, 125, 130, 129, 127, 131, 135, 137, 137, 137, 137, 135, 130, 123, 115, 105, 91, 89, 81, 71, 64, 62, 57, 54, 53, 40, 41, 44, 40, 42, 70, 86, 97, 123, 145, 159, 173, 186, 196, 205, 206, 207, 213, 212, 202, 198, 195, 184, 174, 166, 155, 146, 140, 137, 135, 132, 128, 126, 125, 123, 121, 121, 122, 120, 122, 124, 126, 128, 131, 132, 132, 135, 136, 138, 140, 140, 140, 140, 138, 131, 126, 118, 109, 101, 93, 84, 77, 69, 60, 55, 50, 41, 36, 34, 32, 33, 45, 62, 78, 97, 115, 135, 153, 169, 181, 194, 205, 213, 221, 226, 226, 225, 222, 215, 205, 192, 177, 166, 156, 145, 136, 130, 124, 118, 112, 106, 104, 102, 104, 106, 108, 110, 113, 116, 119, 121, 124, 127, 131, 136, +}; + +const unsigned char eight[] PROGMEM = { +104, 93, 82, 71, 61, 52, 41, 26, 14, 4, 0, 0, 0, 0, 0, 13, 41, 64, 89, 118, 147, 173, 192, 209, 232, 251, 255, 255, 255, 255, 255, 255, 250, 234, 214, 196, 181, 169, 155, 144, 135, 125, 115, 103, 95, 89, 86, 85, 87, 90, 96, 101, 108, 114, 122, 130, 140, 149, 158, 166, 171, 174, 171, 166, 157, 149, 136, 123, 110, 97, 80, 69, 59, 46, 35, 23, 13, 7, 0, 0, 5, 32, 39, 49, 83, 111, 126, 145, 170, 193, 212, 225, 233, 242, 244, 243, 243, 230, 213, 205, 195, 181, 166, 153, 144, 138, 122, 110, 108, 104, 97, 89, 90, 95, 93, 99, 116, 124, 134, 146, 162, 170, 173, 188, 191, 181, 176, 173, 156, 139, 127, 111, 92, 72, 55, 51, 38, 27, 25, 23, 15, 10, 11, 3, 0, 1, 106, 103, 90, 207, 219, 178, 241, 255, 224, 228, 219, 226, 217, 166, 173, 195, 145, 141, 161, 132, 120, 126, 124, 120, 115, 119, 122, 112, 109, 122, 126, 125, 138, 154, 156, 161, 165, 172, 176, 161, 162, 162, 138, 123, 114, 94, 78, 72, 61, 47, 42, 41, 36, 20, 34, 19, 1, 16, 0, 0, 49, 126, 96, 133, 238, 218, 205, 255, 249, 223, 214, 214, 208, 176, 149, 162, 156, 124, 141, 145, 125, 121, 131, 121, 118, 123, 119, 120, 117, 129, 139, 128, 148, 166, 151, 158, 173, 166, 163, 171, 158, 144, 131, 121, 114, 93, 82, 85, 65, 49, 54, 43, 27, 24, 18, 10, 1, 0, 0, 0, 101, 131, 97, 210, 253, 193, 235, 255, 222, 209, 214, 200, 183, 159, 151, 168, 138, 136, 157, 138, 126, 142, 132, 117, 135, 132, 127, 137, 142, 139, 150, 155, 143, 151, 163, 153, 151, 163, 153, 132, 137, 118, 98, 92, 72, 66, 54, 49, 45, 32, 32, 23, 6, 8, 0, 0, 0, 85, 116, 73, 209, 245, 172, 248, 255, 214, 208, 233, 202, 171, 174, 155, 158, 139, 135, 153, 136, 130, 138, 138, 123, 130, 133, 126, 135, 131, 138, 148, 138, 152, 157, 149, 151, 162, 151, 148, 149, 131, 124, 113, 92, 81, 74, 55, 59, 46, 33, 32, 14, 11, 0, 0, 0, 33, 105, 46, 123, 218, 162, 194, 255, 236, 201, 255, 236, 184, 197, 186, 161, 145, 148, 146, 127, 131, 131, 129, 121, 123, 132, 125, 130, 135, 135, 137, 139, 148, 152, 148, 158, 159, 154, 153, 151, 142, 126, 117, 106, 81, 71, 58, 42, 25, 22, 6, 0, 0, 0, 0, 0, 79, 69, 77, 183, 171, 161, 237, 242, 203, 236, 255, 208, 199, 213, 178, 159, 160, 151, 121, 125, 125, 106, 112, 113, 110, 116, 122, 122, 129, 144, 148, 153, 171, 175, 174, 182, 177, 169, 165, 153, 141, 125, 108, 88, 80, 64, 49, 51, 41, 30, 33, 34, 15, 9, 38, 77, 61, 82, 145, 135, 136, 194, 203, 183, 216, 229, 205, 210, 216, 184, 178, 174, 142, 133, 132, 112, 105, 113, 103, 98, 110, 110, 111, 128, 127, 127, 144, 147, 143, 155, 165, 153, 160, 165, 145, 141, 145, 113, 99, 99, 62, 53, 48, 17, 3, 7, 0, 29, 43, 44, 92, 108, 114, 154, 179, 170, 204, 219, 205, 215, 221, 199, 190, 190, 165, 154, 147, 132, 120, 119, 111, 104, 108, 110, 111, 120, 120, 125, 135, 136, 139, 147, 151, 151, 156, 157, 152, 144, 139, 124, 110, 97, 81, 59, 47, 25, 5, 9, 24, 26, 31, 68, 81, 89, 124, 156, 153, 182, 208, 195, 215, 223, 203, 202, 205, 175, 166, 162, 141, 132, 132, 117, 113, 114, 110, 114, 116, 116, 117, 126, 129, 128, 136, 144, 144, 144, 151, 148, 141, 141, 131, 113, 102, 90, 68, 51, 35, 5, 34, 35, 4, 66, 77, 56, 116, 142, 121, 170, 200, 175, 203, 224, 190, 198, 207, 175, 167, 172, 149, 135, 140, 125, 113, 120, 114, 108, 119, 117, 115, 124, 127, 127, 134, 141, 141, 143, 150, 147, 144, 143, 135, 118, 108, 94, 72, 59, 46, 17, 27, 56, 15, 53, 94, 67, 103, 144, 135, 153, 190, 180, 189, 207, 195, 187, 191, 177, 164, 160, 151, 139, 134, 127, 120, 119, 117, 118, 119, 121, 123, 125, 128, 130, 134, 137, 139, 140, 141, 138, 133, 128, 118, 106, 95, 82, 63, 50, 38, 40, 46, 38, 62, 85, 77, 105, 136, 131, 153, 181, 174, 184, 201, 190, 185, 189, 180, 166, 163, 157, 142, 138, 134, 123, 124, 123, 116, 119, 124, 120, 122, 125, 126, 128, 129, 135, 133, 134, 139, 135, 128, 134, 125, 115, 113, 98, 89, 83, 71, 72, 79, 75, 84, 97, 98, 108, 122, 125, 133, 143, 145, 147, 150, 150, 148, 147, 144, 142, 141, 138, 136, 137, 134, 133, 134, 132, 131, 132, 131, 130, 129, 129, 128, 128, 127, 127, 127, 126, 126, 126, 125, 125, 124, 124, 124, 123, 123, 122, 122, 121, 122, 122, 123, 124, 125, 127, 127, 128, 128, 129, 129, 130, 130, 130, 130, 130, 129, 129, 128, 128, 128, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, +}; + +const unsigned char nine[] PROGMEM = { +129, 128, 129, 129, 129, 128, 128, 128, 128, 127, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 127, 128, 127, 128, 128, 129, 128, 128, 129, 128, 128, 128, 127, 128, 125, 125, 125, 123, 121, 119, 122, 116, 116, 118, 118, 116, 118, 117, 117, 117, 118, 118, 117, 120, 119, 123, 121, 124, 124, 122, 127, 124, 127, 127, 129, 131, 134, 136, 137, 140, 141, 142, 142, 146, 143, 146, 146, 145, 143, 142, 141, 137, 136, 133, 130, 127, 126, 122, 121, 119, 120, 117, 118, 117, 118, 118, 119, 120, 121, 123, 125, 125, 126, 128, 127, 128, 125, 127, 122, 124, 119, 119, 117, 114, 114, 111, 113, 110, 106, 107, 104, 106, 106, 104, 109, 107, 114, 114, 118, 122, 127, 134, 143, 148, 156, 163, 171, 177, 179, 184, 183, 184, 181, 180, 174, 168, 162, 156, 147, 140, 130, 123, 117, 110, 106, 102, 100, 98, 99, 99, 100, 103, 105, 109, 112, 116, 119, 120, 123, 124, 126, 126, 127, 126, 126, 124, 122, 121, 118, 116, 112, 109, 105, 101, 97, 97, 92, 91, 89, 85, 85, 82, 83, 83, 89, 98, 107, 117, 130, 143, 157, 170, 183, 193, 198, 203, 205, 205, 203, 201, 195, 188, 181, 171, 159, 148, 139, 128, 119, 113, 107, 102, 101, 99, 98, 101, 104, 108, 115, 121, 126, 133, 140, 143, 146, 151, 152, 151, 150, 147, 141, 136, 131, 122, 115, 108, 100, 93, 85, 78, 72, 67, 62, 58, 58, 60, 60, 64, 68, 69, 73, 76, 78, 83, 92, 100, 110, 129, 147, 156, 172, 189, 196, 203, 214, 217, 217, 220, 219, 210, 203, 198, 185, 170, 161, 147, 133, 123, 115, 105, 100, 97, 92, 88, 89, 90, 92, 97, 103, 108, 117, 127, 134, 142, 149, 156, 161, 166, 167, 166, 164, 163, 156, 149, 142, 133, 124, 117, 108, 97, 90, 83, 75, 67, 63, 59, 54, 54, 54, 51, 53, 57, 58, 62, 67, 78, 85, 95, 110, 122, 139, 158, 171, 180, 195, 207, 212, 215, 221, 222, 219, 221, 214, 200, 190, 183, 175, 153, 138, 125, 107, 102, 95, 89, 89, 92, 95, 99, 109, 117, 124, 133, 140, 148, 153, 152, 151, 150, 151, 147, 142, 137, 132, 129, 126, 120, 112, 109, 110, 106, 101, 95, 91, 89, 82, 75, 71, 67, 66, 70, 76, 75, 72, 81, 85, 103, 122, 136, 145, 170, 230, 240, 198, 157, 141, 138, 142, 143, 134, 142, 165, 175, 165, 149, 130, 126, 131, 130, 120, 118, 123, 130, 136, 135, 127, 125, 126, 126, 130, 137, 139, 139, 147, 155, 156, 148, 139, 132, 133, 134, 131, 127, 123, 123, 126, 124, 116, 110, 102, 93, 89, 88, 83, 80, 78, 78, 78, 82, 88, 92, 82, 65, 67, 94, 126, 143, 154, 157, 204, 239, 204, 143, 106, 104, 124, 160, 168, 161, 164, 179, 173, 156, 132, 111, 114, 130, 139, 139, 138, 132, 133, 136, 134, 125, 122, 121, 118, 122, 133, 138, 139, 145, 149, 147, 145, 140, 132, 132, 134, 132, 132, 131, 129, 128, 125, 120, 115, 106, 97, 94, 93, 93, 92, 94, 90, 89, 88, 85, 83, 80, 73, 69, 76, 97, 122, 146, 209, 244, 218, 165, 108, 72, 80, 129, 168, 188, 183, 166, 141, 136, 141, 136, 130, 123, 115, 120, 132, 139, 145, 143, 140, 131, 128, 119, 110, 112, 118, 129, 143, 164, 171, 165, 153, 133, 118, 115, 118, 130, 143, 144, 135, 125, 124, 117, 114, 111, 102, 92, 84, 81, 85, 87, 84, 88, 80, 60, 60, 78, 100, 130, 195, 247, 231, 182, 119, 71, 73, 113, 156, 179, 173, 154, 142, 140, 146, 150, 144, 135, 126, 125, 129, 127, 131, 132, 130, 134, 134, 126, 117, 112, 113, 118, 133, 145, 163, 173, 167, 158, 138, 117, 111, 121, 131, 135, 135, 131, 125, 129, 124, 116, 110, 103, 97, 87, 80, 72, 65, 64, 68, 66, 64, 82, 95, 117, 205, 255, 232, 178, 112, 61, 70, 125, 165, 189, 176, 143, 127, 129, 134, 147, 150, 138, 130, 124, 125, 131, 137, 140, 142, 136, 128, 124, 117, 112, 106, 111, 126, 142, 164, 178, 180, 167, 144, 121, 110, 118, 130, 136, 130, 118, 109, 117, 129, 132, 119, 99, 92, 82, 70, 49, 38, 46, 57, 85, 104, 114, 169, 229, 227, 187, 126, 73, 69, 110, 165, 201, 195, 152, 120, 114, 128, 151, 157, 143, 132, 135, 140, 138, 136, 134, 138, 138, 128, 117, 107, 102, 111, 124, 144, 170, 183, 177, 164, 141, 121, 117, 119, 124, 132, 125, 120, 120, 123, 126, 123, 114, 105, 97, 88, 72, 53, 54, 61, 64, 69, 77, 77, 157, 248, 250, 202, 121, 52, 51, 113, 171, 210, 199, 159, 130, 120, 118, 126, 139, 143, 154, 155, 142, 130, 126, 127, 137, 143, 139, 131, 120, 113, 111, 115, 138, 169, 178, 170, 151, 132, 129, 137, 135, 128, 120, 113, 113, 117, 123, 123, 108, 96, 92, 88, 73, 55, 41, 34, 51, 84, 111, 124, 183, 234, 214, 164, 99, 52, 70, 128, 170, 193, 181, 148, 143, 156, 160, 157, 143, 124, 124, 132, 134, 136, 137, 134, 139, 142, 130, 120, 119, 122, 147, 165, 153, 137, 136, 139, 151, 157, 138, 120, 114, 113, 115, 121, 118, 117, 117, 105, 91, 78, 59, 41, 35, 45, 70, 98, 109, 148, 211, 221, 180, 125, 84, 77, 118, 157, 165, 164, 160, 155, 160, 160, 146, 135, 131, 126, 130, 140, 141, 138, 148, 150, 143, 146, 130, 114, 110, 136, 158, 159, 149, 137, 138, 145, 143, 129, 128, 124, 122, 119, 115, 112, 110, 112, 106, 89, 75, 73, 70, 58, 43, 39, 66, 102, 127, 195, 246, 201, 129, 92, 82, 97, 135, 156, 154, 161, 167, 161, 159, 146, 129, 129, 137, 137, 136, 134, 128, 135, 143, 139, 134, 131, 125, 127, 144, 145, 133, 128, 129, 133, 138, 138, 132, 127, 128, 130, 125, 117, 111, 113, 111, 105, 95, 89, 83, 77, 73, 57, 53, 80, 93, 99, 188, 240, 190, 145, 125, 106, 111, 131, 122, 125, 152, 169, 165, 156, 144, 141, 148, 143, 134, 129, 127, 127, 132, 135, 132, 128, 130, 134, 148, 149, 136, 131, 130, 129, 131, 133, 130, 127, 131, 134, 128, 119, 105, 96, 100, 102, 92, 84, 81, 72, 65, 61, 58, 79, 95, 117, 174, 202, 177, 150, 148, 138, 127, 126, 133, 146, 154, 159, 154, 149, 148, 148, 144, 137, 135, 135, 131, 129, 132, 132, 138, 144, 139, 143, 141, 133, 131, 128, 127, 129, 130, 130, 129, 127, 119, 109, 105, 101, 92, 88, 90, 81, 70, 71, 68, 61, 54, 56, 72, 110, 169, 187, 174, 168, 169, 160, 141, 129, 132, 145, 153, 153, 158, 161, 156, 157, 154, 144, 141, 138, 127, 127, 131, 129, 136, 153, 151, 141, 141, 137, 132, 130, 130, 130, 128, 127, 124, 123, 122, 112, 106, 103, 96, 86, 81, 79, 72, 67, 66, 63, 63, 58, 61, 86, 134, 160, 164, 176, 182, 174, 153, 143, 139, 140, 144, 147, 154, 158, 161, 160, 157, 152, 145, 138, 136, 133, 129, 131, 145, 154, 143, 143, 147, 137, 132, 134, 132, 130, 125, 124, 123, 119, 114, 105, 99, 101, 91, 83, 86, 79, 73, 68, 62, 57, 57, 41, 43, 72, 113, 146, 152, 178, 187, 178, 170, 163, 157, 147, 145, 151, 157, 153, 156, 163, 157, 152, 152, 146, 139, 135, 131, 136, 155, 148, 136, 148, 141, 132, 134, 135, 130, 129, 128, 125, 124, 119, 114, 108, 100, 101, 95, 82, 86, 83, 70, 71, 70, 65, 55, 45, 48, 57, 102, 131, 143, 179, 179, 177, 182, 166, 159, 161, 154, 153, 166, 159, 152, 161, 155, 151, 150, 143, 137, 136, 133, 141, 155, 143, 144, 149, 138, 135, 137, 134, 131, 128, 127, 125, 120, 116, 108, 101, 97, 95, 86, 80, 79, 74, 68, 67, 63, 57, 55, 48, 58, 86, 115, 134, 159, 182, 183, 181, 175, 169, 161, 160, 161, 157, 157, 159, 158, 156, 155, 152, 146, 139, 136, 140, 147, 147, 147, 150, 146, 139, 137, 135, 133, 130, 128, 130, 126, 121, 120, 113, 104, 101, 95, 89, 83, 77, 76, 68, 61, 65, 60, 54, 49, 42, 40, 64, 106, 112, 142, 178, 175, 183, 185, 177, 179, 171, 167, 178, 168, 156, 162, 160, 153, 153, 149, 145, 143, 140, 138, 141, 148, 145, 142, 143, 139, 134, 134, 134, 132, 131, 130, 129, 127, 124, 120, 116, 111, 103, 97, 93, 85, 81, 76, 69, 67, 61, 51, 44, 38, 31, 38, 58, 69, 84, 111, 127, 138, 152, 158, 164, 175, 183, 185, 189, 193, 189, 186, 179, 172, 166, 156, 148, 143, 140, 137, 137, 137, 140, 137, 135, 137, 135, 133, 135, 133, 133, 134, 132, 130, 131, 131, 128, 127, 126, 122, 118, 113, 108, 101, 93, 86, 78, 67, 58, 52, 40, 30, 27, 25, 35, 54, 66, 80, 107, 125, 135, 150, 158, 163, 173, 183, 185, 189, 193, 190, 187, 183, 176, 170, 162, 154, 148, 143, 139, 136, 134, 135, 133, 131, 133, 133, 132, 133, 134, 133, 134, 132, 129, 128, 125, 120, 115, 110, 105, 99, 94, 90, 86, 82, 79, 77, 75, 74, 75, 75, 77, 80, 82, 85, 88, 90, 95, 106, 116, 123, 134, 147, 157, 167, 175, 182, 189, 193, 194, 195, 194, 190, 184, 177, 171, 164, 154, 144, 138, 132, 127, 125, 125, 125, 126, 128, 129, 130, 131, 131, 131, 130, 128, 126, 123, 120, 116, 112, 106, 101, 97, 94, 91, 89, 88, 88, 88, 86, 87, 89, 90, 92, 95, 99, 102, 103, 105, 106, 107, 111, 117, 122, 127, 135, 144, 152, 160, 166, 172, 177, 180, 182, 182, 180, 177, 173, 169, 163, 157, 150, 144, 138, 132, 128, 126, 124, 124, 124, 125, 126, 126, 126, 125, 125, 123, 122, 120, 117, 114, 112, 111, 109, 107, 105, 104, 104, 103, 102, 101, 102, 102, 102, 103, 104, 106, 109, 111, 114, 115, 117, 119, 121, 124, 126, 130, 133, 135, 138, 141, 144, 146, 148, 150, 151, 152, 153, 153, 153, 152, 151, 150, 149, 146, 144, 141, 139, 137, 135, 133, 132, 130, 129, 128, 127, 125, 124, 123, 122, 121, 120, 119, 119, 119, 119, 119, 119, 120, 120, 121, 122, +}; + +const unsigned char dbm[] PROGMEM = { +126, 127, 126, 128, 126, 128, 124, 126, 124, 129, 126, 133, 137, 141, 152, 128, 122, 119, 117, 114, 125, 123, 128, 122, 132, 140, 127, 127, 127, 125, 117, 123, 124, 127, 118, 127, 127, 125, 121, 129, 126, 126, 135, 134, 137, 130, 130, 127, 119, 118, 142, 128, 137, 138, 128, 129, 120, 121, 121, 123, 113, 129, 123, 116, 126, 129, 123, 129, 133, 127, 134, 128, 133, 130, 131, 127, 135, 131, 125, 138, 128, 133, 126, 137, 126, 126, 131, 125, 128, 122, 132, 124, 128, 120, 126, 125, 120, 124, 124, 124, 121, 125, 120, 126, 120, 124, 127, 122, 122, 127, 128, 119, 132, 127, 124, 132, 128, 127, 132, 132, 128, 135, 132, 132, 139, 135, 136, 141, 141, 138, 141, 141, 143, 142, 140, 141, 143, 138, 137, 137, 137, 133, 128, 134, 128, 123, 122, 124, 115, 114, 117, 108, 109, 109, 106, 102, 106, 103, 102, 106, 99, 107, 106, 101, 107, 111, 100, 104, 110, 98, 106, 99, 97, 109, 113, 107, 126, 140, 131, 151, 157, 163, 171, 174, 180, 182, 174, 178, 177, 163, 161, 153, 145, 135, 129, 123, 117, 112, 110, 112, 107, 112, 116, 116, 119, 125, 127, 131, 135, 137, 139, 140, 141, 139, 136, 134, 131, 126, 123, 119, 116, 111, 109, 105, 103, 101, 97, 95, 92, 91, 87, 88, 90, 85, 91, 91, 89, 90, 97, 120, 100, 119, 152, 131, 145, 172, 167, 168, 184, 185, 186, 180, 181, 184, 164, 162, 162, 145, 136, 138, 126, 120, 119, 117, 116, 114, 119, 121, 121, 125, 131, 129, 131, 138, 134, 135, 137, 136, 133, 130, 128, 123, 120, 115, 110, 106, 100, 97, 93, 91, 89, 88, 85, 86, 90, 87, 87, 92, 90, 87, 106, 111, 101, 125, 143, 132, 145, 168, 163, 166, 178, 183, 180, 177, 183, 177, 166, 164, 161, 148, 141, 140, 130, 125, 124, 123, 121, 120, 125, 126, 125, 129, 130, 130, 131, 132, 130, 128, 126, 123, 119, 113, 110, 105, 100, 97, 92, 92, 89, 87, 88, 86, 88, 87, 84, 91, 88, 84, 102, 110, 99, 121, 141, 129, 145, 163, 161, 167, 176, 183, 181, 180, 184, 178, 169, 167, 162, 149, 144, 141, 132, 127, 126, 125, 123, 123, 125, 127, 127, 128, 131, 131, 129, 131, 128, 124, 122, 118, 112, 107, 102, 99, 94, 88, 90, 86, 81, 85, 82, 81, 84, 81, 83, 85, 96, 107, 103, 121, 138, 135, 145, 164, 166, 167, 180, 182, 181, 180, 180, 175, 166, 163, 157, 149, 140, 139, 132, 127, 127, 125, 127, 123, 128, 128, 127, 131, 131, 130, 129, 129, 126, 123, 119, 115, 110, 104, 102, 95, 91, 90, 85, 82, 83, 80, 80, 80, 80, 80, 85, 98, 101, 109, 122, 132, 139, 148, 163, 165, 171, 182, 182, 181, 182, 180, 172, 168, 162, 154, 147, 141, 136, 129, 129, 126, 127, 127, 125, 131, 129, 131, 132, 131, 132, 130, 129, 126, 121, 117, 115, 105, 103, 98, 90, 90, 86, 83, 80, 83, 79, 79, 82, 82, 85, 91, 97, 107, 114, 124, 137, 143, 154, 165, 170, 177, 183, 183, 185, 181, 177, 173, 163, 154, 148, 139, 132, 126, 122, 121, 119, 122, 125, 127, 131, 137, 138, 140, 143, 144, 141, 138, 136, 130, 124, 118, 113, 105, 100, 96, 91, 87, 83, 82, 80, 77, 79, 78, 77, 79, 88, 96, 88, 115, 121, 115, 143, 146, 154, 165, 174, 182, 184, 186, 192, 184, 178, 178, 164, 154, 148, 137, 129, 124, 117, 115, 115, 116, 118, 124, 129, 135, 137, 143, 145, 144, 144, 142, 140, 133, 132, 125, 118, 114, 106, 99, 93, 88, 84, 81, 80, 77, 76, 77, 76, 74, 73, 79, 93, 88, 102, 121, 116, 133, 148, 153, 162, 177, 179, 185, 190, 187, 188, 180, 176, 170, 161, 151, 146, 135, 127, 124, 118, 115, 116, 118, 118, 123, 130, 134, 136, 143, 145, 142, 144, 143, 137, 135, 130, 124, 119, 112, 106, 102, 98, 93, 92, 90, 90, 88, 90, 92, 92, 95, 100, 105, 109, 116, 123, 127, 132, 140, 145, 146, 151, 155, 155, 156, 157, 156, 153, 152, 151, 149, 147, 144, 142, 140, 137, 135, 134, 132, 130, 129, 127, 126, 125, 124, 123, 122, 122, 122, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 119, 119, 118, 118, 117, 116, 115, 114, 113, 112, 112, 112, 113, 114, 115, 117, 119, 122, 126, 129, 132, 135, 138, 140, 142, 144, 145, 145, 145, 145, 144, 143, 142, 141, 140, 138, 136, 135, 133, 131, 130, 128, 127, 125, 124, 123, 122, 122, 121, 121, 122, 122, 122, 123, 124, 124, 125, 126, 126, 127, 127, 127, 127, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 118, 117, 117, 117, 118, 118, 120, 121, 123, 124, 127, 129, 131, 133, 135, 137, 139, 141, 142, 142, 142, 142, 144, 144, 141, 140, 137, 136, 137, 134, 128, 126, 127, 127, 125, 123, 123, 123, 123, 123, 123, 124, 124, 123, 124, 123, 123, 122, 121, 121, 120, 119, 120, 120, 118, 117, 116, 113, 109, 105, 99, 97, 96, 100, 103, 101, 108, 117, 122, 124, 132, 144, 146, 150, 156, 158, 161, 160, 158, 153, 151, 149, 143, 140, 138, 137, 134, 131, 132, 131, 129, 130, 130, 131, 133, 132, 132, 135, 135, 134, 135, 135, 134, 133, 134, 132, 132, 131, 130, 126, 124, 121, 114, 107, 101, 95, 86, 77, 74, 68, 65, 63, 60, 66, 71, 75, 93, 116, 116, 128, 155, 160, 162, 178, 189, 189, 187, 191, 187, 179, 169, 160, 159, 143, 135, 130, 124, 116, 112, 115, 112, 113, 115, 119, 123, 127, 131, 135, 137, 138, 139, 141, 140, 139, 139, 139, 139, 137, 137, 137, 135, 131, 130, 125, 120, 114, 107, 100, 92, 84, 77, 71, 66, 60, 59, 55, 56, 63, 67, 85, 91, 108, 124, 128, 148, 159, 163, 178, 185, 188, 191, 191, 186, 182, 175, 162, 159, 146, 136, 132, 122, 117, 113, 112, 108, 112, 113, 114, 121, 123, 128, 134, 134, 138, 140, 140, 143, 143, 144, 144, 143, 142, 141, 137, 133, 129, 123, 117, 109, 103, 95, 88, 80, 76, 70, 64, 61, 57, 54, 60, 67, 70, 85, 103, 113, 125, 151, 161, 168, 190, 197, 198, 205, 206, 197, 190, 184, 172, 162, 150, 139, 132, 123, 118, 117, 117, 114, 119, 122, 121, 124, 128, 127, 128, 130, 129, 130, 132, 130, 132, 136, 134, 134, 139, 139, 136, 140, 139, 132, 130, 127, 121, 114, 109, 101, 93, 86, 78, 70, 63, 55, 50, 44, 43, 61, 64, 67, 99, 113, 116, 145, 170, 168, 186, 207, 205, 207, 213, 206, 194, 190, 178, 166, 154, 142, 134, 123, 118, 117, 116, 113, 117, 121, 120, 123, 126, 124, 125, 127, 127, 126, 128, 130, 131, 132, 136, 138, 137, 141, 143, 142, 142, 142, 137, 132, 129, 120, 113, 105, 97, 86, 79, 72, 63, 59, 52, 48, 48, 61, 66, 67, 96, 111, 113, 137, 160, 163, 176, 195, 197, 199, 203, 200, 193, 186, 177, 166, 155, 143, 134, 125, 118, 115, 113, 113, 114, 117, 119, 122, 123, 124, 126, 126, 126, 126, 125, 126, 129, 127, 129, 137, 138, 138, 144, 149, 146, 147, 148, 143, 136, 132, 125, 111, 104, 96, 86, 74, 69, 64, 56, 50, 56, 81, 74, 78, 124, 130, 123, 156, 178, 164, 173, 193, 183, 175, 174, 171, 158, 145, 142, 139, 125, 118, 124, 119, 113, 118, 123, 120, 120, 127, 128, 126, 127, 131, 130, 127, 129, 131, 129, 128, 134, 136, 134, 139, 143, 143, 141, 144, 144, 139, 134, 133, 127, 115, 110, 103, 92, 83, 80, 73, 68, 68, 72, 88, 93, 100, 125, 143, 144, 159, 182, 179, 178, 185, 185, 171, 160, 156, 144, 127, 113, 112, 105, 94, 96, 105, 107, 109, 125, 135, 139, 147, 157, 160, 157, 156, 153, 145, 134, 125, 118, 108, 100, 96, 96, 95, 97, 104, 110, 116, 124, 133, 140, 144, 149, 151, 151, 149, 146, 141, 135, 130, 123, 118, 115, 113, 111, 112, 115, 118, 122, 126, 131, 135, 137, 141, 142, 141, 139, 137, 132, 128, 124, 120, 117, 114, 114, 114, 115, 117, 121, 125, 129, 132, 135, 137, 138, 138, 138, 136, 133, 132, 129, 126, 123, 122, 121, 120, 120, 121, 123, 124, 126, 128, 129, 130, 130, 131, 131, 131, 130, 129, 128, 127, 127, 126, 126, 126, 126, 127, 127, 128, 128, 129, 129, 129, 129, 129, 129, 127, 127, 127, 126, 125, 126, 125, 126, 127, 127, 128, 129, 130, 130, 130, 131, 131, 130, 129, 129, 127, 126, 126, 126, 125, 124, 125, 126, 126, 126, 127, 128, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 128, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 128, 128, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 128, 128, 128, 128, 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 127, 127, 127, 126, 126, 127, 127, 127, 128, 128, 128, 128, 127, 126, 126, 126, 126, 126, 127, 128, 129, 129, 128, 127, 126, 125, 125, 125, 126, 127, 129, 129, 130, 131, 131, 129, 134, 158, 141, 124, 136, 142, 123, 116, 130, 131, 132, 135, 136, 135, 140, 131, 116, 121, 126, 115, 108, 112, 110, 107, 110, 117, 123, 114, 98, 87, 87, 81, 76, 83, 103, 158, 179, 163, 169, 189, 176, 139, 124, 121, 115, 104, 100, 105, 128, 146, 144, 150, 170, 172, 148, 130, 125, 123, 112, 105, 110, 123, 139, 141, 139, 148, 152, 138, 120, 112, 108, 103, 102, 108, 119, 134, 145, 150, 153, 153, 146, 130, 120, 112, 110, 116, 125, 135, 147, 161, 161, 156, 151, 138, 117, 102, 96, 95, 98, 108, 126, 141, 150, 149, 147, 143, 132, 118, 111, 105, 102, 106, 107, 110, 120, 126, 119, 118, 113, 109, 93, 75, 65, 65, 73, 78, 97, 151, 203, 196, 184, 189, 184, 148, 115, 99, 102, 116, 117, 121, 143, 169, 174, 166, 161, 152, 135, 116, 99, 92, 101, 113, 122, 141, 161, 170, 168, 162, 148, 130, 114, 108, 107, 105, 112, 124, 131, 133, 137, 132, 121, 110, 99, 94, 90, 81, 80, 89, 91, 84, 83, 87, 84, 80, 95, 108, 147, 190, 193, 187, 193, 189, 157, 134, 123, 119, 115, 119, 130, 143, 157, 163, 163, 161, 157, 144, 133, 120, 114, 113, 116, 120, 130, 140, 147, 148, 150, 153, 146, 141, 137, 130, 124, 127, 124, 122, 125, 124, 120, 115, 104, 94, 91, 90, 89, 78, 67, 69, 70, 75, 57, 48, 70, 93, 103, 127, 190, 220, 214, 178, 156, 153, 139, 111, 99, 117, 138, 150, 149, 156, 168, 169, 156, 142, 137, 136, 127, 120, 120, 126, 132, 133, 138, 142, 139, 137, 139, 142, 137, 138, 143, 141, 131, 125, 120, 117, 111, 102, 98, 99, 97, 91, 89, 89, 84, 73, 71, 69, 72, 73, 67, 63, 132, 205, 207, 182, 171, 174, 165, 142, 102, 115, 146, 146, 140, 152, 161, 166, 161, 148, 145, 147, 137, 126, 126, 127, 133, 137, 135, 134, 141, 140, 136, 138, 139, 138, 138, 135, 130, 123, 116, 112, 110, 103, 98, 97, 92, 86, 82, 85, 81, 73, 69, 70, 64, 73, 78, 74, 89, 156, 225, 221, 187, 169, 165, 147, 135, 119, 112, 135, 161, 162, 159, 156, 151, 159, 158, 142, 130, 137, 143, 141, 131, 123, 124, 132, 132, 126, 124, 129, 133, 128, 118, 111, 112, 113, 110, 104, 105, 108, 106, 95, 88, 81, 81, 86, 83, 77, 81, 77, 75, 93, 101, 101, 115, 201, 241, 205, 173, 163, 155, 136, 125, 113, 134, 159, 164, 154, 153, 155, 158, 154, 140, 134, 137, 140, 132, 126, 124, 128, 131, 131, 130, 133, 131, 126, 121, 115, 114, 113, 111, 110, 109, 105, 99, 95, 94, 96, 95, 91, 90, 86, 91, 93, 93, 88, 87, 92, 100, 89, 98, 201, 255, 227, 185, 171, 169, 160, 138, 112, 121, 146, 164, 162, 156, 148, 152, 156, 144, 131, 132, 135, 132, 129, 123, 124, 129, 131, 129, 129, 129, 127, 123, 121, 120, 121, 119, 115, 114, 114, 109, 102, 100, 102, 103, 99, 97, 99, 95, 92, 89, 95, 94, 93, 96, 101, 111, 102, 88, 147, 223, 224, 191, 166, 157, 157, 156, 131, 124, 142, 159, 164, 158, 143, 136, 147, 150, 139, 132, 134, 137, 140, 135, 127, 127, 133, 133, 129, 122, 119, 120, 120, 118, 118, 120, 123, 124, 121, 115, 109, 104, 101, 102, 104, 104, 103, 103, 99, 95, 95, 97, 103, 112, 106, 104, 109, 111, 114, 112, 114, 153, 191, 191, 175, 166, 155, 151, 160, 155, 146, 146, 148, 149, 150, 138, 133, 141, 147, 146, 140, 131, 124, 128, 131, 126, 122, 124, 129, 134, 133, 126, 122, 123, 122, 121, 119, 116, 112, 114, 114, 113, 114, 114, 114, 113, 111, 105, 105, 103, 103, 102, 101, 99, 98, 100, 101, 103, 110, 116, 120, 118, 111, 101, 123, 179, 206, 203, 182, 163, 159, 169, 157, 143, 137, 138, 152, 159, 154, 138, 141, 143, 145, 143, 136, 125, 125, 132, 129, 131, 129, 127, 130, 138, 133, 124, 124, 122, 124, 126, 125, 121, 121, 118, 116, 120, 120, 119, 116, 111, 109, 109, 109, 105, 105, 103, 103, 101, 98, 95, 90, 86, 92, 98, 101, 104, 103, 114, 119, 119, 114, 113, 127, 171, 199, 191, 186, 183, 177, 168, 165, 155, 141, 139, 140, 144, 153, 151, 143, 140, 146, 144, 140, 133, 124, 124, 128, 130, 129, 128, 126, 129, 134, 135, 130, 124, 123, 125, 126, 128, 127, 125, 124, 126, 124, 119, 118, 118, 113, 109, 110, 109, 109, 108, 109, 109, 108, 104, 103, 104, 105, 107, 104, 104, 106, 110, 111, 108, 108, 111, 111, 105, 107, 113, 115, 110, 112, 137, 162, 172, 174, 181, 189, 191, 195, 192, 188, 185, 179, 171, 165, 161, 155, 147, 138, 132, 129, 124, 116, 111, 106, 102, 100, 100, 98, 98, 101, 103, 104, 109, 116, 120, 127, 133, 137, 143, 150, 152, 155, 160, 160, 158, 156, 152, 146, 142, 138, 131, 124, 115, 106, 97, 92, 87, 85, 83, 81, 79, 80, 81, 82, 86, 89, 91, 94, 98, 101, 104, 109, 114, 115, 114, 114, 115, 115, 114, 113, 116, 123, 128, 131, 138, 152, 166, 169, 173, 184, 194, 196, 195, 197, 198, 194, 190, 184, 176, 168, 160, 150, 140, 131, 124, 118, 111, 104, 100, 98, 95, 93, 93, 95, 96, 98, 101, 104, 108, 114, 118, 124, 128, 134, 138, 143, 147, 150, 152, 153, 154, 152, 152, 150, 147, 144, 141, 136, 130, 126, 120, 114, 109, 106, 102, 99, 96, 93, 92, 92, 91, 91, 92, 94, 95, 96, 98, 101, 103, 104, 106, 106, 107, 111, 113, 113, 114, 117, 117, 118, 118, 116, 115, 122, 128, 128, 127, 135, 144, 151, 161, 164, 168, 178, 187, 186, 189, 194, 195, 194, 189, 183, 178, 175, 167, 159, 151, 143, 134, 128, 121, 114, 108, 102, 98, 94, 90, 87, 88, 92, 94, 93, 96, 102, 107, 111, 117, 124, 130, 137, 142, 146, 151, 156, 159, 160, 161, 159, 157, 154, 152, 147, 142, 137, 131, 124, 119, 114, 109, 105, 101, 97, 94, 92, 90, 89, 89, 89, 89, 90, 91, 92, 94, 97, 100, 100, 103, 104, 105, 109, 115, 115, 114, 116, 119, 120, 121, 119, 116, 118, 126, 128, 127, 130, 140, 146, 156, 163, 164, 172, 184, 188, 186, 192, 195, 195, 192, 186, 180, 177, 171, 161, 154, 146, 137, 129, 123, 117, 110, 103, 98, 94, 91, 88, 86, 88, 93, 95, 95, 100, 107, 113, 117, 124, 131, 139, 143, 147, 153, 158, 161, 162, 162, 161, 159, 155, 151, 147, 142, 136, 129, 122, 116, 110, 104, 100, 96, 92, 90, 88, 86, 87, 89, 90, 91, 92, 97, 99, 101, 104, 110, 113, 110, 115, 122, 121, 119, 121, 126, 127, 125, 123, 126, 128, 124, 122, 123, 123, 120, 123, 127, 127, 129, 136, 145, 149, 153, 160, 169, 173, 175, 179, 183, 186, 184, 181, 177, 174, 170, 163, 156, 150, 144, 137, 130, 124, 120, 116, 111, 107, 105, 104, 102, 101, 103, 105, 106, 107, 110, 113, 116, 119, 123, 125, 128, 131, 132, 134, 135, 136, 136, 136, 135, 134, 133, 132, 131, 129, 127, 125, 123, 122, 120, 118, 116, 114, 113, 112, 110, 109, 109, 109, 108, 108, 109, 110, 111, 113, 115, 117, 118, 119, 121, 125, 127, 127, 129, 131, 132, 131, 130, 129, 131, 130, 127, 125, 123, 123, 122, 119, 115, 123, 131, 126, 123, 135, 145, 147, 153, 160, 166, 170, 174, 176, 181, 184, 184, 184, 180, 174, 171, 169, 162, 156, 150, 144, 137, 130, 124, 121, 118, 113, 108, 106, 104, 102, 103, 104, 104, 106, 108, 109, 112, 115, 118, 122, 126, 127, 129, 132, 134, 135, 136, 136, 136, 136, 134, 132, 131, 131, 129, 127, 124, 123, 121, 119, 117, 116, 114, 113, 112, 111, 110, 109, 110, 110, 110, 111, 111, 112, 113, 115, 117, 118, 120, 122, 123, 124, 127, 128, 127, 129, 131, 130, 128, 129, 129, +}; + + +/* get our radio ready */ + +void setup() { + Wire.begin(); + Serial.begin(9600); + Serial.print("Radio status: "); + int result = radio.testConnection(); + Serial.println(result); + radio.initialize(); + radio.setFrequency(446000); + radio.setVolume1(0xF); + radio.setVolume2(0xF); + radio.setModeReceive(); + radio.setTxSourceMic(); + radio.setSQLoThresh(80); + radio.setSQOn(); +} + +/* main program loop */ + + +void loop() { + rssi = radio.readRSSI(); + if(rssi > -120) { + for(;;) { + rssi = radio.readRSSI(); + if(rssi < -120) { break; } + if(rssi > peak) { peak = rssi; Serial.print("New peak: "); Serial.println(rssi); } + } + } + + if(rssi < -120) { + Serial.println("Transmit On"); + radio.setTX(1); + delay(250); + tone(11,1000,500); + delay(1000); + itoa(peak,sig,10); + Serial.print(sig); + Serial.print(" dBm..."); + for(int x = 0; x < strlen(sig); x++) { + if(sig[x] = '0') { startPlayback(zero, sizeof(zero)); } + if(sig[x] = '1') { startPlayback(one, sizeof(one)); } + if(sig[x] = '2') { startPlayback(two, sizeof(two)); } + if(sig[x] = '3') { startPlayback(three, sizeof(three)); } + if(sig[x] = '4') { startPlayback(four, sizeof(four)); } + if(sig[x] = '5') { startPlayback(five, sizeof(five)); } + if(sig[x] = '6') { startPlayback(six, sizeof(six)); } + if(sig[x] = '7') { startPlayback(seven, sizeof(seven)); } + if(sig[x] = '8') { startPlayback(eight, sizeof(eight)); } + if(sig[x] = '9') { startPlayback(nine, sizeof(nine)); } + if(sig[x] = '-') { startPlayback(minus, sizeof(minus)); } + delay(1000); + } + startPlayback(dbm,sizeof(dbm)); + delay(2000); + tone(11,1000,500); + delay(1000); + Serial.println("done!"); + radio.morseOut(CALLSIGN); + radio.setTX(0); + Serial.println("Transmit off"); + radio.setModeReceive(); + delay(1000); + } +} + diff --git a/examples/SignalTest/Sounds/0.wav b/examples/SignalTest/Sounds/0.wav new file mode 100755 index 0000000000000000000000000000000000000000..a580efc26ba6421cde424fab8e72d5afe518d6fc GIT binary patch literal 4204 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 literal 0 HcmV?d00001 diff --git a/examples/SignalTest/Sounds/3.wav b/examples/SignalTest/Sounds/3.wav new file mode 100755 index 0000000000000000000000000000000000000000..e8ded200a65d110a30e54cebde84f3d750402e40 GIT binary patch literal 3244 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 YXo&qEB-;y_zb3DALsm)d|1E9!4;#VUegFUf literal 0 HcmV?d00001 diff --git a/examples/SignalTest/Sounds/4.wav b/examples/SignalTest/Sounds/4.wav new file mode 100755 index 0000000000000000000000000000000000000000..b5c3807082c5e5438919adc68d3a1c5c017eee28 GIT binary patch literal 2850 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 literal 0 HcmV?d00001 diff --git a/examples/SignalTest/Sounds/7.wav b/examples/SignalTest/Sounds/7.wav new file mode 100755 index 0000000000000000000000000000000000000000..bf01012e1e53502e3ac9b891e1ffc11eeb79250b GIT binary patch literal 2956 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 literal 0 HcmV?d00001 diff --git a/examples/SignalTest/Sounds/8.wav b/examples/SignalTest/Sounds/8.wav new file mode 100755 index 0000000000000000000000000000000000000000..05c474cf3f80eb8b783bd5d51ce2e68529a6a8d6 GIT binary patch literal 2106 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 W|DPmdSd#jAR$hL3Zsz}+ZSWsi7d|-v literal 0 HcmV?d00001 diff --git a/examples/SignalTest/Sounds/dbm.wav b/examples/SignalTest/Sounds/dbm.wav new file mode 100755 index 0000000000000000000000000000000000000000..e51c41bcae030f2c4150b47716779932bf774246 GIT binary patch literal 6316 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 No1c=M_Wu?(_+NwdM4kWu literal 0 HcmV?d00001 diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..10692e5 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,30 @@ +####################################### +# Syntax Coloring Map HAMShield +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +#SD KEYWORD1 +#File KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +#begin KEYWORD2 +#exists KEYWORD2 +#mkdir KEYWORD2 +#remove KEYWORD2 +#rmdir KEYWORD2 +#open KEYWORD2 +#close KEYWORD2 +#seek KEYWORD2 +#position KEYWORD2 +#size KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +#FILE_READ LITERAL1 +#FILE_WRITE LITERAL1 diff --git a/src/HamShield.cpp b/src/HamShield.cpp new file mode 100644 index 0000000..7e7dab0 --- /dev/null +++ b/src/HamShield.cpp @@ -0,0 +1,1362 @@ +// HAMShield library collection +// Based on Programming Manual rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 11/22/2013 by Morgan Redfield +// 04/26/2015 various changes Casey Halverson + + +#include "HAMShield.h" +#include +// #include + +/* don't change this regulatory value, use dangerMode() and safeMode() instead */ + +bool restrictions = true; + +/* channel lookup tables */ + +uint32_t FRS[] = {0,462562,462587,462612,462637,462662,462687,462712,467562,467587,467612,467637,467662,467687,467712}; + +uint32_t GMRS[] = {0,462550,462575,462600,462625,462650,462675,462700,462725}; + +uint32_t MURS[] = {0,151820,151880,151940,154570,154600}; + +uint32_t WX[] = {0,162550,162400,162475,162425,162450,162500,162525}; + +/* morse code lookup table */ + +const char *ascii = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?'!/()&:;=+-_\"$@", + *itu[] = { ".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",".-.-.-","--..--","..--..",".----.","-.-.--","-..-.","-.--.","-.--.-",".-...","---...","-.-.-.","-...-",".-.-.","-....-","..--.-",".-..-.","...-..-",".--.-." + }; + +/* 2200 Hz */ + +const unsigned char AFSK_mark[] PROGMEM = { 154, 249, 91, 11, 205, 216, 25, 68, 251, 146, 0, 147, 250, 68, 24, 218, 203, 13, 88, 254, 128, 1, 167, 242, 52, 37, 231, 186, 5, 108, 255, 108, 5, 186, 231, 37, 52, 242, 167, 1, 128, 254, 88, 13, 203, 218, 24, 69, 250, 147, 0, 147, 250, 69, 24, 218, 203, 13, 88, 255, 127, 2, 165, 245, 48 }; + +/* 1200 Hz */ + +const unsigned char AFSK_space[] PROGMEM = { 140, 228, 250, 166, 53, 0, 53, 166, 249, 230, 128, 24, 7, 88, 203, 255, 203, 88, 7, 24, 128, 230, 249, 167, 53, 0, 53, 167, 249, 230, 128, 24, 6, 88, 202, 255, 202, 88, 6, 24, 127, 231, 249, 167, 52, 0, 52, 167, 248, 231, 127, 25, 6, 89, 202, 255, 202, 89, 6, 25, 127, 231, 248, 167, 53, 0, 54, 165, 251, 227, 133, 14}; + + +/* Aux button variables */ + +volatile int ptt = false; +volatile long bouncer = 0; + +/** Default constructor, uses default I2C address. + * @see A1846S_DEFAULT_ADDRESS + */ +HAMShield::HAMShield() { + devAddr = A1846S_DEV_ADDR_SENLOW; +} + +/** Specific address constructor. + * @param address I2C address + * @see A1846S_DEFAULT_ADDRESS + * @see A1846S_ADDRESS_AD0_LOW + * @see A1846S_ADDRESS_AD0_HIGH + */ +HAMShield::HAMShield(uint8_t address) { + devAddr = address; +} + +/** Power on and prepare for general usage. + * + */ +void HAMShield::initialize() { + // set up PWM output for RF power control - commenting out to get rid of terrible buzzing noise + // pwr_control_pin = 9; + + + // Note: these initial settings are for UHF 12.5kHz channel + // see the A1846S register table and initial settings for more info + + // TODO: update code to make it easier to change from VHF to UHF and 12.5kHz channel to 25kHz channel + uint16_t tx_data; + + // reset all registers in A1846S + softReset(); + // set pdn_reg bit in control register (0 or 1?) (now done in softReset) + //I2Cdev::writeBitW(devAddr, A1846S_CTL_REG, A1846S_PWR_DWN_BIT, 1); + tx_data = 0x0698; + I2Cdev::writeWord(devAddr, 0x02, tx_data); // why is this here? See A1846S register init table + + //set up clock to ues 12-14MHz + setClkMode(1); + + // set up clock to use 12.8MHz crystal + setXtalFreq(12800); + // set up ADClk frequency to 6.4MHz + setAdcClkFreq(6400); + + tx_data = 0xE000; + I2Cdev::writeWord(devAddr, 0x24, tx_data); // why is this here? See A1846S register init word doc + + //could change GPIO voltage levels with writes to 0x08 and 0x09 + // see A1846S register init table + tx_data = 0x03AC; + I2Cdev::writeWord(devAddr, 0x09, tx_data); // why is this here? See A1846S register init word doc + + // set PA_bias voltage to 1.68V (and do something else too? what's the 3 for?) + tx_data = 0x0320; + I2Cdev::writeWord(devAddr, 0x0A, tx_data); + + tx_data = 0x1A10; + I2Cdev::writeWord(devAddr, 0x0B, tx_data); // why is this here? See A1846S register init table + + tx_data = 0x3E37; + I2Cdev::writeWord(devAddr, 0x11, tx_data); // why is this here? See A1846S register init table + + // Automatic Gain Control stuff + // AGC when band is UHF,0x32 = 0x627C;when band is VHF,0x32 = 0x62BC// + tx_data = 0x627c; // this is uhf, for vhf set to 0x62bc + I2Cdev::writeWord(devAddr, 0x32, tx_data); // why is this here? See A1846S register init table + tx_data = 0x0AF2; + I2Cdev::writeWord(devAddr, 0x33, tx_data); // why is this here? See A1846S register init table + + // why is this here? See A1846S register init word doc + tx_data = 0x0F28; // this is uhf, for vhf set to 0x62bc + I2Cdev::writeWord(devAddr, 0x3C, tx_data); // why is this here? See A1846S register init table + tx_data = 0x200B; + I2Cdev::writeWord(devAddr, 0x3D, tx_data); // why is this here? See A1846S register init table + + // Noise threshold settings + tx_data = 0x1C2F; // see email from Iris + I2Cdev::writeWord(devAddr, 0x47, tx_data); // why is this here? See A1846S register init table + + // SNR LPF settings, sq settings + tx_data = 0x293A; + I2Cdev::writeWord(devAddr, 0x4e, tx_data); // why is this here? See A1846S register init table + + // subaudio decode setting,sq_out_sel,noise threshold value db + tx_data = 0x114A; // A1846S_SQ_OUT_SEL_REG is 0x54 + I2Cdev::writeWord(devAddr, A1846S_SQ_OUT_SEL_REG, tx_data); // why is this here? See A1846S register init table + + // bandwide setting of filter when RSSI is high or low + tx_data = 0x0652; + I2Cdev::writeWord(devAddr, 0x56, tx_data); // why is this here? See A1846S register init table + + tx_data = 0x062d; + I2Cdev::writeWord(devAddr, 0x6e, tx_data); // why is this here? See A1846S register init table + + // note, this is for 12.5kHz channel + tx_data = 0x6C1E; + I2Cdev::writeWord(devAddr, 0x71, tx_data); // why is this here? See A1846S register init table + + // see A1846S register init doc for this + tx_data = 0x00FF; + I2Cdev::writeWord(devAddr, 0x44, tx_data); // why is this here? See A1846S register init table + tx_data = 0x0500; + I2Cdev::writeWord(devAddr, 0x1F, tx_data); // set up GPIO for RX/TX mirroring + + + // set RFoutput power (note that the address is 0x85, so do some rigmaroll) + tx_data = 0x1; + I2Cdev::writeWord(devAddr, 0x7F, tx_data); // prep to write to a reg > 0x7F + // If 0x85 is 0x001F, Rfoutput power is 8dBm , ACP is -63dB in 12.5KHz and -65dB in 25KHz + // If 0x85 is 0x0018, Rfoutput power is 6dBm , ACP is -64dB in 12.5KHz and -66dB in 25KHz + // If 0x85 is 0x0017, Rfoutput power is -3dBm , ACP is -68dBc in 12.5KHz and -68dBc in 25KHz + tx_data = 0x001F; + I2Cdev::writeWord(devAddr, 0x5, tx_data); // set output power, reg 0x85 - 0x80 + tx_data = 0x0; + I2Cdev::writeWord(devAddr, 0x7F, tx_data); // finish writing to a reg > 0x7F + + // set control reg for pdn_reg, rx, and mute when rxno + tx_data = 0xA4; + I2Cdev::writeWord(devAddr, A1846S_CTL_REG, tx_data); // finish writing to a reg > 0x7F + + delay(100); + + // set control reg for chip_cal_en, pdn_reg, rx, and mute when rxno + tx_data = 0xA6; + I2Cdev::writeWord(devAddr, A1846S_CTL_REG, tx_data); // finish writing to a reg > 0x7F + + delay(100); + + // set control reg for chip_cal_en, pdn_reg + tx_data = 0x6; + I2Cdev::writeWord(devAddr, A1846S_CTL_REG, tx_data); // finish writing to a reg > 0x7F + + delay(100); + + // and then I have no idea about this nonsense + // some of these settings seem to be for 12.5kHz channels + // TODO: get A1846S to give us a full register table + tx_data = 0x1d40; + I2Cdev::writeWord(devAddr, 0x54, tx_data); + tx_data = 0x062d; + I2Cdev::writeWord(devAddr, 0x6e, tx_data); + tx_data = 0x102a; + I2Cdev::writeWord(devAddr, 0x70, tx_data); + tx_data = 0x6c1e; + I2Cdev::writeWord(devAddr, 0x71, tx_data); + tx_data = 0x0006; + I2Cdev::writeWord(devAddr, 0x30, tx_data); + + delay(100); + + // setup default values + + setFrequency(446000); + setVolume1(0xF); + setVolume2(0xF); + setModeReceive(); + setTxSourceMic(); + setSQLoThresh(80); + setSQOn(); + +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool HAMShield::testConnection() { + I2Cdev::readWord(devAddr, 0x09, radio_i2c_buf); +// 03ac or 032c + return radio_i2c_buf[0] == 0x03AC; // TODO: find a device ID reg I can use +} + + +/** A1846S each register write is 24-bit long, including a + * r/nw bit, 7-bit register address , and 16-bit data (MSB + * is the first bit). + * R/W, A[6:0], D[15:0] + * + * Note (this shouldn't be necessary, since all ctl registers are below 0x7F) + * If register address is more than 7FH, first write 0x0001 + * to 7FH, and then write value to the address subtracted by + * 80H. Finally write 0x0000 to 7FH + * Example: writing 85H register address is 0x001F . + * Move 7FH 0x0001{ + +} + * Move 05H 0x001F{ + +} 05H=85H-80H + * Move 7FH 0x0000{ + +} + */ + +uint16_t HAMShield::readCtlReg() { + I2Cdev::readWord(devAddr, A1846S_CTL_REG, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +void HAMShield::softReset() { + uint16_t tx_data = 0x1; + I2Cdev::writeWord(devAddr, A1846S_CTL_REG, tx_data); + delay(100); // Note: see A1846S setup info for timing guidelines + tx_data = 0x4; + I2Cdev::writeWord(devAddr, A1846S_CTL_REG, tx_data); +} + + +void HAMShield::setFrequency(uint32_t freq_khz) { + radio_frequency = freq_khz; + uint32_t freq_raw = freq_khz << 3; // shift by 3 to multiply by 8 + + // send top 16 bits to A1846S_FREQ_HI_REG + uint16_t freq_half = (uint16_t) (0x3FFF & (freq_raw >> 16)); + I2Cdev::writeWord(devAddr, A1846S_FREQ_HI_REG, freq_half); + // send bottom 16 bits to A1846S_FREQ_LO_REG + freq_half = (uint16_t) (freq_raw & 0xFFFF); + I2Cdev::writeWord(devAddr, A1846S_FREQ_LO_REG, freq_half); +} + +uint32_t HAMShield::getFrequency() { + return radio_frequency; +} + +void HAMShield::setUHF() { + setGpioHi(2); // turn off VHF + setGpioLow(3); // turn on UHF +} + +void HAMShield::setVHF() { + setGpioHi(3); // turn off UHF + setGpioLow(2); // turn on VHF +} + +void HAMShield::setNoFilters() { + setGpioHi(3); // turn off UHF + setGpioHi(2); // turn off VHF +} + +// band +// 00 - 400-520MHz +// 10 - 200-260MHz +// 11 - 134-174MHz +// TODO: add write to 0x32 based on band selection +void HAMShield::setBand(uint16_t band){ + if (band == 0) { + setUHF(); + } else if (band == 2) { + // not quite in the band for our filters, but use VHF + setVHF(); + } else if (band == 3) { + setVHF(); + } else { + // illegal write code, turn UHF and VHF channels both off + setNoFilters(); + // turn off transmit as well to make sure we don't break anything + setTX(0); + } + I2Cdev::writeBitsW(devAddr, A1846S_BAND_SEL_REG, A1846S_BAND_SEL_BIT, A1846S_BAND_SEL_LENGTH, band); +} +uint16_t HAMShield::getBand(){ + I2Cdev::readBitsW(devAddr, A1846S_BAND_SEL_REG, A1846S_BAND_SEL_BIT, A1846S_BAND_SEL_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// xtal frequency (kHz) +// 12-14MHz crystal: this reg is set to crystal freq_khz +// 24-28MHz crystal: this reg is set to crystal freq_khz / 2 +void HAMShield::setXtalFreq(uint16_t freq_kHz){ + I2Cdev::writeWord(devAddr, A1846S_XTAL_FREQ_REG, freq_kHz); +} +uint16_t HAMShield::getXtalFreq(){ + I2Cdev::readWord(devAddr, A1846S_FREQ_HI_REG, radio_i2c_buf); + + return radio_i2c_buf[0]; +} + +// adclk frequency (kHz) +// 12-14MHz crystal: this reg is set to crystal freq_khz / 2 +// 24-28MHz crystal: this reg is set to crystal freq_khz / 4 +void HAMShield::setAdcClkFreq(uint16_t freq_kHz){ + I2Cdev::writeWord(devAddr, A1846S_ADCLK_FREQ_REG, freq_kHz); +} + +uint16_t HAMShield::getAdcClkFreq(){ + I2Cdev::readWord(devAddr, A1846S_ADCLK_FREQ_REG, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// clk mode +// 12-14MHz: set to 1 +// 24-28MHz: set to 0 +void HAMShield::setClkMode(bool LFClk){ + // include upper bits as default values + uint16_t tx_data = 0x0F11; // NOTE: should this be 0fd1 or 0f11? Programming guide and setup guide disagree + if (!LFClk) { + tx_data = 0x0F10; + } + + I2Cdev::writeWord(devAddr, A1846S_CLK_MODE_REG, tx_data); +} +bool HAMShield::getClkMode(){ + I2Cdev::readBitW(devAddr, A1846S_CLK_MODE_REG, A1846S_CLK_MODE_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// clk example +// 12.8MHz clock +// A1846S_XTAL_FREQ_REG[15:0]= xtal_freq<15:0>=12.8*1000=12800 +// A1846S_ADCLK_FREQ_REG[12:0] =adclk_freq<15:0>=(12.8/2)*1000=6400 +// A1846S_CLK_MODE_REG[0]= clk_mode =1 + +// TX/RX control + +// channel mode +// 11 - 25kHz channel +// 00 - 12.5kHz channel +// 10,01 - reserved +void HAMShield::setChanMode(uint16_t mode){ + I2Cdev::writeBitsW(devAddr, A1846S_CTL_REG, A1846S_CHAN_MODE_BIT, A1846S_CHAN_MODE_LENGTH, mode); +} +uint16_t HAMShield::getChanMode(){ + I2Cdev::readBitsW(devAddr, A1846S_CTL_REG, A1846S_CHAN_MODE_BIT, A1846S_CHAN_MODE_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// choose tx or rx +void HAMShield::setTX(bool on_noff){ + // make sure RX is off + if (on_noff) { + setRX(false); + + // For RF6886: + // first turn on power + // set RX output on + setGpioHi(4); // remember that RX and TX are active low + // set TX output off + setGpioLow(5); // remember that RX and TX are active low + // then turn on VREG (PWM output) + // then apply RF signal + setRfPower(100); // figure out a good default number (or don't set a default) + } + + // todo: make sure gpio are set correctly after this + I2Cdev::writeBitW(devAddr, A1846S_CTL_REG, A1846S_TX_MODE_BIT, on_noff); + + +} +bool HAMShield::getTX(){ + I2Cdev::readBitW(devAddr, A1846S_CTL_REG, A1846S_TX_MODE_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +void HAMShield::setRX(bool on_noff){ + // make sure TX is off + if (on_noff) { + setTX(false); + + // set TX output off + setGpioHi(5); // remember that RX and TX are active low + // set RX output on + setGpioLow(4); // remember that RX and TX are active low + } + + I2Cdev::writeBitW(devAddr, A1846S_CTL_REG, A1846S_RX_MODE_BIT, on_noff); +} +bool HAMShield::getRX(){ + I2Cdev::readBitW(devAddr, A1846S_CTL_REG, A1846S_RX_MODE_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +void HAMShield::setModeTransmit(){ + // check to see if we should allow them to do this + if(restrictions == true) { + if((radio_frequency > 139999) & (radio_frequency < 148001)) { setRX(false); setTX(true); } + if((radio_frequency > 218999) & (radio_frequency < 225001)) { setRX(false); setTX(true); } + if((radio_frequency > 419999) & (radio_frequency < 450001)) { setRX(false); setTX(true); } + } else { + // turn off rx, turn on tx + setRX(false); // break before make + setTX(true); } +} +void HAMShield::setModeReceive(){ + // turn on rx, turn off tx + setTX(false); // break before make + setRX(true); +} +void HAMShield::setModeOff(){ + // turn off rx, turn off tx, set pwr_dwn bit + setTX(false); + setRX(false); +} + +// set tx source +// 00 - Mic source +// 01 - sine source from tone2 +// 10 - tx code from GPIO1 code_in (gpio1<1:0> must be set to 01) +// 11 - no tx source +void HAMShield::setTxSource(uint16_t tx_source){ + I2Cdev::writeBitsW(devAddr, A1846S_TX_VOICE_REG, A1846S_VOICE_SEL_BIT, A1846S_VOICE_SEL_LENGTH, tx_source); +} +void HAMShield::setTxSourceMic(){ + setTxSource(0); +} +void HAMShield::setTxSourceSine(){ + setTxSource(1); +} +void HAMShield::setTxSourceCode(){ + // note, also set GPIO1 to 01 + setGpioMode(1, 1); + + setTxSource(2); +} +void HAMShield::setTxSourceNone(){ + setTxSource(3); +} +uint16_t HAMShield::getTxSource(){ + I2Cdev::readBitsW(devAddr, A1846S_TX_VOICE_REG, A1846S_VOICE_SEL_BIT, A1846S_VOICE_SEL_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// set PA_bias voltage +// 000000: 1.01V +// 000001:1.05V +// 000010:1.09V +// 000100: 1.18V +// 001000: 1.34V +// 010000: 1.68V +// 100000: 2.45V +// 1111111:3.13V +void HAMShield::setPABiasVoltage(uint16_t voltage){ + I2Cdev::writeBitsW(devAddr, A1846S_PABIAS_REG, A1846S_PABIAS_BIT, A1846S_PABIAS_LENGTH, voltage); +} +uint16_t HAMShield::getPABiasVoltage(){ + I2Cdev::readBitsW(devAddr, A1846S_PABIAS_REG, A1846S_PABIAS_BIT, A1846S_PABIAS_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// Subaudio settings +// TX and RX code +/* + Set code mode: + Step1: set 58H[1:0]=11 set voice hpf bypass + Step2: set 58H[5:3]=111 set voice lpf bypass and pre/de-emph bypass + Step3 set 3CH[15:14]=10 set code mode + Step4: set 1FH[3:2]=01 set GPIO code in or code out + + TX code mode: + Step1: 45H[2:0]=010 + + RX code mode: + Step1: set 45H[2:0]=001 + Step2: set 4dH[15:10]=000001 +*/ + +// Ctcss/cdcss mode sel +// x00=disable, +// 001=inner ctcss en, +// 010= inner cdcss en +// 101= outer ctcss en, +// 110=outer cdcss en +// others =disable +void HAMShield::setCtcssCdcssMode(uint16_t mode){ + I2Cdev::writeBitsW(devAddr, A1846S_SUBAUDIO_REG, A1846S_C_MODE_BIT, A1846S_C_MODE_LENGTH, mode); +} +uint16_t HAMShield::getCtcssCdcssMode(){ + I2Cdev::readBitsW(devAddr, A1846S_SUBAUDIO_REG, A1846S_C_MODE_BIT, A1846S_C_MODE_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setInnerCtcssMode(){ + setCtcssCdcssMode(1); +} +void HAMShield::setInnerCdcssMode(){ + setCtcssCdcssMode(2); +} +void HAMShield::setOuterCtcssMode(){ + setCtcssCdcssMode(5); +} +void HAMShield::setOuterCdcssMode(){ + setCtcssCdcssMode(6); +} +void HAMShield::disableCtcssCdcss(){ + setCtcssCdcssMode(0); +} + +// Ctcss_sel +// 1 = ctcss_cmp/cdcss_cmp out via gpio +// 0 = ctcss/cdcss sdo out vio gpio +void HAMShield::setCtcssSel(bool cmp_nsdo){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_CTCSS_SEL_BIT, cmp_nsdo); +} +bool HAMShield::getCtcssSel(){ + I2Cdev::readBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_CTCSS_SEL_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// Cdcss_sel +// 1 = long (24 bit) code +// 0 = short(23 bit) code +void HAMShield::setCdcssSel(bool long_nshort){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_CDCSS_SEL_BIT, long_nshort); +} +bool HAMShield::getCdcssSel(){ + I2Cdev::readBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_CDCSS_SEL_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// Cdcss neg_det_en +void HAMShield::enableCdcssNegDet(){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_NEG_DET_EN_BIT, 1); +} +void HAMShield::disableCdcssNegDet(){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_NEG_DET_EN_BIT, 0); +} +bool HAMShield::getCdcssNegDetEnabled(){ + I2Cdev::readBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_NEG_DET_EN_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// Cdcss pos_det_en +void HAMShield::enableCdcssPosDet(){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_POS_DET_EN_BIT, 1); +} +void HAMShield::disableCdcssPosDet(){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_POS_DET_EN_BIT, 0); +} +bool HAMShield::getCdcssPosDetEnabled(){ + I2Cdev::readBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_POS_DET_EN_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// css_det_en +void HAMShield::enableCssDet(){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_CSS_DET_EN_BIT, 1); +} +void HAMShield::disableCssDet(){ + I2Cdev::writeBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_CSS_DET_EN_BIT, 0); +} +bool HAMShield::getCssDetEnabled(){ + I2Cdev::readBitW(devAddr, A1846S_SUBAUDIO_REG, A1846S_CSS_DET_EN_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// ctcss freq +void HAMShield::setCtcss(float freq) { + int dfreq = freq / 10000; + dfreq = dfreq * 65536; + setCtcssFreq(dfreq); +} + +void HAMShield::setCtcssFreq(uint16_t freq){ + I2Cdev::writeWord(devAddr, A1846S_CTCSS_FREQ_REG, freq); +} +uint16_t HAMShield::getCtcssFreq(){ + I2Cdev::readWord(devAddr, A1846S_CTCSS_FREQ_REG, radio_i2c_buf); + + return radio_i2c_buf[0]; +} +void HAMShield::setCtcssFreqToStandard(){ + // freq must be 134.4Hz for standard cdcss mode + setCtcssFreq(0x2268); +} + +// cdcss codes +void HAMShield::setCdcssCode(uint16_t code) { + // note: assuming a well formed code (xyz, where x, y, and z are all 0-7) + + // Set both code registers at once (23 or 24 bit code) + // sends 100, c1, c2, c3, 11 bits of crc + + // TODO: figure out what to do about 24 or 23 bit codes + + uint32_t cdcss_code = 0x800000; // top three bits are 100 + uint32_t oct_code = code%10; + code = code / 10; + cdcss_code += oct_code << 20; + oct_code = code % 10; + code = code / 10; + cdcss_code += oct_code << 17; + cdcss_code += (code % 10) << 14; + + // TODO: CRC + + // set registers + uint16_t temp_code = (uint16_t) cdcss_code; + I2Cdev::writeWord(devAddr, A1846S_CDCSS_CODE_HI_REG, temp_code); + temp_code = (uint16_t) (cdcss_code >> 16); + I2Cdev::writeWord(devAddr, A1846S_CDCSS_CODE_LO_REG, temp_code); +} +uint16_t HAMShield::getCdcssCode() { + uint32_t oct_code; + I2Cdev::readWord(devAddr, A1846S_CDCSS_CODE_HI_REG, radio_i2c_buf); + oct_code = (radio_i2c_buf[0] << 16); + I2Cdev::readWord(devAddr, A1846S_CDCSS_CODE_LO_REG, radio_i2c_buf); + oct_code += radio_i2c_buf[0]; + + oct_code = oct_code >> 12; + uint16_t code = (oct_code & 0x3); + oct_code = oct_code >> 3; + code += (oct_code & 0x3)*10; + oct_code = oct_code >> 3; + code += (oct_code & 0x3)*100; + + return code; +} + +// SQ +void HAMShield::setSQOn(){ + I2Cdev::writeBitW(devAddr, A1846S_CTL_REG, A1846S_SQ_ON_BIT, 1); +} +void HAMShield::setSQOff(){ + I2Cdev::writeBitW(devAddr, A1846S_CTL_REG, A1846S_SQ_ON_BIT, 0); +} +bool HAMShield::getSQState(){ + I2Cdev::readBitW(devAddr, A1846S_CTL_REG, A1846S_SQ_ON_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// SQ threshold +void HAMShield::setSQHiThresh(uint16_t sq_hi_threshold){ + // Sq detect high th, rssi_cmp will be 1 when rssi>th_h_sq, unit 1/8dB + I2Cdev::writeWord(devAddr, A1846S_SQ_OPEN_THRESH_REG, sq_hi_threshold); +} +uint16_t HAMShield::getSQHiThresh(){ + I2Cdev::readWord(devAddr, A1846S_SQ_OPEN_THRESH_REG, radio_i2c_buf); + + return radio_i2c_buf[0]; +} +void HAMShield::setSQLoThresh(uint16_t sq_lo_threshold){ + // Sq detect low th, rssi_cmp will be 0 when rssi th_h_vox, then vox will be 1(unit mV ) + I2Cdev::writeWord(devAddr, A1846S_TH_H_VOX_REG, vox_open_thresh); +} +uint16_t HAMShield::getVoxOpenThresh(){ + I2Cdev::readWord(devAddr, A1846S_TH_H_VOX_REG, radio_i2c_buf); + + return radio_i2c_buf[0]; +} +void HAMShield::setVoxShutThresh(uint16_t vox_shut_thresh){ + // When vssi < th_l_vox && time delay meet, then vox will be 0 (unit mV ) + I2Cdev::writeWord(devAddr, A1846S_TH_L_VOX_REG, vox_shut_thresh); +} +uint16_t HAMShield::getVoxShutThresh(){ + I2Cdev::readWord(devAddr, A1846S_TH_L_VOX_REG, radio_i2c_buf); + + return radio_i2c_buf[0]; +} + +// Tail Noise +void HAMShield::enableTailNoiseElim(){ + I2Cdev::writeBitW(devAddr, A1846S_CTL_REG, A1846S_TAIL_ELIM_EN_BIT, 1); +} +void HAMShield::disableTailNoiseElim(){ + I2Cdev::writeBitW(devAddr, A1846S_CTL_REG, A1846S_TAIL_ELIM_EN_BIT, 1); +} +bool HAMShield::getTailNoiseElimEnabled(){ + I2Cdev::readBitW(devAddr, A1846S_CTL_REG, A1846S_TAIL_ELIM_EN_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// tail noise shift select +// Select ctcss phase shift when use tail eliminating function when TX +// 00 = 120 degree shift +// 01 = 180 degree shift +// 10 = 240 degree shift +// 11 = reserved +void HAMShield::setShiftSelect(uint16_t shift_sel){ + I2Cdev::writeBitsW(devAddr, A1846S_SUBAUDIO_REG, A1846S_SHIFT_SEL_BIT, A1846S_SHIFT_SEL_LENGTH, shift_sel); +} +uint16_t HAMShield::getShiftSelect(){ + I2Cdev::readBitsW(devAddr, A1846S_SUBAUDIO_REG, A1846S_SHIFT_SEL_BIT, A1846S_SHIFT_SEL_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// DTMF +void HAMShield::setDTMFC0(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C01_REG, A1846S_DTMF_C0_BIT, A1846S_DTMF_C0_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC0() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C01_REG, A1846S_DTMF_C0_BIT, A1846S_DTMF_C0_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setDTMFC1(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C01_REG, A1846S_DTMF_C1_BIT, A1846S_DTMF_C1_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC1() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C01_REG, A1846S_DTMF_C1_BIT, A1846S_DTMF_C1_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setDTMFC2(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C23_REG, A1846S_DTMF_C2_BIT, A1846S_DTMF_C2_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC2() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C23_REG, A1846S_DTMF_C2_BIT, A1846S_DTMF_C2_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setDTMFC3(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C23_REG, A1846S_DTMF_C3_BIT, A1846S_DTMF_C3_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC3() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C23_REG, A1846S_DTMF_C3_BIT, A1846S_DTMF_C3_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setDTMFC4(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C45_REG, A1846S_DTMF_C4_BIT, A1846S_DTMF_C4_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC4() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C45_REG, A1846S_DTMF_C4_BIT, A1846S_DTMF_C4_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setDTMFC5(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C45_REG, A1846S_DTMF_C5_BIT, A1846S_DTMF_C5_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC5() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C45_REG, A1846S_DTMF_C5_BIT, A1846S_DTMF_C5_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setDTMFC6(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C67_REG, A1846S_DTMF_C6_BIT, A1846S_DTMF_C6_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC6() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C67_REG, A1846S_DTMF_C6_BIT, A1846S_DTMF_C6_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setDTMFC7(uint16_t freq) { + I2Cdev::writeBitsW(devAddr, A1846S_DTMF_C67_REG, A1846S_DTMF_C7_BIT, A1846S_DTMF_C7_LENGTH, freq); +} +uint16_t HAMShield::getDTMFC7() { + I2Cdev::readBitsW(devAddr, A1846S_DTMF_C67_REG, A1846S_DTMF_C7_BIT, A1846S_DTMF_C7_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// TX FM deviation +void HAMShield::setFMVoiceCssDeviation(uint16_t deviation){ + I2Cdev::writeBitsW(devAddr, A1846S_FM_DEV_REG, A1846S_FM_DEV_VOICE_BIT, A1846S_FM_DEV_VOICE_LENGTH, deviation); +} +uint16_t HAMShield::getFMVoiceCssDeviation(){ + I2Cdev::readBitsW(devAddr, A1846S_FM_DEV_REG, A1846S_FM_DEV_VOICE_BIT, A1846S_FM_DEV_VOICE_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setFMCssDeviation(uint16_t deviation){ + I2Cdev::writeBitsW(devAddr, A1846S_FM_DEV_REG, A1846S_FM_DEV_CSS_BIT, A1846S_FM_DEV_CSS_LENGTH, deviation); +} +uint16_t HAMShield::getFMCssDeviation(){ + I2Cdev::readBitsW(devAddr, A1846S_FM_DEV_REG, A1846S_FM_DEV_CSS_BIT, A1846S_FM_DEV_CSS_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// RX voice range +void HAMShield::setVolume1(uint16_t volume){ + I2Cdev::writeBitsW(devAddr, A1846S_RX_VOLUME_REG, A1846S_RX_VOL_1_BIT, A1846S_RX_VOL_1_LENGTH, volume); +} +uint16_t HAMShield::getVolume1(){ + I2Cdev::readBitsW(devAddr, A1846S_RX_VOLUME_REG, A1846S_RX_VOL_1_BIT, A1846S_RX_VOL_1_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setVolume2(uint16_t volume){ + I2Cdev::writeBitsW(devAddr, A1846S_RX_VOLUME_REG, A1846S_RX_VOL_2_BIT, A1846S_RX_VOL_2_LENGTH, volume); +} +uint16_t HAMShield::getVolume2(){ + I2Cdev::readBitsW(devAddr, A1846S_RX_VOLUME_REG, A1846S_RX_VOL_2_BIT, A1846S_RX_VOL_2_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// GPIO +void HAMShield::setGpioMode(uint16_t gpio, uint16_t mode){ + uint16_t mode_len = 2; + uint16_t bit = gpio*2 + 1; + + I2Cdev::writeBitsW(devAddr, A1846S_GPIO_MODE_REG, bit, mode_len, mode); +} +void HAMShield::setGpioHiZ(uint16_t gpio){ + setGpioMode(gpio, 0); +} +void HAMShield::setGpioFcn(uint16_t gpio){ + setGpioMode(gpio, 1); +} +void HAMShield::setGpioLow(uint16_t gpio){ + setGpioMode(gpio, 2); +} +void HAMShield::setGpioHi(uint16_t gpio){ + setGpioMode(gpio, 3); +} +uint16_t HAMShield::getGpioMode(uint16_t gpio){ + uint16_t mode_len = 2; + uint16_t bit = gpio*2 + 1; + + I2Cdev::readBitsW(devAddr, A1846S_GPIO_MODE_REG, bit, mode_len, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +// Int +void HAMShield::enableInterrupt(uint16_t interrupt){ + I2Cdev::writeBitW(devAddr, A1846S_INT_MODE_REG, interrupt, 1); +} +void HAMShield::disableInterrupt(uint16_t interrupt){ + I2Cdev::writeBitW(devAddr, A1846S_INT_MODE_REG, interrupt, 0); +} +bool HAMShield::getInterruptEnabled(uint16_t interrupt){ + I2Cdev::readBitW(devAddr, A1846S_INT_MODE_REG, interrupt, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// ST mode +void HAMShield::setStMode(uint16_t mode){ + I2Cdev::writeBitsW(devAddr, A1846S_CTL_REG, A1846S_ST_MODE_BIT, A1846S_ST_MODE_LENGTH, mode); +} +uint16_t HAMShield::getStMode(){ + I2Cdev::readBitsW(devAddr, A1846S_CTL_REG, A1846S_ST_MODE_BIT, A1846S_ST_MODE_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +void HAMShield::setStFullAuto(){ +setStMode(2); +} +void HAMShield::setStRxAutoTxManu(){ +setStMode(1); +} +void HAMShield::setStFullManu(){ +setStMode(0); +} + +// Pre-emphasis, De-emphasis filter +void HAMShield::bypassPreDeEmph(){ + I2Cdev::writeBitW(devAddr, A1846S_EMPH_FILTER_REG, A1846S_EMPH_FILTER_EN, 1); +} +void HAMShield::usePreDeEmph(){ + I2Cdev::writeBitW(devAddr, A1846S_EMPH_FILTER_REG, A1846S_EMPH_FILTER_EN, 0); +} +bool HAMShield::getPreDeEmphEnabled(){ + I2Cdev::readBitW(devAddr, A1846S_EMPH_FILTER_REG, A1846S_EMPH_FILTER_EN, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} + +// Read Only Status Registers +int16_t HAMShield::readRSSI(){ + I2Cdev::readWord(devAddr, A1846S_RSSI_REG, radio_i2c_buf); + + int16_t rssi = (radio_i2c_buf[0] & 0x3FF) / 8 - 135; + return rssi; // only need lowest 10 bits +} +uint16_t HAMShield::readVSSI(){ + I2Cdev::readWord(devAddr, A1846S_VSSI_REG, radio_i2c_buf); + + return radio_i2c_buf[0] & 0x7FF; // only need lowest 10 bits +} +uint16_t HAMShield::readDTMFIndex(){ +// TODO: may want to split this into two (index1 and index2) + I2Cdev::readBitsW(devAddr, A1846S_DTMF_RX_REG, A1846S_DTMF_INDEX_BIT, A1846S_DTMF_INDEX_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} +uint16_t HAMShield::readDTMFCode(){ +// 1:f0+f4, 2:f0+f5, 3:f0+f6, A:f0+f7, +// 4:f1+f4, 5:f1+f5, 6:f1+f6, B:f1+f7, +// 7:f2+f4, 8:f2+f5, 9:f2+f6, C:f2+f7, +// E(*):f3+f4, 0:f3+f5, F(#):f3+f6, D:f3+f7 + I2Cdev::readBitsW(devAddr, A1846S_DTMF_RX_REG, A1846S_DTMF_CODE_BIT, A1846S_DTMF_CODE_LENGTH, radio_i2c_buf); + return radio_i2c_buf[0]; +} + +void HAMShield::setRfPower(uint8_t pwr) { + + // using loop reference voltage input to op-amp + // (see RF6886 datasheet) + // 30 is 0.5V, which is ~min loop reference voltage + // 127 is 2.5V, which is ~max loop ref voltage + int max_pwr = 255; //167; // 167 is 3.3*255/5 - 1; + if (pwr > max_pwr) { + pwr = max_pwr; + } + + + // using open loop reference voltage into Vreg1/2 + /*int max_pwr = 78; // 78 = 1.58*255/5 - 1 + if (pwr > max_pwr) { + pwr = max_pwr; + }*/ + // using loop ref voltage as specified in RF6886 datasheet + // analogWrite(pwr_control_pin, pwr); +} + + +bool HAMShield::frequency(uint32_t freq_khz) { + if((freq_khz >= 137000) && (freq_khz <= 174000)) { + setVHF(); + setBand(3); // 0b11 is 134-174MHz + setFrequency(freq_khz); + return true; + } + + if((freq_khz >= 200000) && (freq_khz <= 260000)) { + setVHF(); + setBand(2); // 10 is 200-260MHz + setFrequency(freq_khz); + return true; + } + + if((freq_khz >= 400000) && (freq_khz <= 520000)) { + setUHF(); + setBand(00); // 00 is 400-520MHz + setFrequency(freq_khz); + return true; + } + return false; +} + +/* FRS Lookup Table */ + +bool HAMShield::setFRSChannel(uint8_t channel) { + if(channel < 15) { + setFrequency(FRS[channel]); + return true; + } + return false; +} + +/* GMRS Lookup Table (borrows from FRS table since channels overlap) */ + +bool HAMShield::setGMRSChannel(uint8_t channel) { + if((channel > 8) & (channel < 16)) { + channel = channel - 7; // we start with 0, to try to avoid channel 8 being nothing + setFrequency(FRS[channel]); + return true; + } + if(channel < 9) { + setFrequency(GMRS[channel]); + return true; + } + return false; +} + +/* MURS band is 11.25KHz (2.5KHz dev) in channel 1-3, 20KHz (5KHz dev) in channel 4-5. Should we set this? */ + +bool HAMShield::setMURSChannel(uint8_t channel) { + if(channel < 6) { + setFrequency(MURS[channel]); + return true; + } +} + +/* Weather radio channels */ + +bool HAMShield::setWXChannel(uint8_t channel) { + if(channel < 8) { + setFrequency(WX[channel]); + setModeReceive(); + // turn off squelch? + // channel bandwidth? + return true; + } + return false; +} + +/* Scan channels for strongest signal. returns channel number. You could do radio.setWXChannel(radio.scanWXChannel()) */ + +uint8_t HAMShield::scanWXChannel() { + uint8_t channel = 0; + int16_t toprssi = 0; + for(int x = 0; x < 8; x++) { + setWXChannel(x); + delay(100); + int16_t rssi = readRSSI(); + if(rssi > toprssi) { toprssi = rssi; channel = x; } + } + return channel; +} + + +/* removes the out of band transmit restrictions for those who hold special licenses */ + +void HAMShield::dangerMode() { + restrictions = false; + return; +} + +/* enable restrictions on out of band transmissions */ + +void HAMShield::safeMode() { + restrictions = true; + return; +} + +/* scanner mode. Scans a range and returns the active frequency when it detects a signal. If none is detected, returns 0. */ + +uint32_t HAMShield::scanMode(uint32_t start,uint32_t stop, uint8_t speed, uint16_t step, uint16_t threshold) { + setModeReceive(); + int16_t rssi = -150; + for(uint32_t freq = start; freq < stop; freq = freq + step) { + setFrequency(freq); + for(int x = 0; x < speed; x++) { + rssi = readRSSI(); + if(rssi > threshold) { return freq; } + } + } + return 0; // found nothing +} + +/* white space finder. (inverted scanner) Scans a range for a white space, and if no signal exists, stop there. */ + +uint32_t HAMShield::findWhitespace(uint32_t start,uint32_t stop, uint8_t dwell, uint16_t step, uint16_t threshold) { + setModeReceive(); + int16_t rssi = -150; + for(uint32_t freq = start; freq < stop; freq = freq + step) { + setFrequency(freq); + for(int x = 0; x < dwell; x++) { + rssi = readRSSI(); + if(rssi > threshold) { break; } + } + if(rssi < threshold) { return freq; } /* found a blank channel */ + } + return 0; // everything is busy +} + +/* +channel scanner. Scans an array of channels for activity. returns channel number if found. Otherwise, returns 0. ignores whatever is in array position +0 +*/ + +uint32_t HAMShield::scanChannels(uint32_t buffer[],uint8_t buffsize, uint8_t speed, uint16_t threshold) { + setModeReceive(); + int16_t rssi = 0; + for(int x = 1; x < buffsize; x++) { + setFrequency(buffer[x]); + for(int y = 0; y < speed; y++) { + rssi = readRSSI(); + if(rssi > threshold) { return x; } + } + } + return 0; + +} + +/* +white space channel finder. Scans an array of channels for white space. returns channel number if empty found. Otherwise, returns 0. ignores whatever is in array position +0 +*/ + +uint32_t HAMShield::findWhitespaceChannels(uint32_t buffer[],uint8_t buffsize, uint8_t dwell, uint16_t threshold) { + setModeReceive(); + int16_t rssi = 0; + for(int x = 1; x < buffsize; x++) { + setFrequency(buffer[x]); + for(int y = 0; y < dwell; y++) { + rssi = readRSSI(); + if(rssi > threshold) { break; } + } + if(rssi < threshold) { return x; } /* found a blank channel */ + } + return 0; // everything is busy +} + + +/* +BUG: I cannot figure out how to attach these interrupt handlers without the error: + +/Users/casey/Documents/Arduino/libraries/HAMShield/HAMShield.cpp: In member function 'void HAMShield::buttonMode(uint8_t)': +/Users/casey/Documents/Arduino/libraries/HAMShield/HAMShield.cpp:1125: error: argument of type 'void (HAMShield::)()' does not match 'void (*)()' +/Users/casey/Documents/Arduino/libraries/HAMShield/HAMShield.cpp:1126: error: argument of type 'void (HAMShield::)()' does not match 'void (*)()' +*/ + + +/* +void HAMShield::buttonMode(uint8_t mode) { + pinMode(HAMSHIELD_AUX_BUTTON,INPUT); // set the pin mode to input + digitalWrite(HAMSHIELD_AUX_BUTTON,HIGH); // turn on internal pull up + if(mode == PTT_MODE) { attachInterrupt(HAMSHIELD_AUX_BUTTON, isr_ptt, CHANGE); } + if(mode == RESET_MODE) { attachInterrupt(HAMSHIELD_AUX_BUTTON, isr_reset, CHANGE); } +} +*/ + +/* Interrupt routines */ + +/* handle aux button to reset condition */ + +void HAMShield::isr_reset() { + wdt_enable(WDTO_15MS); + while(1) { } +} + +/* Transmit on press, receive on release. We need debouncing !! */ + +void HAMShield::isr_ptt() { + if((bouncer + 200) > millis()) { + if(ptt == false) { + ptt = true; + HAMShield::setModeTransmit(); + bouncer = millis(); + } + if(ptt == true) { + ptt = false; + HAMShield::setModeReceive(); + bouncer = millis(); + } } +} + +/* + + Radio etiquette function: Wait for empty channel. + + Optional timeout (0 waits forever) + Optional break window (how much dead air to wait for after a transmission completes) + +Does not take in account the millis() overflow + +*/ + +bool HAMShield::waitForChannel(long timeout = 0, long breakwindow = 0) { + int16_t rssi = 0; // Set RSSI to max received signal + for(int x = 0; x < 20; x++) { rssi = readRSSI(); } // "warm up" to get past RSSI hysteresis + long timer = millis() + timeout; // Setup the timeout value + if(timeout == 0) { timer = 4294967295; } // If we want to wait forever, set it to the max millis() + while(timer > millis()) { // while our timer is not timed out. + rssi = readRSSI(); // Read signal strength + if(rssi < HAMSHIELD_EMPTY_CHANNEL_RSSI) { // If the channel is empty, lets see if anyone breaks in. + timer = millis() + breakwindow; + while(timer > millis()) { + rssi = readRSSI(); + if(rssi > HAMSHIELD_EMPTY_CHANNEL_RSSI) { return false; } // Someone broke into the channel, abort. + } return true; // It passed the test...channel is open. + } + } + return false; +} + + +/* Morse code out, blocking */ + +void HAMShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) { + + for(int x = 0; x < strlen(buffer); x++) { + char output = morseLookup(buffer[x]); + if(buffer[x] != ' ') { + for(int m = 0; m < strlen(itu[output]); m++) { + if(itu[output][m] == '-') { tone(HAMSHIELD_PWM_PIN,1000,HAMSHIELD_MORSE_DOT*3); delay(HAMSHIELD_MORSE_DOT*3); } + else { tone(HAMSHIELD_PWM_PIN,1000,HAMSHIELD_MORSE_DOT); delay(HAMSHIELD_MORSE_DOT); } + delay(HAMSHIELD_MORSE_DOT); + } + delay(HAMSHIELD_MORSE_DOT*3); + } else { delay(HAMSHIELD_MORSE_DOT*7); } + } + return; +} + +/* Morse code lookup table */ + +char HAMShield::morseLookup(char letter) { + for(int x = 0; x < 54; x++) { + if(letter == ascii[x]) { + return x; + // return itu[x]; + } + } +} + +/* + +SSTV VIS Digital Header + +Reference: http://www.barberdsp.com/files/Dayton%20Paper.pdf + +Millis Freq Description +----------------------------------------------- +300 1900 Leader tone +10 1200 break +300 1900 Leader tone +30 1200 VIS start bit +30 bit 0 1100hz = “1”, 1300hz = “0” +30 bit 1 “” +30 bit 2 “” +30 bit 3 “” +30 bit 4 “” +30 bit 5 “” +30 bit 6 “” +30 PARITY Even=1300hz,Odd=1100hz +30 1200 VIS stop bit + +*/ + +void HAMShield::SSTVVISCode(int code) { + toneWait(1900,300); + toneWait(1200,10); + toneWait(1900,300); + toneWait(1200,30); + for(int x = 0; x < 7; x++) { + if(bitRead(code,x)) { toneWait(1100,30); } else { toneWait(1300,30); } + } + if(parityCalc(code)) { toneWait(1300,30); } else { toneWait(1100,30); } + toneWait(1200,30); + return; +} + +/* + +SSTV Test Pattern +Print 6 color bars +MARTIN1 is only supported for this +Reference: http://www.barberdsp.com/files/Dayton%20Paper.pdf + +*/ + +void HAMShield::SSTVTestPattern(int code) { + SSTVVISCode(code); + if(code == MARTIN1) { + for(int x = 0; x < 257; x++){ + + toneWaitU(1200,4862); // sync pulse (4862 uS) + toneWaitU(1500,572); // sync porch (572 uS) + + /* Green Channel - 146.432ms a line (we are doing 144ms) */ + + toneWait(2400,24); + toneWait(2400,24); + toneWait(2400,24); + toneWait(2400,24); + toneWait(1500,24); + toneWait(1500,24); + + toneWaitU(1500,572); // color separator pulse (572 uS) + + /* Blue Channel - 146.432ms a line (we are doing 144ms) */ + + toneWait(2400,24); + toneWait(1500,24); + toneWait(2400,24); + toneWait(1500,24); + toneWait(1500,24); + toneWait(2400,24); + + toneWaitU(1500,572); // color separator pulse (572 uS) + + /* Red Channel - 146.432ms a line (we are doing 144ms) */ + + toneWait(2400,24); + toneWait(2400,24); + toneWait(1500,24); + toneWait(1500,24); + toneWait(2400,24); + toneWait(1500,24); + + toneWaitU(1500,572); // color separator pulse (572 uS) + } + } +} + +/* wait for tone to complete */ + +void HAMShield::toneWait(uint16_t freq, long timer) { + tone(HAMSHIELD_PWM_PIN,freq,timer); + delay(timer); +} + +/* wait microseconds for tone to complete */ + +void HAMShield::toneWaitU(uint16_t freq, long timer) { + if(freq < 16383) { + tone(HAMSHIELD_PWM_PIN,freq); + delayMicroseconds(timer); noTone(HAMSHIELD_PWM_PIN); return; + } + tone(HAMSHIELD_PWM_PIN,freq); + delay(timer / 1000); noTone(HAMSHIELD_PWM_PIN); return; +} + + +bool HAMShield::parityCalc(int code) { + unsigned int v; // word value to compute the parity of + bool parity = false; // parity will be the parity of v + + while (code) + { + parity = !parity; + code = code & (code - 1); + } + + return parity; +} +/* +void HAMShield::AFSKOut(char buffer[80]) { + for(int x = 0; x < 65536; x++) { + startPlayback(AFSK_mark, sizeof(AFSK_mark)); delay(8); + startPlayback(AFSK_space, sizeof(AFSK_space)); delay(8); } + +} +*/ \ No newline at end of file diff --git a/src/HamShield.h b/src/HamShield.h new file mode 100644 index 0000000..84775c6 --- /dev/null +++ b/src/HamShield.h @@ -0,0 +1,554 @@ +// HAMShield library collection +// Based on Programming Manual rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 11/22/2013 by Morgan Redfield +// 04/26/2015 various changes Casey Halverson + + + +#ifndef _HAMSHIELD_H_ +#define _HAMSHIELD_H_ + +#include "I2Cdev_rda.h" +#include + +// HAMShield constants + +#define HAMSHIELD_MORSE_DOT 100 // Morse code dot length (smaller is faster WPM) +#define HAMSHIELD_MORSE_BUFFER_SIZE 80 // Char buffer size for morse code text +#define HAMSHIELD_AUX_BUTTON 5 // Pin assignment for AUX button +#define HAMSHIELD_PWM_PIN 9 // Pin assignment for PWM output +#define HAMSHIELD_EMPTY_CHANNEL_RSSI -110 // Threshold where channel is considered "clear" + +// button modes +#define PTT_MODE 1 +#define RESET_MODE 2 + +// Device Constants +#define A1846S_DEV_ADDR_SENHIGH 0b0101110 +#define A1846S_DEV_ADDR_SENLOW 0b1110001 + + +// Device Registers +#define A1846S_CTL_REG 0x30 // control register +#define A1846S_CLK_MODE_REG 0x04 // clk_mode +#define A1846S_PABIAS_REG 0x0A // control register for bias voltage +#define A1846S_BAND_SEL_REG 0x0F // band_sel register <1:0> +#define A1846S_GPIO_MODE_REG 0x1F // GPIO mode select register +#define A1846S_FREQ_HI_REG 0x29 // freq<29:16> +#define A1846S_FREQ_LO_REG 0x2A // freq<15:0> +#define A1846S_XTAL_FREQ_REG 0x2B // xtal_freq<15:0> +#define A1846S_ADCLK_FREQ_REG 0x2C // adclk_freq<15:0> +#define A1846S_INT_MODE_REG 0x2D // interrupt enables +#define A1846S_TX_VOICE_REG 0x3C // tx voice control reg +#define A1846S_TH_H_VOX_REG 0x41 // register holds vox high (open) threshold bits +#define A1846S_TH_L_VOX_REG 0x42 // register holds vox low (shut) threshold bits +#define A1846S_FM_DEV_REG 0x43 // register holds fm deviation settings +#define A1846S_RX_VOLUME_REG 0x44 // register holds RX volume settings +#define A1846S_SUBAUDIO_REG 0x45 // sub audio register +#define A1846S_SQ_OPEN_THRESH_REG 0x48 // see sq +#define A1846S_SQ_SHUT_THRESH_REG 0x49 // see sq +#define A1846S_CTCSS_FREQ_REG 0x4A // ctcss_freq<15:0> +#define A1846S_CDCSS_CODE_HI_REG 0x4B // cdcss_code<23:16> +#define A1846S_CDCSS_CODE_LO_REG 0x4C // cdccs_code<15:0> +#define A1846S_SQ_OUT_SEL_REG 0x54 // see sq +#define A1846S_EMPH_FILTER_REG 0x58 +#define A1846S_FLAG_REG 0x5C // holds flags for different statuses +#define A1846S_RSSI_REG 0x5F // holds RSSI (unit 1/8dB) +#define A1846S_VSSI_REG 0x60 // holds VSSI (unit mV) +#define A1846S_DTMF_CTL_REG 0x63 // see dtmf +#define A1846S_DTMF_C01_REG 0x66 // holds frequency value for c0 and c1 +#define A1846S_DTMF_C23_REG 0x67 // holds frequency value for c2 and c3 +#define A1846S_DTMF_C45_REG 0x68 // holds frequency value for c4 and c5 +#define A1846S_DTMF_C67_REG 0x69 // holds frequency value for c6 and c7 +#define A1846S_DTMF_RX_REG 0x6C // received dtmf signal + +// NOTE: could add registers and bitfields for dtmf tones, is this necessary? + + +// Device Bit Fields + +// Bitfields for A1846S_CTL_REG +#define A1846S_CHAN_MODE_BIT 13 //channel_mode<1:0> +#define A1846S_CHAN_MODE_LENGTH 2 +#define A1846S_TAIL_ELIM_EN_BIT 11 // enables tail elim when set to 1 +#define A1846S_ST_MODE_BIT 9 // set mode for txon and rxon +#define A1846S_ST_MODE_LENGTH 2 +#define A1846S_MUTE_BIT 7 // 0 no mute, 1 mute when rxno +#define A1846S_TX_MODE_BIT 6 //tx-on +#define A1846S_RX_MODE_BIT 5 //rx-on +#define A1846S_VOX_ON_BIT 4 // 0 off, 1 on and chip auto-vox +#define A1846S_SQ_ON_BIT 3 // auto sq enable bit +#define A1846S_PWR_DWN_BIT 2 // power control bit +#define A1846S_CHIP_CAL_EN_BIT 1 // 0 cal disable, 1 cal enable +#define A1846S_SOFT_RESET_BIT 0 // 0 normal value, 1 reset all registers to normal value + +// Bitfields for A1846S_CLK_MODE_REG +#define A1846S_CLK_MODE_BIT 0 // 0 24-28MHz, 1 12-14MHz + +// Bitfields for A1846S_PABIAS_REG +#define A1846S_PABIAS_BIT 5 // pabias_voltage<5:0> +#define A1846S_PABIAS_LENGTH 6 + +// Bitfields for A1846S_BAND_SEL_REG +#define A1846S_BAND_SEL_BIT 7 // band_sel<1:0> +#define A1846S_BAND_SEL_LENGTH 2 + +// Bitfields for RDA1864_GPIO_MODE_REG +#define RDA1864_GPIO7_MODE_BIT 15 // <1:0> 00=hi-z,01=vox,10=low,11=hi +#define RDA1864_GPIO7_MODE_LENGTH 2 +#define RDA1864_GPIO6_MODE_BIT 13 // <1:0> 00=hi-z,01=sq or =sq&ctcss/cdcss when sq_out_sel=1,10=low,11=hi +#define RDA1864_GPIO6_MODE_LENGTH 2 +#define RDA1864_GPIO5_MODE_BIT 11 // <1:0> 00=hi-z,01=txon_rf,10=low,11=hi +#define RDA1864_GPIO5_MODE_LENGTH 2 +#define RDA1864_GPIO4_MODE_BIT 9 // <1:0> 00=hi-z,01=rxon_rf,10=low,11=hi +#define RDA1864_GPIO4_MODE_LENGTH 2 +#define RDA1864_GPIO3_MODE_BIT 7 // <1:0> 00=hi-z,01=sdo,10=low,11=hi +#define RDA1864_GPIO3_MODE_LENGTH 2 +#define RDA1864_GPIO2_MODE_BIT 5 // <1:0> 00=hi-z,01=int,10=low,11=hi +#define RDA1864_GPIO2_MODE_LENGTH 2 +#define RDA1864_GPIO1_MODE_BIT 3 // <1:0> 00=hi-z,01=code_out/code_in,10=low,11=hi +#define RDA1864_GPIO1_MODE_LENGTH 2 +#define RDA1864_GPIO0_MODE_BIT 1 // <1:0> 00=hi-z,01=css_out/css_in/css_cmp,10=low,11=hi +#define RDA1864_GPIO0_MODE_LENGTH 2 + +// Bitfields for A1846S_INT_MODE_REG +#define A1846S_CSS_CMP_INT_BIT 9 // css_cmp_uint16_t enable +#define A1846S_RXON_RF_INT_BIT 8 // rxon_rf_uint16_t enable +#define A1846S_TXON_RF_INT_BIT 7 // txon_rf_uint16_t enable +#define A1846S_DTMF_IDLE_INT_BIT 6 // dtmf_idle_uint16_t enable +#define A1846S_CTCSS_PHASE_INT_BIT 5 // ctcss phase shift detect uint16_t enable +#define A1846S_IDLE_TIMEOUT_INT_BIT 4 // idle state time out uint16_t enable +#define A1846S_RXON_RF_TIMeOUT_INT_BIT 3 // rxon_rf timerout uint16_t enable +#define A1846S_SQ_INT_BIT 2 // sq uint16_t enable +#define A1846S_TXON_RF_TIMEOUT_INT_BIT 1 // txon_rf time out uint16_t enable +#define A1846S_VOX_INT_BIT 0 // vox uint16_t enable + +// Bitfields for A1846S_TX_VOICE_REG +#define A1846S_VOICE_SEL_BIT 15 //voice_sel<1:0> +#define A1846S_VOICE_SEL_LENGTH 2 + +// Bitfields for A1846S_TH_H_VOX_REG +#define A1846S_TH_H_VOX_BIT 14 // th_h_vox<14:0> +#define A1846S_TH_H_VOX_LENGTH 15 + +// Bitfields for A1846S_FM_DEV_REG +#define A1846S_FM_DEV_VOICE_BIT 12 // CTCSS/CDCSS and voice deviation <6:0> +#define A1846S_FM_DEV_VOICE_LENGTH 7 +#define A1846S_FM_DEV_CSS_BIT 5 // CTCSS/CDCSS deviation only <5:0> +#define A1846S_FM_DEV_CSS_LENGTH 6 + +// Bitfields for A1846S_RX_VOLUME_REG +#define A1846S_RX_VOL_1_BIT 7 // volume 1 <3:0>, (0000)-15dB~(1111)0dB, step 1dB +#define A1846S_RX_VOL_1_LENGTH 4 +#define A1846S_RX_VOL_2_BIT 3 // volume 2 <3:0>, (0000)-15dB~(1111)0dB, step 1dB +#define A1846S_RX_VOL_2_LENGTH 4 + +// Bitfields for A1846S_SUBAUDIO_REG Sub Audio Register +#define A1846S_SHIFT_SEL_BIT 15 // shift_sel<1:0> see eliminating tail noise +#define A1846S_SHIFT_SEL_LENGTH 2 +#define A1846S_POS_DET_EN_BIT 11 // if 1, cdcss code will be detected +#define A1846S_CSS_DET_EN_BIT 10 // 1 - sq detect will add ctcss/cdcss detect result and control voice output on or off +#define A1846S_NEG_DET_EN_BIT 7 // if 1, cdcss inverse code will be detected at same time +#define A1846S_CDCSS_SEL_BIT 4 // cdcss_sel +#define A1846S_CTCSS_SEL_BIT 3 // ctcss_sel +#define A1846S_C_MODE_BIT 2 // c_mode<2:0> +#define A1846S_C_MODE_LENGTH 3 + +// Bitfields for A1846S_SQ_THRESH_REG +#define A1846S_SQ_OPEN_THRESH_BIT 9 // sq open threshold <9:0> +#define A1846S_SQ_OPEN_THRESH_LENGTH 10 + +// Bitfields for A1846S_SQ_SHUT_THRESH_REG +#define A1846S_SQ_SHUT_THRESH_BIT 9 // sq shut threshold <9:0> +#define A1846S_SQ_SHUT_THRESH_LENGTH 10 + +// Bitfields for A1846S_SQ_OUT_SEL_REG +#define A1846S_SQ_OUT_SEL_BIT 7 // sq_out_sel + +// Bitfields for A1846S_EMPH_FILTER_REG +#define A1846S_EMPH_FILTER_EN 3 + +// Bitfields for A1846S_FLAG_REG +#define A1846S_DTMF_IDLE_FLAG_BIT 12 // dtmf idle flag +#define A1846S_RXON_RF_FLAG_BIT 10 // 1 when rxon is enabled +#define A1846S_TXON_RF_FLAG_BIT 9 // 1 when txon is enabled +#define A1846S_INVERT_DET_FLAG_BIT 7 // ctcss phase shift detect +#define A1846S_CSS_CMP_FLAG_BIT 2 // ctcss/cdcss compared +#define A1846S_SQ_FLAG_BIT 1 // sq final signal out from dsp +#define A1846S_VOX_FLAG_BIT 0 // vox out from dsp + +// Bitfields for A1846S_RSSI_REG +#define A1846S_RSSI_BIT 9 // RSSI readings <9:0> +#define A1846S_RSSI_LENGTH 10 + +// Bitfields for A1846S_VSSI_REG +#define A1846S_VSSI_BIT 14 // voice signal strength indicator <14:0> (unit mV) +#define A1846S_VSSI_LENGTH 15 + +// Bitfields for A1846S_DTMF_CTL_REG +#define A1846S_DTMF_MODE_BIT 9 // +#define A1846S_DTMF_MODE_LENGTH 2 +#define A1846S_DTMF_EN_BIT 8 // enable dtmf +#define A1846S_DTMF_TIME1_BIT 7 // dtmf time 1 <3:0> +#define A1846S_DTMF_TIME1_LENGTH 4 +#define A1846S_DTMF_TIME2_BIT 3 // dtmf time 2 <3:0> +#define A1846S_DTMF_TIME2_LENGTH 4 + +// Bitfields for A1846S_DTMF_RX_REG +#define A1846S_DTMF_INDEX_BIT 10 // dtmf index <5:3> - tone 1 detect index, <2:0> - tone 2 detect index +#define A1846S_DTMF_INDEX_LENGTH 6 +#define A1846S_DTMF_TONE1_IND_BIT 10 +#define A1846S_DTMF_TONE1_IND_LENGTH 3 +#define A1846S_DTMF_TONE2_IND_BIT 7 +#define A1846S_DTMF_TONE2_IND_LENGTH 3 +#define A1846S_DTMF_FLAG_BIT 4 +#define A1846S_DTMF_CODE_BIT 3 // dtmf code out <3:0> +#define A1846S_DTMF_CODE_LENGTH 4 +// dtmf code out +// 1:f0+f4, 2:f0+f5, 3:f0+f6, A:f0+f7, +// 4:f1+f4, 5:f1+f5, 6:f1+f6, B:f1+f7, +// 7:f2+f4, 8:f2+f5, 9:f2+f6, C:f2+f7, +// E(*):f3+f4, 0:f3+f5, F(#):f3+f6, D:f3+f7 + +// Bitfields for DTMF registers +#define A1846S_DTMF_C0_BIT 15 +#define A1846S_DTMF_C0_LENGTH 8 +#define A1846S_DTMF_C1_BIT 7 +#define A1846S_DTMF_C1_LENGTH 8 +#define A1846S_DTMF_C2_BIT 15 +#define A1846S_DTMF_C2_LENGTH 8 +#define A1846S_DTMF_C3_BIT 7 +#define A1846S_DTMF_C3_LENGTH 8 +#define A1846S_DTMF_C4_BIT 15 +#define A1846S_DTMF_C4_LENGTH 8 +#define A1846S_DTMF_C5_BIT 7 +#define A1846S_DTMF_C5_LENGTH 8 +#define A1846S_DTMF_C6_BIT 15 +#define A1846S_DTMF_C6_LENGTH 8 +#define A1846S_DTMF_C7_BIT 7 +#define A1846S_DTMF_C7_LENGTH 8 + +// SSTV VIS Codes + + +#define ROBOT8BW 2 +#define SC2-180 55 +#define MARTIN1 44 + +// RTTY Frequencies + +#define HAMSHIELD_RTTY_FREQ 2200 +#define HAMSHIELD_RTTY_SHIFT 850 +#define HAMSHIELD_RTTY_BAUD 75 + +// PSK31 Frequencies + +#define HAMSHIELD_PSK31_FREQ 1000 + + + +class HAMShield { + public: + HAMShield(); + HAMShield(uint8_t address); + + void initialize(); + bool testConnection(); + + // read control reg + uint16_t readCtlReg(); + void softReset(); + + // center frequency + void setFrequency(uint32_t freq_khz); + uint32_t getFrequency(); + + // band + // 00 - 400-520MHz + // 10 - 200-260MHz + // 11 - 134-174MHz + void setBand(uint16_t band); + uint16_t getBand(); + + void setUHF(); + void setVHF(); + void setNoFilters(); + bool frequency(uint32_t freq_khz); + + // xtal frequency (kHz) + // 12-14MHz crystal: this reg is set to crystal freq_khz + // 24-28MHz crystal: this reg is set to crystal freq_khz / 2 + void setXtalFreq(uint16_t freq_kHz); + uint16_t getXtalFreq(); + + // adclk frequency (kHz) + // 12-14MHz crystal: this reg is set to crystal freq_khz / 2 + // 24-28MHz crystal: this reg is set to crystal freq_khz / 4 + void setAdcClkFreq(uint16_t freq_kHz); + uint16_t getAdcClkFreq(); + + // clk mode + // 12-14MHz: set to 1 + // 24-28MHz: set to 0 + void setClkMode(bool LFClk); + bool getClkMode(); + + // clk example + // 12.8MHz clock + // A1846S_XTAL_FREQ_REG[15:0]= xtal_freq<15:0>=12.8*1000=12800 + // A1846S_ADCLK_FREQ_REG[12:0] =adclk_freq<15:0>=(12.8/2)*1000=6400 + // A1846S_CLK_MODE_REG[0]= clk_mode =1 + + // TX/RX control + + // channel mode + // 11 - 25kHz channel + // 00 - 12.5kHz channel + // 10,01 - reserved + void setChanMode(uint16_t mode); + uint16_t getChanMode(); + + // choose tx or rx + void setTX(bool on_noff); + bool getTX(); + + void setRX(bool on_noff); + bool getRX(); + + void setModeTransmit(); // turn off rx, turn on tx + void setModeReceive(); // turn on rx, turn off tx + void setModeOff(); // turn off rx, turn off tx, set pwr_dwn bit + + // set tx source + // 00 - Mic source + // 01 - sine source from tone2 + // 10 - tx code from GPIO1 code_in (gpio1<1:0> must be set to 01) + // 11 - no tx source + void setTxSource(uint16_t tx_source); + void setTxSourceMic(); + void setTxSourceSine(); + void setTxSourceCode(); + void setTxSourceNone(); + uint16_t getTxSource(); + + // set PA_bias voltage + // 000000: 1.01V + // 000001:1.05V + // 000010:1.09V + // 000100: 1.18V + // 001000: 1.34V + // 010000: 1.68V + // 100000: 2.45V + // 1111111:3.13V + void setPABiasVoltage(uint16_t voltage); + uint16_t getPABiasVoltage(); + + // Subaudio settings + + // Ctcss/cdcss mode sel + // x00=disable, + // 001=inner ctcss en, + // 010= inner cdcss en + // 101= outer ctcss en, + // 110=outer cdcss en + // others =disable + void setCtcssCdcssMode(uint16_t mode); + uint16_t getCtcssCdcssMode(); + void setInnerCtcssMode(); + void setInnerCdcssMode(); + void setOuterCtcssMode(); + void setOuterCdcssMode(); + void disableCtcssCdcss(); + + // Ctcss_sel + // 1 = ctcss_cmp/cdcss_cmp out via gpio + // 0 = ctcss/cdcss sdo out vio gpio + void setCtcssSel(bool cmp_nsdo); + bool getCtcssSel(); + + // Cdcss_sel + // 1 = long (24 bit) code + // 0 = short(23 bit) code + void setCdcssSel(bool long_nshort); + bool getCdcssSel(); + // Cdcss neg_det_en + void enableCdcssNegDet(); + void disableCdcssNegDet(); + bool getCdcssNegDetEnabled(); + + // Cdcss pos_det_en + void enableCdcssPosDet(); + void disableCdcssPosDet(); + bool getCdcssPosDetEnabled(); + + // css_det_en + void enableCssDet(); + void disableCssDet(); + bool getCssDetEnabled(); + + // ctcss freq + void setCtcss(float freq); + void setCtcssFreq(uint16_t freq); + uint16_t getCtcssFreq(); + void setCtcssFreqToStandard(); // freq must be 134.4Hz for standard cdcss mode + + // cdcss codes + void setCdcssCode(uint16_t code); + uint16_t getCdcssCode(); + + // SQ + void setSQOn(); + void setSQOff(); + bool getSQState(); + + // SQ threshold + void setSQHiThresh(uint16_t sq_hi_threshold); // Sq detect high th, rssi_cmp will be 1 when rssi>th_h_sq, unit 1/8dB + uint16_t getSQHiThresh(); + void setSQLoThresh(uint16_t sq_lo_threshold); // Sq detect low th, rssi_cmp will be 0 when rssi th_h_vox, then vox will be 1(unit mV ) + uint16_t getVoxOpenThresh(); + void setVoxShutThresh(uint16_t vox_shut_thresh); // When vssi < th_l_vox && time delay meet, then vox will be 0 (unit mV ) + uint16_t getVoxShutThresh(); + + // Tail Noise + void enableTailNoiseElim(); + void disableTailNoiseElim(); + bool getTailNoiseElimEnabled(); + + // tail noise shift select + // Select ctcss phase shift when use tail eliminating function when TX + // 00 = 120 degree shift + // 01 = 180 degree shift + // 10 = 240 degree shift + // 11 = reserved + void setShiftSelect(uint16_t shift_sel); + uint16_t getShiftSelect(); + + // DTMF + void setDTMFC0(uint16_t freq); + uint16_t getDTMFC0(); + void setDTMFC1(uint16_t freq); + uint16_t getDTMFC1(); + void setDTMFC2(uint16_t freq); + uint16_t getDTMFC2(); + void setDTMFC3(uint16_t freq); + uint16_t getDTMFC3(); + void setDTMFC4(uint16_t freq); + uint16_t getDTMFC4(); + void setDTMFC5(uint16_t freq); + uint16_t getDTMFC5(); + void setDTMFC6(uint16_t freq); + uint16_t getDTMFC6(); + void setDTMFC7(uint16_t freq); + uint16_t getDTMFC7(); + + // TX FM deviation + void setFMVoiceCssDeviation(uint16_t deviation); + uint16_t getFMVoiceCssDeviation(); + void setFMCssDeviation(uint16_t deviation); + uint16_t getFMCssDeviation(); + + // RX voice range + void setVolume1(uint16_t volume); + uint16_t getVolume1(); + void setVolume2(uint16_t volume); + uint16_t getVolume2(); + + // GPIO + void setGpioMode(uint16_t gpio, uint16_t mode); + void setGpioHiZ(uint16_t gpio); + void setGpioFcn(uint16_t gpio); + void setGpioLow(uint16_t gpio); + void setGpioHi(uint16_t gpio); + uint16_t getGpioMode(uint16_t gpio); + + // Int + void enableInterrupt(uint16_t interrupt); + void disableInterrupt(uint16_t interrupt); + bool getInterruptEnabled(uint16_t interrupt); + + // ST mode + void setStMode(uint16_t mode); + uint16_t getStMode(); + void setStFullAuto(); + void setStRxAutoTxManu(); + void setStFullManu(); + + // Pre-emphasis, De-emphasis filter + void bypassPreDeEmph(); + void usePreDeEmph(); + bool getPreDeEmphEnabled(); + + // Read Only Status Registers + int16_t readRSSI(); + uint16_t readVSSI(); + uint16_t readDTMFIndex(); // may want to split this into two (index1 and index2) + uint16_t readDTMFCode(); + + // set output power of radio + void setRfPower(uint8_t pwr); + + // channel helper functions + bool setGMRSChannel(uint8_t channel); + bool setFRSChannel(uint8_t channel); + bool setMURSChannel(uint8_t channel); + bool setWXChannel(uint8_t channel); + uint8_t scanWXChannel(); + + + // restrictions control + void dangerMode(); + void safeMode(); + + // utilities + uint32_t scanMode(uint32_t start,uint32_t stop, uint8_t speed, uint16_t step, uint16_t threshold); + uint32_t findWhitespace(uint32_t start,uint32_t stop, uint8_t dwell, uint16_t step, uint16_t threshold); + uint32_t scanChannels(uint32_t buffer[],uint8_t buffsize, uint8_t speed, uint16_t threshold); + uint32_t findWhitespaceChannels(uint32_t buffer[],uint8_t buffsize, uint8_t dwell, uint16_t threshold); + void buttonMode(uint8_t mode); + void isr_ptt(); + void isr_reset(); + void morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]); + char morseLookup(char letter); + bool waitForChannel(long timeout, long breakwindow); + void SSTVVISCode(int code); + void SSTVTestPattern(int code); + void toneWait(uint16_t freq, long timer); + void toneWaitU(uint16_t freq, long timer); + bool parityCalc(int code); + // void AFSKOut(char buffer[80]); + + + private: + uint8_t devAddr; + uint16_t radio_i2c_buf[4]; + int pwr_control_pin; + uint32_t radio_frequency; + uint32_t FRS[]; + uint32_t GMRS[]; + uint32_t MURS[]; + uint32_t WX[]; + + +// int8_t A1846S::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout); +// int8_t A1846S::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout); +// int8_t A1846S::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout); +// int8_t A1846S::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout); +// bool A1846S::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); +// bool A1846S::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); +}; + +#endif /* _HAMSHIELD_H_ */ diff --git a/src/I2Cdev_rda.cpp b/src/I2Cdev_rda.cpp new file mode 100644 index 0000000..2cc4e2b --- /dev/null +++ b/src/I2Cdev_rda.cpp @@ -0,0 +1,1458 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// +// Changelog: +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev_rda.h" + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + + #ifdef I2CDEV_IMPLEMENTATION_WARNINGS + #if ARDUINO < 100 + #warning Using outdated Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.0.1+ with I2Cdev Fastwire implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #warning - Timeout detection (some Wire requests block forever) + #elif ARDUINO == 100 + #warning Using outdated Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.0.1+ with I2Cdev Fastwire implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #warning - Timeout detection (some Wire requests block forever) + #elif ARDUINO > 100 + #warning Using current Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.0.1+ with I2CDEV_BUILTIN_FASTWIRE implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Timeout detection (some Wire requests block forever) + #endif + #endif + +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + + //#error The I2CDEV_BUILTIN_FASTWIRE implementation is known to be broken right now. Patience, Iago! + +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + + #ifdef I2CDEV_IMPLEMENTATION_WARNINGS + #warning Using I2CDEV_BUILTIN_NBWIRE implementation may adversely affect interrupt detection. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #endif + + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + TwoWire Wire; + +#endif + +/** Default constructor. + */ +I2Cdev::I2Cdev() { +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { + uint8_t b; + uint8_t count = readByte(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) { + uint16_t b; + uint8_t count = readWord(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) { + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { + return readBytes(devAddr, regAddr, 1, data, timeout); +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) { + return readWords(devAddr, regAddr, 1, data, timeout); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of bytes read (-1 indicates failure) + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") reading "); + Serial.print(length, DEC); + Serial.print(" bytes from 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + + int8_t count = 0; + uint32_t t1 = millis(); + + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) + + #if (ARDUINO < 100) + // Arduino v00xx (before v1.0), Wire library + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.send(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = Wire.receive(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + + Wire.endTransmission(); + } + #elif (ARDUINO == 100) + // Arduino v1.0.0, Wire library + // Adds standardized write() and read() stream methods instead of send() and receive() + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + + Wire.endTransmission(); + } + #elif (ARDUINO > 100) + // Arduino v1.0.1+, Wire library + // Adds official support for repeated start condition, yay! + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + } + #endif + + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + + // Fastwire library + // no loop required for fastwire + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, data, length); + if (status == 0) { + count = length; // success + } else { + count = -1; // error + } + + #endif + + // check for timeout + if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout + + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(". Done ("); + Serial.print(count, DEC); + Serial.println(" read)."); + #endif + + return count; +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") reading "); + Serial.print(length, DEC); + Serial.print(" words from 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + + int8_t count = 0; + uint32_t t1 = millis(); + + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) + + #if (ARDUINO < 100) + // Arduino v00xx (before v1.0), Wire library + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.send(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = Wire.receive() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= Wire.receive(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + + Wire.endTransmission(); + } + #elif (ARDUINO == 100) + // Arduino v1.0.0, Wire library + // Adds standardized write() and read() stream methods instead of send() and receive() + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = Wire.read() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + + Wire.endTransmission(); + } + #elif (ARDUINO > 100) + //Serial.println("wires"); + // Arduino v1.0.1+, Wire library + // Adds official support for repeated start condition, yay! + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(false); +// Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = Wire.read() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + + Wire.endTransmission(); + } + #endif + + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + + // Fastwire library + // no loop required for fastwire + uint16_t intermediate[(uint8_t)length]; + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, (uint8_t *)intermediate, (uint8_t)(length * 2)); + if (status == 0) { + count = length; // success + for (uint8_t i = 0; i < length; i++) { + data[i] = (intermediate[2*i] << 8) | intermediate[2*i + 1]; + } + } else { + count = -1; // error + } + + #endif + + if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout + + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(". Done ("); + Serial.print(count, DEC); + Serial.println(" read)."); + #endif + + return count; +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { + uint8_t b; + readByte(devAddr, regAddr, &b); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return writeByte(devAddr, regAddr, b); +} + +/** write a single bit in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-15) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { + uint16_t w; + readWord(devAddr, regAddr, &w); + w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); + return writeWord(devAddr, regAddr, w); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (readByte(devAddr, regAddr, &b) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return writeByte(devAddr, regAddr, b); + } else { + return false; + } +} + +/** Write multiple bits in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-15) + * @param length Number of bits to write (not more than 16) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { + // 010 value to write + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 0001110000000000 mask word + // 1010111110010110 original value (sample) + // 1010001110010110 original & ~mask + // 1010101110010110 masked | value + uint16_t w; + if (readWord(devAddr, regAddr, &w) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + w &= ~(mask); // zero all important bits in existing word + w |= data; // combine data with existing word + return writeWord(devAddr, regAddr, w); + } else { + return false; + } +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + return writeBytes(devAddr, regAddr, 1, &data); +} + +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { + return writeWords(devAddr, regAddr, 1, &data); +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") writing "); + Serial.print(length, DEC); + Serial.print(" bytes to 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + uint8_t status = 0; + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.beginTransmission(devAddr); + Wire.send((uint8_t) regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.beginTransmission(devAddr); + Wire.write((uint8_t) regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::beginTransmission(devAddr); + Fastwire::write(regAddr); + #endif + for (uint8_t i = 0; i < length; i++) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[i], HEX); + if (i + 1 < length) Serial.print(" "); + #endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.send((uint8_t) data[i]); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.write((uint8_t) data[i]); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::write((uint8_t) data[i]); + #endif + } + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::stop(); + //status = Fastwire::endTransmission(); + #endif + #ifdef I2CDEV_SERIAL_DEBUG + Serial.println(". Done."); + #endif + return status == 0; +} + +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") writing "); + Serial.print(length, DEC); + Serial.print(" words to 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + uint8_t status = 0; + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.beginTransmission(devAddr); + Wire.send(regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.beginTransmission(devAddr); + Wire.write(regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::beginTransmission(devAddr); + Fastwire::write(regAddr); + #endif + for (uint8_t i = 0; i < length * 2; i++) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[i], HEX); + if (i + 1 < length) Serial.print(" "); + #endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.send((uint8_t)(data[i] >> 8)); // send MSB + Wire.send((uint8_t)data[i++]); // send LSB + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.write((uint8_t)(data[i] >> 8)); // send MSB + Wire.write((uint8_t)data[i++]); // send LSB + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB + status = Fastwire::write((uint8_t)data[i++]); // send LSB + if (status != 0) break; + #endif + } + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::stop(); + //status = Fastwire::endTransmission(); + #endif + #ifdef I2CDEV_SERIAL_DEBUG + Serial.println(". Done."); + #endif + return status == 0; +} + +/** Default timeout value for read operations. + * Set this to 0 to disable timeout detection. + */ +uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + // I2C library + ////////////////////// + // Copyright(C) 2012 + // Francesco Ferrara + // ferrara[at]libero[point]it + ////////////////////// + + /* + FastWire + - 0.24 added stop + - 0.23 added reset + + This is a library to help faster programs to read I2C devices. + Copyright(C) 2012 Francesco Ferrara + occhiobello at gmail dot com + [used by Jeff Rowberg for I2Cdevlib with permission] + */ + + boolean Fastwire::waitInt() { + int l = 250; + while (!(TWCR & (1 << TWINT)) && l-- > 0); + return l > 0; + } + + void Fastwire::setup(int khz, boolean pullup) { + TWCR = 0; + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // activate internal pull-ups for twi (PORTC bits 4 & 5) + // as per note from atmega8 manual pg167 + if (pullup) PORTC |= ((1 << 4) | (1 << 5)); + else PORTC &= ~((1 << 4) | (1 << 5)); + #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) + // activate internal pull-ups for twi (PORTC bits 0 & 1) + if (pullup) PORTC |= ((1 << 0) | (1 << 1)); + else PORTC &= ~((1 << 0) | (1 << 1)); + #else + // activate internal pull-ups for twi (PORTD bits 0 & 1) + // as per note from atmega128 manual pg204 + if (pullup) PORTD |= ((1 << 0) | (1 << 1)); + else PORTD &= ~((1 << 0) | (1 << 1)); + #endif + + TWSR = 0; // no prescaler => prescaler = 1 + TWBR = ((16000L / khz) - 16) / 2; // change the I2C clock rate + TWCR = 1 << TWEN; // enable twi module, no interrupt + } + + // added by Jeff Rowberg 2013-05-07: + // Arduino Wire-style "beginTransmission" function + // (takes 7-bit device address like the Wire method, NOT 8-bit: 0x68, not 0xD0/0xD1) + byte Fastwire::beginTransmission(byte device) { + byte twst, retry; + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 2; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device << 1; // send device address without read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 3; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 4; + return 0; + } + + byte Fastwire::writeBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 2; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device & 0xFE; // send device address without read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 3; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 4; + + //Serial.print(address, HEX); + //Serial.print(" "); + TWDR = address; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 5; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 6; + + for (byte i = 0; i < num; i++) { + //Serial.print(data[i], HEX); + //Serial.print(" "); + TWDR = data[i]; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 7; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 8; + } + //Serial.print("\n"); + + return 0; + } + + byte Fastwire::write(byte value) { + byte twst; + //Serial.println(value, HEX); + TWDR = value; // send data + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 2; + return 0; + } + + byte Fastwire::readBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 16; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 17; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device & 0xfe; // send device address to write + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 18; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 19; + + //Serial.print(address, HEX); + //Serial.print(" "); + TWDR = address; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 20; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 21; + + /***/ + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 22; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 23; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device | 0x01; // send device address with the read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 24; + twst = TWSR & 0xF8; + } while (twst == TW_MR_SLA_NACK && retry-- > 0); + if (twst != TW_MR_SLA_ACK) return 25; + + for (uint8_t i = 0; i < num; i++) { + if (i == num - 1) + TWCR = (1 << TWINT) | (1 << TWEN); + else + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); + if (!waitInt()) return 26; + twst = TWSR & 0xF8; + if (twst != TW_MR_DATA_ACK && twst != TW_MR_DATA_NACK) return twst; + data[i] = TWDR; + //Serial.print(data[i], HEX); + //Serial.print(" "); + } + //Serial.print("\n"); + stop(); + + return 0; + } + + void Fastwire::reset() { + TWCR = 0; + } + + byte Fastwire::stop() { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); + if (!waitInt()) return 1; + return 0; + } +#endif + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + + /* + call this version 1.0 + + Offhand, the only funky part that I can think of is in nbrequestFrom, where the buffer + length and index are set *before* the data is actually read. The problem is that these + are variables local to the TwoWire object, and by the time we actually have read the + data, and know what the length actually is, we have no simple access to the object's + variables. The actual bytes read *is* given to the callback function, though. + + The ISR code for a slave receiver is commented out. I don't have that setup, and can't + verify it at this time. Save it for 2.0! + + The handling of the read and write processes here is much like in the demo sketch code: + the process is broken down into sequential functions, where each registers the next as a + callback, essentially. + + For example, for the Read process, twi_read00 just returns if TWI is not yet in a + ready state. When there's another interrupt, and the interface *is* ready, then it + sets up the read, starts it, and registers twi_read01 as the function to call after + the *next* interrupt. twi_read01, then, just returns if the interface is still in a + "reading" state. When the reading is done, it copies the information to the buffer, + cleans up, and calls the user-requested callback function with the actual number of + bytes read. + + The writing is similar. + + Questions, comments and problems can go to Gene@Telobot.com. + + Thumbs Up! + Gene Knight + + */ + + uint8_t TwoWire::rxBuffer[NBWIRE_BUFFER_LENGTH]; + uint8_t TwoWire::rxBufferIndex = 0; + uint8_t TwoWire::rxBufferLength = 0; + + uint8_t TwoWire::txAddress = 0; + uint8_t TwoWire::txBuffer[NBWIRE_BUFFER_LENGTH]; + uint8_t TwoWire::txBufferIndex = 0; + uint8_t TwoWire::txBufferLength = 0; + + //uint8_t TwoWire::transmitting = 0; + void (*TwoWire::user_onRequest)(void); + void (*TwoWire::user_onReceive)(int); + + static volatile uint8_t twi_transmitting; + static volatile uint8_t twi_state; + static uint8_t twi_slarw; + static volatile uint8_t twi_error; + static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; + static volatile uint8_t twi_masterBufferIndex; + static uint8_t twi_masterBufferLength; + static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; + static volatile uint8_t twi_rxBufferIndex; + //static volatile uint8_t twi_Interrupt_Continue_Command; + static volatile uint8_t twi_Return_Value; + static volatile uint8_t twi_Done; + void (*twi_cbendTransmissionDone)(int); + void (*twi_cbreadFromDone)(int); + + void twi_init() { + // initialize state + twi_state = TWI_READY; + + // activate internal pull-ups for twi + // as per note from atmega8 manual pg167 + sbi(PORTC, 4); + sbi(PORTC, 5); + + // initialize twi prescaler and bit rate + cbi(TWSR, TWPS0); // TWI Status Register - Prescaler bits + cbi(TWSR, TWPS1); + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ + + TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register + // enable twi module, acks, and twi interrupt + + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); + + /* TWEN - TWI Enable Bit + TWIE - TWI Interrupt Enable + TWEA - TWI Enable Acknowledge Bit + TWINT - TWI Interrupt Flag + TWSTA - TWI Start Condition + */ + } + + typedef struct { + uint8_t address; + uint8_t* data; + uint8_t length; + uint8_t wait; + uint8_t i; + } twi_Write_Vars; + + twi_Write_Vars *ptwv = 0; + static void (*fNextInterruptFunction)(void) = 0; + + void twi_Finish(byte bRetVal) { + if (ptwv) { + free(ptwv); + ptwv = 0; + } + twi_Done = 0xFF; + twi_Return_Value = bRetVal; + fNextInterruptFunction = 0; + } + + uint8_t twii_WaitForDone(uint16_t timeout) { + uint32_t endMillis = millis() + timeout; + while (!twi_Done && (timeout == 0 || millis() < endMillis)) continue; + return twi_Return_Value; + } + + void twii_SetState(uint8_t ucState) { + twi_state = ucState; + } + + void twii_SetError(uint8_t ucError) { + twi_error = ucError ; + } + + void twii_InitBuffer(uint8_t ucPos, uint8_t ucLength) { + twi_masterBufferIndex = 0; + twi_masterBufferLength = ucLength; + } + + void twii_CopyToBuf(uint8_t* pData, uint8_t ucLength) { + uint8_t i; + for (i = 0; i < ucLength; ++i) { + twi_masterBuffer[i] = pData[i]; + } + } + + void twii_CopyFromBuf(uint8_t *pData, uint8_t ucLength) { + uint8_t i; + for (i = 0; i < ucLength; ++i) { + pData[i] = twi_masterBuffer[i]; + } + } + + void twii_SetSlaRW(uint8_t ucSlaRW) { + twi_slarw = ucSlaRW; + } + + void twii_SetStart() { + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + } + + void twi_write01() { + if (TWI_MTX == twi_state) return; // blocking test + twi_transmitting = 0 ; + if (twi_error == 0xFF) + twi_Finish (0); // success + else if (twi_error == TW_MT_SLA_NACK) + twi_Finish (2); // error: address send, nack received + else if (twi_error == TW_MT_DATA_NACK) + twi_Finish (3); // error: data send, nack received + else + twi_Finish (4); // other twi error + if (twi_cbendTransmissionDone) return twi_cbendTransmissionDone(twi_Return_Value); + return; + } + + + void twi_write00() { + if (TWI_READY != twi_state) return; // blocking test + if (TWI_BUFFER_LENGTH < ptwv -> length) { + twi_Finish(1); // end write with error 1 + return; + } + twi_Done = 0x00; // show as working + twii_SetState(TWI_MTX); // to transmitting + twii_SetError(0xFF); // to No Error + twii_InitBuffer(0, ptwv -> length); // pointer and length + twii_CopyToBuf(ptwv -> data, ptwv -> length); // get the data + twii_SetSlaRW((ptwv -> address << 1) | TW_WRITE); // write command + twii_SetStart(); // start the cycle + fNextInterruptFunction = twi_write01; // next routine + return twi_write01(); + } + + void twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) { + uint8_t i; + ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); + ptwv -> address = address; + ptwv -> data = data; + ptwv -> length = length; + ptwv -> wait = wait; + fNextInterruptFunction = twi_write00; + return twi_write00(); + } + + void twi_read01() { + if (TWI_MRX == twi_state) return; // blocking test + if (twi_masterBufferIndex < ptwv -> length) ptwv -> length = twi_masterBufferIndex; + twii_CopyFromBuf(ptwv -> data, ptwv -> length); + twi_Finish(ptwv -> length); + if (twi_cbreadFromDone) return twi_cbreadFromDone(twi_Return_Value); + return; + } + + void twi_read00() { + if (TWI_READY != twi_state) return; // blocking test + if (TWI_BUFFER_LENGTH < ptwv -> length) twi_Finish(0); // error return + twi_Done = 0x00; // show as working + twii_SetState(TWI_MRX); // reading + twii_SetError(0xFF); // reset error + twii_InitBuffer(0, ptwv -> length - 1); // init to one less than length + twii_SetSlaRW((ptwv -> address << 1) | TW_READ); // read command + twii_SetStart(); // start cycle + fNextInterruptFunction = twi_read01; + return twi_read01(); + } + + void twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) { + uint8_t i; + + ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); + ptwv -> address = address; + ptwv -> data = data; + ptwv -> length = length; + fNextInterruptFunction = twi_read00; + return twi_read00(); + } + + void twi_reply(uint8_t ack) { + // transmit master read ready signal, with or without ack + if (ack){ + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); + } else { + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + } + } + + void twi_stop(void) { + // send stop condition + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + + // wait for stop condition to be exectued on bus + // TWINT is not set after a stop condition! + while (TWCR & _BV(TWSTO)) { + continue; + } + + // update twi state + twi_state = TWI_READY; + } + + void twi_releaseBus(void) { + // release bus + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + + // update twi state + twi_state = TWI_READY; + } + + SIGNAL(TWI_vect) { + switch (TW_STATUS) { + // All Master + case TW_START: // sent start condition + case TW_REP_START: // sent repeated start condition + // copy device address and r/w bit to output register and ack + TWDR = twi_slarw; + twi_reply(1); + break; + + // Master Transmitter + case TW_MT_SLA_ACK: // slave receiver acked address + case TW_MT_DATA_ACK: // slave receiver acked data + // if there is data to send, send it, otherwise stop + if (twi_masterBufferIndex < twi_masterBufferLength) { + // copy data to output register and ack + TWDR = twi_masterBuffer[twi_masterBufferIndex++]; + twi_reply(1); + } else { + twi_stop(); + } + break; + + case TW_MT_SLA_NACK: // address sent, nack received + twi_error = TW_MT_SLA_NACK; + twi_stop(); + break; + + case TW_MT_DATA_NACK: // data sent, nack received + twi_error = TW_MT_DATA_NACK; + twi_stop(); + break; + + case TW_MT_ARB_LOST: // lost bus arbitration + twi_error = TW_MT_ARB_LOST; + twi_releaseBus(); + break; + + // Master Receiver + case TW_MR_DATA_ACK: // data received, ack sent + // put byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + + case TW_MR_SLA_ACK: // address sent, ack received + // ack if more bytes are expected, otherwise nack + if (twi_masterBufferIndex < twi_masterBufferLength) { + twi_reply(1); + } else { + twi_reply(0); + } + break; + + case TW_MR_DATA_NACK: // data received, nack sent + // put final byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + + case TW_MR_SLA_NACK: // address sent, nack received + twi_stop(); + break; + + // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case + + // Slave Receiver (NOT IMPLEMENTED YET) + /* + case TW_SR_SLA_ACK: // addressed, returned ack + case TW_SR_GCALL_ACK: // addressed generally, returned ack + case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack + case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack + // enter slave receiver mode + twi_state = TWI_SRX; + + // indicate that rx buffer can be overwritten and ack + twi_rxBufferIndex = 0; + twi_reply(1); + break; + + case TW_SR_DATA_ACK: // data received, returned ack + case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack + // if there is still room in the rx buffer + if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { + // put byte in buffer and ack + twi_rxBuffer[twi_rxBufferIndex++] = TWDR; + twi_reply(1); + } else { + // otherwise nack + twi_reply(0); + } + break; + + case TW_SR_STOP: // stop or repeated start condition received + // put a null char after data if there's room + if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { + twi_rxBuffer[twi_rxBufferIndex] = 0; + } + + // sends ack and stops interface for clock stretching + twi_stop(); + + // callback to user defined callback + twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); + + // since we submit rx buffer to "wire" library, we can reset it + twi_rxBufferIndex = 0; + + // ack future responses and leave slave receiver state + twi_releaseBus(); + break; + + case TW_SR_DATA_NACK: // data received, returned nack + case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack + // nack back at master + twi_reply(0); + break; + + // Slave Transmitter + case TW_ST_SLA_ACK: // addressed, returned ack + case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack + // enter slave transmitter mode + twi_state = TWI_STX; + + // ready the tx buffer index for iteration + twi_txBufferIndex = 0; + + // set tx buffer length to be zero, to verify if user changes it + twi_txBufferLength = 0; + + // request for txBuffer to be filled and length to be set + // note: user must call twi_transmit(bytes, length) to do this + twi_onSlaveTransmit(); + + // if they didn't change buffer & length, initialize it + if (0 == twi_txBufferLength) { + twi_txBufferLength = 1; + twi_txBuffer[0] = 0x00; + } + + // transmit first byte from buffer, fall through + + case TW_ST_DATA_ACK: // byte sent, ack returned + // copy data to output register + TWDR = twi_txBuffer[twi_txBufferIndex++]; + + // if there is more to send, ack, otherwise nack + if (twi_txBufferIndex < twi_txBufferLength) { + twi_reply(1); + } else { + twi_reply(0); + } + break; + + case TW_ST_DATA_NACK: // received nack, we are done + case TW_ST_LAST_DATA: // received ack, but we are done already! + // ack future responses + twi_reply(1); + // leave slave receiver state + twi_state = TWI_READY; + break; + */ + + // all + case TW_NO_INFO: // no state information + break; + + case TW_BUS_ERROR: // bus error, illegal stop/start + twi_error = TW_BUS_ERROR; + twi_stop(); + break; + } + + if (fNextInterruptFunction) return fNextInterruptFunction(); + } + + TwoWire::TwoWire() { } + + void TwoWire::begin(void) { + rxBufferIndex = 0; + rxBufferLength = 0; + + txBufferIndex = 0; + txBufferLength = 0; + + twi_init(); + } + + void TwoWire::beginTransmission(uint8_t address) { + //beginTransmission((uint8_t)address); + + // indicate that we are transmitting + twi_transmitting = 1; + + // set address of targeted slave + txAddress = address; + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + } + + uint8_t TwoWire::endTransmission(uint16_t timeout) { + // transmit buffer (blocking) + //int8_t ret = + twi_cbendTransmissionDone = NULL; + twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + int8_t ret = twii_WaitForDone(timeout); + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + + // indicate that we are done transmitting + // twi_transmitting = 0; + return ret; + } + + void TwoWire::nbendTransmission(void (*function)(int)) { + twi_cbendTransmissionDone = function; + twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + return; + } + + void TwoWire::send(uint8_t data) { + if (twi_transmitting) { + // in master transmitter mode + // don't bother if buffer is full + if (txBufferLength >= NBWIRE_BUFFER_LENGTH) { + return; + } + + // put byte in tx buffer + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + + // update amount in buffer + txBufferLength = txBufferIndex; + } else { + // in slave send mode + // reply to master + //twi_transmit(&data, 1); + } + } + + uint8_t TwoWire::receive(void) { + // default to returning null char + // for people using with char strings + uint8_t value = 0; + + // get each successive byte on each call + if (rxBufferIndex < rxBufferLength) { + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + } + + return value; + } + + uint8_t TwoWire::requestFrom(uint8_t address, int quantity, uint16_t timeout) { + // clamp to buffer length + if (quantity > NBWIRE_BUFFER_LENGTH) { + quantity = NBWIRE_BUFFER_LENGTH; + } + + // perform blocking read into buffer + twi_cbreadFromDone = NULL; + twi_readFrom(address, rxBuffer, quantity); + uint8_t read = twii_WaitForDone(timeout); + + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = read; + + return read; + } + + void TwoWire::nbrequestFrom(uint8_t address, int quantity, void (*function)(int)) { + // clamp to buffer length + if (quantity > NBWIRE_BUFFER_LENGTH) { + quantity = NBWIRE_BUFFER_LENGTH; + } + + // perform blocking read into buffer + twi_cbreadFromDone = function; + twi_readFrom(address, rxBuffer, quantity); + //uint8_t read = twii_WaitForDone(); + + // set rx buffer iterator vars + //rxBufferIndex = 0; + //rxBufferLength = read; + + rxBufferIndex = 0; + rxBufferLength = quantity; // this is a hack + + return; //read; + } + + uint8_t TwoWire::available(void) { + return rxBufferLength - rxBufferIndex; + } + +#endif diff --git a/src/I2Cdev_rda.h b/src/I2Cdev_rda.h new file mode 100644 index 0000000..56850f2 --- /dev/null +++ b/src/I2Cdev_rda.h @@ -0,0 +1,269 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// +// Changelog: +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_RDA_H_ +#define _I2CDEV_RDA_H_ + +// ----------------------------------------------------------------------------- +// I2C interface implementation setting +// ----------------------------------------------------------------------------- +#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE + +// comment this out if you are using a non-optimal IDE/implementation setting +// but want the compiler to shut up about it +#define I2CDEV_IMPLEMENTATION_WARNINGS + +// ----------------------------------------------------------------------------- +// I2C interface implementation options +// ----------------------------------------------------------------------------- +#define I2CDEV_ARDUINO_WIRE 1 // Wire object from Arduino +#define I2CDEV_BUILTIN_NBWIRE 2 // Tweaked Wire object from Gene Knight's NBWire project + // ^^^ NBWire implementation is still buggy w/some interrupts! +#define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project +#define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library + +// ----------------------------------------------------------------------------- +// Arduino-style "Serial.print" debug constant (uncomment to enable) +// ----------------------------------------------------------------------------- +//#define I2CDEV_SERIAL_DEBUG + +#ifdef ARDUINO + #if ARDUINO < 100 + #include "WProgram.h" + #else + #include "Arduino.h" + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY + #include + #endif +#endif + +// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") +#define I2CDEV_DEFAULT_READ_TIMEOUT 1000 + +class I2Cdev { + public: + I2Cdev(); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static uint16_t readTimeout; +}; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + ////////////////////// + // FastWire 0.24 + // This is a library to help faster programs to read I2C devices. + // Copyright(C) 2012 + // Francesco Ferrara + ////////////////////// + + /* Master */ + #define TW_START 0x08 + #define TW_REP_START 0x10 + + /* Master Transmitter */ + #define TW_MT_SLA_ACK 0x18 + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_ACK 0x28 + #define TW_MT_DATA_NACK 0x30 + #define TW_MT_ARB_LOST 0x38 + + /* Master Receiver */ + #define TW_MR_ARB_LOST 0x38 + #define TW_MR_SLA_ACK 0x40 + #define TW_MR_SLA_NACK 0x48 + #define TW_MR_DATA_ACK 0x50 + #define TW_MR_DATA_NACK 0x58 + + #define TW_OK 0 + #define TW_ERROR 1 + + class Fastwire { + private: + static boolean waitInt(); + + public: + static void setup(int khz, boolean pullup); + static byte beginTransmission(byte device); + static byte write(byte value); + static byte writeBuf(byte device, byte address, byte *data, byte num); + static byte readBuf(byte device, byte address, byte *data, byte num); + static void reset(); + static byte stop(); + }; +#endif + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + + #define NBWIRE_BUFFER_LENGTH 32 + + class TwoWire { + private: + static uint8_t rxBuffer[]; + static uint8_t rxBufferIndex; + static uint8_t rxBufferLength; + + static uint8_t txAddress; + static uint8_t txBuffer[]; + static uint8_t txBufferIndex; + static uint8_t txBufferLength; + + // static uint8_t transmitting; + static void (*user_onRequest)(void); + static void (*user_onReceive)(int); + static void onRequestService(void); + static void onReceiveService(uint8_t*, int); + + public: + TwoWire(); + void begin(); + void begin(uint8_t); + void begin(int); + void beginTransmission(uint8_t); + //void beginTransmission(int); + uint8_t endTransmission(uint16_t timeout=0); + void nbendTransmission(void (*function)(int)) ; + uint8_t requestFrom(uint8_t, int, uint16_t timeout=0); + //uint8_t requestFrom(int, int); + void nbrequestFrom(uint8_t, int, void (*function)(int)); + void send(uint8_t); + void send(uint8_t*, uint8_t); + //void send(int); + void send(char*); + uint8_t available(void); + uint8_t receive(void); + void onReceive(void (*)(int)); + void onRequest(void (*)(void)); + }; + + #define TWI_READY 0 + #define TWI_MRX 1 + #define TWI_MTX 2 + #define TWI_SRX 3 + #define TWI_STX 4 + + #define TW_WRITE 0 + #define TW_READ 1 + + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_NACK 0x30 + + #define CPU_FREQ 16000000L + #define TWI_FREQ 100000L + #define TWI_BUFFER_LENGTH 32 + + /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ + + #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) + #define TW_STATUS (TWSR & TW_STATUS_MASK) + #define TW_START 0x08 + #define TW_REP_START 0x10 + #define TW_MT_SLA_ACK 0x18 + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_ACK 0x28 + #define TW_MT_DATA_NACK 0x30 + #define TW_MT_ARB_LOST 0x38 + #define TW_MR_ARB_LOST 0x38 + #define TW_MR_SLA_ACK 0x40 + #define TW_MR_SLA_NACK 0x48 + #define TW_MR_DATA_ACK 0x50 + #define TW_MR_DATA_NACK 0x58 + #define TW_ST_SLA_ACK 0xA8 + #define TW_ST_ARB_LOST_SLA_ACK 0xB0 + #define TW_ST_DATA_ACK 0xB8 + #define TW_ST_DATA_NACK 0xC0 + #define TW_ST_LAST_DATA 0xC8 + #define TW_SR_SLA_ACK 0x60 + #define TW_SR_ARB_LOST_SLA_ACK 0x68 + #define TW_SR_GCALL_ACK 0x70 + #define TW_SR_ARB_LOST_GCALL_ACK 0x78 + #define TW_SR_DATA_ACK 0x80 + #define TW_SR_DATA_NACK 0x88 + #define TW_SR_GCALL_DATA_ACK 0x90 + #define TW_SR_GCALL_DATA_NACK 0x98 + #define TW_SR_STOP 0xA0 + #define TW_NO_INFO 0xF8 + #define TW_BUS_ERROR 0x00 + + //#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) + //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) + + #ifndef sbi // set bit + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + #endif // sbi + + #ifndef cbi // clear bit + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) + #endif // cbi + + extern TwoWire Wire; + +#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + +#endif /* _I2CDEV_RDA_H_ */