DIY Smart Station-Avoiding Spirit Radio
Designed and programmed by Two Faces. An experimental prototype.
This radio skips over stations automatically as it scans through the FM frequencies, in tenths or hundredths of Mhz. It can scan in-order or randomly. The delay between stations, as well as the width of the avoided area are adjustable. You can also select just a portion of the dial to scan within.
A minimum or maximum station power threshold can be set so that it can skip frequencies with too high or too low of a signal. By default, we have it set to skip over any frequency with more than ‘5’ as the power level, so we hear only the empty space between stations.
Ingredients
- Arduino Uno Clone – highly recommend this SMD version
- TEA5767 FM Stereo Radio Module
- LCD Touch Display
Optional
- Inline Volume Control
- Wires with Pin/Sockets (If you don’t want to solder)
- Uno Enclosure
- Lipo Battery
- Battery Management Module
- Switch – Hella Tiny Toggle
Hardware Construction
Connect the 5V+ and GND pins between the Uno and the TEA5767 Module.
Next connect the data pins. SLC connects to Uno pin A5, SDA connects to Uno pin A4. (SCL & SLC mean the same thing)
Special versions of the Uno like this one have extra places where you can connect to these pins, which is what we did in our prototype pictured below.
Both can be powered together by a USB battery connected to the Uno’s USB port.
***IMPORTANT
The display needs one of it’s pins moved to be compatible with the FM module.
I cut two pins, and ran a wire between one of then and another pin. Keep this in mind if you are using wires with connectors as well, this wire will need to be connected to the display the way my soldered wire does.
Photos of Our Prototype Construction
Firmware Code
For the Arduino IDE
Don’t forget to download the appropriate libraries
This code is Open Source so that the community can debunk and debug it’s use with full scientific disclosure. This code is provided in good faith with the understanding that it is not to be distributed in a commercial product, in whole or in part, without the written permission of Two Faces.
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft; // hard-wired for UNO shields anyway.
#include <TouchScreen.h>
#include <Wire.h>
#include <TEA5767.h>
#include "img.h"
TEA5767 radio = TEA5767();
float freq = 88;
byte stren;
float lastFreq;
bool touch;
byte spd;
bool scan;
bool scanRev;
byte si[200];
bool hide[200];
byte index;
byte oldIndex;
float startFreq = 88;
byte param;
bool autoHide;
byte hideWidth;
bool hund; // hundreths
byte maxStr = 4;
byte minStr;
bool shuf;
float fi;
byte minI = 0;
byte maxI = 199;
char *name = "woz.lol"; //edit name of shield
const int XP = 8, XM = A2, YP = A3, YM = 9; //240x320 ID=0x9341
const int TS_LEFT = 929, TS_RT = 94, TS_TOP = 76, TS_BOT = 906;
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
TSPoint tp;
#define MINPRESSURE 200
#define MAXPRESSURE 1000
#define LCD_RESET 0
int16_t BOXSIZE;
int16_t PENRADIUS = 1;
uint16_t ID, oldcolor, currentcolor;
uint8_t Orientation = 2; //PORTRAIT
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
void setup(void) {
Wire.begin();
randomSeed(radio.getSignalLevel());
lastFreq = 0;
tft.reset();
ID = tft.readID();
tft.begin(ID);
Serial.begin(9600);
tft.setRotation(Orientation);
BOXSIZE = tft.width() / 6;
tft.fillScreen(BLACK);
tft.drawBitmap(5, tft.height() - BOXSIZE + 7, rbshuf, 31, 26, BLUE);
tft.drawBitmap(BOXSIZE + 3, tft.height() - BOXSIZE + 8, rbspeed, 35, 26, YELLOW);
tft.drawBitmap(BOXSIZE * 2 + 7, tft.height() - BOXSIZE + 6, rbrange, 28, 28, MAGENTA);
tft.drawBitmap(BOXSIZE * 3 + 4, tft.height() - BOXSIZE + 11, rb1, 33, 21, MAGENTA);
tft.drawBitmap(BOXSIZE * 4 + 7, tft.height() - BOXSIZE + 14, rbwidth, 28, 18, CYAN);
tft.drawLine(BOXSIZE * 4 + 19 - (6 * hideWidth), tft.height() - BOXSIZE + 9, BOXSIZE * 4 + 22 + (6 * hideWidth), tft.height() - BOXSIZE + 9, CYAN);
tft.drawLine(BOXSIZE * 4 + 18 - (6 * hideWidth), tft.height() - BOXSIZE + 7, BOXSIZE * 4 + 18 - (6 * hideWidth), tft.height() - BOXSIZE + 11, CYAN);
tft.drawLine(BOXSIZE * 4 + 23 + (6 * hideWidth), tft.height() - BOXSIZE + 7, BOXSIZE * 4 + 23 + (6 * hideWidth), tft.height() - BOXSIZE + 11, CYAN);
tft.drawBitmap(BOXSIZE * 5 + 7, tft.height() - BOXSIZE + 14, rbwidth, 28, 18, CYAN);
tft.drawBitmap(BOXSIZE * 5 + 15, tft.height() - BOXSIZE + 4, rbx, 12, 11, CYAN);
tft.drawBitmap(tft.width() - BOXSIZE + 9, tft.height() - BOXSIZE * 2 + 4, rbbottom, 24, 33, GREEN);
tft.drawBitmap(tft.width() - BOXSIZE + 9, tft.height() - BOXSIZE * 3 + 3, rbtop, 24, 34, RED);
tft.drawBitmap(tft.width() - BOXSIZE + 4, tft.height() - BOXSIZE * 4 + 3, rbauto, 35, 34, CYAN);
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 5 + 8, rbplay, 28, 23, WHITE);
tft.setTextSize(1);
tft.setCursor(143, 15);
tft.setTextColor(GREEN);
tft.print("Min");
tft.setTextColor(CYAN);
tft.setTextColor(WHITE);
tft.print(" Power ");
tft.setTextColor(RED);
tft.print("Max");
updateHund();
updateRange();
updateBar();
updateStr();
updateSpd();
updateArrows();
updateFreq();
}
void loop() {
touchCheck();
if (scan) {
if (shuf) {
index = (random(minI, maxI));
while ((!autoHide) && ((hide[index]) || ((hideWidth) && (index < 199) && (hide[index + 1])) || ((hideWidth) && (index > 0) && (hide[index - 1])) || ((hideWidth == 2) && (index < 198) && (hide[index + 2])) || ((hideWidth == 2) && (index > 1) && (hide[index - 2])))) {
index = (random(minI, maxI));
}
fi = index;
freq = (fi / 10) + startFreq;
float r = random(10) / 100.00;
if (hund) freq = freq - .05 + r;
} else {
if (hund) {
if (scanRev) {
freq -= .01;
fi = index;
if (freq <= (fi / 10) + startFreq - .05) {
index--;
if ((index == 255) || (index < minI)) {
index = maxI;
fi = index;
freq = (fi / 10) + startFreq;
}
}
} else {
freq += .01;
fi = index;
if (freq >= (fi / 10) + startFreq + .05) {
index++;
if ((index > 199) || (index > maxI)) {
index = minI;
fi = index;
freq = (fi / 10) + startFreq;
}
}
}
} else { // if not hund
if (scanRev) {
index--;
if ((index == 255) || (index < minI) || (index > maxI)) {
if (index < 199) tft.fillRect(((index + 1) - (((index + 1) / 50) * 50)) * 4, (((index + 1) / 50) * 60) + 86, 4, 4, BLACK);
index = maxI;
}
} else {
index++;
if ((index > 199) || (index > maxI) || (index < minI)) {
tft.fillRect(((index - 1) - (((index - 1) / 50) * 50)) * 4, (((index - 1) / 50) * 60) + 86, 4, 4, BLACK);
index = minI;
}
}
fi = index;
freq = (fi / 10) + startFreq;
}
}
updateFreq();
scanDelay();
} // end if scan active
touch = false;
}
void scanDelay() {
for (int c = 0; c <= sq(spd); c++) {
touchCheck();
if (touch) return;
}
}
void updateFreq() {
byte row;
if ((scan) && ((hide[index]) || ((hideWidth) && (index < 199) && (hide[index + 1])) || ((hideWidth) && (index > 0) && (hide[index - 1])) || ((hideWidth == 2) && (index < 198) && (hide[index + 2])) || ((hideWidth == 2) && (index > 1) && (hide[index - 2])))) {
touch = true;
} else {
if (freq != lastFreq) {
radio.setFrequency(freq);
if ((freq >= 100) && (lastFreq < 100) || (freq <= 100) && (lastFreq > 100)) {
updateHund();
}
lastFreq = freq;
delay(20);
stren = radio.getSignalLevel();
if ((scan) && (autoHide) && ((stren < minStr) || (stren > maxStr))) {
hide[index] = true;
touch = true;
} else if ((scan) && (autoHide)) {
hide[index] = false;
}
tft.fillRect(0, 0, 130, 21, BLACK);
tft.setCursor(0, 0);
tft.setTextColor(WHITE);
tft.setTextSize(3);
tft.print(freq, 2);
tft.setTextSize(1);
tft.print("MHz");
tft.fillRect(177, 0, 24, 14, BLACK);
tft.setCursor(177, 0);
tft.setTextSize(2);
if (hide[index]) {
tft.setTextColor(CYAN);
} else {
tft.setTextColor(WHITE);
}
if (stren < 10) tft.print("0");
tft.print(stren);
updateBar();
}
}
if (index == 0) tft.fillRect(196, 251, 4, 4, BLACK);
if (index == 199) tft.fillRect(0, 86, 4, 4, BLACK);
row = index / 50;
// tft.fillRect(((index - 1) - (((index - 1) / 50) * 50)) * 4, (((index - 1) / 50) * 60) + 86, 4, 4, BLACK);
// if (index < 199) tft.fillRect(((index + 1) - (((index + 1) / 50) * 50)) * 4, (((index + 1) / 50) * 60) + 86, 4, 4, BLACK);
tft.fillRect((oldIndex - ((oldIndex / 50) * 50)) * 4, ((oldIndex / 50) * 60) + 86, 4, 4, BLACK);
oldIndex = index;
tft.fillRect((index - (row * 50)) * 4, (row * 60) + 86, 4, 4, WHITE);
}
void updateRange() {
byte row;
tft.fillRect(0, 31, 101, 8, BLACK);
tft.setTextColor(MAGENTA);
tft.setTextSize(1);
tft.setCursor(0, 31);
fi = minI;
tft.print(startFreq + (fi / 10), 2);
tft.print("-");
fi = maxI + 1;
tft.print(startFreq + (fi / 10), 2);
tft.print(" MHz");
for (int ti = 0; ti < 200; ti++) {
row = ti / 50;
tft.fillRect((ti - (row * 50)) * 4, (row * 60) + 90, 4, 4, tft.color565(0, 0, 0));
tft.fillRect((ti - (row * 50)) * 4, (row * 60) + 90, 4, 3 + ((ti % 10) == 0) - 2 * ((ti >= minI) && (ti <= maxI)), tft.color565(128, 128 * ((ti >= minI) && (ti <= maxI)), 128));
}
}
void updateBar() {
byte row;
row = index / 50;
if (hide[index]) {
tft.fillRect((index - (row * 50)) * 4, (row * 60) + 40, 4, 45, tft.color565(0, 64, 64));
} else {
tft.fillRect((index - (row * 50)) * 4, (row * 60) + 40, 4, 45, BLACK);
}
tft.fillRect((index - (row * 50)) * 4, (row * 60) + 85 - (stren * 3), 4, stren * 3, tft.color565(255 - (stren * 17), stren * 17, hide[index] * 128));
}
void updateStr() {
tft.fillRect(140, 0, 36, 14, BLACK);
tft.setCursor(140, 0);
tft.setTextSize(2);
tft.setTextColor(GREEN);
if (minStr < 10) tft.print("0");
tft.print(minStr);
tft.print("<");
tft.setCursor(200, 0);
tft.fillRect(200, 0, 36, 14, BLACK);
tft.setTextColor(RED);
tft.print("<");
if (maxStr < 10) tft.print("0");
tft.print(maxStr);
}
void updateSpd() {
tft.fillRect(212, 22, 24, 17, BLACK);
tft.setTextSize(1);
tft.setCursor(182, 25);
tft.setTextColor(YELLOW);
tft.print("Wait ");
tft.setTextSize(2);
tft.print(spd);
}
void updateHund() {
tft.setTextSize(3);
tft.setTextColor(BLACK);
tft.setCursor(54, 6);
tft.print("___");
tft.setTextColor(WHITE);
tft.setCursor(54 + (hund * 18) + ((freq >= 100) * 18), 6);
tft.print("_");
}
void boxReset() {
tft.drawRect(BOXSIZE * 2 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
tft.drawRect(BOXSIZE + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
tft.drawRect(BOXSIZE * 4 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 2 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 3 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
tft.drawBitmap(BOXSIZE * 2 + 7, tft.height() - BOXSIZE + 6, rbrange, 28, 28, MAGENTA);
}
void updateArrows() {
switch (param) {
case 0:
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 6 + 2, rbdown, 28, 34, WHITE);
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 7 + 4, rbup, 28, 34, WHITE);
break;
case 1:
case 2:
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 6 + 2, rbdown, 28, 34, MAGENTA);
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 7 + 4, rbup, 28, 34, MAGENTA);
break;
case 3:
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 6 + 2, rbdown, 28, 34, YELLOW);
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 7 + 4, rbup, 28, 34, YELLOW);
break;
case 4:
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 6 + 2, rbdown, 28, 34, GREEN);
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 7 + 4, rbup, 28, 34, GREEN);
break;
case 5:
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 6 + 2, rbdown, 28, 34, RED);
tft.drawBitmap(tft.width() - BOXSIZE + 7, tft.height() - BOXSIZE * 7 + 4, rbup, 28, 34, RED);
break;
}
}
void touchCheck() {
byte row;
uint16_t xpos, ypos; //screen coordinates
tp = ts.getPoint(); //tp.x, tp.y are ADC values
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) {
// tp = ts.getPoint(); //tp.x, tp.y are ADC values
if (!touch) {
touch = true;
switch (Orientation) {
case 0:
xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width());
ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height());
break;
case 1:
xpos = map(tp.y, TS_TOP, TS_BOT, 0, tft.width());
ypos = map(tp.x, TS_RT, TS_LEFT, 0, tft.height());
break;
case 2:
xpos = map(tp.x, TS_RT, TS_LEFT, 0, tft.width());
ypos = map(tp.y, TS_BOT, TS_TOP, 0, tft.height());
break;
case 3:
xpos = map(tp.y, TS_BOT, TS_TOP, 0, tft.width());
ypos = map(tp.x, TS_LEFT, TS_RT, 0, tft.height());
break;
}
if (ypos > tft.height() - BOXSIZE) {
if (xpos < BOXSIZE) {
if (shuf) {
shuf = false;
tft.drawRect(2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
} else {
shuf = true;
tft.drawRect(2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
}
delay(400);
} else if (xpos < BOXSIZE * 2) {
if (param == 3) { // speed
tft.drawRect(BOXSIZE * 1 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
param = 0;
updateArrows();
} else {
param = 3;
updateArrows();
boxReset();
tft.drawRect(BOXSIZE + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
}
delay(400);
} else if (xpos < BOXSIZE * 3) {
if (param < 3) {
param++;
} else {
param = 1;
}
if (param > 2) { // // range
tft.drawRect(BOXSIZE * 2 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
tft.drawBitmap(BOXSIZE * 2 + 7, tft.height() - BOXSIZE + 6, rbrange, 28, 28, MAGENTA);
param = 0;
updateArrows();
} else {
updateArrows();
boxReset();
tft.drawRect(BOXSIZE * 2 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
if (param == 1) {
tft.drawLine(BOXSIZE * 2 + 8, tft.height() - BOXSIZE + 6, BOXSIZE * 2 + 8, tft.height() - BOXSIZE + 10, WHITE);
tft.drawLine(BOXSIZE * 2 + 10, tft.height() - BOXSIZE + 8, BOXSIZE * 2 + 19, tft.height() - BOXSIZE + 8, WHITE);
} else {
tft.drawBitmap(BOXSIZE * 2 + 7, tft.height() - BOXSIZE + 6, rbrange, 28, 28, MAGENTA);
tft.drawLine(BOXSIZE * 2 + 20, tft.height() - BOXSIZE + 8, BOXSIZE * 2 + 32, tft.height() - BOXSIZE + 8, WHITE);
tft.drawLine(BOXSIZE * 2 + 33, tft.height() - BOXSIZE + 6, BOXSIZE * 2 + 33, tft.height() - BOXSIZE + 10, WHITE);
}
}
delay(400);
} else if (xpos < BOXSIZE * 4) { // hund
if (hund) {
tft.drawRect(BOXSIZE * 3 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
hund = false;
} else {
tft.drawRect(BOXSIZE * 3 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
hund = true;
}
updateHund();
delay(400);
} else if (xpos < BOXSIZE * 5) { //hide width
tft.drawLine(BOXSIZE * 4 + 19 - (6 * hideWidth), tft.height() - BOXSIZE + 9, BOXSIZE * 4 + 22 + (6 * hideWidth), tft.height() - BOXSIZE + 9, BLACK);
tft.drawLine(BOXSIZE * 4 + 18 - (6 * hideWidth), tft.height() - BOXSIZE + 7, BOXSIZE * 4 + 18 - (6 * hideWidth), tft.height() - BOXSIZE + 11, BLACK);
tft.drawLine(BOXSIZE * 4 + 23 + (6 * hideWidth), tft.height() - BOXSIZE + 7, BOXSIZE * 4 + 23 + (6 * hideWidth), tft.height() - BOXSIZE + 11, BLACK);
hideWidth++;
if (hideWidth > 2) hideWidth = 0;
tft.drawLine(BOXSIZE * 4 + 19 - (6 * hideWidth), tft.height() - BOXSIZE + 9, BOXSIZE * 4 + 22 + (6 * hideWidth), tft.height() - BOXSIZE + 9, CYAN);
tft.drawLine(BOXSIZE * 4 + 18 - (6 * hideWidth), tft.height() - BOXSIZE + 7, BOXSIZE * 4 + 18 - (6 * hideWidth), tft.height() - BOXSIZE + 11, CYAN);
tft.drawLine(BOXSIZE * 4 + 23 + (6 * hideWidth), tft.height() - BOXSIZE + 7, BOXSIZE * 4 + 23 + (6 * hideWidth), tft.height() - BOXSIZE + 11, CYAN);
tft.drawRect(BOXSIZE * 4 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
delay(400);
tft.drawRect(BOXSIZE * 4 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
} else if (xpos < BOXSIZE * 6) {
if (hide[index]) {
hide[index] = false;
} else {
hide[index] = true;
}
tft.drawRect(BOXSIZE * 5 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
delay(200);
tft.drawRect(BOXSIZE * 5 + 2, tft.height() - BOXSIZE + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
updateBar();
}
} // end bottom row
if ((xpos > tft.width() - BOXSIZE) && (ypos < tft.height() - BOXSIZE)) {
if (ypos > tft.height() - BOXSIZE * 2) {
if (param == 4) { // minStr
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 2 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
param = 0;
updateArrows();
} else {
param = 4;
updateArrows();
boxReset();
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 2 + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
}
delay(400);
} else if (ypos > tft.height() - BOXSIZE * 3) {
if (param == 5) { // maxStr
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 3 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
param = 0;
updateArrows();
} else {
param = 5;
updateArrows();
boxReset();
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 3 + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
}
delay(400);
} else if (ypos > tft.height() - BOXSIZE * 4) {
if (autoHide) { // autoHide
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 4 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
autoHide = false;
} else {
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 4 + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
autoHide = true;
}
delay(400);
} else if (ypos > tft.height() - BOXSIZE * 5) {
if (scan) { // play
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 5 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
scan = false;
} else {
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 5 + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
scan = true;
}
delay(400);
} else if (ypos > tft.height() - BOXSIZE * 6) { // down
touch = false;
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 6 + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
switch (param) {
case 0:
if (scan) scanRev = true;
if (hund) {
freq -= .01;
fi = index;
if (freq <= (fi / 10) + startFreq - .05) {
index--;
if (index == 255) {
index = 199;
freq = startFreq + 19.9;
}
}
} else {
index--;
if (index == 255) index = 199;
fi = index;
freq = (fi / 10) + startFreq;
}
updateFreq();
break;
case 1:
minI--;
if (minI == 255) minI = 0;
updateRange();
break;
case 2:
maxI--;
if (maxI == 255) maxI = 0;
updateRange();
break;
case 3: //speed
spd--;
if (spd > 99) spd = 99;
updateSpd();
break;
case 4:
minStr--;
if (minStr == 255) minStr = 15;
updateStr();
break;
case 5:
maxStr--;
if (maxStr == 255) maxStr = 15;
updateStr();
break;
}
delay(100);
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 6 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
} else if (ypos > tft.height() - BOXSIZE * 7) { // up
touch = false;
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 7 + 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
switch (param) {
case 0:
if (scan) scanRev = false;
if (hund) {
freq += .01;
fi = index;
if (freq >= (fi / 10) + startFreq + .05) {
index++;
if (index > 199) {
index = 0;
freq = startFreq;
}
}
} else {
index++;
if (index > 199) index = 0;
fi = index;
freq = (fi / 10) + startFreq;
}
updateFreq();
break;
case 1:
minI++;
if (minI > 199) minI = 199;
updateRange();
break;
case 2:
maxI++;
if (maxI > 199) maxI = 199;
updateRange();
break;
case 3: //speed
spd++;
if (spd > 99) spd = 0;
updateSpd();
break;
case 4:
minStr++;
if (minStr > 15) minStr = 0;
updateStr();
break;
case 5:
maxStr++;
if (maxStr > 15) maxStr = 0;
updateStr();
break;
}
delay(100);
tft.drawRect(tft.width() - BOXSIZE + 2, tft.height() - BOXSIZE * 7 + 1, BOXSIZE - 2, BOXSIZE - 2, BLACK);
}
} // end right column of buttons
if (xpos < 140 && ypos < 20) {
boxReset();
param = 0;
updateArrows();
} //end check
if ((xpos < tft.width() - BOXSIZE) && (ypos > 30) && (ypos < tft.height() - BOXSIZE)) {
for (byte ti = 0; ti < 200; ti++) {
row = ti / 50;
if ((xpos == (ti - (row * 50)) * 4) && (ypos > (row * 60) + 30) && (ypos < (row * 60) + 90)) {
switch (param) { //
case 1:
minI = ti;
updateRange();
break;
case 2:
maxI = ti;
updateRange();
break;
default:
tft.fillRect((index - ((index / 50) * 50)) * 4, ((index / 50) * 60) + 86, 4, 4, BLACK);
index = ti;
fi = index;
freq = (fi / 10) + startFreq;
updateFreq();
updateBar();
break;
}
}
}
} //end check
} //end check if new touch
} //end touch check
}
// contents of img.h
// image bitmaps file (Arduino tab)
// 'rbplay', 28x23px
const unsigned char rbplay [] PROGMEM = {
0x80, 0x01, 0xf1, 0xf0, 0xc0, 0x01, 0xf1, 0xf0, 0xe0, 0x01, 0xf1, 0xf0, 0xf0, 0x01, 0xf1, 0xf0,
0xf8, 0x01, 0xf1, 0xf0, 0xfc, 0x01, 0xf1, 0xf0, 0xfe, 0x01, 0xf1, 0xf0, 0xff, 0x01, 0xf1, 0xf0,
0xff, 0x81, 0xf1, 0xf0, 0xff, 0xc1, 0xf1, 0xf0, 0xff, 0xe1, 0xf1, 0xf0, 0xff, 0xf1, 0xf1, 0xf0,
0xff, 0xe1, 0xf1, 0xf0, 0xff, 0xc1, 0xf1, 0xf0, 0xff, 0x81, 0xf1, 0xf0, 0xff, 0x01, 0xf1, 0xf0,
0xfe, 0x01, 0xf1, 0xf0, 0xfc, 0x01, 0xf1, 0xf0, 0xf8, 0x01, 0xf1, 0xf0, 0xf0, 0x01, 0xf1, 0xf0,
0xe0, 0x01, 0xf1, 0xf0, 0xc0, 0x01, 0xf1, 0xf0, 0x80, 0x01, 0xf1, 0xf0
};
// 'rbshuf', 31x26px
const unsigned char rbshuf [] PROGMEM = {
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x1c,
0x7f, 0x00, 0x03, 0xfe, 0xff, 0xc0, 0x0f, 0xfe, 0x01, 0xe0, 0x1e, 0x1c, 0x00, 0x70, 0x38, 0x38,
0x00, 0x38, 0x70, 0x70, 0x00, 0x1c, 0x60, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xc0, 0x00,
0x00, 0x18, 0xe0, 0x20, 0x00, 0x38, 0x70, 0x70, 0x00, 0x70, 0x38, 0x38, 0x01, 0xe0, 0x1e, 0x1c,
0xff, 0xc0, 0x0f, 0xfe, 0x7f, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x38,
0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x20
};
// 'rbdown', 28x34px
const unsigned char rbdown [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x1f, 0x80, 0x00,
0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00,
0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00,
0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x18, 0x3f, 0xc1, 0x80,
0x7c, 0x3f, 0xc3, 0xe0, 0xfe, 0x3f, 0xc7, 0xf0, 0xff, 0x3f, 0xcf, 0xf0, 0xff, 0xbf, 0xdf, 0xf0,
0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0x80,
0x0f, 0xff, 0xff, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xf8, 0x00,
0x00, 0xff, 0xf0, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x1f, 0x80, 0x00,
0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00
};
// 'rbrange', 28x28px
const unsigned char rbrange [] PROGMEM = {
0x40, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x20, 0x7f, 0xff, 0xff, 0xe0, 0x40, 0x00, 0x00, 0x20,
0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x80, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0xf0, 0x80, 0x00, 0x00, 0x10,
0x8f, 0xc0, 0x00, 0x10, 0x98, 0x60, 0x7f, 0x90, 0x90, 0x20, 0x00, 0x10, 0xa0, 0x10, 0x00, 0x10,
0xa0, 0x10, 0x7f, 0x90, 0xa0, 0x10, 0x00, 0x10, 0x90, 0x20, 0x00, 0x10, 0x98, 0x60, 0x7f, 0x90,
0x87, 0x80, 0x00, 0x10, 0x80, 0x00, 0x00, 0x30, 0x7f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00
};
// 'rbbottom', 24x33px
const unsigned char rbbottom [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfc, 0x00, 0x03, 0xf8, 0x00,
0x0f, 0xe0, 0x00, 0x3f, 0x80, 0x00, 0xfe, 0x00, 0x03, 0xfc, 0x00, 0x0f, 0xf0, 0x00, 0x1f, 0xc0,
0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x0f, 0xf0, 0x00, 0x03, 0xf8, 0x00,
0x00, 0xfe, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x0f, 0xe0, 0x00, 0x07, 0xf8, 0x00, 0x01, 0xfc, 0x00,
0x00, 0x7e, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
// 'rb1', 33x21px
const unsigned char rb1 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x07, 0x06, 0x00, 0x07, 0x02, 0x0f, 0x0e, 0x00, 0x05,
0x02, 0x09, 0x8a, 0x00, 0x01, 0x04, 0x08, 0x82, 0x00, 0x01, 0x04, 0x10, 0x82, 0x00, 0x01, 0x04,
0x10, 0x82, 0x00, 0x01, 0x04, 0x10, 0x82, 0x00, 0x01, 0x04, 0x10, 0x82, 0x00, 0x01, 0x04, 0x10,
0x82, 0x00, 0x01, 0x08, 0x10, 0x82, 0x00, 0x01, 0x08, 0x10, 0x82, 0x00, 0x01, 0x08, 0x10, 0x82,
0x00, 0x01, 0x08, 0x10, 0x82, 0x00, 0x01, 0x08, 0x08, 0x82, 0x00, 0x01, 0x08, 0x09, 0x82, 0x00,
0x47, 0xc8, 0x8d, 0x0f, 0x80, 0x47, 0xd0, 0x87, 0x0f, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'rbspeed', 35x26px
const unsigned char rbspeed [] PROGMEM = {
0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00,
0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x07, 0xf8, 0x7f, 0xfc, 0x00, 0x07, 0xfd,
0xf0, 0x1e, 0x00, 0x00, 0x01, 0xc1, 0x0f, 0x00, 0x00, 0x03, 0x83, 0x03, 0x80, 0x00, 0x07, 0x03,
0x03, 0x80, 0x3f, 0xc7, 0x03, 0x01, 0xc0, 0x00, 0x06, 0x03, 0x01, 0xc0, 0x00, 0x0e, 0x03, 0x00,
0xc0, 0x00, 0x0e, 0x03, 0x00, 0xc0, 0x7f, 0x8e, 0x01, 0xf8, 0xc0, 0x00, 0x0e, 0x00, 0x00, 0xc0,
0x00, 0x0e, 0x00, 0x00, 0xc0, 0x00, 0x06, 0x00, 0x01, 0xc0, 0x3f, 0xc7, 0x00, 0x01, 0x80, 0x00,
0x03, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x07, 0x00, 0x00, 0x01, 0xc0, 0x0f, 0x00, 0x07, 0xf8,
0xf0, 0x3e, 0x00, 0x07, 0xfc, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
// 'rbx', 12x11px
const unsigned char rbx [] PROGMEM = {
0xc0, 0x30, 0x60, 0x60, 0x30, 0xc0, 0x19, 0x80, 0x0f, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x19, 0x80,
0x30, 0xc0, 0x60, 0x60, 0xc0, 0x30
};
// 'rbauto', 35x34px
const unsigned char rbauto [] PROGMEM = {
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00,
0x1f, 0x9c, 0x00, 0x00, 0x00, 0x7f, 0x9f, 0x00, 0x00, 0x01, 0xe7, 0x03, 0xc0, 0x00, 0x03, 0x86,
0x00, 0xe0, 0x00, 0x07, 0x04, 0x00, 0x70, 0x00, 0x0e, 0x00, 0x00, 0x38, 0x00, 0x1c, 0x03, 0xc0,
0x1c, 0x00, 0x38, 0x03, 0xc0, 0x0e, 0x00, 0x30, 0x03, 0xc0, 0x06, 0x00, 0x70, 0xf3, 0xcf, 0x07,
0x00, 0x60, 0xf3, 0xcf, 0x03, 0x00, 0x60, 0xf3, 0xcf, 0x03, 0x00, 0x60, 0xf3, 0xcf, 0x03, 0x00,
0xe4, 0xf3, 0xcf, 0x39, 0x80, 0xc4, 0xf3, 0xcf, 0x39, 0x80, 0xc4, 0xf3, 0xcf, 0x39, 0x80, 0xe4,
0xf3, 0xcf, 0x39, 0x80, 0x64, 0xf3, 0xcf, 0x23, 0x80, 0x64, 0xf3, 0xcf, 0x2b, 0x00, 0x64, 0xf3,
0xcf, 0x2f, 0x00, 0x20, 0xf3, 0xcf, 0x2f, 0xe0, 0x00, 0xf3, 0xcf, 0x2f, 0xc0, 0x1f, 0x33, 0xcf,
0x27, 0x00, 0x3f, 0x93, 0xcf, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x10, 0x00, 0x3e, 0x00, 0x00, 0x38,
0x00, 0x37, 0x80, 0x00, 0x70, 0x00, 0x11, 0xc0, 0x01, 0xe0, 0x00, 0x00, 0xf8, 0x0f, 0x80, 0x00,
0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00
};
// 'rbwidth', 28x18px
const unsigned char rbwidth [] PROGMEM = {
0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x03, 0xcf, 0x3c, 0x00,
0x03, 0xcf, 0x3c, 0x00, 0x03, 0xcf, 0x3c, 0x00, 0x03, 0xcf, 0x3c, 0x00, 0xf3, 0xcf, 0x3c, 0xf0,
0xf3, 0xcf, 0x3c, 0xf0, 0xf3, 0xcf, 0x3c, 0xf0, 0xf3, 0xcf, 0x3c, 0xf0, 0xf3, 0xcf, 0x3c, 0xf0,
0xf3, 0xcf, 0x3c, 0xf0, 0xf3, 0xcf, 0x3c, 0xf0, 0xf3, 0xcf, 0x3c, 0xf0, 0xf3, 0xcf, 0x3c, 0xf0,
0xf3, 0xcf, 0x3c, 0xf0, 0xf3, 0xcf, 0x3c, 0xf0
};
// 'rbtop', 24x34px
const unsigned char rbtop [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
0x00, 0x7e, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x1f, 0xe0, 0x00, 0x07, 0xf0, 0x00, 0x01, 0xfc, 0x00,
0x00, 0x7f, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x0f, 0xf0, 0x00, 0x03, 0xfc, 0x00, 0x00, 0xfe, 0x00,
0x00, 0xfe, 0x00, 0x03, 0xf8, 0x00, 0x0f, 0xf0, 0x00, 0x3f, 0xc0, 0x00, 0x7f, 0x00, 0x01, 0xfc,
0x00, 0x07, 0xf0, 0x00, 0x1f, 0xc0, 0x00, 0x3f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'rbup', 28x34px
const unsigned char rbup [] PROGMEM = {
0x00, 0x06, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x3f, 0xc0, 0x00,
0x00, 0x7f, 0xe0, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xfc, 0x00,
0x07, 0xff, 0xfe, 0x00, 0x0f, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0xc0,
0x7f, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xbf, 0xdf, 0xf0, 0xff, 0x3f, 0xcf, 0xf0,
0xfe, 0x3f, 0xc7, 0xf0, 0x7c, 0x3f, 0xc3, 0xe0, 0x18, 0x3f, 0xc1, 0x80, 0x00, 0x3f, 0xc0, 0x00,
0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00,
0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00,
0x00, 0x3f, 0xc0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x1f, 0x80, 0x00,
0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};