diff --git a/examples/APRS-Beacon/1200.wav b/examples/APRS-Beacon/1200.wav new file mode 100755 index 0000000..de71193 Binary files /dev/null and b/examples/APRS-Beacon/1200.wav differ diff --git a/examples/APRS-Beacon/2200.wav b/examples/APRS-Beacon/2200.wav new file mode 100755 index 0000000..2c7d9a0 Binary files /dev/null and b/examples/APRS-Beacon/2200.wav differ diff --git a/examples/ChromeHAMShield/background.js b/examples/ChromeHAMShield/background.js new file mode 100755 index 0000000..a800665 --- /dev/null +++ b/examples/ChromeHAMShield/background.js @@ -0,0 +1,8 @@ +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create("window.html", { + "bounds": { + "width": 400, + "height": 500 + } + }); +}); \ No newline at end of file diff --git a/examples/ChromeHAMShield/manifest.json b/examples/ChromeHAMShield/manifest.json new file mode 100755 index 0000000..11f79c9 --- /dev/null +++ b/examples/ChromeHAMShield/manifest.json @@ -0,0 +1,10 @@ +{ + "name": "", + "description": "HAMShield", + "version": "1.0.0", + "app": { + "background": { + "scripts": ["background.js"] + } + } + } \ No newline at end of file diff --git a/examples/ChromeHAMShield/project.ps b/examples/ChromeHAMShield/project.ps new file mode 100755 index 0000000..7b341aa --- /dev/null +++ b/examples/ChromeHAMShield/project.ps @@ -0,0 +1 @@ +chromeApp \ No newline at end of file diff --git a/examples/ChromeHAMShield/styles.css b/examples/ChromeHAMShield/styles.css new file mode 100755 index 0000000..ab5f11c --- /dev/null +++ b/examples/ChromeHAMShield/styles.css @@ -0,0 +1 @@ +body{} \ No newline at end of file diff --git a/examples/ChromeHAMShield/window.html b/examples/ChromeHAMShield/window.html new file mode 100755 index 0000000..d6bfb7c --- /dev/null +++ b/examples/ChromeHAMShield/window.html @@ -0,0 +1,13 @@ + + + + + +
+ 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 0000000..a580efc Binary files /dev/null and b/examples/SignalTest/Sounds/0.wav differ diff --git a/examples/SignalTest/Sounds/1.wav b/examples/SignalTest/Sounds/1.wav new file mode 100755 index 0000000..327b3bf Binary files /dev/null and b/examples/SignalTest/Sounds/1.wav differ diff --git a/examples/SignalTest/Sounds/2.wav b/examples/SignalTest/Sounds/2.wav new file mode 100755 index 0000000..f2fe384 Binary files /dev/null and b/examples/SignalTest/Sounds/2.wav differ diff --git a/examples/SignalTest/Sounds/3.wav b/examples/SignalTest/Sounds/3.wav new file mode 100755 index 0000000..e8ded20 Binary files /dev/null and b/examples/SignalTest/Sounds/3.wav differ diff --git a/examples/SignalTest/Sounds/4.wav b/examples/SignalTest/Sounds/4.wav new file mode 100755 index 0000000..b5c3807 Binary files /dev/null and b/examples/SignalTest/Sounds/4.wav differ diff --git a/examples/SignalTest/Sounds/5.wav b/examples/SignalTest/Sounds/5.wav new file mode 100755 index 0000000..be9a31b Binary files /dev/null and b/examples/SignalTest/Sounds/5.wav differ diff --git a/examples/SignalTest/Sounds/6.wav b/examples/SignalTest/Sounds/6.wav new file mode 100755 index 0000000..6eb054c Binary files /dev/null and b/examples/SignalTest/Sounds/6.wav differ diff --git a/examples/SignalTest/Sounds/7.wav b/examples/SignalTest/Sounds/7.wav new file mode 100755 index 0000000..bf01012 Binary files /dev/null and b/examples/SignalTest/Sounds/7.wav differ diff --git a/examples/SignalTest/Sounds/8.wav b/examples/SignalTest/Sounds/8.wav new file mode 100755 index 0000000..05c474c Binary files /dev/null and b/examples/SignalTest/Sounds/8.wav differ diff --git a/examples/SignalTest/Sounds/9.wav b/examples/SignalTest/Sounds/9.wav new file mode 100755 index 0000000..3bcd22d Binary files /dev/null and b/examples/SignalTest/Sounds/9.wav differ diff --git a/examples/SignalTest/Sounds/dbm.wav b/examples/SignalTest/Sounds/dbm.wav new file mode 100755 index 0000000..e51c41b Binary files /dev/null and b/examples/SignalTest/Sounds/dbm.wav differ diff --git a/examples/SignalTest/Sounds/minus.wav b/examples/SignalTest/Sounds/minus.wav new file mode 100755 index 0000000..8b85cd0 Binary files /dev/null and b/examples/SignalTest/Sounds/minus.wav differ 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_ */