|
| 1 | +/* |
| 2 | +does: |
| 3 | + * can make calls on the speaker & mic |
| 4 | +todo: |
| 5 | + * status notification updates in loop() |
| 6 | + * dim screen when no touches in 1 minute |
| 7 | + * receive calls |
| 8 | + * receive texts |
| 9 | + * candy crush |
| 10 | + |
| 11 | +*/ |
| 12 | + |
| 13 | + |
| 14 | +#include <SPI.h> |
| 15 | +#include <Wire.h> // this is needed even tho we aren't using it |
| 16 | +#include "Adafruit_GFX.h" |
| 17 | +#include "Adafruit_ILI9341.h" |
| 18 | +#include <Adafruit_STMPE610.h> |
| 19 | +#include <SoftwareSerial.h> |
| 20 | +#include "Adafruit_FONA.h" |
| 21 | + |
| 22 | +#define FONA_RX 2 |
| 23 | +#define FONA_TX 3 |
| 24 | +#define FONA_RST 4 |
| 25 | + |
| 26 | +SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX); |
| 27 | +Adafruit_FONA fona = Adafruit_FONA(FONA_RST); |
| 28 | + |
| 29 | + |
| 30 | +// For the Adafruit TFT shield, these are the default. |
| 31 | +#define TFT_DC 9 |
| 32 | +#define TFT_CS 10 |
| 33 | + |
| 34 | +// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC |
| 35 | +Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); |
| 36 | + |
| 37 | +// The STMPE610 uses hardware SPI on the shield, and #8 |
| 38 | +#define STMPE_CS 8 |
| 39 | +Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS); |
| 40 | + |
| 41 | +// This is calibration data for the raw touch data to the screen coordinates |
| 42 | +#define TS_MINX 150 |
| 43 | +#define TS_MINY 130 |
| 44 | +#define TS_MAXX 3800 |
| 45 | +#define TS_MAXY 4000 |
| 46 | + |
| 47 | +/******************* UI details */ |
| 48 | +#define BUTTON_X 40 |
| 49 | +#define BUTTON_Y 100 |
| 50 | +#define BUTTON_W 60 |
| 51 | +#define BUTTON_H 30 |
| 52 | +#define BUTTON_SPACING_X 20 |
| 53 | +#define BUTTON_SPACING_Y 20 |
| 54 | +#define BUTTON_TEXTSIZE 2 |
| 55 | + |
| 56 | +// text box where numbers go |
| 57 | +#define TEXT_X 10 |
| 58 | +#define TEXT_Y 10 |
| 59 | +#define TEXT_W 220 |
| 60 | +#define TEXT_H 50 |
| 61 | +#define TEXT_TSIZE 3 |
| 62 | +#define TEXT_TCOLOR ILI9341_MAGENTA |
| 63 | +// the data (phone #) we store in the textfield |
| 64 | +#define TEXT_LEN 12 |
| 65 | +char textfield[TEXT_LEN+1] = ""; |
| 66 | +uint8_t textfield_i=0; |
| 67 | + |
| 68 | +// We have a status line for like, is FONA working |
| 69 | +#define STATUS_X 10 |
| 70 | +#define STATUS_Y 65 |
| 71 | + |
| 72 | +/* create 15 buttons, in classic candybar phone style */ |
| 73 | +char buttonlabels[15][5] = {"Send", "Clr", "End", "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#" }; |
| 74 | +uint16_t buttoncolors[15] = {ILI9341_DARKGREEN, ILI9341_DARKGREY, ILI9341_RED, |
| 75 | + ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE, |
| 76 | + ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE, |
| 77 | + ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE, |
| 78 | + ILI9341_ORANGE, ILI9341_BLUE, ILI9341_ORANGE}; |
| 79 | +Adafruit_GFX_Button buttons[15]; |
| 80 | + |
| 81 | +// Print something in the mini status bar with either flashstring |
| 82 | +void status(const __FlashStringHelper *msg) { |
| 83 | + tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK); |
| 84 | + tft.setCursor(STATUS_X, STATUS_Y); |
| 85 | + tft.setTextColor(ILI9341_WHITE); |
| 86 | + tft.setTextSize(1); |
| 87 | + tft.print(msg); |
| 88 | +} |
| 89 | +// or charstring |
| 90 | +void status(char *msg) { |
| 91 | + tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK); |
| 92 | + tft.setCursor(STATUS_X, STATUS_Y); |
| 93 | + tft.setTextColor(ILI9341_WHITE); |
| 94 | + tft.setTextSize(1); |
| 95 | + tft.print(msg); |
| 96 | +} |
| 97 | + |
| 98 | +void setup() { |
| 99 | + Serial.begin(9600); |
| 100 | + Serial.println("Arduin-o-Phone!"); |
| 101 | + |
| 102 | + // clear the screen |
| 103 | + tft.begin(); |
| 104 | + tft.fillScreen(ILI9341_BLACK); |
| 105 | + |
| 106 | + // eep touchscreen not found? |
| 107 | + if (!ts.begin()) { |
| 108 | + Serial.println("Couldn't start touchscreen controller"); |
| 109 | + while (1); |
| 110 | + } |
| 111 | + Serial.println("Touchscreen started"); |
| 112 | + |
| 113 | + // create buttons |
| 114 | + for (uint8_t row=0; row<5; row++) { |
| 115 | + for (uint8_t col=0; col<3; col++) { |
| 116 | + buttons[col + row*3].initButton(&tft, BUTTON_X+col*(BUTTON_W+BUTTON_SPACING_X), |
| 117 | + BUTTON_Y+row*(BUTTON_H+BUTTON_SPACING_Y), // x, y, w, h, outline, fill, text |
| 118 | + BUTTON_W, BUTTON_H, ILI9341_WHITE, buttoncolors[col+row*3], ILI9341_WHITE, |
| 119 | + buttonlabels[col + row*3], BUTTON_TEXTSIZE); |
| 120 | + buttons[col + row*3].drawButton(); |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + // create 'text field' |
| 125 | + tft.drawRect(TEXT_X, TEXT_Y, TEXT_W, TEXT_H, ILI9341_WHITE); |
| 126 | + |
| 127 | + status(F("Checking for FONA...")); |
| 128 | + // Check FONA is there |
| 129 | + fonaSS.begin(4800); // if you're using software serial |
| 130 | + |
| 131 | + // See if the FONA is responding |
| 132 | + if (! fona.begin(fonaSS)) { // can also try fona.begin(Serial1) |
| 133 | + status(F("Couldn't find FONA :(")); |
| 134 | + while (1); |
| 135 | + } |
| 136 | + status(F("FONA is OK!")); |
| 137 | + |
| 138 | + // Check we connect to the network |
| 139 | + while (fona.getNetworkStatus() != 1) { |
| 140 | + status(F("Looking for service...")); |
| 141 | + delay(100); |
| 142 | + } |
| 143 | + status(F("Connected to network!")); |
| 144 | + |
| 145 | + // set to external mic & headphone |
| 146 | + fona.setAudio(FONA_EXTAUDIO); |
| 147 | +} |
| 148 | + |
| 149 | + |
| 150 | +void loop(void) { |
| 151 | + TS_Point p; |
| 152 | + |
| 153 | + if (ts.bufferSize()) { |
| 154 | + p = ts.getPoint(); |
| 155 | + } else { |
| 156 | + // this is our way of tracking touch 'release'! |
| 157 | + p.x = p.y = p.z = -1; |
| 158 | + } |
| 159 | + |
| 160 | + // Scale from ~0->4000 to tft.width using the calibration #'s |
| 161 | + if (p.z != -1) { |
| 162 | + p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width()); |
| 163 | + p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height()); |
| 164 | + Serial.print("("); Serial.print(p.x); Serial.print(", "); |
| 165 | + Serial.print(p.y); Serial.print(", "); |
| 166 | + Serial.print(p.z); Serial.println(") "); |
| 167 | + } |
| 168 | + |
| 169 | + // go thru all the buttons, checking if they were pressed |
| 170 | + for (uint8_t b=0; b<15; b++) { |
| 171 | + if (buttons[b].contains(p.x, p.y)) { |
| 172 | + //Serial.print("Pressing: "); Serial.println(b); |
| 173 | + buttons[b].press(true); // tell the button it is pressed |
| 174 | + } else { |
| 175 | + buttons[b].press(false); // tell the button it is NOT pressed |
| 176 | + } |
| 177 | + } |
| 178 | + |
| 179 | + // now we can ask the buttons if their state has changed |
| 180 | + for (uint8_t b=0; b<15; b++) { |
| 181 | + if (buttons[b].justReleased()) { |
| 182 | + // Serial.print("Released: "); Serial.println(b); |
| 183 | + buttons[b].drawButton(); // draw normal |
| 184 | + } |
| 185 | + |
| 186 | + if (buttons[b].justPressed()) { |
| 187 | + buttons[b].drawButton(true); // draw invert! |
| 188 | + |
| 189 | + // if a numberpad button, append the relevant # to the textfield |
| 190 | + if (b >= 3) { |
| 191 | + if (textfield_i < TEXT_LEN) { |
| 192 | + textfield[textfield_i] = buttonlabels[b][0]; |
| 193 | + textfield_i++; |
| 194 | + textfield[textfield_i] = 0; // zero terminate |
| 195 | + |
| 196 | + fona.playDTMF(buttonlabels[b][0]); |
| 197 | + } |
| 198 | + } |
| 199 | + |
| 200 | + // clr button! delete char |
| 201 | + if (b == 1) { |
| 202 | + |
| 203 | + textfield[textfield_i] = 0; |
| 204 | + if (textfield > 0) { |
| 205 | + textfield_i--; |
| 206 | + textfield[textfield_i] = ' '; |
| 207 | + } |
| 208 | + } |
| 209 | + |
| 210 | + // update the current text field |
| 211 | + Serial.println(textfield); |
| 212 | + tft.setCursor(TEXT_X + 2, TEXT_Y+10); |
| 213 | + tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK); |
| 214 | + tft.setTextSize(TEXT_TSIZE); |
| 215 | + tft.print(textfield); |
| 216 | + |
| 217 | + // its always OK to just hang up |
| 218 | + if (b == 2) { |
| 219 | + status(F("Hanging up")); |
| 220 | + fona.hangUp(); |
| 221 | + } |
| 222 | + // we dont really check that the text field makes sense |
| 223 | + // just try to call |
| 224 | + if (b == 0) { |
| 225 | + status(F("Calling")); |
| 226 | + Serial.print("Calling "); Serial.print(textfield); |
| 227 | + |
| 228 | + fona.callPhone(textfield); |
| 229 | + } |
| 230 | + |
| 231 | + delay(100); // UI debouncing |
| 232 | + } |
| 233 | + } |
| 234 | +} |
0 commit comments