├── KiCad └── phone.zip ├── README.md ├── BuratinoPhone ├── includes │ ├── FONAExtIncludes.h │ ├── FONAConfig.h │ └── platform │ │ ├── FONAPlatform.h │ │ └── FONAPlatStd.h ├── Adafruit_FONA.h ├── BuratinoPhone.ino └── Adafruit_FONA.cpp ├── BuratinoBreakout ├── joystick.cpp ├── beeping.cpp ├── font.c ├── sequencer.cpp └── BuratinoBreakout.ino ├── BuratinoTetris ├── joystick.cpp ├── beeping.cpp ├── sequencer.cpp ├── font.c └── BuratinoTetris_1.ino └── BuratinoFlappy └── flappy2.ino /KiCad/phone.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/koptserg/buratino-phone/HEAD/KiCad/phone.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Buratino Phone 2 | Phone based on Atmega328 and SIM800C with TFT touchscreen display and Arduino bootloader. The case is wooden. 3 | 4 | ![Prototype](http://realsystem.ru/new/sites/default/files/imagecache/product/img_20190531_194437.jpg) 5 | ![Prototype](http://realsystem.ru/new/sites/default/files/imagecache/galleryformatter_slide/img_20190523_203713.jpg) 6 | ![Prototype](http://realsystem.ru/new/sites/default/files/imagecache/galleryformatter_slide/img_20190523_204034.jpg) 7 | 8 | #More info 9 | 10 | - https://realsystem.ru/new/blogs/100583 11 | - https://habr.com/ru/post/457790/ 12 | 13 | #KiCad project 14 | 15 | - [KiCad project](KiCad/) 16 | 17 | #Source code 18 | 19 | - [BuratinoPhone](BuratinoPhone/) https://youtu.be/XU4-bb_q9Ig 20 | - [BuratinoTetris](BuratinoTetris/) https://youtu.be/fjvIASpnl2U 21 | - [BuratinoBreakout](BuratinoBreakout/) https://youtu.be/2zxG_oKdt0Y 22 | - [BuratinoFlappy](BuratinoFlappy/) https://youtu.be/Fy7Xq8D3JLE 23 | 24 | #Contributing 25 | 26 | Feel free to make this project better by contributing with source code, improvements, bug reports, fixes, new games, etc. 27 | -------------------------------------------------------------------------------- /BuratinoPhone/includes/FONAExtIncludes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FONAExtIncludes.h -- system-wide includes 3 | * This is part of the library for the Adafruit FONA Cellular Module 4 | * 5 | * Designed specifically to work with the Adafruit FONA 6 | * ----> https://www.adafruit.com/products/1946 7 | * ----> https://www.adafruit.com/products/1963 8 | * ----> http://www.adafruit.com/products/2468 9 | * ----> http://www.adafruit.com/products/2542 10 | * 11 | * Adafruit invests time and resources providing this open source code, 12 | * please support Adafruit and open-source hardware by purchasing 13 | * products from Adafruit! 14 | * 15 | * Written by Pat Deegan, http://flyingcarsandstuff.com, for inclusion in 16 | * the Adafruit_FONA_Library and released under the 17 | * BSD license, all text above must be included in any redistribution. 18 | * 19 | * Created on: Jan 16, 2016 20 | * Author: Pat Deegan 21 | */ 22 | 23 | 24 | #ifndef ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_FONAEXTINCLUDES_H_ 25 | #define ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_FONAEXTINCLUDES_H_ 26 | 27 | 28 | #include "FONAConfig.h" 29 | // include any system-wide includes required here 30 | 31 | 32 | 33 | #endif /* ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_FONAEXTINCLUDES_H_ */ 34 | -------------------------------------------------------------------------------- /BuratinoPhone/includes/FONAConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FONAConfig.h -- compile-time configuration 3 | * This is part of the library for the Adafruit FONA Cellular Module 4 | * 5 | * Designed specifically to work with the Adafruit FONA 6 | * ----> https://www.adafruit.com/products/1946 7 | * ----> https://www.adafruit.com/products/1963 8 | * ----> http://www.adafruit.com/products/2468 9 | * ----> http://www.adafruit.com/products/2542 10 | * 11 | * Adafruit invests time and resources providing this open source code, 12 | * please support Adafruit and open-source hardware by purchasing 13 | * products from Adafruit! 14 | * 15 | * Written by Pat Deegan, http://flyingcarsandstuff.com, for inclusion in 16 | * the Adafruit_FONA_Library and released under the 17 | * BSD license, all text above must be included in any redistribution. 18 | * 19 | * Created on: Jan 16, 2016 20 | * Author: Pat Deegan 21 | */ 22 | 23 | #ifndef ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_FONACONFIG_H_ 24 | #define ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_FONACONFIG_H_ 25 | 26 | /* ADAFRUIT_FONA_DEBUG 27 | * When defined, will cause extensive debug output on the 28 | * DebugStream set in the appropriate platform/ header. 29 | */ 30 | 31 | //#define ADAFRUIT_FONA_DEBUG 32 | 33 | 34 | #endif /* ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_FONACONFIG_H_ */ 35 | -------------------------------------------------------------------------------- /BuratinoBreakout/joystick.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JOYSTICKCPP 3 | #define JOYSTICKCPP 4 | 5 | #include 6 | 7 | #define XPIN 0 8 | #define YPIN 1 9 | #define FIREPIN 19 10 | 11 | #define CENTER 512 12 | 13 | class Joystick 14 | { 15 | public: 16 | 17 | static void init () 18 | { 19 | pinMode ( FIREPIN, INPUT_PULLUP ); 20 | } 21 | 22 | static int getX() 23 | { 24 | return getPosition(XPIN) * -1; 25 | } 26 | 27 | static int getY() 28 | { 29 | return getPosition(YPIN) * -1; 30 | } 31 | 32 | static boolean fire() 33 | { 34 | return digitalRead(FIREPIN) == LOW; 35 | } 36 | 37 | static void waitForRelease() 38 | { 39 | while (fire()); 40 | } 41 | 42 | static void waitForRelease(int howLong) 43 | { 44 | int c = 0; 45 | do 46 | { 47 | delay (10); 48 | c += 10; 49 | } 50 | while ((fire() || getY() != 0 || getX() != 0) && c < howLong); 51 | } 52 | 53 | static void waitForClick() 54 | { 55 | while (!fire()); 56 | } 57 | 58 | private: 59 | 60 | static int getPosition (int pin) 61 | { 62 | // int n = analogRead(pin); 63 | 64 | // n -= CENTER; 65 | 66 | // n /= 128; 67 | 68 | // return n; 69 | const int n = 512 - CENTER; 70 | return n / 128; 71 | } 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /BuratinoTetris/joystick.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JOYSTICKCPP 3 | #define JOYSTICKCPP 4 | 5 | #include 6 | 7 | // analog pins 8 | 9 | #define XPIN 0 10 | #define YPIN 1 11 | 12 | // digital pin 13 | 14 | #define FIREPIN 19 15 | 16 | // joystick center for both axis 17 | 18 | #define CENTER 512 19 | 20 | class Joystick 21 | { 22 | public: 23 | 24 | // joystick position constants 25 | 26 | static const int NEUTRAL = 0; 27 | static const int SOFT = 1; 28 | static const int HARD = 2; 29 | static const int HARDER = 3; 30 | 31 | static void init () 32 | { 33 | pinMode ( FIREPIN, INPUT_PULLUP ); 34 | } 35 | 36 | static int getX() 37 | { 38 | return getPosition(XPIN) * -1; 39 | } 40 | 41 | static int getY() 42 | { 43 | return getPosition(YPIN) * -1; 44 | } 45 | 46 | static boolean fire() 47 | { 48 | return digitalRead(FIREPIN) == LOW; 49 | } 50 | 51 | static void waitForRelease() 52 | { 53 | while (fire()); 54 | } 55 | 56 | static void waitForRelease(int howLong) 57 | { 58 | int c = 0; 59 | do 60 | { 61 | delay (10); 62 | c += 10; 63 | } 64 | while ((fire() || getY() != 0 || getX() != 0) && c < howLong); 65 | } 66 | 67 | static void waitForClick() 68 | { 69 | while (!fire()); 70 | } 71 | 72 | private: 73 | 74 | static int getPosition (int pin) 75 | { 76 | // const int n = analogRead(pin) - CENTER; 77 | const int n = 512 - CENTER; 78 | return n / 128; 79 | } 80 | 81 | }; 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /BuratinoPhone/includes/platform/FONAPlatform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FONAPlatform.h -- platform definitions includes. 3 | * 4 | * This is part of the library for the Adafruit FONA Cellular Module 5 | * 6 | * Designed specifically to work with the Adafruit FONA 7 | * ----> https://www.adafruit.com/products/1946 8 | * ----> https://www.adafruit.com/products/1963 9 | * ----> http://www.adafruit.com/products/2468 10 | * ----> http://www.adafruit.com/products/2542 11 | * 12 | * Adafruit invests time and resources providing this open source code, 13 | * please support Adafruit and open-source hardware by purchasing 14 | * products from Adafruit! 15 | * 16 | * Written by Pat Deegan, http://flyingcarsandstuff.com, for inclusion in 17 | * the Adafruit_FONA_Library and released under the 18 | * BSD license, all text above must be included in any redistribution. 19 | * 20 | * Created on: Jan 16, 2016 21 | * Author: Pat Deegan 22 | */ 23 | 24 | 25 | #ifndef ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_PLATFORM_FONAPLATFORM_H_ 26 | #define ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_PLATFORM_FONAPLATFORM_H_ 27 | 28 | #include "../FONAConfig.h" 29 | 30 | // only "standard" config supported in this release -- namely AVR-based arduino type affairs 31 | #include "FONAPlatStd.h" 32 | 33 | 34 | 35 | #ifndef DEBUG_PRINT 36 | // debug is disabled 37 | 38 | #define DEBUG_PRINT(...) 39 | #define DEBUG_PRINTLN(...) 40 | 41 | #endif 42 | 43 | 44 | #ifndef prog_char_strcmp 45 | #define prog_char_strcmp(a, b) strcmp((a), (b)) 46 | #endif 47 | 48 | #ifndef prog_char_strstr 49 | #define prog_char_strstr(a, b) strstr((a), (b)) 50 | #endif 51 | 52 | #ifndef prog_char_strlen 53 | #define prog_char_strlen(a) strlen((a)) 54 | #endif 55 | 56 | 57 | #ifndef prog_char_strcpy 58 | #define prog_char_strcpy(to, fromprogmem) strcpy((to), (fromprogmem)) 59 | #endif 60 | 61 | 62 | #endif /* ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_PLATFORM_FONAPLATFORM_H_ */ 63 | -------------------------------------------------------------------------------- /BuratinoPhone/includes/platform/FONAPlatStd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FONAPlatStd.h -- standard AVR/Arduino platform. 3 | * 4 | * This is part of the library for the Adafruit FONA Cellular Module 5 | * 6 | * Designed specifically to work with the Adafruit FONA 7 | * ----> https://www.adafruit.com/products/1946 8 | * ----> https://www.adafruit.com/products/1963 9 | * ----> http://www.adafruit.com/products/2468 10 | * ----> http://www.adafruit.com/products/2542 11 | * 12 | * Adafruit invests time and resources providing this open source code, 13 | * please support Adafruit and open-source hardware by purchasing 14 | * products from Adafruit! 15 | * 16 | * Written by Pat Deegan, http://flyingcarsandstuff.com, for inclusion in 17 | * the Adafruit_FONA_Library and released under the 18 | * BSD license, all text above must be included in any redistribution. 19 | * 20 | * Created on: Jan 16, 2016 21 | * Author: Pat Deegan 22 | */ 23 | 24 | 25 | #ifndef ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_PLATFORM_FONAPLATSTD_H_ 26 | #define ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_PLATFORM_FONAPLATSTD_H_ 27 | 28 | #include "../FONAConfig.h" 29 | 30 | 31 | #if (ARDUINO >= 100) 32 | #include "Arduino.h" 33 | #if !defined(__SAM3X8E__) && !defined(ARDUINO_ARCH_SAMD) // Arduino Due doesn't support #include 34 | #endif 35 | #else 36 | #include "WProgram.h" 37 | #include 38 | #endif 39 | 40 | #if (defined(__AVR__)) 41 | #include 42 | #elif (defined(ESP8266)) 43 | #include 44 | #endif 45 | 46 | // DebugStream sets the Stream output to use 47 | // for debug (only applies when ADAFRUIT_FONA_DEBUG 48 | // is defined in config) 49 | #define DebugStream Serial 50 | 51 | #ifdef ADAFRUIT_FONA_DEBUG 52 | // need to do some debugging... 53 | #define DEBUG_PRINT(...) DebugStream.print(__VA_ARGS__) 54 | #define DEBUG_PRINTLN(...) DebugStream.println(__VA_ARGS__) 55 | #endif 56 | 57 | // a few typedefs to keep things portable 58 | typedef Stream FONAStreamType; 59 | typedef const __FlashStringHelper * FONAFlashStringPtr; 60 | 61 | #define prog_char char PROGMEM 62 | 63 | #define prog_char_strcmp(a, b) strcmp_P((a), (b)) 64 | // define prog_char_strncmp(a, b, c) strncmp_P((a), (b), (c)) 65 | #define prog_char_strstr(a, b) strstr_P((a), (b)) 66 | #define prog_char_strlen(a) strlen_P((a)) 67 | #define prog_char_strcpy(to, fromprogmem) strcpy_P((to), (fromprogmem)) 68 | //define prog_char_strncpy(to, from, len) strncpy_P((to), (fromprogmem), (len)) 69 | 70 | #endif /* ADAFRUIT_FONA_LIBRARY_SRC_INCLUDES_PLATFORM_FONAPLATSTD_H_ */ 71 | -------------------------------------------------------------------------------- /BuratinoTetris/beeping.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SOUNDCPP 3 | #define SOUNDCPP 4 | 5 | #include 6 | 7 | #define SPEAKER 11 8 | 9 | #define NOTE_B2 123 10 | #define NOTE_C3 131 11 | #define NOTE_CS3 139 12 | #define NOTE_D3 147 13 | #define NOTE_DS3 156 14 | #define NOTE_E3 165 15 | #define NOTE_F3 175 16 | #define NOTE_FS3 185 17 | #define NOTE_G3 196 18 | #define NOTE_GS3 208 19 | #define NOTE_A3 220 20 | #define NOTE_AS3 233 21 | #define NOTE_B3 247 22 | #define NOTE_C4 262 23 | #define NOTE_CS4 277 24 | #define NOTE_D4 294 25 | #define NOTE_DS4 311 26 | #define NOTE_E4 330 27 | #define NOTE_F4 349 28 | #define NOTE_FS4 370 29 | #define NOTE_G4 392 30 | #define NOTE_GS4 415 31 | #define NOTE_A4 440 32 | #define NOTE_AS4 466 33 | #define NOTE_B4 494 34 | #define NOTE_C5 523 35 | #define NOTE_CS5 554 36 | #define NOTE_D5 587 37 | #define NOTE_DS5 622 38 | #define NOTE_E5 659 39 | #define NOTE_F5 698 40 | #define NOTE_FS5 740 41 | #define NOTE_G5 784 42 | #define NOTE_GS5 831 43 | #define NOTE_A5 880 44 | #define NOTE_AS5 932 45 | #define NOTE_B5 988 46 | #define NOTE_C6 1047 47 | #define NOTE_CS6 1109 48 | #define NOTE_D6 1175 49 | #define NOTE_DS6 1245 50 | #define NOTE_E6 1319 51 | #define NOTE_F6 1397 52 | #define NOTE_FS6 1480 53 | #define NOTE_G6 1568 54 | #define NOTE_GS6 1661 55 | #define NOTE_A6 1760 56 | #define NOTE_AS6 1865 57 | #define NOTE_B6 1976 58 | #define NOTE_C7 2093 59 | #define NOTE_CS7 2217 60 | #define NOTE_D7 2349 61 | #define NOTE_DS7 2489 62 | #define NOTE_E7 2637 63 | #define NOTE_F7 2794 64 | #define NOTE_FS7 2960 65 | #define NOTE_G7 3136 66 | #define NOTE_GS7 3322 67 | #define NOTE_A7 3520 68 | #define NOTE_AS7 3729 69 | #define NOTE_B7 3951 70 | #define NOTE_C8 4186 71 | #define NOTE_CS8 4435 72 | #define NOTE_D8 4699 73 | #define NOTE_DS8 4978 74 | 75 | class Beeping 76 | { 77 | public: 78 | 79 | static void beep(int frq, int d) 80 | { 81 | tone(SPEAKER, frq, d); 82 | delay( d); 83 | } 84 | 85 | static void mute() 86 | { 87 | noTone(SPEAKER); 88 | } 89 | 90 | static void turnOn() 91 | { 92 | for (int i = 250; i < 2500; i += 100) 93 | { 94 | tone(SPEAKER, i, 10); 95 | delay(10); 96 | tone(SPEAKER, i / 2, 10); 97 | delay(20); 98 | } 99 | 100 | tone(SPEAKER, 1000, 50); 101 | delay(100); 102 | tone(SPEAKER, 2000, 50); 103 | delay(100); 104 | tone(SPEAKER, 500, 50); 105 | delay(100); 106 | } 107 | }; 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /BuratinoBreakout/beeping.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SOUNDCPP 3 | #define SOUNDCPP 4 | 5 | #include 6 | 7 | #define SPEAKER 11 8 | 9 | #define NOTE_AS2 117 10 | #define NOTE_B2 123 11 | #define NOTE_C3 131 12 | #define NOTE_CS3 139 13 | #define NOTE_D3 147 14 | #define NOTE_DS3 156 15 | #define NOTE_E3 165 16 | #define NOTE_F3 175 17 | #define NOTE_FS3 185 18 | #define NOTE_G3 196 19 | #define NOTE_GS3 208 20 | #define NOTE_A3 220 21 | #define NOTE_AS3 233 22 | #define NOTE_B3 247 23 | #define NOTE_C4 262 24 | #define NOTE_CS4 277 25 | #define NOTE_D4 294 26 | #define NOTE_DS4 311 27 | #define NOTE_E4 330 28 | #define NOTE_F4 349 29 | #define NOTE_FS4 370 30 | #define NOTE_G4 392 31 | #define NOTE_GS4 415 32 | #define NOTE_A4 440 33 | #define NOTE_AS4 466 34 | #define NOTE_B4 494 35 | #define NOTE_C5 523 36 | #define NOTE_CS5 554 37 | #define NOTE_D5 587 38 | #define NOTE_DS5 622 39 | #define NOTE_E5 659 40 | #define NOTE_F5 698 41 | #define NOTE_FS5 740 42 | #define NOTE_G5 784 43 | #define NOTE_GS5 831 44 | #define NOTE_A5 880 45 | #define NOTE_AS5 932 46 | #define NOTE_B5 988 47 | #define NOTE_C6 1047 48 | #define NOTE_CS6 1109 49 | #define NOTE_D6 1175 50 | #define NOTE_DS6 1245 51 | #define NOTE_E6 1319 52 | #define NOTE_F6 1397 53 | #define NOTE_FS6 1480 54 | #define NOTE_G6 1568 55 | #define NOTE_GS6 1661 56 | #define NOTE_A6 1760 57 | #define NOTE_AS6 1865 58 | #define NOTE_B6 1976 59 | #define NOTE_C7 2093 60 | #define NOTE_CS7 2217 61 | #define NOTE_D7 2349 62 | #define NOTE_DS7 2489 63 | #define NOTE_E7 2637 64 | #define NOTE_F7 2794 65 | #define NOTE_FS7 2960 66 | #define NOTE_G7 3136 67 | #define NOTE_GS7 3322 68 | #define NOTE_A7 3520 69 | #define NOTE_AS7 3729 70 | #define NOTE_B7 3951 71 | #define NOTE_C8 4186 72 | #define NOTE_CS8 4435 73 | #define NOTE_D8 4699 74 | #define NOTE_DS8 4978 75 | 76 | class Beeping 77 | { 78 | public: 79 | 80 | static void beep(int frq, int d) 81 | { 82 | tone(SPEAKER, frq, d); 83 | } 84 | 85 | static void mute() 86 | { 87 | noTone(SPEAKER); 88 | } 89 | 90 | static void turnOn() 91 | { 92 | for (int i = 250; i < 2500; i += 100) 93 | { 94 | tone(SPEAKER, i, 10); 95 | delay(10); 96 | tone(SPEAKER, i / 2, 10); 97 | delay(20); 98 | } 99 | 100 | Beeping::beep(NOTE_C4,40); 101 | Beeping::beep(NOTE_F4,40); 102 | Beeping::beep(NOTE_G4,40); 103 | Beeping::beep(NOTE_D5,40); 104 | Beeping::beep(NOTE_G5,40); 105 | Beeping::beep(NOTE_A5,40); 106 | Beeping::beep(NOTE_C6,40); 107 | Beeping::beep(NOTE_F6,40); 108 | } 109 | }; 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /BuratinoTetris/sequencer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SEQUENCERCPP 3 | #define SEQUENCERCPP 4 | 5 | #include "Arduino.h" 6 | #include "beeping.cpp" 7 | 8 | static const int song[] = { 9 | 10 | NOTE_E5, 4, 11 | NOTE_B4, 2, 12 | NOTE_C5, 2, 13 | 14 | NOTE_D5, 2, 15 | NOTE_E5, 1, 16 | NOTE_D5, 1, 17 | NOTE_C5, 2, 18 | NOTE_B4, 2, 19 | 20 | NOTE_A4, 4, 21 | NOTE_A4, 2, 22 | NOTE_C5, 2, 23 | 24 | NOTE_E5, 4, 25 | NOTE_D5, 2, 26 | NOTE_C5, 2, 27 | 28 | NOTE_B4, 2, 29 | NOTE_E4, 2, 30 | NOTE_B4, 2, 31 | NOTE_C5, 2, 32 | 33 | NOTE_D5, 4, 34 | NOTE_E5, 4, 35 | 36 | NOTE_C5, 4, 37 | NOTE_A4, 4, 38 | 39 | NOTE_A4, 2, 40 | NOTE_A3, 2, 41 | NOTE_B3, 2, 42 | NOTE_C4, 2, 43 | 44 | NOTE_D4, 2, 45 | NOTE_D5, 4, 46 | NOTE_F5, 2, 47 | 48 | NOTE_A5, 2, 49 | NOTE_A5, 1, 50 | NOTE_A5, 1, 51 | NOTE_G5, 2, 52 | NOTE_F5, 2, 53 | 54 | NOTE_E5, 6, 55 | NOTE_C5, 2, 56 | 57 | NOTE_E5, 2, 58 | NOTE_F5, 1, 59 | NOTE_E5, 1, 60 | NOTE_D5, 2, 61 | NOTE_C5, 2, 62 | 63 | NOTE_B4, 4, 64 | NOTE_B4, 2, 65 | NOTE_C5, 2, 66 | 67 | NOTE_D5, 4, 68 | NOTE_E5, 4, 69 | 70 | NOTE_C5, 4, 71 | NOTE_A4, 4, 72 | 73 | NOTE_A4, 8, 74 | 75 | // repeat 76 | 77 | NOTE_E5, 4, 78 | NOTE_B4, 2, 79 | NOTE_C5, 2, 80 | 81 | NOTE_D5, 2, 82 | NOTE_E5, 1, 83 | NOTE_D5, 1, 84 | NOTE_C5, 2, 85 | NOTE_B4, 2, 86 | 87 | NOTE_A4, 4, 88 | NOTE_A4, 2, 89 | NOTE_C5, 2, 90 | 91 | NOTE_E5, 4, 92 | NOTE_D5, 2, 93 | NOTE_C5, 2, 94 | 95 | NOTE_B4, 2, 96 | NOTE_E4, 2, 97 | NOTE_B4, 2, 98 | NOTE_C5, 2, 99 | 100 | NOTE_D5, 4, 101 | NOTE_E5, 4, 102 | 103 | NOTE_C5, 4, 104 | NOTE_A4, 4, 105 | 106 | NOTE_A4, 2, 107 | NOTE_A3, 2, 108 | NOTE_B3, 2, 109 | NOTE_C4, 2, 110 | 111 | NOTE_D4, 2, 112 | NOTE_D5, 4, 113 | NOTE_F5, 2, 114 | 115 | NOTE_A5, 2, 116 | NOTE_A5, 1, 117 | NOTE_A5, 1, 118 | NOTE_G5, 2, 119 | NOTE_F5, 2, 120 | 121 | NOTE_E5, 6, 122 | NOTE_C5, 2, 123 | 124 | NOTE_E5, 2, 125 | NOTE_F5, 1, 126 | NOTE_E5, 1, 127 | NOTE_D5, 2, 128 | NOTE_C5, 2, 129 | 130 | NOTE_B4, 4, 131 | NOTE_B4, 2, 132 | NOTE_C5, 2, 133 | 134 | NOTE_D5, 4, 135 | NOTE_E5, 4, 136 | 137 | NOTE_C5, 4, 138 | NOTE_A4, 4, 139 | 140 | NOTE_A4, 8, 141 | -1 142 | 143 | }; 144 | 145 | static volatile unsigned long last; 146 | static volatile int c; 147 | static volatile int w; 148 | static volatile boolean songOn; 149 | 150 | 151 | class Sequencer { 152 | public: 153 | 154 | static void init() { 155 | 156 | // enable timer, used to play music sequencer async 157 | TCCR1A = 0; // No options in control register A 158 | TCCR1B = (1 << CS10); // Set prescaler to divide by 8 159 | TIMSK1 = (1 << OCIE1A); // Call ISR when TCNT2 = OCRA2 160 | OCR1A = 0;// Set frequency of generated wave 161 | sei(); // Enable interrupts to generate waveform! 162 | 163 | last = c = w = 0; 164 | songOn = false; 165 | } 166 | 167 | static void start() { 168 | init(); 169 | songOn = true; 170 | } 171 | 172 | static void stop() { 173 | songOn = false; 174 | Beeping::mute(); 175 | } 176 | 177 | static void play() 178 | { 179 | if (!songOn) 180 | { 181 | return; 182 | } 183 | 184 | unsigned long m = millis(); 185 | if ( m - last > w) 186 | { 187 | last = m; 188 | 189 | int fr = song[c++]; 190 | int d = song[c++]; 191 | 192 | Beeping::beep (fr, d * 100 ); 193 | w = d * 105; 194 | 195 | if ( song[c] == -1 ) { 196 | c = 0; 197 | w = 10000; 198 | Beeping::mute(); 199 | } 200 | } 201 | } 202 | }; 203 | 204 | 205 | #endif 206 | -------------------------------------------------------------------------------- /BuratinoTetris/font.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | const unsigned char simpleFont[][8] PROGMEM= 5 | { 6 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 7 | {0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00}, 8 | {0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00}, 9 | {0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00}, 10 | {0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00}, 11 | {0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00}, 12 | {0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00}, 13 | {0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00}, 14 | {0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00}, 15 | {0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00}, 16 | {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00}, 17 | {0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00}, 18 | {0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00}, 19 | {0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, 20 | {0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, 21 | {0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00}, 22 | {0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00}, 23 | {0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00}, 24 | {0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00}, 25 | {0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00}, 26 | {0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00}, 27 | {0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00}, 28 | {0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00}, 29 | {0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00}, 30 | {0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00}, 31 | {0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00}, 32 | {0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00}, 33 | {0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00}, 34 | {0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00}, 35 | {0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00}, 36 | {0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00}, 37 | {0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00}, 38 | {0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00}, 39 | {0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00}, 40 | {0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00}, 41 | {0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00}, 42 | {0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00}, 43 | {0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00}, 44 | {0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00}, 45 | {0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00}, 46 | {0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00}, 47 | {0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00}, 48 | {0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00}, 49 | {0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00}, 50 | {0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00}, 51 | {0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00}, 52 | {0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00}, 53 | {0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00}, 54 | {0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00}, 55 | {0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00}, 56 | {0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00}, 57 | {0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00}, 58 | {0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00}, 59 | {0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00}, 60 | {0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00}, 61 | {0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00}, 62 | {0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00}, 63 | {0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00}, 64 | {0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00}, 65 | {0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00}, 66 | {0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00}, 67 | {0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00}, 68 | {0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00}, 69 | {0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00}, 70 | {0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00}, 71 | {0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00}, 72 | {0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00}, 73 | {0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00}, 74 | {0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00}, 75 | {0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00}, 76 | {0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00}, 77 | {0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00}, 78 | {0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00}, 79 | {0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00}, 80 | {0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00}, 81 | {0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00}, 82 | {0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00}, 83 | {0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00}, 84 | {0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00}, 85 | {0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00}, 86 | {0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00}, 87 | {0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00}, 88 | {0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00}, 89 | {0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00}, 90 | {0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00}, 91 | {0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00}, 92 | {0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00}, 93 | {0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00}, 94 | {0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00}, 95 | {0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00}, 96 | {0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00}, 97 | {0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00}, 98 | {0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00}, 99 | {0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00}, 100 | {0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00}, 101 | {0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00} 102 | }; 103 | -------------------------------------------------------------------------------- /BuratinoBreakout/font.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | const unsigned char simpleFont[][8] PROGMEM= 6 | { 7 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8 | {0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00}, 9 | {0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00}, 10 | {0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00}, 11 | {0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00}, 12 | {0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00}, 13 | {0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00}, 14 | {0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00}, 15 | {0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00}, 16 | {0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00}, 17 | {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00}, 18 | {0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00}, 19 | {0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00}, 20 | {0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, 21 | {0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, 22 | {0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00}, 23 | {0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00}, 24 | {0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00}, 25 | {0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00}, 26 | {0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00}, 27 | {0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00}, 28 | {0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00}, 29 | {0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00}, 30 | {0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00}, 31 | {0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00}, 32 | {0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00}, 33 | {0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00}, 34 | {0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00}, 35 | {0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00}, 36 | {0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00}, 37 | {0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00}, 38 | {0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00}, 39 | {0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00}, 40 | {0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00}, 41 | {0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00}, 42 | {0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00}, 43 | {0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00}, 44 | {0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00}, 45 | {0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00}, 46 | {0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00}, 47 | {0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00}, 48 | {0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00}, 49 | {0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00}, 50 | {0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00}, 51 | {0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00}, 52 | {0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00}, 53 | {0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00}, 54 | {0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00}, 55 | {0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00}, 56 | {0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00}, 57 | {0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00}, 58 | {0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00}, 59 | {0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00}, 60 | {0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00}, 61 | {0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00}, 62 | {0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00}, 63 | {0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00}, 64 | {0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00}, 65 | {0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00}, 66 | {0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00}, 67 | {0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00}, 68 | {0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00}, 69 | {0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00}, 70 | {0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00}, 71 | {0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00}, 72 | {0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00}, 73 | {0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00}, 74 | {0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00}, 75 | {0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00}, 76 | {0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00}, 77 | {0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00}, 78 | {0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00}, 79 | {0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00}, 80 | {0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00}, 81 | {0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00}, 82 | {0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00}, 83 | {0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00}, 84 | {0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00}, 85 | {0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00}, 86 | {0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00}, 87 | {0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00}, 88 | {0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00}, 89 | {0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00}, 90 | {0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00}, 91 | {0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00}, 92 | {0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00}, 93 | {0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00}, 94 | {0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00}, 95 | {0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00}, 96 | {0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00}, 97 | {0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00}, 98 | {0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00}, 99 | {0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00}, 100 | {0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00}, 101 | {0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00}, 102 | {0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00} 103 | }; 104 | -------------------------------------------------------------------------------- /BuratinoPhone/Adafruit_FONA.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for our Adafruit FONA Cellular Module 3 | 4 | Designed specifically to work with the Adafruit FONA 5 | ----> http://www.adafruit.com/products/1946 6 | ----> http://www.adafruit.com/products/1963 7 | 8 | These displays use TTL Serial to communicate, 2 pins are required to 9 | interface 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit and open-source hardware by purchasing 12 | products from Adafruit! 13 | 14 | Written by Limor Fried/Ladyada for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | ****************************************************/ 17 | #ifndef ADAFRUIT_FONA_H 18 | #define ADAFRUIT_FONA_H 19 | 20 | #include "includes/FONAConfig.h" 21 | #include "includes/FONAExtIncludes.h" 22 | #include "includes/platform/FONAPlatform.h" 23 | 24 | 25 | 26 | #define FONA800L 1 27 | #define FONA800H 6 28 | 29 | #define FONA808_V1 2 30 | #define FONA808_V2 3 31 | 32 | #define FONA3G_A 4 33 | #define FONA3G_E 5 34 | 35 | // Set the preferred SMS storage. 36 | // Use "SM" for storage on the SIM. 37 | // Use "ME" for internal storage on the FONA chip 38 | #define FONA_PREF_SMS_STORAGE "\"SM\"" 39 | //#define FONA_PREF_SMS_STORAGE "\"ME\"" 40 | 41 | #define FONA_HEADSETAUDIO 0 42 | #define FONA_EXTAUDIO 1 43 | 44 | #define FONA_STTONE_DIALTONE 1 45 | #define FONA_STTONE_BUSY 2 46 | #define FONA_STTONE_CONGESTION 3 47 | #define FONA_STTONE_PATHACK 4 48 | #define FONA_STTONE_DROPPED 5 49 | #define FONA_STTONE_ERROR 6 50 | #define FONA_STTONE_CALLWAIT 7 51 | #define FONA_STTONE_RINGING 8 52 | #define FONA_STTONE_BEEP 16 53 | #define FONA_STTONE_POSTONE 17 54 | #define FONA_STTONE_ERRTONE 18 55 | #define FONA_STTONE_INDIANDIALTONE 19 56 | #define FONA_STTONE_USADIALTONE 20 57 | 58 | #define FONA_DEFAULT_TIMEOUT_MS 500 59 | 60 | #define FONA_HTTP_GET 0 61 | #define FONA_HTTP_POST 1 62 | #define FONA_HTTP_HEAD 2 63 | 64 | #define FONA_CALL_READY 0 65 | #define FONA_CALL_FAILED 1 66 | #define FONA_CALL_UNKNOWN 2 67 | #define FONA_CALL_RINGING 3 68 | #define FONA_CALL_INPROGRESS 4 69 | 70 | class Adafruit_FONA : public FONAStreamType { 71 | public: 72 | Adafruit_FONA(int8_t r); 73 | boolean begin(FONAStreamType &port); 74 | uint8_t type(); 75 | 76 | // Stream 77 | int available(void); 78 | size_t write(uint8_t x); 79 | int read(void); 80 | int peek(void); 81 | void flush(); 82 | 83 | // FONA 3G requirements 84 | boolean setBaudrate(uint16_t baud); 85 | 86 | // RTC 87 | boolean enableRTC(uint8_t i); 88 | boolean readRTC(uint8_t *year, uint8_t *month, uint8_t *date, uint8_t *hr, uint8_t *min, uint8_t *sec); 89 | 90 | // Battery and ADC 91 | boolean getADCVoltage(uint16_t *v); 92 | boolean getBattPercent(uint16_t *p); 93 | boolean getBatt(char *buff, uint16_t maxlen); 94 | boolean getBattVoltage(uint16_t *v); 95 | 96 | // SIM query 97 | uint8_t unlockSIM(char *pin); 98 | uint8_t getSIMCCID(char *ccid); 99 | uint8_t getNetworkStatus(void); 100 | uint8_t getRSSI(void); 101 | 102 | // IMEI 103 | uint8_t getIMEI(char *imei); 104 | 105 | // set Audio output 106 | boolean setAudio(uint8_t a); 107 | boolean setVolume(uint8_t i); 108 | uint8_t getVolume(void); 109 | boolean playToolkitTone(uint8_t t, uint16_t len); 110 | boolean setMicVolume(uint8_t a, uint8_t level); 111 | boolean playDTMF(char tone); 112 | 113 | // FM radio functions. 114 | boolean tuneFMradio(uint16_t station); 115 | boolean FMradio(boolean onoff, uint8_t a = FONA_HEADSETAUDIO); 116 | boolean setFMVolume(uint8_t i); 117 | int8_t getFMVolume(); 118 | int8_t getFMSignalLevel(uint16_t station); 119 | 120 | // SMS handling 121 | boolean setSMSInterrupt(uint8_t i); 122 | uint8_t getSMSInterrupt(void); 123 | int8_t getNumSMS(void); 124 | boolean readSMS(uint8_t i, char *smsbuff, uint16_t max, uint16_t *readsize); 125 | boolean sendSMS(char *smsaddr, char *smsmsg); 126 | boolean deleteSMS(uint8_t i); 127 | boolean getSMSSender(uint8_t i, char *sender, int senderlen); 128 | boolean sendUSSD(char *ussdmsg, char *ussdbuff, uint16_t maxlen, uint16_t *readlen); 129 | 130 | // SMS event 131 | boolean getEventSMS(char *i); 132 | 133 | // SIM phone book 134 | boolean getSIMSender(uint8_t i, char *sender, int senderlen); 135 | boolean getSIMSendernName(uint8_t i, char *sendername, int senderlen); 136 | 137 | // Time 138 | boolean enableNetworkTimeSync(boolean onoff); 139 | boolean enableNTPTimeSync(boolean onoff, FONAFlashStringPtr ntpserver=0); 140 | boolean getTime(char *buff, uint16_t maxlen); 141 | 142 | // GPRS handling 143 | boolean enableGPRS(boolean onoff); 144 | uint8_t GPRSstate(void); 145 | boolean getGSMLoc(uint16_t *replycode, char *buff, uint16_t maxlen); 146 | boolean getGSMLoc(float *lat, float *lon); 147 | void setGPRSNetworkSettings(FONAFlashStringPtr apn, FONAFlashStringPtr username=0, FONAFlashStringPtr password=0); 148 | 149 | // GPS handling 150 | boolean enableGPS(boolean onoff); 151 | int8_t GPSstatus(void); 152 | uint8_t getGPS(uint8_t arg, char *buffer, uint8_t maxbuff); 153 | boolean getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, float *altitude=0); 154 | boolean enableGPSNMEA(uint8_t nmea); 155 | 156 | // TCP raw connections 157 | boolean TCPconnect(char *server, uint16_t port); 158 | boolean TCPclose(void); 159 | boolean TCPconnected(void); 160 | boolean TCPsend(char *packet, uint8_t len); 161 | uint16_t TCPavailable(void); 162 | uint16_t TCPread(uint8_t *buff, uint8_t len); 163 | 164 | // HTTP low level interface (maps directly to SIM800 commands). 165 | boolean HTTP_init(); 166 | boolean HTTP_term(); 167 | void HTTP_para_start(FONAFlashStringPtr parameter, boolean quoted = true); 168 | boolean HTTP_para_end(boolean quoted = true); 169 | boolean HTTP_para(FONAFlashStringPtr parameter, const char *value); 170 | boolean HTTP_para(FONAFlashStringPtr parameter, FONAFlashStringPtr value); 171 | boolean HTTP_para(FONAFlashStringPtr parameter, int32_t value); 172 | boolean HTTP_data(uint32_t size, uint32_t maxTime=10000); 173 | boolean HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout = 10000); 174 | boolean HTTP_readall(uint16_t *datalen); 175 | boolean HTTP_ssl(boolean onoff); 176 | 177 | // HTTP high level interface (easier to use, less flexible). 178 | boolean HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen); 179 | void HTTP_GET_end(void); 180 | boolean HTTP_POST_start(char *url, FONAFlashStringPtr contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen); 181 | void HTTP_POST_end(void); 182 | void setUserAgent(FONAFlashStringPtr useragent); 183 | 184 | // HTTPS 185 | void setHTTPSRedirect(boolean onoff); 186 | 187 | // PWM (buzzer) 188 | boolean setPWM(uint16_t period, uint8_t duty = 50); 189 | 190 | // Phone calls 191 | boolean callPhone(char *phonenum); 192 | uint8_t getCallStatus(void); 193 | boolean hangUp(void); 194 | boolean pickUp(void); 195 | boolean callerIdNotification(boolean enable, uint8_t interrupt = 0); 196 | boolean incomingCallNumber(char* phonenum); 197 | 198 | // Helper functions to verify responses. 199 | boolean expectReply(FONAFlashStringPtr reply, uint16_t timeout = 10000); 200 | boolean sendCheckReply(char *send, char *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 201 | boolean sendCheckReply(FONAFlashStringPtr send, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 202 | boolean sendCheckReply(char* send, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 203 | 204 | protected: 205 | int8_t _rstpin; 206 | uint8_t _type; 207 | 208 | char replybuffer[255]; 209 | FONAFlashStringPtr apn; 210 | FONAFlashStringPtr apnusername; 211 | FONAFlashStringPtr apnpassword; 212 | boolean httpsredirect; 213 | FONAFlashStringPtr useragent; 214 | FONAFlashStringPtr ok_reply; 215 | 216 | // HTTP helpers 217 | boolean HTTP_setup(char *url); 218 | 219 | void flushInput(); 220 | uint16_t readRaw(uint16_t b); 221 | uint8_t readline(uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS, boolean multiline = false); 222 | uint8_t getReply(char *send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 223 | uint8_t getReply(FONAFlashStringPtr send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 224 | uint8_t getReply(FONAFlashStringPtr prefix, char *suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 225 | uint8_t getReply(FONAFlashStringPtr prefix, int32_t suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 226 | uint8_t getReply(FONAFlashStringPtr prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout); // Don't set default value or else function call is ambiguous. 227 | uint8_t getReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 228 | 229 | boolean sendCheckReply(FONAFlashStringPtr prefix, char *suffix, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 230 | boolean sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 231 | boolean sendCheckReply(FONAFlashStringPtr prefix, int32_t suffix, int32_t suffix2, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 232 | boolean sendCheckReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS); 233 | 234 | 235 | boolean parseReply(FONAFlashStringPtr toreply, 236 | uint16_t *v, char divider = ',', uint8_t index=0); 237 | boolean parseReply(FONAFlashStringPtr toreply, 238 | char *v, char divider = ',', uint8_t index=0); 239 | boolean parseReplyQuoted(FONAFlashStringPtr toreply, 240 | char *v, int maxlen, char divider, uint8_t index); 241 | 242 | boolean sendParseReply(FONAFlashStringPtr tosend, 243 | FONAFlashStringPtr toreply, 244 | uint16_t *v, char divider = ',', uint8_t index=0); 245 | 246 | static boolean _incomingCall; 247 | static void onIncomingCall(); 248 | 249 | FONAStreamType *mySerial; 250 | }; 251 | 252 | class Adafruit_FONA_3G : public Adafruit_FONA { 253 | 254 | public: 255 | Adafruit_FONA_3G (int8_t r) : Adafruit_FONA(r) { _type = FONA3G_A; } 256 | 257 | boolean getBattVoltage(uint16_t *v); 258 | boolean playToolkitTone(uint8_t t, uint16_t len); 259 | boolean hangUp(void); 260 | boolean pickUp(void); 261 | boolean enableGPRS(boolean onoff); 262 | boolean enableGPS(boolean onoff); 263 | 264 | protected: 265 | boolean parseReply(FONAFlashStringPtr toreply, 266 | float *f, char divider, uint8_t index); 267 | 268 | boolean sendParseReply(FONAFlashStringPtr tosend, 269 | FONAFlashStringPtr toreply, 270 | float *f, char divider = ',', uint8_t index=0); 271 | }; 272 | 273 | #endif 274 | -------------------------------------------------------------------------------- /BuratinoBreakout/sequencer.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef SEQUENCERCPP 4 | #define SEQUENCERCPP 5 | 6 | #include "Arduino.h" 7 | #include "beeping.cpp" 8 | 9 | static const int song1[] = { 10 | 11 | NOTE_C4, 4, 12 | NOTE_A4, 4, 13 | NOTE_A4, 4, 14 | NOTE_G4, 4, 15 | NOTE_A4, 4, 16 | NOTE_F4, 4, 17 | NOTE_C4, 4, 18 | NOTE_C4, 4, 19 | NOTE_C4, 4, 20 | NOTE_A4, 4, 21 | NOTE_A4, 4, 22 | NOTE_AS4, 4, 23 | NOTE_G4, 4, 24 | NOTE_C5, 2, 25 | NOTE_C5, 8, 26 | NOTE_D4, 4, 27 | NOTE_D4, 4, 28 | NOTE_AS4, 4, 29 | NOTE_AS4, 4, 30 | NOTE_A4, 4, 31 | NOTE_G4, 4, 32 | NOTE_F4, 4, 33 | NOTE_C4, 4, 34 | NOTE_A4, 4, 35 | NOTE_A4, 4, 36 | NOTE_G4, 4, 37 | NOTE_A4, 4, 38 | NOTE_F4, 2 39 | }; 40 | 41 | static const int song[] = { 42 | 43 | // tone(tonePin, 174, 249.99975); 44 | // delay(277.7775); 45 | NOTE_F3, 2.5, 46 | // tone(tonePin, 233, 499.9995); 47 | // delay(555.555); 48 | NOTE_AS3, 5, 49 | // tone(tonePin, 174, 374.999625); 50 | // delay(416.66625); 51 | NOTE_F3, 3.7, 52 | // tone(tonePin, 195, 124.999875); 53 | // delay(138.88875); 54 | NOTE_G3, 1.2, 55 | // tone(tonePin, 220, 499.9995); 56 | // delay(555.555); 57 | NOTE_A3, 5, 58 | // tone(tonePin, 146, 249.99975); 59 | // delay(277.7775); 60 | NOTE_D3, 2.5, 61 | // tone(tonePin, 146, 249.99975); 62 | // delay(277.7775); 63 | NOTE_D3, 2.5, 64 | // tone(tonePin, 195, 499.9995); 65 | // delay(555.555); 66 | NOTE_G3, 5, 67 | // tone(tonePin, 174, 374.999625); 68 | // delay(416.66625); 69 | NOTE_F3, 3.7, 70 | // tone(tonePin, 155, 124.999875); 71 | // delay(138.88875); 72 | NOTE_DS3, 1.2, 73 | // tone(tonePin, 174, 499.9995); 74 | // delay(555.555); 75 | NOTE_F3, 5, 76 | // tone(tonePin, 116, 249.99975); 77 | // delay(277.7775); 78 | NOTE_AS2, 2.5, 79 | // tone(tonePin, 116, 249.99975); 80 | // delay(277.7775); 81 | NOTE_AS2, 2.5, 82 | // tone(tonePin, 130, 499.9995); 83 | // delay(555.555); 84 | NOTE_C3, 5, 85 | // tone(tonePin, 130, 374.999625); 86 | // delay(416.66625); 87 | NOTE_C3, 3.7, 88 | // tone(tonePin, 146, 124.999875); 89 | // delay(138.88875); 90 | NOTE_D3, 1.2, 91 | // tone(tonePin, 155, 499.9995); 92 | // delay(555.555); 93 | NOTE_DS3, 5, 94 | // tone(tonePin, 155, 374.999625); 95 | // delay(416.66625); 96 | NOTE_DS3, 3.7, 97 | // tone(tonePin, 174, 124.999875); 98 | // delay(138.88875); 99 | NOTE_F3, 1.2, 100 | // tone(tonePin, 195, 499.9995); 101 | // delay(555.555); 102 | NOTE_G3, 5, 103 | // tone(tonePin, 220, 374.999625); 104 | // delay(416.66625); 105 | NOTE_A3, 3.7, 106 | // tone(tonePin, 233, 124.999875); 107 | // delay(138.88875); 108 | NOTE_AS3, 1.2, 109 | // tone(tonePin, 261, 749.99925); 110 | // delay(833.3325); 111 | NOTE_C4, 7.5, 112 | // tone(tonePin, 174, 249.99975); 113 | // delay(277.7775); 114 | NOTE_F3, 2.5, 115 | // tone(tonePin, 293, 499.9995); 116 | // delay(555.555); 117 | NOTE_D4, 5, 118 | // tone(tonePin, 261, 374.999625); 119 | // delay(416.66625); 120 | NOTE_C4, 3.7, 121 | // tone(tonePin, 233, 124.999875); 122 | // delay(138.88875); 123 | NOTE_AS3, 1.2, 124 | // tone(tonePin, 261, 499.9995); 125 | // delay(555.555); 126 | NOTE_C4, 5, 127 | // tone(tonePin, 174, 249.99975); 128 | // delay(277.7775); 129 | NOTE_F3, 2.5, 130 | // tone(tonePin, 174, 249.99975); 131 | // delay(277.7775); 132 | NOTE_F3, 2.5, 133 | // tone(tonePin, 233, 499.9995); 134 | // delay(555.555); 135 | NOTE_AS3, 5, 136 | // tone(tonePin, 220, 374.999625); 137 | // delay(416.66625); 138 | NOTE_A3, 3.7, 139 | // tone(tonePin, 195, 124.999875); 140 | // delay(138.88875); 141 | NOTE_G3, 1.2, 142 | // tone(tonePin, 220, 499.9995); 143 | // delay(555.555); 144 | NOTE_A3, 5, 145 | // tone(tonePin, 146, 374.999625); 146 | // delay(416.66625); 147 | NOTE_D3, 3.7, 148 | // tone(tonePin, 146, 124.999875); 149 | // delay(138.88875); 150 | NOTE_D3, 1.2, 151 | // tone(tonePin, 195, 499.9995); 152 | // delay(555.555); 153 | NOTE_G3, 5, 154 | // tone(tonePin, 174, 374.999625); 155 | // delay(416.66625); 156 | NOTE_F3, 3.7, 157 | // tone(tonePin, 155, 124.999875); 158 | // delay(138.88875); 159 | NOTE_DS3, 1.2, 160 | // tone(tonePin, 174, 499.9995); 161 | // delay(555.555); 162 | NOTE_F3, 5, 163 | // tone(tonePin, 116, 374.999625); 164 | // delay(416.66625); 165 | NOTE_AS2, 3.7, 166 | // tone(tonePin, 116, 124.999875); 167 | // delay(138.88875); 168 | NOTE_AS2, 1.2, 169 | // tone(tonePin, 233, 499.9995); 170 | // delay(555.555); 171 | NOTE_AS3, 5, 172 | // tone(tonePin, 220, 374.999625); 173 | // delay(416.66625); 174 | NOTE_A3, 3.7, 175 | // tone(tonePin, 195, 124.999875); 176 | // delay(138.88875); 177 | NOTE_G3, 1.2, 178 | // tone(tonePin, 174, 999.999); 179 | // delay(1111.11); 180 | NOTE_F3, 10, 181 | // tone(tonePin, 293, 999.999); 182 | // delay(1111.11); 183 | NOTE_D4, 10, 184 | // tone(tonePin, 261, 249.99975); 185 | // delay(277.7775); 186 | NOTE_C4, 2.5, 187 | // tone(tonePin, 233, 249.99975); 188 | // delay(277.7775); 189 | NOTE_AS3, 2.5, 190 | // tone(tonePin, 220, 249.99975); 191 | // delay(277.7775); 192 | NOTE_A3, 2.5, 193 | // tone(tonePin, 233, 249.99975); 194 | // delay(277.7775); 195 | NOTE_AS3, 2.5, 196 | // tone(tonePin, 261, 749.99925); 197 | // delay(833.3325); 198 | NOTE_C4, 7.5, 199 | // tone(tonePin, 174, 249.99975); 200 | // delay(277.7775); 201 | NOTE_F3, 2.5, 202 | // tone(tonePin, 174, 999.999); 203 | // delay(1111.11); 204 | NOTE_F3, 10, 205 | // tone(tonePin, 233, 999.999); 206 | // delay(1111.11); 207 | NOTE_AS3, 10, 208 | // tone(tonePin, 220, 249.99975); 209 | // delay(277.7775); 210 | NOTE_A3, 2.5, 211 | // tone(tonePin, 195, 249.99975); 212 | // delay(277.7775); 213 | NOTE_G3, 2.5, 214 | // tone(tonePin, 174, 249.99975); 215 | // delay(277.7775); 216 | NOTE_F3, 2.5, 217 | // tone(tonePin, 195, 249.99975); 218 | // delay(277.7775); 219 | NOTE_G3, 2.5, 220 | // tone(tonePin, 220, 749.99925); 221 | // delay(833.3325); 222 | NOTE_A3, 7.5, 223 | // tone(tonePin, 146, 249.99975); 224 | // delay(277.7775); 225 | NOTE_D3, 2.5, 226 | // tone(tonePin, 146, 999.999); 227 | // delay(1111.11); 228 | NOTE_D3, 10, 229 | // tone(tonePin, 233, 499.9995); 230 | // delay(555.555); 231 | NOTE_AS3, 5, 232 | // tone(tonePin, 195, 374.999625); 233 | // delay(416.66625); 234 | NOTE_G3, 3.7, 235 | // tone(tonePin, 220, 124.999875); 236 | // delay(138.88875); 237 | NOTE_A3, 1.2, 238 | // tone(tonePin, 233, 499.9995); 239 | // delay(555.555); 240 | NOTE_AS3, 5, 241 | // tone(tonePin, 195, 374.999625); 242 | // delay(416.66625); 243 | NOTE_G3, 3.7, 244 | // tone(tonePin, 220, 124.999875); 245 | // delay(138.88875); 246 | NOTE_A3, 1.2, 247 | // tone(tonePin, 233, 499.9995); 248 | // delay(555.555); 249 | NOTE_AS3, 5, 250 | // tone(tonePin, 195, 374.999625); 251 | // delay(416.66625); 252 | NOTE_G3, 3.7, 253 | // tone(tonePin, 233, 124.999875); 254 | // delay(138.88875); 255 | NOTE_AS3, 1.2, 256 | // tone(tonePin, 311, 999.999); 257 | // delay(1111.11); 258 | NOTE_DS4, 10, 259 | // tone(tonePin, 311, 999.999); 260 | // delay(1111.11); 261 | NOTE_DS4, 10, 262 | // tone(tonePin, 293, 249.99975); 263 | // delay(277.7775); 264 | NOTE_D4, 2.5, 265 | // tone(tonePin, 261, 249.99975); 266 | // delay(277.7775); 267 | NOTE_C4, 2.5, 268 | // tone(tonePin, 233, 249.99975); 269 | // delay(277.7775); 270 | NOTE_AS3, 2.5, 271 | // tone(tonePin, 261, 249.99975); 272 | // delay(277.7775); 273 | NOTE_C4, 2.5, 274 | // tone(tonePin, 293, 749.99925); 275 | // delay(833.3325); 276 | NOTE_D4, 7.5, 277 | // tone(tonePin, 233, 249.99975); 278 | // delay(277.7775); 279 | NOTE_AS3, 2.5, 280 | // tone(tonePin, 233, 999.999); 281 | // delay(1111.11); 282 | NOTE_AS3, 10, 283 | // tone(tonePin, 261, 999.999); 284 | // delay(1111.11); 285 | NOTE_C4, 10, 286 | // tone(tonePin, 233, 249.99975); 287 | // delay(277.7775); 288 | NOTE_AS3, 2.5, 289 | // tone(tonePin, 220, 249.99975); 290 | // delay(277.7775); 291 | NOTE_A3, 2.5, 292 | // tone(tonePin, 195, 249.99975); 293 | // delay(277.7775); 294 | NOTE_G3, 2.5, 295 | // tone(tonePin, 220, 249.99975); 296 | // delay(277.7775); 297 | NOTE_A3, 2.5, 298 | // tone(tonePin, 233, 749.99925); 299 | // delay(833.3325); 300 | NOTE_AS3, 7.5, 301 | // tone(tonePin, 195, 249.99975); 302 | // delay(277.7775); 303 | NOTE_G3, 2.5, 304 | // tone(tonePin, 195, 999.999); 305 | // delay(1111.11); 306 | NOTE_G3, 10, 307 | // tone(tonePin, 233, 499.9995); 308 | // delay(555.555); 309 | NOTE_AS3, 5, 310 | // tone(tonePin, 220, 374.999625); 311 | // delay(416.66625); 312 | NOTE_A3, 3.7, 313 | // tone(tonePin, 195, 124.999875); 314 | // delay(138.88875); 315 | NOTE_G3, 1.2, 316 | // tone(tonePin, 174, 499.9995); 317 | // delay(555.555); 318 | NOTE_F3, 5, 319 | // tone(tonePin, 116, 374.999625); 320 | // delay(416.66625); 321 | NOTE_AS2, 3.7, 322 | // tone(tonePin, 116, 124.999875); 323 | // delay(138.88875); 324 | NOTE_AS2, 1.2, 325 | // tone(tonePin, 174, 999.999); 326 | // delay(1111.11); 327 | NOTE_F3, 10, 328 | // tone(tonePin, 195, 499.9995); 329 | // delay(555.555); 330 | NOTE_G3, 5, 331 | // tone(tonePin, 220, 499.9995); 332 | // delay(555.555); 333 | NOTE_A3, 5, 334 | // tone(tonePin, 233, 1999.998); 335 | // delay(2222.22); 336 | NOTE_AS3, 20 337 | }; 338 | 339 | static volatile unsigned long slast; 340 | static volatile int c; 341 | static volatile int w; 342 | static volatile boolean songOn; 343 | 344 | 345 | class Sequencer { 346 | public: 347 | 348 | static void init() { 349 | 350 | // enable timer, used to play music sequencer async 351 | TCCR1A = 0; // No options in control register A 352 | TCCR1B = (1 << CS10); // Set prescaler to divide by 8 353 | TIMSK1 = (1 << OCIE1A); // Call ISR when TCNT2 = OCRA2 354 | OCR1A = 0;// Set frequency of generated wave 355 | sei(); // Enable interrupts to generate waveform! 356 | 357 | slast = c = w = 0; 358 | songOn = false; 359 | } 360 | 361 | static void start() { 362 | init(); 363 | songOn = true; 364 | } 365 | 366 | static void stop() { 367 | songOn = false; 368 | Beeping::mute(); 369 | } 370 | 371 | static void play() 372 | { 373 | if (!songOn) 374 | { 375 | return; 376 | } 377 | 378 | unsigned long m = millis(); 379 | if ( m - slast > w) 380 | { 381 | slast = m; 382 | 383 | int fr = song[c++]; 384 | int d = song[c++]; 385 | 386 | Beeping::beep (fr, d * 120 ); 387 | w = d * 133; 388 | 389 | if ( song[c] == -1 ) { 390 | c = 0; 391 | w = 10000; 392 | Beeping::mute(); 393 | } 394 | } 395 | } 396 | }; 397 | 398 | 399 | #endif 400 | -------------------------------------------------------------------------------- /BuratinoTetris/BuratinoTetris_1.ino: -------------------------------------------------------------------------------- 1 | 2 | //#include "TFTv2_extended.h" 3 | //#include 4 | #include 5 | #include "ILI9488.h" 6 | #include // Core graphics library 7 | Adafruit_GFX_Button buttons[4]; 8 | 9 | // Color definitions 10 | #define BLACK 0x0000 ///< 0, 0, 0 11 | //#define NAVY 0x000F ///< 0, 0, 123 12 | #define DARKGREEN 0x03E0 ///< 0, 125, 0 13 | //#define DARKCYAN 0x03EF ///< 0, 125, 123 14 | //#define MAROON 0x7800 ///< 123, 0, 0 15 | #define PURPLE 0x780F ///< 123, 0, 123 16 | //#define OLIVE 0x7BE0 ///< 123, 125, 0 17 | #define LIGHTGREY 0xC618 ///< 198, 195, 198 18 | #define DARKGREY 0x7BEF ///< 123, 125, 123 19 | #define BLUE 0x001F ///< 0, 0, 255 20 | #define GREEN 0x07E0 ///< 0, 255, 0 21 | #define CYAN 0x07FF ///< 0, 255, 255 22 | #define RED 0xF800 ///< 255, 0, 0 23 | #define MAGENTA 0xF81F ///< 255, 0, 255 24 | #define YELLOW 0xFFE0 ///< 255, 255, 0 25 | #define WHITE 0xFFFF ///< 255, 255, 255 26 | #define ORANGE 0xFD20 ///< 255, 165, 0 27 | //#define GREENYELLOW 0xAFE5 ///< 173, 255, 41 28 | //#define PINK 0xFC18 ///< 255, 130, 198 29 | 30 | #include "joystick.cpp" 31 | #include "beeping.cpp" 32 | //#include "tetris.cpp" 33 | #include "sequencer.cpp" 34 | 35 | #define LCD_CS A3 // Chip Select goes to Analog 3 36 | #define LCD_RS A2 // Command/Data goes to Analog 2 37 | #define LCD_WR A1 // LCD Write goes to Analog 1 38 | #define LCD_RD A0 // LCD Read goes to Analog 0 39 | #define LCD_RST A4 // Can alternately just connect to Arduino's reset pin 40 | 41 | ILI9488 tft(LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RST); 42 | 43 | const uint8_t YP = A2; // Вывод Y+ должен быть подключен к аналоговому входу 44 | const uint8_t XM = A3; // Вывод X- должен быть подключен к аналоговому входу 45 | const uint8_t YM = 8; // Вывод Y- 46 | const uint8_t XP = 9; // Вывод X+ 47 | #define TS_MINX 65 48 | #define TS_MINY 120 49 | #define TS_MAXX 940 50 | #define TS_MAXY 920 51 | 52 | TouchScreen ts = TouchScreen(XP, YP, XM, YM); // Создаём объект для работы с TouchScreen 53 | 54 | //////////////// 55 | #define LCD_WIDTH 480 56 | #define LCD_HEIGHT 320 57 | 58 | #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) 59 | 60 | #define BOARD_WIDTH 11 61 | #define BOARD_HEIGHT 20 62 | 63 | #define BLOCK_SIZE MIN( (LCD_WIDTH-1) / BOARD_WIDTH, (LCD_HEIGHT-1) / BOARD_HEIGHT ) 64 | 65 | #define BOARD_LEFT (LCD_WIDTH - BOARD_WIDTH * BLOCK_SIZE)/4*2 66 | #define BOARD_RIGHT (BOARD_LEFT + BLOCK_SIZE * BOARD_WIDTH) 67 | #define BOARD_TOP (LCD_HEIGHT - BOARD_HEIGHT * BLOCK_SIZE) / 2 68 | #define BOARD_BOTTOM (BOARD_TOP + BOARD_HEIGHT * BLOCK_SIZE) 69 | 70 | #define PIT_COLOR CYAN 71 | #define BG_COLOR BLACK 72 | 73 | #define DROP_WAIT_INIT 800 74 | #define INPUT_WAIT_FIRE 10 75 | #define INPUT_WAIT_ROT 200 76 | #define INPUT_WAIT_MOVE 100 77 | 78 | #define INPUT_WAIT_NEW_SHAPE 600 79 | 80 | ///////////////// 81 | 82 | uint8_t disp = 1; // display on 83 | uint8_t bb=5; 84 | 85 | void setup() { 86 | Serial.begin(9600); 87 | while (!Serial) { 88 | } 89 | Serial.println("BuratinoTetris!"); 90 | 91 | Sequencer::init(); 92 | 93 | tft.begin(); 94 | tft.setRotation(3); 95 | DISPpower(disp); 96 | 97 | // play turnon sound 98 | Beeping::turnOn(); 99 | 100 | // initialize joystick 101 | Joystick::init(); 102 | } 103 | 104 | void loop() { 105 | 106 | // title screen 107 | drawPreGameScreen(); 108 | 109 | // wait a bit before playing sounds 110 | delay(700); 111 | 112 | // start playing tetris theme 113 | Sequencer::start(); 114 | 115 | // wait for click 116 | while (bb !=1 && !Joystick::fire()){pressbutt();} 117 | bb=5; 118 | 119 | // stop playing tetris theme 120 | Sequencer::stop(); 121 | 122 | // load game 123 | // Tetris t; 124 | trun(); 125 | 126 | // game ended 127 | gameOver(); 128 | } 129 | 130 | void drawPreGameScreen() 131 | { 132 | // draw background 133 | int c = LCD_HEIGHT / 28; 134 | for (int i = LCD_HEIGHT - 1; i >= 0; i -= 2) 135 | { 136 | tft.fillRect(0, i, LCD_WIDTH, 2, 0x1f - i / c); 137 | } 138 | // tft.fillScreen(WHITE); 139 | tft.setCursor(90, 40); 140 | tft.setTextColor(ORANGE); tft.setTextSize(8); 141 | tft.println("Tetris"); 142 | // tft.drawCenteredString("Tetris", 40, 8, BLUE); 143 | tft.setCursor(150, 110); 144 | tft.setTextColor(WHITE); tft.setTextSize(2); 145 | tft.println("Click F to play"); 146 | // tft.drawCenteredString("Click to play", 110, 2, BLACK); 147 | // tft.setCursor(20, 220); 148 | // tft.setTextColor(PURPLE); tft.setTextSize(2); 149 | // tft.println("http://vilaca.eu"); 150 | // tft.drawCenteredString("http://vilaca.eu", 220, 2, PURPLE); 151 | create_butt(); 152 | } 153 | 154 | 155 | void gameOver() 156 | { 157 | tft.fillRect(102, 84, 256, 52, BLACK); 158 | tft.setCursor(118, 94); 159 | tft.setTextColor(WHITE, BLACK); tft.setTextSize(4); 160 | tft.println("Game Over"); 161 | // tft.drawString("Game Over", 48, 94, 4, 0x3ffff); 162 | tft.drawRect(102, 84, 256, 52, RED); 163 | 164 | Beeping::beep(600, 200); 165 | delay(300); 166 | Beeping::beep(600, 200); 167 | delay(300); 168 | Beeping::beep(200, 600); 169 | delay(1500); 170 | while(!Joystick::fire() && bb !=1) {pressbutt();} 171 | bb=5; 172 | // Joystick::waitForClick(); 173 | } 174 | 175 | 176 | ISR(TIMER1_COMPA_vect) { 177 | 178 | // sequencer plays tetris theme 179 | Sequencer::play(); 180 | } 181 | 182 | void DISPpower(uint8_t disp) { 183 | pinMode(10, OUTPUT); 184 | if (disp == 1){ 185 | digitalWrite(10, LOW); 186 | } 187 | if (disp == 0){ 188 | digitalWrite(10, HIGH); 189 | } 190 | // ring(400, 50); 191 | // new_millis = millis(); 192 | } 193 | 194 | /////////////////////////////////// 195 | 196 | // used to clear the position from the screen 197 | typedef struct Backup { 198 | byte x, y, rot; 199 | }; 200 | 201 | byte l_shape[4][4][2] { 202 | {{0, 0}, {0, 1}, {0, 2}, {1, 2}}, 203 | {{0, 1}, {1, 1}, {2, 0}, {2, 1}}, 204 | {{0, 0}, {1, 0}, {1, 1}, {1, 2}}, 205 | {{0, 0}, {0, 1}, {1, 0}, {2, 0}}, 206 | }; 207 | 208 | byte j_shape[4][4][2] { 209 | {{1, 0}, {1, 1}, {0, 2}, {1, 2}}, 210 | {{0, 0}, {1, 0}, {2, 0}, {2, 1}}, 211 | {{0, 0}, {1, 0}, {0, 1}, {0, 2}}, 212 | {{0, 0}, {0, 1}, {1, 1}, {2, 1}}, 213 | }; 214 | 215 | byte o_shape[1][4][2] { 216 | { {0, 0}, {0, 1}, {1, 0}, {1, 1}} 217 | }; 218 | 219 | byte s_shape[2][4][2] { 220 | {{0, 1}, {1, 0}, {1, 1}, {2, 0}}, 221 | {{0, 0}, {0, 1}, {1, 1}, {1, 2}} 222 | }; 223 | 224 | byte z_shape[2][4][2] { 225 | {{0, 0}, {1, 0}, {1, 1}, {2, 1}}, 226 | {{1, 0}, {0, 1}, {1, 1}, {0, 2}} 227 | }; 228 | 229 | byte t_shape[4][4][2] { 230 | {{0, 0}, {1, 0}, {2, 0}, {1, 1}}, 231 | {{0, 0}, {0, 1}, {1, 1}, {0, 2}}, 232 | {{1, 0}, {0, 1}, {1, 1}, {2, 1}}, 233 | {{1, 0}, {0, 1}, {1, 1}, {1, 2}} 234 | }; 235 | 236 | byte i_shape[2][4][2] { 237 | {{0, 0}, {1, 0}, {2, 0}, {3, 0}}, 238 | {{0, 0}, {0, 1}, {0, 2}, {0, 3}} 239 | }; 240 | 241 | // All game shapes and their colors 242 | 243 | byte *all_shapes[7] = {l_shape[0][0], j_shape[0][0], o_shape[0][0], s_shape[0][0], z_shape[0][0], t_shape[0][0], i_shape[0][0]}; 244 | 245 | unsigned int colors[7] = {ORANGE, BLUE, YELLOW, GREEN, RED, MAGENTA, CYAN}; 246 | 247 | 248 | // how many rotated variations each shape has 249 | 250 | byte shapes[7] = {4, 4, 1, 2, 2, 4, 2}; 251 | 252 | 253 | // game progress 254 | 255 | int lines, level; 256 | 257 | // current shapes 258 | 259 | byte current; 260 | 261 | // tetris guidelines have all 7 shapes 262 | // selected in sequence to avoid 263 | // long runs without a shape 264 | 265 | byte next[7]; 266 | byte next_c; 267 | 268 | unsigned long lastInput, lastDrop; 269 | 270 | byte board[BOARD_HEIGHT][BOARD_WIDTH]; 271 | 272 | byte x, y, rot; 273 | Backup old; 274 | 275 | boolean newShape; 276 | 277 | int dropWait; 278 | 279 | void trun() 280 | { 281 | // analog 2 MUST NOT be connected to anything... 282 | 283 | randomSeed(analogRead(2)); 284 | 285 | // clear board 286 | 287 | for ( int i = 0; i < BOARD_WIDTH; i++ ) 288 | { 289 | for ( int j = 0; j < BOARD_HEIGHT; j++) 290 | { 291 | board[j][i] = 0; 292 | } 293 | } 294 | 295 | //next shape 296 | 297 | randomizer(); 298 | 299 | // initialize game logic 300 | 301 | lastInput = 0; 302 | lastDrop = 0; 303 | dropWait = DROP_WAIT_INIT; 304 | level = 1; 305 | 306 | // draw background 307 | 308 | int c = LCD_HEIGHT / 28; 309 | for (int i = LCD_HEIGHT - 1; i >= 0; i -= 2) 310 | { 311 | tft.fillRect(0, i, LCD_WIDTH, 2, 0x1f - i / c); 312 | } 313 | 314 | tft.fillRect(BOARD_LEFT, 0, BOARD_RIGHT-BOARD_LEFT-1, BOARD_BOTTOM, BG_COLOR); 315 | create_butt(); 316 | // draw board left limit 317 | 318 | tft.drawLine ( 319 | BOARD_LEFT - 1, 320 | BOARD_TOP, 321 | BOARD_LEFT - 1, 322 | BOARD_BOTTOM, 323 | PIT_COLOR); 324 | 325 | // draw board right limit 326 | 327 | tft.drawLine ( 328 | BOARD_RIGHT, 329 | BOARD_TOP, 330 | BOARD_RIGHT, 331 | BOARD_BOTTOM, 332 | PIT_COLOR); 333 | 334 | // draw board bottom limit 335 | 336 | tft.drawLine ( 337 | BOARD_LEFT - 1, 338 | BOARD_BOTTOM, 339 | BOARD_RIGHT + 1, 340 | BOARD_BOTTOM, 341 | PIT_COLOR); 342 | 343 | for ( int i = BOARD_LEFT + BLOCK_SIZE - 1; i < BOARD_RIGHT; i += BLOCK_SIZE) 344 | { 345 | tft.drawLine ( 346 | i, 347 | BOARD_TOP, 348 | i, 349 | BOARD_BOTTOM - 1, 350 | DARKGREY); 351 | } 352 | 353 | for ( int i = BOARD_TOP + BLOCK_SIZE - 1; i < BOARD_BOTTOM; i += BLOCK_SIZE) 354 | { 355 | tft.drawLine ( 356 | BOARD_LEFT, 357 | i, 358 | BOARD_RIGHT - 1, 359 | i, 360 | DARKGREY); 361 | } 362 | 363 | scoreBoard(); 364 | 365 | do { 366 | pressbutt(); 367 | // get clock 368 | const unsigned long now = millis(); 369 | 370 | // display new shape 371 | if ( newShape ) 372 | { 373 | Joystick::waitForRelease(INPUT_WAIT_NEW_SHAPE); 374 | newShape = false; 375 | 376 | // a new shape enters the game 377 | chooseNewShape(); 378 | 379 | // draw next box 380 | tft.fillRect(350, 3, BLOCK_SIZE * 6, BLOCK_SIZE * 5, BLACK); 381 | tft.drawRect(349, 2, BLOCK_SIZE * 6 + 1, BLOCK_SIZE * 5 + 1, WHITE); 382 | 383 | byte *shape = all_shapes[next[next_c]]; 384 | for ( int i = 0; i < 4; i++ ) 385 | { 386 | byte *block = shape + i * 2; 387 | tft.fillRect( 388 | 350 + BLOCK_SIZE + block[0]*BLOCK_SIZE, 389 | 3 + BLOCK_SIZE + block[1]*BLOCK_SIZE, 390 | BLOCK_SIZE - 2, 391 | BLOCK_SIZE - 2 , 392 | colors[next[next_c]]); 393 | } 394 | 395 | // check if new shape is placed over other shape(s) 396 | // on the board 397 | if ( touches(0, 0, 0 )) 398 | { 399 | // draw shape to screen 400 | draw(); 401 | return; 402 | } 403 | 404 | // draw shape to screen 405 | draw(); 406 | } 407 | else 408 | { 409 | // check if enough time has passed since last time the shape 410 | // was moved down the board 411 | // if ( now - lastDrop > dropWait || Joystick::getY() > Joystick::NEUTRAL) 412 | if ( now - lastDrop > dropWait) 413 | { 414 | // update clock 415 | lastDrop = now; 416 | moveDown(); 417 | } 418 | } 419 | 420 | if (!newShape) 421 | { 422 | userInput(now); 423 | // bb=5; 424 | } 425 | // delay(10); 426 | 427 | delay(10); 428 | } while (true); 429 | 430 | } 431 | 432 | void chooseNewShape() 433 | { 434 | current = next[next_c]; 435 | 436 | next_c++; 437 | 438 | if ( next_c == 7 ) 439 | { 440 | randomizer(); 441 | } 442 | 443 | // new shape must be positioned at the middle of 444 | // the top of the board 445 | // with zero rotation 446 | 447 | rot = 0; 448 | y = 0; 449 | x = BOARD_WIDTH / 2; 450 | 451 | old.rot = rot; 452 | old.y = y; 453 | old.x = x; 454 | } 455 | 456 | void userInput(unsigned long now) 457 | { 458 | unsigned long waited = now - lastInput; 459 | 460 | int jx = Joystick::getX(); 461 | 462 | // int move = INPUT_WAIT_MOVE / jx; 463 | int move = INPUT_WAIT_MOVE; 464 | // if ( jx < Joystick::NEUTRAL && waited > -move) 465 | if (bb==2 && waited > move) 466 | { 467 | if (x > 0 && !touches(-1, 0, 0)) 468 | { 469 | x--; 470 | lastInput = now; 471 | draw(); 472 | } 473 | } 474 | // else if ( jx > Joystick::NEUTRAL && waited > move ) 475 | else if (bb==3 && waited > move) 476 | { 477 | if ( x < BOARD_WIDTH && !touches(1, 0, 0)) 478 | { 479 | x++; 480 | lastInput = now; 481 | draw(); 482 | } 483 | } 484 | 485 | if ( bb==1 or Joystick::fire()) 486 | // if ( bb==1 && waited > INPUT_WAIT_FIRE) 487 | { 488 | while ( !touches(0, 1, 0 )) 489 | { 490 | delay(INPUT_WAIT_FIRE); 491 | y++; 492 | } 493 | lastInput = now; 494 | draw(); 495 | } 496 | 497 | int my = Joystick::getY(); 498 | // if (( my == -Joystick::HARD && waited > INPUT_WAIT_ROT ) || ( my == -Joystick::HARDER && waited > INPUT_WAIT_ROT / 2 )) 499 | // { 500 | // if (Joystick::getY() < 0 && !touches(0, 0, 1)) 501 | 502 | if (bb==0 && waited > INPUT_WAIT_ROT) 503 | { 504 | rot++; 505 | rot %= shapes[current]; 506 | lastInput = now; 507 | draw(); 508 | } 509 | // } 510 | } 511 | 512 | void moveDown() 513 | { 514 | // prepare to move down 515 | // check if board is clear bellow 516 | 517 | if ( touches(0, 1, 0 )) 518 | { 519 | // moving down touches another shape 520 | newShape = true; 521 | 522 | // this shape wont move again 523 | // add it to the board 524 | 525 | byte *shape = all_shapes[current]; 526 | for ( int i = 0; i < 4; i++ ) 527 | { 528 | byte *block = (shape + (rot * 4 + i) * 2); 529 | board[block[1] + y][block[0] + x] = current + 1; 530 | } 531 | 532 | // check if lines were made 533 | 534 | score(); 535 | Beeping::beep(1500, 25); 536 | } 537 | else 538 | { 539 | // move shape down 540 | y += 1; 541 | draw(); 542 | } 543 | } 544 | 545 | void draw() 546 | { 547 | byte *shape = all_shapes[current]; 548 | for ( int i = 0; i < 4; i++ ) 549 | { 550 | byte *block = (shape + (rot * 4 + i) * 2); 551 | 552 | // tft.fillRectangleUseBevel( 553 | tft.fillRect( 554 | BOARD_LEFT + block[0]*BLOCK_SIZE + BLOCK_SIZE * x, 555 | BOARD_TOP + block[1]*BLOCK_SIZE + BLOCK_SIZE * y, 556 | BLOCK_SIZE - 2, 557 | BLOCK_SIZE - 2 , 558 | colors[current]); 559 | 560 | board[block[1] + y][block[0] + x] = 255; 561 | } 562 | 563 | // erase old 564 | for ( int i = 0; i < 4; i++ ) 565 | { 566 | byte *block = (shape + (old.rot * 4 + i) * 2); 567 | 568 | if ( board[block[1] + old.y][block[0] + old.x] == 255 ) 569 | continue; 570 | 571 | tft.fillRect( 572 | BOARD_LEFT + block[0]*BLOCK_SIZE + BLOCK_SIZE * old.x, 573 | BOARD_TOP + block[1]*BLOCK_SIZE + BLOCK_SIZE * old.y, 574 | BLOCK_SIZE - 2, 575 | BLOCK_SIZE - 2 , 576 | BG_COLOR); 577 | } 578 | 579 | for ( int i = 0; i < 4; i++ ) 580 | { 581 | byte *block = (shape + (rot * 4 + i) * 2); 582 | board[block[1] + y][block[0] + x] = 0; 583 | } 584 | 585 | old.x = x; 586 | old.y = y; 587 | old.rot = rot; 588 | } 589 | 590 | boolean touches(int xi, int yi, int roti) 591 | { 592 | byte *shape = all_shapes[current]; 593 | for ( int i = 0; i < 4; i++ ) 594 | { 595 | byte *block = (shape + (((rot + roti) % shapes[current]) * 4 + i) * 2); 596 | 597 | int x2 = x + block[0] + xi; 598 | int y2 = y + block[1] + yi; 599 | 600 | if ( y2 == BOARD_HEIGHT || x2 == BOARD_WIDTH || board[y2][x2] != 0 ) 601 | { 602 | return true; 603 | } 604 | } 605 | return false; 606 | } 607 | 608 | void score() 609 | { 610 | // we scan a max of 4 lines 611 | int ll; 612 | if ( y + 3 >= BOARD_HEIGHT ) 613 | { 614 | ll = BOARD_HEIGHT - 1; 615 | } 616 | 617 | // scan board from current position 618 | for (int l = y; l <= ll; l++) 619 | { 620 | // check if there's a complete line on the board 621 | boolean line = true; 622 | 623 | for ( int c = 0; c < BOARD_WIDTH; c++ ) 624 | { 625 | if (board[l][c] == 0) 626 | { 627 | line = false; 628 | break; 629 | } 630 | } 631 | 632 | if ( !line ) 633 | { 634 | // move to next line 635 | continue; 636 | } 637 | 638 | Beeping::beep(3000, 50); 639 | 640 | lines++; 641 | 642 | if ( lines % 10 == 0 ) 643 | { 644 | level++; 645 | dropWait -= 200; 646 | } 647 | 648 | scoreBoard(); 649 | 650 | // move board down 651 | for ( int row = l; row > 0; row -- ) 652 | { 653 | for ( int c = 0; c < BOARD_WIDTH; c++ ) 654 | { 655 | byte v = board[row - 1][c]; 656 | 657 | board[row][c] = v; 658 | // tft.fillRectangleUseBevel( 659 | tft.fillRect( 660 | BOARD_LEFT + BLOCK_SIZE * c, 661 | BOARD_TOP + BLOCK_SIZE * row, 662 | BLOCK_SIZE - 2, 663 | BLOCK_SIZE - 2 , 664 | v == 0 ? BLACK : colors[v - 1] ) ; 665 | } 666 | } 667 | 668 | // clear top line 669 | for ( int c = 0; c < BOARD_WIDTH; c++ ) 670 | { 671 | board[0][c] = 0; 672 | } 673 | 674 | tft.fillRect( 675 | BOARD_LEFT, 676 | 0, 677 | BOARD_RIGHT - BOARD_LEFT, 678 | BLOCK_SIZE, 679 | BLACK ) ; 680 | } 681 | 682 | delay(350); 683 | } 684 | 685 | void scoreBoard() 686 | { 687 | tft.fillRect(11, 8, 128, 50, BLACK); 688 | tft.setCursor(13, 13); 689 | tft.setTextColor(YELLOW); tft.setTextSize(2); 690 | tft.println("Level"); 691 | tft.setCursor(13, 37); 692 | tft.setTextColor(0x3f); tft.setTextSize(2); 693 | tft.println("Lines"); 694 | tft.setCursor(79, 13); 695 | tft.setTextColor(YELLOW); tft.setTextSize(2); 696 | tft.println(level); 697 | tft.setCursor(79, 37); 698 | tft.setTextColor(0x3f); tft.setTextSize(2); 699 | tft.println(lines); 700 | tft.drawRect(10, 7, 130, 52, 0xffff); 701 | } 702 | 703 | // create a sequence of 7 random shapes 704 | 705 | void randomizer() 706 | { 707 | // randomize 7 shapes 708 | 709 | for ( byte i = 0; i < 7; i ++) 710 | { 711 | boolean retry; 712 | byte shape; 713 | do 714 | { 715 | shape = random(7); 716 | 717 | // check if already in sequence 718 | 719 | retry= false; 720 | for ( int j = 0; j < i; j++) 721 | { 722 | if ( shape == next[j] ) 723 | { 724 | retry = true; 725 | break; 726 | } 727 | } 728 | 729 | } while (retry); 730 | next[i] = shape; 731 | } 732 | next_c = 0; 733 | } 734 | 735 | void create_butt() { 736 | char buttonlabels[4][2]={"S", "F", "<", ">"}; 737 | uint16_t buttoncolors[4] = { DARKGREY, RED, DARKGREEN, 738 | ORANGE}; 739 | // tft.fillRect(0, 150, 320, 480, BLACK); 740 | for (uint8_t row=0; row<2; row++) { 741 | for (uint8_t col=0; col<2; col++) { 742 | buttons[col + row*2].initButton(&tft, 70+col*(80+260), 743 | 175+row*(50+40), // x, y, w, h, outline, fill, text 744 | 80, 50, WHITE, buttoncolors[col+row*2], WHITE, 745 | buttonlabels[col + row*2], 2); 746 | buttons[col + row*2].drawButton(); 747 | } 748 | } 749 | } 750 | 751 | void pressbutt() 752 | { 753 | bb=5; 754 | // delay(20); 755 | TSPoint p = ts.getPoint(); 756 | pinMode(XM, OUTPUT); // Возвращаем режим работы вывода X- в значение «выход» для работы с дисплеем 757 | pinMode(YP, OUTPUT); // Возвращаем режим работы вывода Y+ в значение «выход» для работы с дисплеем 758 | if (p.z>100) { 759 | // Выводим «сырые» показания TouchScreen: 760 | // Serial.println((String) "X="+p.x+",\tY="+p.y); 761 | uint16_t x = p.x; 762 | uint16_t y = p.y; 763 | p.y = map(x, TS_MINY, TS_MAXY, 320, 0); 764 | p.x = map(y, TS_MINX, TS_MAXX, 0, 480); 765 | //Serial.println((String) "X="+p.x+",\tY="+p.y); 766 | } else {p.x = p.y = -1;} 767 | 768 | // go thru all the buttons, checking if they were pressed 769 | for (uint8_t b=0; b<4; b++) { 770 | if (buttons[b].contains(p.x, p.y)) { 771 | //Serial.print("Pressing: "); Serial.println(b); 772 | buttons[b].press(true); // tell the button it is pressed 773 | bb=b; 774 | // Beeping::beep(600, 40); 775 | } else { 776 | buttons[b].press(false); // tell the button it is NOT pressed 777 | } 778 | } 779 | 780 | // for (uint8_t b=0; b<4; b++) { 781 | // if (buttons[b].justReleased()) { 782 | //Serial.print("Released: "); Serial.println(b); 783 | // buttons[b].drawButton(); // draw normal 784 | // } 785 | // Serial.println(bb); 786 | // if (buttons[b].justPressed()) { 787 | // buttons[b].drawButton(true); // draw invert! 788 | // } 789 | // } 790 | } 791 | -------------------------------------------------------------------------------- /BuratinoFlappy/flappy2.ino: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // ============================================================================= 3 | 4 | #include 5 | //#include 6 | //#include 7 | #include 8 | #include "ILI9488.h" 9 | 10 | Adafruit_GFX_Button buttons[4]; 11 | 12 | // initialize Sainsmart 1.8" TFT screen 13 | // (connect pins accordingly or change these values) 14 | //#define TFT_DC 9 // Sainsmart RS/DC 15 | //#define TFT_RST 8 // Sainsmart RES 16 | //#define TFT_CS 10 // Sainsmart CS 17 | // initialize screen with pins 18 | //static Adafruit_ST7735 TFT = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); 19 | 20 | #define LCD_CS A3 // Chip Select goes to Analog 3 21 | #define LCD_RS A2 // Command/Data goes to Analog 2 22 | #define LCD_WR A1 // LCD Write goes to Analog 1 23 | #define LCD_RD A0 // LCD Read goes to Analog 0 24 | #define LCD_RST A4 // Can alternately just connect to Arduino's reset pin 25 | 26 | ILI9488 TFT(LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RST); 27 | 28 | const uint8_t YP = A2; // Вывод Y+ должен быть подключен к аналоговому входу 29 | const uint8_t XM = A3; // Вывод X- должен быть подключен к аналоговому входу 30 | const uint8_t YM = 8; // Вывод Y- 31 | const uint8_t XP = 9; // Вывод X+ 32 | // This is calibration data for the raw touch data to the screen coordinates 33 | #define TS_MINX 65 34 | #define TS_MINY 120 35 | #define TS_MAXX 940 36 | #define TS_MAXY 920 37 | 38 | TouchScreen ts = TouchScreen(XP, YP, XM, YM); // Создаём объект для работы с TouchScreen 39 | 40 | // instead of using TFT.width() and TFT.height() set constant values 41 | // (we can change the size of the game easily that way) 42 | #define TFTW 320//128 // screen width 43 | #define TFTH 450//160 // screen height 44 | #define TFTW2 160//64 // half screen width 45 | #define TFTH2 225//80 // half screen height 46 | // game constant 47 | #define SPEED 1 48 | #define GRAVITY 2.8 49 | #define JUMP_FORCE 0.5//2.15 50 | #define SKIP_TICKS 20.0 // 1000 / 50fps 51 | #define MAX_FRAMESKIP 1//5 52 | // bird size 53 | #define BIRDW 16 // bird width 54 | #define BIRDH 16 // bird height 55 | #define BIRDW2 BIRDW/2 // half width 56 | #define BIRDH2 BIRDH/2 // half height 57 | #define BIRDX 50 // x posizion 58 | // pipe size 59 | uint8_t PIPEW = 24 ;//12 // pipe width 60 | uint16_t GAPHEIGHT = 60 ; // pipe gap height 61 | // prize 62 | uint16_t PRZY = 10; 63 | boolean PRZON = 1; 64 | // prize1 65 | int PRZ1X = 160; 66 | uint16_t PRZ1Y = 120; 67 | uint8_t PRZW = 8; 68 | uint8_t PRZH = 8; 69 | //brick 70 | int BRICKX = 100; 71 | uint16_t BRICKY = 0; 72 | uint8_t BRICKW = 8; 73 | uint8_t BRICKH = 8; 74 | uint8_t SPEEDBRICK = 3; 75 | boolean BRICKON = 1; 76 | 77 | // floor size 78 | uint16_t FLOORH = 40 ;//20 // floor height (from bottom of the screen) 79 | // grass size 80 | #define GRASSH BIRDH+2//4 // grass height (inside floor, starts at floor y) 81 | 82 | uint16_t GAMEH = TFTH-FLOORH; 83 | 84 | // background 85 | const unsigned int BCKGRDCOL = TFT.Color565(138,235,244); 86 | // bird 87 | const unsigned int BIRDCOL = TFT.Color565(255,254,174); 88 | // pipe 89 | const unsigned int PIPECOL = TFT.Color565(99,255,78); 90 | // pipe highlight 91 | const unsigned int PIPEHIGHCOL = TFT.Color565(250,255,250); 92 | // pipe seam 93 | const unsigned int PIPESEAMCOL = TFT.Color565(0,0,0); 94 | // floor 95 | const unsigned int FLOORCOL = TFT.Color565(246,240,163); 96 | // grass (col2 is the stripe color) 97 | const unsigned int GRASSCOL = TFT.Color565(141,225,87); 98 | const unsigned int GRASSCOL2 = TFT.Color565(156,239,88); 99 | 100 | // bird sprite 101 | // bird sprite colors (Cx name for values to keep the array readable) 102 | #define ST7735_BLACK 0x0000 ///< 0, 0, 0 103 | 104 | #define C0 BCKGRDCOL 105 | #define C1 TFT.Color565(195,165,75) 106 | #define C2 BIRDCOL 107 | #define ST7735_WHITE 0xFFFF ///< 255, 255, 255 108 | #define C3 ST7735_WHITE 109 | #define ST7735_RED 0xF800 ///< 255, 0, 0 110 | #define C4 ST7735_RED 111 | #define C5 TFT.Color565(251,216,114) 112 | static unsigned int birdcol[] = 113 | { 114 | C0, C0, C1, C1, C1, C1, C1, C0, 115 | C0, C1, C2, C2, C2, C1, C3, C1, 116 | C0, C2, C2, C2, C2, C1, C3, C1, 117 | C1, C1, C1, C2, C2, C3, C1, C1, 118 | C1, C2, C2, C2, C2, C2, C4, C4, 119 | C1, C2, C2, C2, C1, C5, C4, C0, 120 | C0, C1, C2, C1, C5, C5, C5, C0, 121 | C0, C0, C1, C5, C5, C5, C0, C0, 122 | 123 | C0, C0, C1, C1, C1, C1, C1, C0, 124 | C0, C1, C2, C2, C2, C1, C3, C1, 125 | C0, C2, C2, C2, C2, C1, C3, C1, 126 | C1, C1, C1, C2, C2, C3, C1, C1, 127 | C1, C2, C2, C2, C2, C2, C4, C4, 128 | C1, C2, C2, C2, C1, C5, C4, C0, 129 | C0, C1, C2, C1, C5, C5, C5, C0, 130 | C0, C0, C1, C5, C5, C5, C0, C0 131 | }; 132 | 133 | // bird structure 134 | static struct BIRD { 135 | int x, y, old_y; 136 | unsigned int col; 137 | float vel_y; 138 | } bird; 139 | // pipe structure 140 | static struct PIPE { 141 | // char x, gap_y; 142 | int x; 143 | int gap_y; 144 | unsigned int col; 145 | } pipe; 146 | // prize1 structure 147 | static struct PRIZE1 { 148 | // char x, y; 149 | int x; 150 | int y; 151 | unsigned int col; 152 | } prize1; 153 | // brick structure 154 | static struct BRICK { 155 | // char x, y; 156 | int x; 157 | int y; 158 | int old_y; 159 | unsigned int col; 160 | } brick; 161 | 162 | // live 163 | static short live = 5; 164 | // score 165 | static short score; 166 | // prize 167 | static short prize; 168 | // temporary x and y var 169 | static short tmpx, tmpy; 170 | // temporary bx and by var 171 | static short tmpbx, tmpby; 172 | 173 | // --------------- 174 | // draw pixel 175 | // --------------- 176 | // faster TFT.drawPixel method by inlining calls and using setAddrWindow and pushColor 177 | // using macro to force inlining 178 | //#define TFT.drawPixel(a, b, c) TFT.setAddrWindow(a, b, a, b); TFT.pushColors(c,8,1) 179 | 180 | // --------------- 181 | // initial setup 182 | // --------------- 183 | void setup() { 184 | Serial.begin(9600); 185 | while (!Serial) { 186 | } 187 | Serial.println("Flappy"); 188 | // initialize the push button on pin 2 as an input 189 | // DDRD &= ~(1< (TFTH - bird.y)) {FLOORH = TFTH - bird.y - 20;} 220 | drawfloor(); 221 | // grass x position (for stripe animation) 222 | int grassx = TFTW; 223 | // game loop time variables 224 | double delta, old_time, next_game_tick, current_time; 225 | next_game_tick = current_time = millis(); 226 | int loops; 227 | // passed pipe flag to count score 228 | bool passed_pipe = false; 229 | // passed prize flag to count score 230 | bool passed_prize = false; 231 | bool passed_prize_1 = false; 232 | // temp var for setAddrWindow 233 | int px; 234 | int pbx; 235 | 236 | while (1) { 237 | loops = 0; 238 | while( millis() > next_game_tick && loops < MAX_FRAMESKIP) { 239 | // =============== 240 | // input 241 | // =============== 242 | // if ( !(PIND & (1< BIRDH2*0.5) bird.vel_y = -JUMP_FORCE; 247 | // else zero velocity 248 | else bird.vel_y = 0; 249 | } 250 | 251 | // =============== 252 | // update 253 | // =============== 254 | // calculate delta time 255 | // --------------- 256 | old_time = current_time; 257 | current_time = millis(); 258 | delta = (current_time-old_time)/1000; 259 | 260 | // bird 261 | // --------------- 262 | bird.vel_y += GRAVITY * delta; 263 | bird.y += bird.vel_y; 264 | 265 | // pipe 266 | // --------------- 267 | pipe.x -= SPEED; 268 | prize1.x -= SPEED; 269 | brick.x -= SPEED; 270 | // if pipe reached edge of the screen reset its position and gap 271 | // if ((prize1.x > brick.x && prize1.x < -PRZW) or (brick.x > prize1.x && brick.x < -BRICKW)) { 272 | if (prize1.x < -PRZW) { 273 | TFT.fillRect(0, GAMEH, TFTW, FLOORH, BCKGRDCOL); 274 | pipe.x = TFTW; 275 | PIPEW = random(20, TFTW2/2); 276 | pipe.gap_y = random(10, GAMEH-(10+GAPHEIGHT)); 277 | FLOORH = random(10, TFTH - pipe.gap_y - 30); 278 | if ( (FLOORH+10) > (TFTH - bird.y)) {FLOORH = TFTH - bird.y - 20;} 279 | GAPHEIGHT = random(BIRDH*3, TFTH-pipe.gap_y-FLOORH-20); 280 | if ( (FLOORH+10) > (TFTH - pipe.gap_y-GAPHEIGHT)) {FLOORH = TFTH - pipe.gap_y - GAPHEIGHT - 20;} 281 | PRZY = random(10, GAPHEIGHT-BIRDH-10); 282 | PRZ1X = random(PIPEW+50, TFTW-20); 283 | PRZ1Y = random(10, TFTH-FLOORH-20); 284 | uint8_t przint = random(0, 10); 285 | if (przint >= 5) PRZON = 1; 286 | if (przint < 5) PRZON = 0; 287 | drawfloor(); 288 | passed_prize = false; 289 | passed_prize_1 = false; 290 | prize1.x = TFTW+PRZ1X; 291 | int brickint = random(-1,1); 292 | if (brickint==0) {BRICKON = 0; BRICKX = 0;} 293 | if (brickint > 0) {BRICKON = 1; BRICKX = random(PIPEW+BRICKW, PRZ1X-BRICKW);} 294 | if (brickint < 0) {BRICKON = 1; BRICKX = random(-TFTW+BIRDX+BIRDW+40, 0-BRICKW);} 295 | // BRICKX = random(-TFTW+BIRDX+BIRDW+20, PRZ1X-20); 296 | // BRICKX = random(random(-TFTW+BIRDX+BIRDW+BIRDW+20, 0-BRICKW), random(PIPEW+BRICKW+BRICKW, PRZ1X-BRICKW)); 297 | brick.x = TFTW+BRICKX; 298 | // brick.y = BRICKY; 299 | } 300 | if (brick.x < -BRICKH or brick.y > GAMEH-GRASSH) { 301 | // brick.x = TFTW+BRICKX; 302 | brick.y = BRICKY; 303 | SPEEDBRICK = random(2,4); 304 | } 305 | // --------------- 306 | next_game_tick += SKIP_TICKS; 307 | loops++; 308 | } 309 | 310 | // =============== 311 | // draw 312 | // =============== 313 | // draw prize 314 | // --------------- 315 | if (pipe.x >= 0 && pipe.x < TFTW && !passed_prize && PRZON) { 316 | TFT.drawFastVLine(pipe.x+(PIPEW/2)-(PRZW/2), pipe.gap_y+PRZY+bird.vel_y, PRZH, ST7735_RED); 317 | TFT.drawFastVLine(pipe.x+(PIPEW/2)-(PRZW/2)+PRZW, pipe.gap_y+PRZY+bird.vel_y, PRZH, BCKGRDCOL); 318 | } 319 | if (pipe.x >= 0 && pipe.x < TFTW && passed_prize && PRZON) { 320 | if (bird.x < pipe.x+(PIPEW/2)-(PRZW/2)+PRZW && bird.y != pipe.gap_y+PRZY) { 321 | TFT.drawFastVLine(pipe.x+(PIPEW/2)-(PRZW/2), pipe.gap_y+PRZY, PRZH, BIRDCOL); 322 | TFT.drawFastVLine(pipe.x+(PIPEW/2)-(PRZW/2)+PRZW, pipe.gap_y+PRZY, PRZH, BCKGRDCOL); 323 | } 324 | } 325 | // erase behind prize 326 | if (pipe.x <= TFTW && PRZON) TFT.drawFastVLine(pipe.x+(PIPEW/2)-(PRZW/2)+PRZW, pipe.gap_y+PRZY, PRZH, BCKGRDCOL); 327 | 328 | // draw prize 1 329 | if (prize1.x >= 0 && prize1.x < TFTW && !passed_prize_1) { 330 | TFT.drawFastVLine(prize1.x, PRZ1Y-bird.vel_y, PRZH, ST7735_RED); 331 | TFT.drawFastVLine(prize1.x+PRZW, PRZ1Y-bird.vel_y, PRZH, BCKGRDCOL); 332 | } 333 | if (prize1.x >= 0 && prize1.x < TFTW && passed_prize_1) { 334 | if (bird.x < prize1.x+PRZW && bird.y != PRZ1Y) { 335 | TFT.drawFastVLine(prize1.x, PRZ1Y, PRZH, BIRDCOL); 336 | TFT.drawFastVLine(prize1.x+PRZW, PRZ1Y, PRZH, BCKGRDCOL); 337 | } 338 | } 339 | // erase behind prize1 340 | if (prize1.x <= TFTW+PRZ1X) TFT.drawFastVLine(prize1.x+PRZW, 0, GAMEH, BCKGRDCOL); 341 | 342 | // draw brick 343 | 344 | if (brick.y >=0 && brick.y < GAMEH && brick.x >= 0 && brick.x < TFTW && BRICKON) { 345 | brick.y += SPEEDBRICK; 346 | TFT.drawFastVLine(brick.x, brick.y, BRICKH, ST7735_BLACK); 347 | TFT.drawFastVLine(brick.x+BRICKW, brick.y, BRICKH, BCKGRDCOL); 348 | } 349 | 350 | // erase behind brick 351 | if (brick.x <= TFTW+BRICKX && BRICKON) {TFT.drawFastVLine(brick.x+BRICKW, 0, GAMEH, BCKGRDCOL);} 352 | 353 | // =============== 354 | // draw 355 | // =============== 356 | // pipe 357 | // --------------- 358 | // we save cycles if we avoid drawing the pipe when outside the screen 359 | if (pipe.x >= 0 && pipe.x < TFTW) { 360 | // pipe color 361 | TFT.drawFastVLine(pipe.x+3, 0, pipe.gap_y, PIPECOL); 362 | TFT.drawFastVLine(pipe.x+3, pipe.gap_y+GAPHEIGHT+1, GAMEH-(pipe.gap_y+GAPHEIGHT+1), PIPECOL); 363 | // highlight 364 | TFT.drawFastVLine(pipe.x, 0, pipe.gap_y, PIPEHIGHCOL); 365 | TFT.drawFastVLine(pipe.x, pipe.gap_y+GAPHEIGHT+1, GAMEH-(pipe.gap_y+GAPHEIGHT+1), PIPEHIGHCOL); 366 | // bottom and top border of pipe 367 | TFT.drawPixel(pipe.x, pipe.gap_y, PIPESEAMCOL); 368 | TFT.drawPixel(pipe.x, pipe.gap_y+GAPHEIGHT, PIPESEAMCOL); 369 | // pipe seam 370 | TFT.drawPixel(pipe.x, pipe.gap_y-6, PIPESEAMCOL); 371 | TFT.drawPixel(pipe.x, pipe.gap_y+GAPHEIGHT+6, PIPESEAMCOL); 372 | TFT.drawPixel(pipe.x+3, pipe.gap_y-6, PIPESEAMCOL); 373 | TFT.drawPixel(pipe.x+3, pipe.gap_y+GAPHEIGHT+6, PIPESEAMCOL); 374 | } 375 | // erase behind pipe 376 | if (pipe.x <= TFTW) TFT.drawFastVLine(pipe.x+PIPEW, 0, GAMEH, BCKGRDCOL); 377 | 378 | // bird 379 | // --------------- 380 | tmpx = BIRDW-1; 381 | do { 382 | /* px = bird.x+tmpx+BIRDW; 383 | // clear bird at previous position stored in old_y 384 | // we can't just erase the pixels before and after current position 385 | // because of the non-linear bird movement (it would leave 'dirty' pixels) 386 | tmpy = BIRDH - 1; 387 | 388 | do { 389 | TFT.drawPixel(px, bird.old_y + tmpy, BCKGRDCOL); 390 | } while (tmpy--); 391 | // draw bird sprite at new position 392 | tmpy = BIRDH-1; 393 | do { 394 | TFT.drawPixel(px, bird.y + tmpy, birdcol[tmpx + (tmpy * BIRDW)]); 395 | } while (tmpy--); 396 | */ 397 | px = bird.x+tmpx; 398 | ///erase bird rasrt 399 | TFT.drawFastVLine(px, bird.old_y, BIRDH, BCKGRDCOL); 400 | // draw bird rastr 401 | if (tmpx GAMEH) {crach(); break;} 427 | // checking for bird collision with pipe 428 | if (bird.x+BIRDW >= pipe.x && bird.x <= pipe.x+PIPEW) { 429 | // bird entered a pipe, check for collision 430 | if (bird.y < pipe.gap_y || bird.y+BIRDH > pipe.gap_y+GAPHEIGHT) {crach(); break;} 431 | else {passed_pipe = true;} 432 | } 433 | // if bird has passed the pipe increase score 434 | else if (bird.x > pipe.x+PIPEW-BIRDW && passed_pipe) { 435 | passed_pipe = false; 436 | // increase score since we successfully passed a pipe 437 | score++; 438 | tone(11, 1000, 20); 439 | drawscore(); 440 | } 441 | // checking for bird collision with brick 442 | if (BRICKON && brick.x <= bird.x+BIRDW && brick.x > bird.x && brick.y+BRICKH >= bird.y && brick.y+BRICKH < bird.y+BIRDH) { 443 | crach(); break; 444 | } 445 | // checking for bird collision with prize 446 | if (!passed_prize && PRZON && 447 | ((bird.x+BIRDW > pipe.x+(PIPEW/2)&& bird.x+BIRDW < pipe.x+(PIPEW/2)-(PRZW/2)+PRZW) or (bird.x > pipe.x+(PIPEW/2) && bird.x < pipe.x+(PIPEW/2)-(PRZW/2)+PRZW)) 448 | && 449 | ((bird.y+BIRDH > pipe.gap_y+PRZY && bird.y+BIRDH < pipe.gap_y+PRZY+PRZH) or (bird.y > pipe.gap_y+PRZY && bird.y < pipe.gap_y+PRZY+PRZH)) 450 | ) 451 | { 452 | passed_prize = true; 453 | prize++; 454 | tone(11, 1000, 20); 455 | drawscore(); 456 | } 457 | // checking for bird collision with prize1 458 | if (!passed_prize_1 && 459 | ((bird.x+BIRDW > prize1.x && bird.x+BIRDW < prize1.x+PRZW) or (bird.x > prize1.x && bird.x < prize1.x+PRZW)) 460 | && 461 | ((bird.y+BIRDH > PRZ1Y && bird.y+BIRDH < PRZ1Y+PRZH) or (bird.y > PRZ1Y && bird.y < PRZ1Y+PRZH)) 462 | ) 463 | { 464 | passed_prize_1 = true; 465 | prize++; 466 | tone(11, 1000, 20); 467 | drawscore(); 468 | } 469 | // checking for bird collision with prize1 470 | // passed_brick = true; 471 | } 472 | 473 | // add a small delay to show how the player lost 474 | // delay(1200); 475 | live --; 476 | drawscore(); 477 | while (1) { 478 | // wait for push button 479 | uint8_t bdis = digitalRead(19); 480 | if ( bdis == 0 or presstouch()) break; 481 | } 482 | } 483 | 484 | // --------------- 485 | // game start 486 | // --------------- 487 | void game_start() { 488 | TFT.fillScreen(ST7735_BLACK); 489 | TFT.fillRect(10, TFTH2 - 20, TFTW-20, 1, ST7735_WHITE); 490 | TFT.fillRect(10, TFTH2 + 32, TFTW-20, 1, ST7735_WHITE); 491 | TFT.setTextColor(ST7735_WHITE); 492 | TFT.setTextSize(3); 493 | // half width - num char * char width in pixels 494 | TFT.setCursor( TFTW2-(6*9), TFTH2 - 16); 495 | TFT.println("FLAPPY"); 496 | TFT.setTextSize(3); 497 | TFT.setCursor( TFTW2-(6*9), TFTH2 + 8); 498 | TFT.println("-BIRD-"); 499 | TFT.setTextSize(0); 500 | TFT.setCursor( TFTW2 - (12*3) - 1, TFTH2 - 30); 501 | TFT.println("BuratinoPhone"); 502 | TFT.setCursor( TFTW2 - (12*3) - 1, TFTH2 + 34); 503 | TFT.println("press button"); 504 | while (1) { 505 | // wait for push button 506 | uint8_t bdis = digitalRead(19); 507 | // if ( !(PIND & (1<100) { 621 | // Выводим «сырые» показания TouchScreen: 622 | // Serial.println((String) "X="+p.x+",\tY="+p.y); 623 | p.x = map(p.x, TS_MINX, TS_MAXX, 0, 320); 624 | p.y = map(p.y, TS_MINY, TS_MAXY, 0, 480); 625 | return true; 626 | //Serial.println((String) "X="+p.x+",\tY="+p.y); 627 | } else {p.x = p.y = -1; return false;} 628 | } 629 | void drawfloor(){ 630 | GAMEH = TFTH-FLOORH; 631 | // draw the floor once, we will not overwrite on this area in-game 632 | // black line 633 | TFT.drawFastHLine(0, GAMEH, TFTW, ST7735_BLACK); 634 | // grass and stripe 635 | TFT.fillRect(0, GAMEH+1, TFTW2, GRASSH, GRASSCOL); 636 | TFT.fillRect(TFTW2, GAMEH+1, TFTW2, GRASSH, GRASSCOL2); 637 | // black line 638 | TFT.drawFastHLine(0, GAMEH+GRASSH, TFTW, ST7735_BLACK); 639 | // mud 640 | TFT.fillRect(0, GAMEH+GRASSH+1, TFTW, FLOORH-GRASSH, FLOORCOL); 641 | } 642 | -------------------------------------------------------------------------------- /BuratinoBreakout/BuratinoBreakout.ino: -------------------------------------------------------------------------------- 1 | 2 | //#include 3 | #include 4 | #include "ILI9488.h" 5 | #include // Core graphics library 6 | Adafruit_GFX_Button buttons[4]; 7 | 8 | // Color definitions 9 | #define BLACK 0x0000 ///< 0, 0, 0 10 | #define NAVY 0x000F ///< 0, 0, 123 11 | #define DARKGREEN 0x03E0 ///< 0, 125, 0 12 | #define DARKCYAN 0x03EF ///< 0, 125, 123 13 | #define MAROON 0x7800 ///< 123, 0, 0 14 | #define PURPLE 0x780F ///< 123, 0, 123 15 | #define OLIVE 0x7BE0 ///< 123, 125, 0 16 | #define LIGHTGREY 0xC618 ///< 198, 195, 198 17 | #define DARKGREY 0x7BEF ///< 123, 125, 123 18 | #define GRAY2 0x7BEF ///< 123, 125, 123 19 | #define BLUE 0x001F ///< 0, 0, 255 20 | #define GREEN 0x07E0 ///< 0, 255, 0 21 | #define LIGHTGREEN 0xAFE5 22 | #define CYAN 0x07FF ///< 0, 255, 255 23 | #define RED 0xF800 ///< 255, 0, 0 24 | #define MAGENTA 0xF81F ///< 255, 0, 255 25 | #define YELLOW 0xFFE0 ///< 255, 255, 0 26 | #define WHITE 0xFFFF ///< 255, 255, 255 27 | #define ORANGE 0xFD20 ///< 255, 165, 0 28 | #define GREENYELLOW 0xAFE5 ///< 173, 255, 41 29 | #define PINK 0xFC18 ///< 255, 130, 198 30 | 31 | //////config 32 | #define ROWS 6 33 | #define COLS 14 34 | 35 | #define TILE_W (int)((MAX_X + 1) / COLS) 36 | #define TILE_H (int)(TILE_W / 2.2) 37 | 38 | #define BALL_R 2 39 | #define BALL_SPEED_H 1 40 | #define BALL_SPEED_V 1 41 | #define BALL_COLOR CYAN 42 | #define BALL_MOVE_WAIT 7 //4 43 | 44 | #define PADDLE_W 16 45 | #define PADDLE_H 5 46 | #define PADDLE_TOLERANCE 4 47 | #define PADDLE_COLOR LIGHTGREEN 48 | #define PADDLE_MOVE_WAIT 7 // 5 49 | 50 | #define BOARD_LEFT (int)(2) 51 | #define BOARD_RIGHT (int)(MAX_X - 2) 52 | #define BOARD_TOP 23 53 | 54 | #define TILES_LEFT (int)(((MAX_X + 1) - ( COLS * TILE_W ) )/ 2) 55 | #define TILES_TOP (BOARD_TOP + 2.8 * TILE_H) 56 | 57 | #define TILE_IS_DRAWN 1 58 | #define TILE_IS_NOT_DRAWN 0 59 | 60 | #define SCOREBOARD_COLOR LIGHTGREY //WHITE 61 | #define BACKGROUND_COLOR BLACK 62 | ///////// 63 | 64 | int beep; 65 | unsigned long last; 66 | 67 | // Scoreboard 68 | #define GAME_LEVEL 1 69 | #define GAME_LIVES 5 70 | #define GAME_SCORE 0 71 | 72 | int level = GAME_LEVEL; 73 | int lives = GAME_LIVES; 74 | unsigned long score = GAME_SCORE; 75 | 76 | const int COLORS[ROWS] = { RED, MAGENTA, OLIVE, YELLOW, GREEN, NAVY }; 77 | byte tiles[ROWS][COLS]; 78 | int tilesLeft; 79 | 80 | 81 | #define FONT_SPACE 6 82 | #define FONT_X 8 83 | #define MIN_X 0 84 | #define MIN_Y 0 85 | #define MAX_X 319 86 | #define MAX_Y 319 87 | 88 | #include "beeping.cpp" 89 | #include "sequencer.cpp" 90 | //#include "breakout.cpp" 91 | //#include "ball.cpp" 92 | //#include "paddle.cpp" 93 | #include "joystick.cpp" 94 | //#include "config.h" 95 | //#include "scoreboard.cpp" 96 | //#include "tiles.cpp" 97 | 98 | 99 | #define LCD_CS A3 // Chip Select goes to Analog 3 100 | #define LCD_RS A2 // Command/Data goes to Analog 2 101 | #define LCD_WR A1 // LCD Write goes to Analog 1 102 | #define LCD_RD A0 // LCD Read goes to Analog 0 103 | #define LCD_RST A4 // Can alternately just connect to Arduino's reset pin 104 | 105 | ILI9488 tft(LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RST); 106 | 107 | const uint8_t YP = A2; // Вывод Y+ должен быть подключен к аналоговому входу 108 | const uint8_t XM = A3; // Вывод X- должен быть подключен к аналоговому входу 109 | const uint8_t YM = 8; // Вывод Y- 110 | const uint8_t XP = 9; // Вывод X+ 111 | #define TS_MINX 65 112 | #define TS_MINY 120 113 | #define TS_MAXX 940 114 | #define TS_MAXY 920 115 | 116 | TouchScreen ts = TouchScreen(XP, YP, XM, YM); // Создаём объект для работы с TouchScreen 117 | 118 | uint8_t disp = 1; // display on 119 | uint8_t bb=5; 120 | 121 | void setup() { 122 | 123 | Serial.begin(9600); 124 | while (!Serial) { 125 | } 126 | Serial.println("BuratinoBreakout!"); 127 | 128 | tft.begin(); 129 | tft.setRotation(2); 130 | DISPpower(disp); 131 | 132 | Joystick::init(); 133 | 134 | Beeping::turnOn(); 135 | } 136 | 137 | void loop() { 138 | 139 | drawWallTiles(); 140 | 141 | char* bo ="BREAKOUT"; 142 | const int len = strlen (bo) * FONT_SPACE * 6; 143 | const int left = (MAX_X - len ) / 2; 144 | 145 | // tft.drawStringWithShadow(bo, left, 78, 6, WHITE, BLACK); 146 | tft.setCursor(left, 78); 147 | tft.setTextColor(BLUE); tft.setTextSize(6); 148 | tft.println(bo); 149 | 150 | boolean go = false; 151 | create_butt(); 152 | 153 | delay(700); 154 | Sequencer::start(); 155 | do 156 | { 157 | 158 | // tft.drawCenteredString("Press fire to play!", 136, 2, CYAN); 159 | tft.setCursor(50, 144); 160 | tft.setTextColor(YELLOW); tft.setTextSize(2); 161 | tft.println("Press fire to play!"); 162 | 163 | unsigned long last = millis(); 164 | do 165 | { 166 | pressbutt(); 167 | go = Joystick::fire() || bb ==1; 168 | 169 | if ( millis() - last > 8000 ) break; 170 | 171 | } while (!go); 172 | 173 | } while (!go); 174 | 175 | Sequencer::stop(); 176 | 177 | // Breakout game; 178 | gamerun(); 179 | } 180 | 181 | ISR(TIMER1_COMPA_vect) { 182 | 183 | // sequencer plays tetris theme 184 | Sequencer::play(); 185 | } 186 | 187 | void drawWallTiles() 188 | { 189 | for ( int c = 0; c < 320; c+=40) 190 | { 191 | 192 | tft.fillRect(c+0, 0, 40, 480, RED); 193 | 194 | for ( int i = 20; i < 480; i+= 20) 195 | { 196 | tft.drawFastHLine(c+0, i, 40, GRAY2); 197 | tft.drawFastHLine(c+0, i+1, 40, GRAY2); 198 | } 199 | 200 | for ( int i = 0; i < 480; i+= 40) 201 | { 202 | tft.drawFastVLine(c+20, i, 20, GRAY2 ); 203 | tft.drawFastVLine(c+21, i, 20, GRAY2 ); 204 | tft.drawFastVLine(c+39, i+20, 20, GRAY2 ); 205 | tft.drawFastVLine(c+38, i+20, 20, GRAY2 ); 206 | } 207 | } 208 | } 209 | 210 | 211 | void DISPpower(uint8_t disp) { 212 | pinMode(10, OUTPUT); 213 | if (disp == 1){ 214 | digitalWrite(10, LOW); 215 | } 216 | if (disp == 0){ 217 | digitalWrite(10, HIGH); 218 | } 219 | // ring(400, 50); 220 | // new_millis = millis(); 221 | } 222 | 223 | /////////////////////// breakout 224 | 225 | Joystick js; 226 | // Ball ball; 227 | // Paddle paddle; 228 | // Scoreboard score; 229 | // Tiles tiles; 230 | 231 | void gamerun() 232 | { 233 | // Scoreboard 234 | level = GAME_LEVEL; 235 | lives = GAME_LIVES; 236 | score = GAME_SCORE; 237 | 238 | // blank board 239 | tft.fillRect(0, 0, 320, MAX_Y, BACKGROUND_COLOR); 240 | tft.fillRect(0, 0, MAX_X, BOARD_TOP, SCOREBOARD_COLOR); 241 | tft.fillRect(0, 0, BOARD_LEFT - 0, MAX_Y - PADDLE_H - 2, SCOREBOARD_COLOR); 242 | tft.fillRect(BOARD_RIGHT, 0, TILE_W / 2, MAX_Y - PADDLE_H - 2, SCOREBOARD_COLOR); 243 | tft.fillRect(BOARD_LEFT, BOARD_TOP, BOARD_RIGHT - BOARD_LEFT , MAX_Y - BOARD_TOP - PADDLE_H, BACKGROUND_COLOR); 244 | // tft.fillRect(0, MAX_Y - PADDLE_H, MAX_X, MAX_Y, BACKGROUND_COLOR); 245 | tft.fillRect(0, MAX_Y, MAX_X, 2, SCOREBOARD_COLOR); 246 | 247 | scoreinit(); 248 | 249 | // initialize tile matrix 250 | newLevel(); 251 | paddlesetXY((MAX_X -PADDLE_W)/ 2, MAX_Y - PADDLE_H); 252 | paddledraw(); 253 | 254 | // create_butt(); 255 | 256 | do 257 | { 258 | 259 | serve(); 260 | play(); 261 | 262 | } while (scorehasLivesLeft()); 263 | 264 | const char *go ="GAME OVER"; 265 | const int font_size = 5; 266 | int cursor = (MAX_X - font_size * FONT_SPACE * 9) / 2; 267 | 268 | boolean skip = false; 269 | 270 | for ( int i= 0; i < 9; i++) 271 | { 272 | if ( go[i] != ' ') 273 | { 274 | // tft.fillRect(cursor, 94, FONT_SPACE * font_size - 2, FONT_X * font_size, RED); 275 | // tft.drawChar(go[i], cursor - FONT_SPACE / 2, 94 + FONT_SPACE / 2, font_size, WHITE); 276 | tft.setCursor(cursor - FONT_SPACE / 2, 124 + FONT_SPACE / 2); 277 | tft.setTextColor(WHITE); tft.setTextSize(font_size); 278 | tft.println(go[i]); 279 | } 280 | 281 | cursor += font_size * FONT_SPACE; 282 | 283 | skip = skip || Joystick::fire(); 284 | 285 | if ( skip ) continue; 286 | 287 | for (int j = (10-i) * 100; j > 200; j-=1500 / (i+1)) 288 | { 289 | Beeping::beep(j, 100); 290 | delay(100); 291 | } 292 | } 293 | 294 | while (bb !=1 && !Joystick::fire()){pressbutt();} 295 | } 296 | 297 | void serve() 298 | { 299 | ballsetXY(paddlegetX(), MAX_Y - PADDLE_H - BALL_R * 2 - 2); 300 | balldraw(); 301 | do 302 | { 303 | pressbutt(); 304 | // const int m = js.getX(); 305 | 306 | int m = 0; 307 | if (bb == 2) 308 | { 309 | m=-3; 310 | } 311 | if (bb == 3) 312 | { 313 | m=3; 314 | } 315 | 316 | if ( m != 0) 317 | { 318 | paddledraw(m); 319 | ballclear(); 320 | ballsetX(paddlegetX()); 321 | balldraw(); 322 | delay(5); 323 | } 324 | // } while (!Joystick::fire()); 325 | } while (bb !=1 && !Joystick::fire()); 326 | } 327 | 328 | 329 | void play() 330 | { 331 | for(;;) 332 | { 333 | pressbutt(); 334 | 335 | unsigned long waited = millis() - last; 336 | 337 | if ( waited > BALL_MOVE_WAIT ) 338 | { 339 | last = millis(); 340 | 341 | ballclear(); 342 | move(); 343 | balldraw(); 344 | 345 | // if (ball.collision(paddle)) 346 | if (collision()) // отскок от лопаты работает 347 | { 348 | beep = 200; 349 | Beeping::beep(400,30); 350 | } 351 | 352 | // check collision w/ tiles 353 | // int scored = ball.collision(tiles); 354 | int scored = ballcollision(); 355 | 356 | if ( scored > 0) 357 | { 358 | beep *=1.1; 359 | if ( beep > 3000) beep = 3000; 360 | Beeping::beep(beep,25); 361 | } 362 | 363 | if (scored > 0) 364 | { 365 | scoreupdate(scored); 366 | 367 | if ( tilesallGone() ) 368 | { 369 | ballclear(); 370 | newLevel(); 371 | scorenextLevel(); 372 | break; 373 | } 374 | } 375 | 376 | // if (ballescaped(paddle)) 377 | if (ballescaped()) // пропустил шар работает 378 | { 379 | scoredied(); 380 | 381 | for (int i = 54; i > 30; i--) 382 | { 383 | Beeping::beep(random(i,i*i), 3); 384 | delay(6); 385 | } 386 | 387 | ballclear(); 388 | 389 | break; 390 | } 391 | } 392 | 393 | // const int m = js.getX(); 394 | 395 | int m = 0; 396 | if (bb == 2) 397 | { 398 | m=-3; 399 | } 400 | if (bb == 3) 401 | { 402 | m=3; 403 | } 404 | 405 | if (waited > PADDLE_MOVE_WAIT && m != 0) 406 | // if (m != 0) 407 | { 408 | last = millis(); 409 | paddledraw(m); 410 | } 411 | } 412 | } 413 | 414 | void newLevel() 415 | { 416 | // ANALOG 7 SHOULD NOT BE CONNECTED TO ANYTHING. 417 | // PLEASE LEAVE PIN FLOATING 418 | 419 | randomSeed(analogRead(7)); 420 | 421 | tilesdrawAll(); 422 | 423 | ballsetXY(MAX_X / 2, MAX_Y - PADDLE_H - BALL_R * 2 - 2); 424 | ballsetXiYi(-BALL_SPEED_H, -BALL_SPEED_V); 425 | 426 | beep = 200; 427 | } 428 | 429 | /////////scoreboard 430 | 431 | void scoreinit() 432 | { 433 | // draw back wall and sidewalls 434 | 435 | tft.setCursor(0, 4); 436 | tft.setTextColor(BLACK); tft.setTextSize(2); 437 | tft.println(" 000000000 0"); 438 | 439 | tft.setCursor(6, 4); 440 | tft.setTextColor(BLUE); tft.setTextSize(2); 441 | tft.println(" S L B"); 442 | 443 | tft.setCursor(0, 4); 444 | tft.setTextColor(RED); tft.setTextSize(2); 445 | // tft.println(" 0 1 4"); 446 | tft.print(" ");tft.print(score);tft.print(" ");tft.print(level);tft.print(" ");tft.println(lives); 447 | } 448 | 449 | void scoreupdate( int scored ){ 450 | score+= scored; 451 | int digits = nDigits(score); 452 | // tft.drawNumber(score, (15-digits)*12, 4, 2, RED, SCOREBOARD_COLOR); 453 | tft.setCursor((15-digits)*12, 4); 454 | tft.setTextColor(RED, SCOREBOARD_COLOR); tft.setTextSize(2); 455 | tft.println(score); 456 | } 457 | 458 | void scorenextLevel() 459 | { 460 | level++; 461 | int digits = nDigits(level); 462 | // tft.drawNumber(level,(20-digits)*12, 4, 2, RED, SCOREBOARD_COLOR); 463 | tft.setCursor((20-digits)*12, 4); 464 | tft.setTextColor( RED, SCOREBOARD_COLOR); tft.setTextSize(2); 465 | tft.println(level); 466 | } 467 | 468 | void scoredied() 469 | { 470 | lives--; // вечная жизнь 471 | if ( lives < 0) return; 472 | int digits = nDigits(lives); 473 | // tft.drawNumber(lives,(24-digits)*12, 4, 2, RED, SCOREBOARD_COLOR); 474 | tft.setCursor((24-digits)*12, 4); 475 | tft.setTextColor( RED, SCOREBOARD_COLOR); tft.setTextSize(2); 476 | tft.println(lives); 477 | } 478 | 479 | boolean scorehasLivesLeft() 480 | { 481 | return lives > 0; 482 | } 483 | 484 | int nDigits(int value) 485 | { 486 | int digits = 1; 487 | long compare = 10; 488 | while (compare <= value) 489 | { 490 | compare *= 10; 491 | digits++; 492 | } 493 | return digits; 494 | } 495 | 496 | /////////////ball 497 | 498 | const int SCORE[7] = {0, 1, 1, 3, 5, 5, 7}; 499 | 500 | int left=BOARD_LEFT; 501 | int right=BOARD_RIGHT-3; 502 | int top=BOARD_TOP; 503 | int bottom=MAX_Y; 504 | 505 | float x, y, xi, yi; 506 | 507 | void ballclear() //очистить шар работает 508 | { 509 | tft.fillRect(x, y, BALL_R * 2, BALL_R * 2, BLACK); 510 | } 511 | 512 | void balldraw() //нарисовать шар работает 513 | { 514 | tft.fillRect(x, y, BALL_R * 2, BALL_R * 2, BALL_COLOR); 515 | } 516 | 517 | void ballsetXY(int x_, int y_) //установить шар в центр лопаты работает 518 | { 519 | x = x_; 520 | y = y_; 521 | } 522 | 523 | void ballsetX(int x_) //установть шар на лопате по X 524 | { 525 | x = x_; 526 | } 527 | 528 | void ballsetXiYi(int xi_, int yi_) //-1.00 -1.00 показывает когда шар в центре лопаты 529 | { 530 | xi = xi_; 531 | yi = yi_; 532 | } 533 | 534 | // bool escaped(Paddle &paddle) 535 | bool ballescaped() // шар не отбит работает 536 | { 537 | return y >= paddlegetY(); 538 | } 539 | 540 | void move() // генерирует движение мяча x,y координаты 541 | { 542 | if((xi < 0 && x + xi < left)||(xi > 0 && x +xi >= right)) 543 | { 544 | xi *= -1; 545 | } 546 | 547 | if(yi < 0 && y+yi-BALL_R*2 < top) 548 | { 549 | yi *= -1; 550 | } 551 | 552 | x+= xi; 553 | y+= yi; 554 | } 555 | 556 | int ballgetX() 557 | { 558 | return x; 559 | } 560 | 561 | int ballgetY() 562 | { 563 | return y; 564 | } 565 | 566 | int ballgetXi() 567 | { 568 | return xi; 569 | } 570 | 571 | // check for collision with paddle 572 | // calculate score and bounce 573 | 574 | // int collision(Tiles &tiles) 575 | 576 | int ballcollision() 577 | { 578 | // const int x = this->x+xi; 579 | // const int y = this->y+yi; 580 | const int bx = x+xi; 581 | const int by = y+yi; 582 | 583 | int hit; 584 | 585 | if ( hit = hitTile( bx, by )) 586 | { 587 | return SCORE[hit]; 588 | } 589 | 590 | if ( hit = hitTile( bx + BALL_R * 2, by + BALL_R * 2 )) 591 | { 592 | return SCORE[hit]; 593 | } 594 | 595 | if ( hit = hitTile( bx + BALL_R * 2, by )) 596 | { 597 | return SCORE[hit]; 598 | } 599 | 600 | hit = hitTile( bx, by + BALL_R * 2 ); 601 | 602 | return SCORE[hit]; 603 | } 604 | 605 | // check for collision with paddle 606 | // and bounce 607 | // bool collision(Paddle &paddle) 608 | bool collision() 609 | { 610 | // only interested if ball is moving down 611 | if ( yi < 0 ) return false; 612 | 613 | const int ny = y+yi+BALL_R*2; 614 | 615 | if ( ny < paddlegetY() ) return false; 616 | 617 | // ball center 618 | const int bc = x + BALL_R; 619 | 620 | const int diff = bc - paddlegetX(); 621 | 622 | if ( diff < -PADDLE_W-PADDLE_TOLERANCE || diff > PADDLE_W + PADDLE_TOLERANCE) 623 | { 624 | return false; 625 | } 626 | else if (diff > 0) 627 | { 628 | const int hit = diff / ((PADDLE_W + PADDLE_TOLERANCE)/2); 629 | xi = (float)hit * .5f + .5f; 630 | yi = - 2 + xi; 631 | } 632 | else if (diff < 0) 633 | { 634 | const int hit = diff / ((PADDLE_W + PADDLE_TOLERANCE)/2); 635 | xi = (float)hit * .5f - .5f; 636 | yi = - 2 - xi; 637 | } 638 | else 639 | { 640 | yi *= -1; 641 | } 642 | 643 | return true; 644 | } 645 | 646 | // int hitTile(Tiles &tiles, int x, int y) 647 | int hitTile( int x, int y) 648 | { 649 | int ty =(y - TILES_TOP)/ TILE_H; 650 | int tx =(x - TILES_LEFT)/ TILE_W; 651 | 652 | const boolean hit = ty >= 0 && ty < ROWS && tx >= 0 && tx < COLS && tilesexists(tx,ty); 653 | 654 | if (!hit) return 0; 655 | 656 | clearTile( tx, ty ); 657 | 658 | const int score = ROWS - ty; 659 | 660 | ty*= TILE_H; 661 | ty+= TILES_TOP; 662 | 663 | tft.fillRect(TILES_LEFT + tx * TILE_W, ty, TILE_W - 2, TILE_H - 2, BACKGROUND_COLOR); 664 | 665 | const int ty2= ty + TILE_H; 666 | 667 | if ( (yi > 0 && y > ty) || (yi < 0 && y > ty2)) 668 | { 669 | xi *=-1; 670 | } 671 | else 672 | { 673 | yi *=-1; 674 | } 675 | 676 | return score; 677 | } 678 | 679 | ////// tiles 680 | 681 | boolean tilesallGone() 682 | { 683 | return tilesLeft == 0; 684 | } 685 | 686 | void tilesdrawAll() 687 | { 688 | for(int i = 0; i < ROWS; i++) 689 | { 690 | for(int j = 0; j < COLS; j++) 691 | { 692 | tiles[i][j] = TILE_IS_NOT_DRAWN; 693 | } 694 | } 695 | 696 | int tilesLeftToDraw = ROWS * COLS; 697 | 698 | while ( tilesLeftToDraw > 0) 699 | { 700 | int c = random(COLS); 701 | int r = random(ROWS); 702 | if (tiles[r][c] == TILE_IS_DRAWN) 703 | { 704 | continue; 705 | } 706 | 707 | tft.fillRect(TILES_LEFT + c * TILE_W, TILES_TOP + r * TILE_H, TILE_W - 2, TILE_H - 2, COLORS[r]); 708 | tiles[r][c]= TILE_IS_DRAWN; 709 | tilesLeftToDraw--; 710 | 711 | Beeping::beep( 400 + r* 35 + c * 2, 5 ); 712 | delay(5); 713 | } 714 | 715 | tilesLeft = ROWS * COLS; 716 | } 717 | 718 | void clearTile( int x, int y ) 719 | { 720 | tiles[y][x] = TILE_IS_NOT_DRAWN; 721 | tilesLeft--; 722 | } 723 | 724 | boolean tilesexists(int x, int y) 725 | { 726 | return tiles[y][x] == TILE_IS_DRAWN; 727 | } 728 | 729 | ///////paddle 730 | 731 | int px, py; 732 | 733 | // draws paddle on screen when it moves 734 | // to avoid spending too much time clearing the screen and drawing 735 | // only the same amount of pixels that the paddle moves are cleared and drawn 736 | 737 | void paddledraw(int m) 738 | { 739 | if ( m < 0 && px > PADDLE_W ) 740 | { 741 | // cant move beyond the screen border 742 | if ( m < -(px - PADDLE_W)) m = -(px - PADDLE_W); 743 | 744 | // remove part of the old paddle on the left 745 | tft.fillRect( px + PADDLE_W + m, py, -m, PADDLE_H, BACKGROUND_COLOR); 746 | 747 | // add a bit more to the left of the existing paddle 748 | tft.fillRect( px - PADDLE_W + m, py, -m, PADDLE_H, PADDLE_COLOR); 749 | 750 | // remember m < 0 751 | px+=m; 752 | } 753 | else if ( m > 0 && x < MAX_X - PADDLE_W ) 754 | { 755 | // cant move beyond the screen border 756 | if ( m > MAX_X - px - PADDLE_W ) m = MAX_X - px - PADDLE_W; 757 | 758 | // remove a part of the old paddle on the right 759 | tft.fillRect( px - PADDLE_W, py, m, PADDLE_H, BACKGROUND_COLOR); 760 | 761 | // add a bit more of paddle to the left of the existing paddle 762 | tft.fillRect( px + PADDLE_W, py, m, PADDLE_H, PADDLE_COLOR ); 763 | 764 | px+=m; 765 | } 766 | } 767 | 768 | // draws paddle the first time 769 | // all paddle must be drawn 770 | 771 | void paddledraw() 772 | { 773 | tft.fillRect(px- PADDLE_W, py, PADDLE_W * 2, PADDLE_H, PADDLE_COLOR); 774 | } 775 | 776 | void paddlesetXY(int x_, int y_) 777 | { 778 | px = x_; 779 | py = y_; 780 | } 781 | 782 | int paddlegetX() 783 | { 784 | return px; 785 | } 786 | 787 | int paddlegetY() 788 | { 789 | return py; 790 | } 791 | void create_butt() { 792 | char buttonlabels[4][2]={"P", "F", "<", ">"}; 793 | uint16_t buttoncolors[4] = { DARKGREY, PURPLE, DARKGREEN,ORANGE}; 794 | for (uint8_t row=0; row<2; row++) { 795 | for (uint8_t col=0; col<2; col++) { 796 | buttons[col + row*2].initButton(&tft, 60+col*(80+120), 797 | 370+row*(50+20), // x, y, w, h, outline, fill, text 798 | 80, 50, WHITE, buttoncolors[col+row*2], WHITE, 799 | buttonlabels[col + row*2], 2); 800 | buttons[col + row*2].drawButton(); 801 | } 802 | } 803 | } 804 | 805 | 806 | void pressbutt() 807 | { 808 | bb=5; 809 | bool isPaused = true; 810 | while(isPaused) 811 | { 812 | TSPoint p = ts.getPoint(); 813 | pinMode(XM, OUTPUT); // Возвращаем режим работы вывода X- в значение «выход» для работы с дисплеем 814 | pinMode(YP, OUTPUT); // Возвращаем режим работы вывода Y+ в значение «выход» для работы с дисплеем 815 | if (p.z>100) { 816 | // Выводим «сырые» показания TouchScreen: 817 | // Serial.println((String) "X="+p.x+",\tY="+p.y); 818 | p.x = map(p.x, TS_MINX, TS_MAXX, 0, 320); 819 | p.y = map(p.y, TS_MINY, TS_MAXY, 0, 480); 820 | //Serial.println((String) "X="+p.x+",\tY="+p.y); 821 | } else {p.x = p.y = -1;} 822 | 823 | // go thru all the buttons, checking if they were pressed 824 | for (uint8_t b=0; b<4; b++) { 825 | if (buttons[b].contains(p.x, p.y)) { 826 | //Serial.print("Pressing: "); Serial.println(b); 827 | buttons[b].press(true); // tell the button it is pressed 828 | bb=b; 829 | } else { 830 | buttons[b].press(false); // tell the button it is NOT pressed 831 | } 832 | } 833 | if(bb !=0) isPaused = false; 834 | } 835 | } 836 | -------------------------------------------------------------------------------- /BuratinoPhone/BuratinoPhone.ino: -------------------------------------------------------------------------------- 1 | #include "Adafruit_GFX.h" 2 | #include "ILI9488.h" 3 | #include 4 | #include 5 | #include "Adafruit_FONA.h" 6 | 7 | #define ADAFRUIT_FONA_DEBUG 0 8 | 9 | SoftwareSerial fonaSS = SoftwareSerial(13, 12); 10 | Adafruit_FONA fona = Adafruit_FONA(4); 11 | 12 | // For the Adafruit TFT shield, these are the default. 13 | #define LCD_CS A3 // Chip Select goes to Analog 3 14 | #define LCD_RS A2 // Command/Data goes to Analog 2 15 | #define LCD_WR A1 // LCD Write goes to Analog 1 16 | #define LCD_RD A0 // LCD Read goes to Analog 0 17 | #define LCD_RST A4 // Can alternately just connect to Arduino's reset pin 18 | 19 | // Color definitions 20 | #define BLACK 0x0000 ///< 0, 0, 0 21 | //#define NAVY 0x000F ///< 0, 0, 123 22 | #define DARKGREEN 0x03E0 ///< 0, 125, 0 23 | //#define DARKCYAN 0x03EF ///< 0, 125, 123 24 | //#define MAROON 0x7800 ///< 123, 0, 0 25 | //#define PURPLE 0x780F ///< 123, 0, 123 26 | //#define OLIVE 0x7BE0 ///< 123, 125, 0 27 | //#define LIGHTGREY 0xC618 ///< 198, 195, 198 28 | #define DARKGREY 0x7BEF ///< 123, 125, 123 29 | #define BLUE 0x001F ///< 0, 0, 255 30 | //#define GREEN 0x07E0 ///< 0, 255, 0 31 | //#define CYAN 0x07FF ///< 0, 255, 255 32 | #define RED 0xF800 ///< 255, 0, 0 33 | //#define MAGENTA 0xF81F ///< 255, 0, 255 34 | #define YELLOW 0xFFE0 ///< 255, 255, 0 35 | #define WHITE 0xFFFF ///< 255, 255, 255 36 | #define ORANGE 0xFD20 ///< 255, 165, 0 37 | //#define GREENYELLOW 0xAFE5 ///< 173, 255, 41 38 | //#define PINK 0xFC18 ///< 255, 130, 198 39 | 40 | // Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC 41 | ILI9488 tft(LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RST); 42 | 43 | // The STMPE610 uses hardware SPI on the shield, and #8 44 | const uint8_t YP = A2; // Вывод Y+ должен быть подключен к аналоговому входу 45 | const uint8_t XM = A3; // Вывод X- должен быть подключен к аналоговому входу 46 | const uint8_t YM = 8; // Вывод Y- 47 | const uint8_t XP = 9; // Вывод X+ 48 | // This is calibration data for the raw touch data to the screen coordinates 49 | #define TS_MINX 65 50 | #define TS_MINY 120 51 | #define TS_MAXX 940 52 | #define TS_MAXY 920 53 | 54 | TouchScreen ts = TouchScreen(XP, YP, XM, YM); // Создаём объект для работы с TouchScreen 55 | 56 | // text box where numbers go 57 | #define TEXT_X 20 58 | #define TEXT_Y 30 59 | #define TEXT_W 300 60 | #define TEXT_H 50 61 | #define TEXT_TSIZE 4 62 | #define TEXT_TCOLOR WHITE 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 85 71 | //line date and time 72 | //#define TIME_X 80 73 | //#define TIME_Y 10 74 | 75 | /* create 15 buttons, in classic candybar phone style */ 76 | char buttonlabels[15][6]={"S", "M", "C", "1", "2abc", "3def", "4ghi", "5jkl", "6mno", "7pqrs", "8tuv", "9wxyz", "*", "0+ ", "#" }; 77 | 78 | Adafruit_GFX_Button buttons[15]; 79 | 80 | uint8_t CallStatus = 0; 81 | uint8_t oldCallStatus = 5; 82 | uint16_t callstatus_i = 1000; 83 | uint8_t bmax = 15; 84 | uint8_t bbook = 0; 85 | boolean incallnum = false; // входящий номер 86 | uint8_t oldbutt = 15; 87 | uint8_t ibut=0; 88 | uint8_t sbook=0; 89 | //char replybuf[1] = ""; 90 | char replybuf[60]= " ... BuratinoPhone ..."; 91 | uint8_t oldnsms = 20; 92 | uint8_t disp = 1; // display on 93 | uint8_t olddisp = 0; 94 | unsigned long new_millis = millis(); 95 | uint8_t bdis_max = 0; 96 | uint8_t dn = 1; 97 | char bt[2]= "."; 98 | 99 | void setup() { 100 | 101 | Serial.begin(9600); 102 | while (!Serial) { 103 | } 104 | Serial.println("Real_o_Phone!"); 105 | 106 | // clear the screen 107 | tft.begin(); 108 | tft.setRotation(2); 109 | tft.fillScreen( BLACK); 110 | status(replybuf); // приветствие 111 | // Check FONA is there 112 | // FONApowerOn(); 113 | DISPpower(disp); 114 | fonaSS.begin(19200); // if you're using software serial 115 | // проверяем есть ли связь с GPRS устройством 116 | // See if the FONA is responding 117 | if (! fona.begin(fonaSS)) { // can also try fona.begin(Serial1) 118 | status(F("Does not work")); 119 | while (1); 120 | } 121 | status(F("OK!")); 122 | 123 | // create 'text field' 124 | tft.drawRect(TEXT_X-10, TEXT_Y, TEXT_W, TEXT_H, WHITE); 125 | 126 | // Check we connect to the network 127 | while (fona.getNetworkStatus() != 1) { 128 | status(F("Looking for service...")); 129 | delay(100); 130 | } 131 | status(F("Connected to network!")); 132 | 133 | // set to external mic & headphone 134 | fona.setAudio(FONA_EXTAUDIO); 135 | fona.setVolume(100); // 0-100, defaul 40 136 | fona.callerIdNotification(1); // включить АОН 137 | // fonaSS.println(F("AT+CLIP=1")); 138 | // задать AT командами из GPRSAT Commands сохраняемые режимы 139 | // AT+CMGF=1 //текстовый режим 140 | // AT+CSCS="GSM" // режим GSM 141 | // AT+CLTS=1 // Get Local Timestamp 142 | // AT&W // сохранение текущего профиля и нужно перезагрузить модем 143 | // привязка BT-гарнитуры 144 | // AT+BTPOWER=1 // включит BT 145 | // AT+BTPAIRCFG=0 // сопряжение: 0 с подтверждением, 2 автоматическое 146 | // AT+BTUNPAIR=0 // удалить все сопряженные 147 | // AT+BTSCAN=1 // сканирование доступных устройств 148 | // AT+BTPAIR=0,1 // установить сопряжение с первым устройством из списка найденных 149 | // AT+BTSTATUS? // проверка есть ли в списке сопряженных 150 | // AT+BTACPT=1 // подтверждение запроса на подключение; 151 | fonaSS.println(F("AT+CNMI=2,1,0,0,0")); //запись входящих SMS на СИМ-карту 152 | fonaSS.println(F("AT+CUSD=1")); // режим USSD - выполнить запрос, вернуть ответ 153 | fonaSS.println(F("AT+BTPOWER=1")); // включить BT 154 | delay(1500); 155 | pinMode(19, INPUT); // A5 определяем как цифровой вход 156 | pinMode(20, INPUT); // A6 определяем как цифровой вход 157 | } 158 | 159 | void loop(void) { 160 | uint8_t ri = analogRead(20); 161 | if (ri==0){ 162 | if (CallStatus != 3) { 163 | delay(500); 164 | eventsms(); 165 | CallStatus = fona.getCallStatus(); 166 | // oldCallStatus = 5; 167 | } 168 | } 169 | uint8_t bdis = digitalRead(19); 170 | if (bdis ==0 && olddisp == 0) { 171 | olddisp = 1; 172 | if (disp == 0) { 173 | disp = 1; 174 | } else { 175 | disp = 0; 176 | } 177 | DISPpower(disp); 178 | } 179 | if (bdis !=0 && olddisp == 1) { 180 | olddisp = 0; 181 | } 182 | if ((millis() - new_millis > 30000) && disp == 1) { 183 | disp = 0; 184 | DISPpower(disp); 185 | } 186 | if (callstatus_i == 0) { 187 | event(); 188 | CallStatus = fona.getCallStatus(); 189 | if (disp==1 or incallnum == false){ 190 | getGetBatt(); 191 | Time(); 192 | } 193 | if (CallStatus == 0) { 194 | if (bbook==0) { 195 | status(F("Ready")); 196 | } 197 | if (bbook==1 && sbook==0){ 198 | status(F("Ready/Book")); 199 | } 200 | if (bbook==2 && sbook==0){ 201 | status(F("Ready/SMS Send")); 202 | } 203 | if (bbook==3 && sbook==0){ 204 | status(F("Ready/SMS Read")); 205 | } 206 | if (bbook==1 && sbook==1 && textfield_i !=0){ 207 | status(F("Ready/Book/Save")); 208 | } 209 | if (bbook==2 && sbook==1 && textfield_i !=0){ 210 | status(F("Ready/SMS Send/Send")); 211 | } 212 | if (bbook==1 && sbook==1 && textfield_i ==0){ 213 | status(F("Ready/Book/Del")); 214 | } 215 | if (bbook==3 && sbook==1 && textfield_i ==0){ 216 | status(F("Ready/SMS Read/Del")); 217 | } 218 | if (oldCallStatus != CallStatus){ 219 | bmax = 15; 220 | create_butt(5); 221 | oldCallStatus = CallStatus; 222 | } 223 | 224 | } 225 | if (CallStatus == 2) {status(F("Unkown"));} 226 | // Serial.println(incallnum); 227 | // Serial.println(CallStatus); 228 | if (CallStatus == 3) { 229 | status(F("Ring")); 230 | if (!incallnum){ 231 | fona.incomingCallNumber(textfield) ; 232 | char cring[] = "Ringing: "; 233 | status(strcat(cring, textfield)); 234 | textfield_i = 12; 235 | clear_textfild(); 236 | update_textfild(); 237 | incallnum = true; 238 | } 239 | if (oldCallStatus != CallStatus){ 240 | bmax = 3; 241 | create_butt(1); 242 | oldCallStatus = CallStatus; 243 | } 244 | disp = 1; 245 | DISPpower(disp); 246 | ring(400,50); ring(600,100); 247 | } else { incallnum = false;} 248 | if (CallStatus == 4) { 249 | status(F("Talk")); 250 | if (oldCallStatus != CallStatus){ 251 | bmax = 3; 252 | create_butt(1); 253 | oldCallStatus = CallStatus; 254 | } 255 | } 256 | 257 | callstatus_i = 2000; 258 | } 259 | callstatus_i = callstatus_i-1; 260 | 261 | TSPoint p = ts.getPoint(); 262 | pinMode(XM, OUTPUT); // Возвращаем режим работы вывода X- в значение «выход» для работы с дисплеем 263 | pinMode(YP, OUTPUT); // Возвращаем режим работы вывода Y+ в значение «выход» для работы с дисплеем 264 | 265 | // Scale from ~0->4000 to tft.width using the calibration #'s 266 | if (p.z>100 && disp == 1) { 267 | new_millis = millis(); 268 | // Выводим «сырые» показания TouchScreen: 269 | // Serial.println((String) "X="+p.x+",\tY="+p.y); 270 | // p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width()); 271 | // p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height()); 272 | // uint16_t x = p.x; 273 | // uint16_t y = p.y; 274 | p.x = map(p.x, TS_MINX, TS_MAXX, 0, 320); 275 | p.y = map(p.y, TS_MINY, TS_MAXY, 0, 480); 276 | } else {p.x = p.y = -1;} 277 | 278 | // go thru all the buttons, checking if they were pressed 279 | for (uint8_t b=0; b= 3 && b <= 15) { 301 | if (bbook == 0 && textfield_i < TEXT_LEN) { 302 | ring(b*100, 50); 303 | if (oldbutt!=b){ 304 | oldbutt = b; 305 | textfield[textfield_i] = buttonlabels[b][0]; 306 | textfield_i++; 307 | textfield[textfield_i] = 0; // zero terminate 308 | ibut=1; 309 | } 310 | else { 311 | if (ibut <= (strlen(buttonlabels[b])-1)) { 312 | textfield_i--; 313 | textfield[textfield_i] = buttonlabels[b][ibut]; 314 | textfield_i++; 315 | textfield[textfield_i] = 0; // zero terminate 316 | ibut++; 317 | if (ibut >(strlen(buttonlabels[b])-1)) {ibut=0;} 318 | } 319 | } 320 | } 321 | char ph_number[13]=""; 322 | char ph_name[13]=""; 323 | if (bbook == 1 or bbook == 2){ 324 | fona.getSIMSender(b-2, ph_number, 12); 325 | fona.getSIMSendernName(b-2, ph_name, 12); 326 | } 327 | if (bbook == 1 && sbook == 0 && ph_number[0] != '\0'){ // выбор из книги 328 | ring(b*100, 50); 329 | char csel[21] = ""; 330 | sprintf(csel,"Book %d: ", b-2); 331 | status(strcat(csel, ph_name)); 332 | strcpy(textfield, ph_number); 333 | textfield_i = strlen(textfield); 334 | textfield[textfield_i] = 0; 335 | clear_textfild(); 336 | update_textfild(); 337 | oldCallStatus = 5; 338 | bbook = 0; 339 | oldbutt = 15; 340 | } 341 | char sms_name[13]=""; 342 | char sms_number[13]=""; 343 | if (bbook == 3) { 344 | fona.getSMSSender(b-2, sms_number, 13); 345 | fona.readSMS(b-2, sms_name, 44, 44); 346 | } 347 | if (bbook == 3 && sbook == 0 && sms_name[0] != '\0'){ // выбор из списка смс 348 | ring(b*100, 50); 349 | char cselsms[51] = ""; 350 | sprintf(cselsms,"SMS %d:",b-2); 351 | strcat(cselsms, sms_name); 352 | status(cselsms); 353 | strncpy(textfield, sms_number, 12); 354 | textfield_i = strlen(textfield); 355 | textfield[textfield_i] = 0; 356 | clear_textfild(); 357 | update_textfild(); 358 | // oldCallStatus = 5; 359 | // bbook = 0; 360 | // oldbutt = 15; 361 | } 362 | if (bbook == 3 && sbook == 1 && textfield_i == 0){ // удаление SMS 363 | ring(b*100, 50); 364 | char smsdel[13] = ""; 365 | sprintf(smsdel,"Delete SMS %d",b-2); 366 | status(smsdel); 367 | fona.deleteSMS(b-2); 368 | bbook = 0; 369 | sbook = 0; 370 | oldCallStatus = 5; 371 | } 372 | if (bbook == 1 && sbook == 1 && textfield_i == 0){ // удаление из книги 373 | ring(b*100, 50); 374 | char cd[2] = ""; 375 | itoa(b-2, cd, 10); 376 | char msgdel[15] = "Delete Phone "; 377 | // char msgdel[15] = ""; 378 | // sprintf(msgdel,"Delete Phone %d", b-2); 379 | // status(msgdel); 380 | status(strcat(msgdel, cd)); 381 | fonaSS.print(F("AT+CPBW=")); 382 | fonaSS.println(b-2); 383 | bbook = 0; 384 | sbook = 0; 385 | oldCallStatus = 5; 386 | } 387 | if (bbook == 1 && sbook == 1 && textfield_i != 0){ //запись в книгу имени и номера 388 | // AT+CPBW=4,"+71234567890",145,"Test" 389 | fonaSS.print(F("AT+CPBW=")); 390 | fonaSS.print(b-2); 391 | fonaSS.print(F(",\"")); 392 | if (textfield[0] == '+' or textfield[0] == '#') { 393 | fonaSS.print(textfield); 394 | } else { 395 | fonaSS.print(ph_number); 396 | } 397 | fonaSS.print(F("\",145,\"")); 398 | if (ph_name[0] == '\0') fonaSS.print(b-2); 399 | if (ph_name[0] != '\0') fonaSS.print(textfield); 400 | fonaSS.println(F("\"")); 401 | ring(b*100, 50); 402 | char sbb[2] = ""; 403 | itoa(b-2, sbb, 10); 404 | char msgsave[12] = "Save Book "; 405 | strcat(msgsave, sbb); 406 | status(msgsave); 407 | bbook = 0; 408 | sbook = 0; 409 | oldCallStatus = 5; 410 | } 411 | if (bbook == 2 && sbook == 0 && textfield_i != 0 && ph_number[0] != '\0'){ //отправить SMS 412 | fona.sendSMS(ph_number, textfield); 413 | delay(2000); 414 | ring(b*100, 50); 415 | char smssave[23] = "Send SMS: "; 416 | strcat(smssave, ph_number); 417 | status(smssave); 418 | bbook = 0; 419 | sbook = 0; 420 | oldCallStatus = 5; 421 | } 422 | } 423 | 424 | // clr button! delete char 425 | if (b == 1) { 426 | if (CallStatus == 0){ 427 | ring(b*100, 50); 428 | bmax = 11; 429 | if (bbook <= 2){ 430 | bbook++; 431 | } else { 432 | bbook=1; 433 | } 434 | if ( bbook == 1) { 435 | status(F("Ready/Book")); 436 | } 437 | if ( bbook == 2) { 438 | status(F("Ready/SMS Send")); 439 | if (textfield_i == 0){ 440 | bbook = 3; 441 | } 442 | } 443 | if ( bbook == 3) { 444 | status(F("Ready/SMS Read")); 445 | } 446 | create_book(); 447 | sbook = 0; 448 | } 449 | } 450 | // its always OK to just hang up 451 | if (b == 2) { 452 | ring(b*100, 50); 453 | oldbutt = 15; 454 | sbook = 0; 455 | if (CallStatus == 0 && textfield_i != 0 && bbook == 0){ 456 | textfield[textfield_i] = 0; 457 | if (textfield_i > 0) { 458 | textfield_i--; 459 | textfield[textfield_i] = ' '; 460 | } 461 | } 462 | else { 463 | status(F("End")); 464 | fona.hangUp(); 465 | oldCallStatus = 5; 466 | bbook = 0; 467 | } 468 | } 469 | // update the current text field 470 | update_textfild(); 471 | // we dont really check that the text field makes sense 472 | // just try to call 473 | if (b == 0) { 474 | // bbook = 0; 475 | oldbutt = 15; 476 | if (CallStatus == 0 && (bbook == 1 or bbook == 3 )){ 477 | ring(50, 50); 478 | status(F("Save")); 479 | sbook=1; 480 | } 481 | if (CallStatus == 0 && (textfield[0] == '+' or textfield[0] == '#' or textfield[0] == '*') && bbook == 0){ 482 | ring(50, 50); 483 | status(F("Call")); 484 | char call[20] = "Call: "; 485 | status(strcat(call, textfield)); 486 | bmax = 3; 487 | create_butt(1); 488 | fona.callPhone(textfield); 489 | oldCallStatus = 5; 490 | } 491 | if (CallStatus == 3){ 492 | ring(50, 50); 493 | status(F("Answ")); 494 | fona.pickUp(); 495 | } 496 | } 497 | // Serial.print(CallStatus); 498 | delay(100); 499 | } 500 | 501 | } 502 | 503 | } 504 | 505 | void Time() { 506 | //+CCLK: "18/12/09,14:38:38+20" 507 | char buff[20] = ""; 508 | while(!fona.getTime(buff, 19)); 509 | char timeB[9]=""; 510 | char dateB[9]=""; 511 | if (buff[0] != '\0'){ 512 | uint8_t inbr = 1; 513 | for (uint8_t i=0; i<=7; i++) { 514 | dateB[i] = buff[inbr]; 515 | inbr++ ; 516 | } 517 | dateB[9]= '\0'; 518 | inbr=10; 519 | for (uint8_t i=0; i<=7; i++) { 520 | timeB[i] = buff[inbr]; 521 | inbr++ ; 522 | } 523 | timeB[9]= '\0'; 524 | } 525 | tft.fillRect(105, 10, 320, 16, BLACK); 526 | tft.setCursor(105, 10); 527 | tft.setTextColor(DARKGREY); 528 | tft.setTextSize(2); 529 | tft.print(dateB); tft.print(" "); tft.print(timeB); 530 | } 531 | 532 | void getGetBatt() { 533 | //+CBC: 0,99,4205 534 | char batt[12] = ""; 535 | while(!fona.getBatt(batt, 11)); 536 | char batt_pr[4]=""; 537 | uint8_t li = 0; 538 | while ( batt[li] != ',') { 539 | li++ ; 540 | } 541 | li=li+1; 542 | uint8_t i = 0; 543 | while ( batt[li] != ',') { 544 | batt_pr[i] = batt[li]; 545 | li++ ; 546 | i++; 547 | } 548 | batt_pr[i] = '\0'; 549 | uint8_t rssi = fona.getRSSI(); 550 | tft.fillRect(10, 10, 95, 16, BLACK); 551 | tft.setCursor(10, 10); 552 | tft.setTextColor(DARKGREY); 553 | tft.setTextSize(2); 554 | tft.print(batt_pr); tft.print("% "); tft.print(rssi); tft.print(bt); 555 | } 556 | 557 | void update_textfild(void){ 558 | // update the current text field 559 | tft.setCursor(TEXT_X-2, TEXT_Y+10); 560 | tft.setTextColor(TEXT_TCOLOR, BLACK); 561 | tft.setTextSize(TEXT_TSIZE); 562 | tft.print(textfield); 563 | } 564 | 565 | void clear_textfild(void){ 566 | tft.fillRect(TEXT_X-9, TEXT_Y+1, TEXT_W-2, TEXT_H-2, BLACK); 567 | } 568 | 569 | void ring(uint16_t tones, uint16_t durat) { 570 | tone( 11, tones, durat * 2 ); 571 | delay( durat * 2 ); 572 | noTone( 11 ); 573 | } 574 | 575 | void DISPpower(uint8_t disp) { 576 | pinMode(10, OUTPUT); 577 | if (disp == 1){ 578 | digitalWrite(10, LOW); 579 | } 580 | if (disp == 0){ 581 | digitalWrite(10, HIGH); 582 | } 583 | ring(400, 50); 584 | new_millis = millis(); 585 | } 586 | 587 | void FONApowerOn() { 588 | delay(1000); 589 | pinMode(11, OUTPUT); 590 | // if (!digitalRead(10)) { 591 | digitalWrite(11, HIGH); 592 | delay(1000); 593 | // } 594 | digitalWrite(11, LOW); 595 | delay(1000); 596 | } 597 | 598 | void create_butt(uint8_t row_button) { 599 | 600 | uint16_t buttoncolors[15] = { DARKGREEN, DARKGREY, RED, 601 | BLUE, BLUE, BLUE, 602 | BLUE, BLUE, BLUE, 603 | BLUE, BLUE, BLUE, 604 | ORANGE, BLUE, ORANGE}; 605 | tft.fillRect(0, 150, 320, 480, BLACK); 606 | for (uint8_t row=0; row= n) { 645 | for (uint8_t i=n; i<=k; i++) { 646 | varreply[inbr] = replybuf[i]; 647 | inbr++ ; 648 | } 649 | } 650 | varreply[inbr]= '\0'; 651 | } 652 | 653 | void eventsms() { 654 | readline(500); 655 | //RING+CLIP: "",145,"",0,"",0 656 | // if (strncmp(replybuf, "RING+CLIP: ", 11) == 0 && incallnum == 0){ 657 | // uint8_t li = 0; 658 | // while ( replybuf[li] != '\"') { 659 | // li++ ; 660 | // } 661 | // li=li+1; 662 | // uint8_t ln=li; 663 | // while ( replybuf[li] != '\"') { 664 | // li++ ; 665 | // } 666 | // uint8_t lk=li-1; 667 | // char nsms[13]=""; 668 | // reply(nsms, ln, lk); 669 | // char newsms[] = "Ringing: "; 670 | // strcat(newsms, nsms); 671 | // status(newsms); 672 | // strncpy(textfield, nsms, 12); 673 | // textfield_i = strlen(textfield); 674 | // textfield[textfield_i] = 0; 675 | // update_textfild(); 676 | // incallnum = 1; 677 | // } 678 | //+CMTI: "SM",4 679 | if (strncmp(replybuf, "+CMTI: \"SM\",", 11) == 0){ 680 | uint8_t len = strlen(replybuf); 681 | uint8_t li = len; 682 | while ( replybuf[li] != ',') { 683 | li-- ; 684 | } 685 | char nsms[2]=""; 686 | reply(nsms, li+1, li+1); 687 | disp = 1; 688 | DISPpower(disp); 689 | uint8_t tsms = strtoul(nsms, NULL, 10); 690 | clear_textfild(); 691 | char sms_name[15]=""; 692 | char sms_number[13]=""; 693 | delay(300); 694 | while(!fona.readSMS(tsms, sms_name, 15, 15)); 695 | while(!fona.getSMSSender(tsms, sms_number, 13)); 696 | char newsms[] = ""; 697 | sprintf(newsms,"New SMS %d:", tsms); 698 | strcat(newsms, sms_name); 699 | status(newsms); 700 | ring(400, 50); 701 | strncpy(textfield, sms_number, 12); 702 | textfield_i = strlen(textfield); 703 | textfield[textfield_i] = 0; 704 | update_textfild(); 705 | uint8_t db = tsms+1; 706 | if (tsms == 5) db = 1; 707 | while(!fona.deleteSMS(db)); 708 | } 709 | } 710 | 711 | void event() { 712 | char ussd[13] = ""; 713 | readline(100); 714 | //+CUSD: 0,"Balance:439r",64 715 | if (strncmp(replybuf, "+CUSD: ", 7) == 0){ 716 | // uint8_t len = strlen(replybuf); 717 | uint8_t li = 0; 718 | while ( replybuf[li] != '\"') { 719 | li++ ; 720 | } 721 | li=li+1; 722 | uint8_t ln=li; 723 | while ( replybuf[li] != '\"') { 724 | li++ ; 725 | } 726 | uint8_t lk=li-1; 727 | reply(ussd, ln, lk); 728 | char newussd[] = "USSD: "; 729 | strcat(newussd, ussd); 730 | newussd[25] = '\0'; 731 | status(newussd); 732 | ring(400, 50); 733 | disp = 1; 734 | DISPpower(disp); 735 | } 736 | //+BTCONNECTING: 1c:52:16:b3:f5:a8,"HFG" 737 | if (strncmp(replybuf, "+BTCONNECTING: ", 15) == 0){ 738 | fonaSS.println(F("AT+BTACPT=1")); 739 | readline(200); 740 | //OK+BTCONNECT: 1,"Mi Bluetooth Hea",1c:52:16:b3:f5:a8,"HFG" 741 | if (strncmp(replybuf, "OK+BTCONNECT: ", 14) == 0){ 742 | uint8_t li = 0; 743 | while ( replybuf[li] != '\"') { 744 | li++ ; 745 | } 746 | li=li+1; 747 | uint8_t ln=li; 748 | while ( replybuf[li] != '\"') { 749 | li++ ; 750 | } 751 | uint8_t lk=li-1; 752 | reply(ussd, ln, lk); 753 | char newussd[] = "BT CONNECT: "; 754 | strcat(newussd, ussd); 755 | newussd[25] = '\0'; 756 | status(newussd); 757 | } 758 | ring(400, 50); 759 | disp = 1; 760 | DISPpower(disp); 761 | bt[0]= '*'; 762 | bt[1]= '\0'; 763 | } 764 | //+BTDISCONN: "Mi Bluetooth Hea",1c:52:16:b3:f5:a8,"HFG" 765 | if (strncmp(replybuf, "+BTDISCONN: ", 12) == 0){ 766 | uint8_t li = 0; 767 | while ( replybuf[li] != '\"') { 768 | li++ ; 769 | } 770 | li=li+1; 771 | uint8_t ln=li; 772 | while ( replybuf[li] != '\"') { 773 | li++ ; 774 | } 775 | uint8_t lk=li-1; 776 | reply(ussd, ln, lk); 777 | char newussd[] = "BT DISCONNECT: "; 778 | strcat(newussd, ussd); 779 | newussd[25] = '\0'; 780 | status(newussd); 781 | ring(400, 50); 782 | disp = 1; 783 | DISPpower(disp); 784 | bt[0]= '.'; 785 | bt[1]= '\0'; 786 | } 787 | } 788 | 789 | void readline(uint16_t timeout) { 790 | uint16_t replyidx = 0; 791 | while (timeout--) { 792 | if (replyidx >= 255) { //обязательно буфер модема читаем до конца 256 символов 793 | break; 794 | } 795 | while(fonaSS.available()) { 796 | char c = fonaSS.read(); 797 | if (c == '\n') continue; 798 | if (c == '\r') continue; 799 | // if (c == 0xA) { 800 | // if (replyidx == 0) // the first 0x0A is ignored 801 | // continue; 802 | // } 803 | replybuf[replyidx] = c; 804 | replyidx++; 805 | } 806 | if (timeout == 0) { 807 | break; 808 | } 809 | delay(1); 810 | } 811 | replybuf[replyidx] = 0; 812 | //Serial.println(timeout); //Serial.println(replyidx); // 813 | // Serial.println(replybuf); 814 | } 815 | 816 | // Print something in the mini status bar with either flashstring 817 | void status(const __FlashStringHelper *msg) { 818 | tft.fillRect(10, 125, 320, 16, BLACK); 819 | tft.setCursor(10, 125); 820 | tft.setTextColor( WHITE); 821 | tft.setTextSize(2); 822 | tft.print(msg); 823 | } 824 | // or charstring 825 | void status(char *msg) { 826 | // char msg1[26] = ""; 827 | // char msg2[26] = ""; 828 | tft.fillRect(0, 85, 320, 38, BLACK); 829 | // uint8_t len = strlen(msg); 830 | // uint8_t li = 0; 831 | // while ( li < 25 && li < len ) { 832 | // msg1[li] = msg[li]; 833 | // li++ ; 834 | // } 835 | // msg1[li] = '\0'; 836 | // uint8_t li2 = 0; 837 | // while ( li2 < 25 && li < len ) { 838 | // msg2[li2] = msg[li]; 839 | // li++ ; 840 | // li2++ ; 841 | // } 842 | // msg2[li2] = '\0'; 843 | tft.setCursor(10, 85); 844 | tft.setTextColor(DARKGREY); 845 | tft.setTextSize(2); 846 | tft.print(msg); 847 | // tft.setCursor(10, 105); 848 | // tft.setTextColor(DARKGREY); 849 | // tft.setTextSize(2); 850 | // tft.print(msg2); 851 | } 852 | -------------------------------------------------------------------------------- /BuratinoPhone/Adafruit_FONA.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for our Adafruit FONA Cellular Module 3 | 4 | Designed specifically to work with the Adafruit FONA 5 | ----> http://www.adafruit.com/products/1946 6 | ----> http://www.adafruit.com/products/1963 7 | 8 | These displays use TTL Serial to communicate, 2 pins are required to 9 | interface 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit and open-source hardware by purchasing 12 | products from Adafruit! 13 | 14 | Written by Limor Fried/Ladyada for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | ****************************************************/ 17 | // next line per http://postwarrior.com/arduino-ethershield-error-prog_char-does-not-name-a-type/ 18 | 19 | #include "Adafruit_FONA.h" 20 | 21 | #if defined(ESP8266) 22 | // ESP8266 doesn't have the min and max functions natively available like 23 | // AVR libc seems to provide. Include the STL algorithm library to get these. 24 | // Unfortunately algorithm isn't available in AVR libc so this is ESP8266 25 | // specific (and likely needed for ARM or other platforms, but they lack 26 | // software serial and are currently incompatible with the FONA library). 27 | #include 28 | using namespace std; 29 | #endif 30 | 31 | 32 | Adafruit_FONA::Adafruit_FONA(int8_t rst) 33 | { 34 | _rstpin = rst; 35 | 36 | apn = F("FONAnet"); 37 | apnusername = 0; 38 | apnpassword = 0; 39 | mySerial = 0; 40 | httpsredirect = false; 41 | useragent = F("FONA"); 42 | ok_reply = F("OK"); 43 | } 44 | 45 | uint8_t Adafruit_FONA::type(void) { 46 | return _type; 47 | } 48 | 49 | boolean Adafruit_FONA::begin(Stream &port) { 50 | mySerial = &port; 51 | 52 | pinMode(_rstpin, OUTPUT); 53 | digitalWrite(_rstpin, HIGH); 54 | delay(10); 55 | digitalWrite(_rstpin, LOW); 56 | delay(100); 57 | digitalWrite(_rstpin, HIGH); 58 | 59 | DEBUG_PRINTLN(F("Attempting to open comm with ATs")); 60 | // give 7 seconds to reboot 61 | int16_t timeout = 7000; 62 | 63 | while (timeout > 0) { 64 | while (mySerial->available()) mySerial->read(); 65 | if (sendCheckReply(F("AT"), ok_reply)) 66 | break; 67 | while (mySerial->available()) mySerial->read(); 68 | if (sendCheckReply(F("AT"), F("AT"))) 69 | break; 70 | delay(500); 71 | timeout-=500; 72 | } 73 | 74 | if (timeout <= 0) { 75 | #ifdef ADAFRUIT_FONA_DEBUG 76 | DEBUG_PRINTLN(F("Timeout: No response to AT... last ditch attempt.")); 77 | #endif 78 | sendCheckReply(F("AT"), ok_reply); 79 | delay(100); 80 | sendCheckReply(F("AT"), ok_reply); 81 | delay(100); 82 | sendCheckReply(F("AT"), ok_reply); 83 | delay(100); 84 | } 85 | 86 | // turn off Echo! 87 | sendCheckReply(F("ATE0"), ok_reply); 88 | delay(100); 89 | 90 | if (! sendCheckReply(F("ATE0"), ok_reply)) { 91 | return false; 92 | } 93 | 94 | // turn on hangupitude 95 | sendCheckReply(F("AT+CVHU=0"), ok_reply); 96 | 97 | delay(100); 98 | flushInput(); 99 | 100 | 101 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN("ATI"); 102 | 103 | mySerial->println("ATI"); 104 | readline(500, true); 105 | 106 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 107 | 108 | 109 | 110 | if (prog_char_strstr(replybuffer, (prog_char *)F("SIM808 R14")) != 0) { 111 | _type = FONA808_V2; 112 | } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIM808 R13")) != 0) { 113 | _type = FONA808_V1; 114 | } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIM800 R13")) != 0) { 115 | _type = FONA800L; 116 | } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIMCOM_SIM5320A")) != 0) { 117 | _type = FONA3G_A; 118 | } else if (prog_char_strstr(replybuffer, (prog_char *)F("SIMCOM_SIM5320E")) != 0) { 119 | _type = FONA3G_E; 120 | } 121 | 122 | if (_type == FONA800L) { 123 | // determine if L or H 124 | 125 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN("AT+GMM"); 126 | 127 | mySerial->println("AT+GMM"); 128 | readline(500, true); 129 | 130 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 131 | 132 | 133 | if (prog_char_strstr(replybuffer, (prog_char *)F("SIM800H")) != 0) { 134 | _type = FONA800H; 135 | } 136 | } 137 | 138 | #if defined(FONA_PREF_SMS_STORAGE) 139 | sendCheckReply(F("AT+CPMS=" FONA_PREF_SMS_STORAGE "," FONA_PREF_SMS_STORAGE "," FONA_PREF_SMS_STORAGE), ok_reply); 140 | #endif 141 | 142 | return true; 143 | } 144 | 145 | 146 | /********* Serial port ********************************************/ 147 | boolean Adafruit_FONA::setBaudrate(uint16_t baud) { 148 | return sendCheckReply(F("AT+IPREX="), baud, ok_reply); 149 | } 150 | 151 | /********* Real Time Clock ********************************************/ 152 | 153 | boolean Adafruit_FONA::readRTC(uint8_t *year, uint8_t *month, uint8_t *date, uint8_t *hr, uint8_t *min, uint8_t *sec) { 154 | uint16_t v; 155 | sendParseReply(F("AT+CCLK?"), F("+CCLK: "), &v, '/', 0); 156 | *year = v; 157 | 158 | DEBUG_PRINTLN(*year); 159 | } 160 | 161 | 162 | boolean Adafruit_FONA::enableRTC(uint8_t i) { 163 | if (! sendCheckReply(F("AT+CLTS="), i, ok_reply)) 164 | return false; 165 | return sendCheckReply(F("AT&W"), ok_reply); 166 | } 167 | 168 | 169 | /********* BATTERY & ADC ********************************************/ 170 | 171 | /* returns value in mV (uint16_t) */ 172 | boolean Adafruit_FONA::getBattVoltage(uint16_t *v) { 173 | return sendParseReply(F("AT+CBC"), F("+CBC: "), v, ',', 2); 174 | } 175 | 176 | /* returns value in mV (uint16_t) */ 177 | boolean Adafruit_FONA_3G::getBattVoltage(uint16_t *v) { 178 | float f; 179 | boolean b = sendParseReply(F("AT+CBC"), F("+CBC: "), &f, ',', 2); 180 | *v = f*1000; 181 | return b; 182 | } 183 | 184 | 185 | /* returns the percentage charge of battery as reported by sim800 */ 186 | boolean Adafruit_FONA::getBattPercent(uint16_t *p) { 187 | return sendParseReply(F("AT+CBC"), F("+CBC: "), p, ',', 1); 188 | } 189 | 190 | boolean Adafruit_FONA::getADCVoltage(uint16_t *v) { 191 | return sendParseReply(F("AT+CADC?"), F("+CADC: 1,"), v); 192 | } 193 | 194 | /********* SIM ***********************************************************/ 195 | 196 | uint8_t Adafruit_FONA::unlockSIM(char *pin) 197 | { 198 | char sendbuff[14] = "AT+CPIN="; 199 | sendbuff[8] = pin[0]; 200 | sendbuff[9] = pin[1]; 201 | sendbuff[10] = pin[2]; 202 | sendbuff[11] = pin[3]; 203 | sendbuff[12] = '\0'; 204 | 205 | return sendCheckReply(sendbuff, ok_reply); 206 | } 207 | 208 | uint8_t Adafruit_FONA::getSIMCCID(char *ccid) { 209 | getReply(F("AT+CCID")); 210 | // up to 28 chars for reply, 20 char total ccid 211 | if (replybuffer[0] == '+') { 212 | // fona 3g? 213 | strncpy(ccid, replybuffer+8, 20); 214 | } else { 215 | // fona 800 or 800 216 | strncpy(ccid, replybuffer, 20); 217 | } 218 | ccid[20] = 0; 219 | 220 | readline(); // eat 'OK' 221 | 222 | return strlen(ccid); 223 | } 224 | 225 | /********* IMEI **********************************************************/ 226 | 227 | uint8_t Adafruit_FONA::getIMEI(char *imei) { 228 | getReply(F("AT+GSN")); 229 | 230 | // up to 15 chars 231 | strncpy(imei, replybuffer, 15); 232 | imei[15] = 0; 233 | 234 | readline(); // eat 'OK' 235 | 236 | return strlen(imei); 237 | } 238 | 239 | /********* NETWORK *******************************************************/ 240 | 241 | uint8_t Adafruit_FONA::getNetworkStatus(void) { 242 | uint16_t status; 243 | 244 | if (! sendParseReply(F("AT+CREG?"), F("+CREG: "), &status, ',', 1)) return 0; 245 | 246 | return status; 247 | } 248 | 249 | 250 | uint8_t Adafruit_FONA::getRSSI(void) { 251 | uint16_t reply; 252 | 253 | if (! sendParseReply(F("AT+CSQ"), F("+CSQ: "), &reply) ) return 0; 254 | 255 | return reply; 256 | } 257 | 258 | /********* AUDIO *******************************************************/ 259 | 260 | boolean Adafruit_FONA::setAudio(uint8_t a) { 261 | // 0 is headset, 1 is external audio 262 | if (a > 1) return false; 263 | 264 | return sendCheckReply(F("AT+CHFA="), a, ok_reply); 265 | } 266 | 267 | uint8_t Adafruit_FONA::getVolume(void) { 268 | uint16_t reply; 269 | 270 | if (! sendParseReply(F("AT+CLVL?"), F("+CLVL: "), &reply) ) return 0; 271 | 272 | return reply; 273 | } 274 | 275 | boolean Adafruit_FONA::setVolume(uint8_t i) { 276 | return sendCheckReply(F("AT+CLVL="), i, ok_reply); 277 | } 278 | 279 | 280 | boolean Adafruit_FONA::playDTMF(char dtmf) { 281 | char str[4]; 282 | str[0] = '\"'; 283 | str[1] = dtmf; 284 | str[2] = '\"'; 285 | str[3] = 0; 286 | return sendCheckReply(F("AT+CLDTMF=3,"), str, ok_reply); 287 | } 288 | 289 | boolean Adafruit_FONA::playToolkitTone(uint8_t t, uint16_t len) { 290 | return sendCheckReply(F("AT+STTONE=1,"), t, len, ok_reply); 291 | } 292 | 293 | boolean Adafruit_FONA_3G::playToolkitTone(uint8_t t, uint16_t len) { 294 | if (! sendCheckReply(F("AT+CPTONE="), t, ok_reply)) 295 | return false; 296 | delay(len); 297 | return sendCheckReply(F("AT+CPTONE=0"), ok_reply); 298 | } 299 | 300 | boolean Adafruit_FONA::setMicVolume(uint8_t a, uint8_t level) { 301 | // 0 is headset, 1 is external audio 302 | if (a > 1) return false; 303 | 304 | return sendCheckReply(F("AT+CMIC="), a, level, ok_reply); 305 | } 306 | 307 | /********* FM RADIO *******************************************************/ 308 | 309 | 310 | boolean Adafruit_FONA::FMradio(boolean onoff, uint8_t a) { 311 | if (! onoff) { 312 | return sendCheckReply(F("AT+FMCLOSE"), ok_reply); 313 | } 314 | 315 | // 0 is headset, 1 is external audio 316 | if (a > 1) return false; 317 | 318 | return sendCheckReply(F("AT+FMOPEN="), a, ok_reply); 319 | } 320 | 321 | boolean Adafruit_FONA::tuneFMradio(uint16_t station) { 322 | // Fail if FM station is outside allowed range. 323 | if ((station < 870) || (station > 1090)) 324 | return false; 325 | 326 | return sendCheckReply(F("AT+FMFREQ="), station, ok_reply); 327 | } 328 | 329 | boolean Adafruit_FONA::setFMVolume(uint8_t i) { 330 | // Fail if volume is outside allowed range (0-6). 331 | if (i > 6) { 332 | return false; 333 | } 334 | // Send FM volume command and verify response. 335 | return sendCheckReply(F("AT+FMVOLUME="), i, ok_reply); 336 | } 337 | 338 | int8_t Adafruit_FONA::getFMVolume() { 339 | uint16_t level; 340 | 341 | if (! sendParseReply(F("AT+FMVOLUME?"), F("+FMVOLUME: "), &level) ) return 0; 342 | 343 | return level; 344 | } 345 | 346 | int8_t Adafruit_FONA::getFMSignalLevel(uint16_t station) { 347 | // Fail if FM station is outside allowed range. 348 | if ((station < 875) || (station > 1080)) { 349 | return -1; 350 | } 351 | 352 | // Send FM signal level query command. 353 | // Note, need to explicitly send timeout so right overload is chosen. 354 | getReply(F("AT+FMSIGNAL="), station, FONA_DEFAULT_TIMEOUT_MS); 355 | // Check response starts with expected value. 356 | char *p = prog_char_strstr(replybuffer, PSTR("+FMSIGNAL: ")); 357 | if (p == 0) return -1; 358 | p+=11; 359 | // Find second colon to get start of signal quality. 360 | p = strchr(p, ':'); 361 | if (p == 0) return -1; 362 | p+=1; 363 | // Parse signal quality. 364 | int8_t level = atoi(p); 365 | readline(); // eat the "OK" 366 | return level; 367 | } 368 | 369 | /********* PWM/BUZZER **************************************************/ 370 | 371 | boolean Adafruit_FONA::setPWM(uint16_t period, uint8_t duty) { 372 | if (period > 2000) return false; 373 | if (duty > 100) return false; 374 | 375 | return sendCheckReply(F("AT+SPWM=0,"), period, duty, ok_reply); 376 | } 377 | 378 | /********* CALL PHONES **************************************************/ 379 | boolean Adafruit_FONA::callPhone(char *number) { 380 | char sendbuff[35] = "ATD"; 381 | strncpy(sendbuff+3, number, min(30, (int)strlen(number))); 382 | uint8_t x = strlen(sendbuff); 383 | sendbuff[x] = ';'; 384 | sendbuff[x+1] = 0; 385 | //DEBUG_PRINTLN(sendbuff); 386 | 387 | return sendCheckReply(sendbuff, ok_reply); 388 | } 389 | 390 | 391 | uint8_t Adafruit_FONA::getCallStatus(void) { 392 | uint16_t phoneStatus; 393 | 394 | if (! sendParseReply(F("AT+CPAS"), F("+CPAS: "), &phoneStatus)) 395 | return FONA_CALL_FAILED; // 1, since 0 is actually a known, good reply 396 | 397 | return phoneStatus; // 0 ready, 2 unkown, 3 ringing, 4 call in progress 398 | } 399 | 400 | boolean Adafruit_FONA::hangUp(void) { 401 | // return sendCheckReply(F("ATH0"), ok_reply); 402 | return sendCheckReply(F("ATH"), ok_reply); 403 | } 404 | 405 | boolean Adafruit_FONA_3G::hangUp(void) { 406 | getReply(F("ATH")); 407 | 408 | return (prog_char_strstr(replybuffer, (prog_char *)F("VOICE CALL: END")) != 0); 409 | } 410 | 411 | boolean Adafruit_FONA::pickUp(void) { 412 | return sendCheckReply(F("ATA"), ok_reply); 413 | } 414 | 415 | boolean Adafruit_FONA_3G::pickUp(void) { 416 | return sendCheckReply(F("ATA"), F("VOICE CALL: BEGIN")); 417 | } 418 | 419 | 420 | void Adafruit_FONA::onIncomingCall() { 421 | 422 | // DEBUG_PRINT(F("> ")); DEBUG_PRINTLN(F("Incoming call...")); 423 | 424 | Adafruit_FONA::_incomingCall = true; 425 | } 426 | 427 | boolean Adafruit_FONA::_incomingCall = false; 428 | 429 | boolean Adafruit_FONA::callerIdNotification(boolean enable, uint8_t interrupt) { 430 | if(enable){ 431 | attachInterrupt(interrupt, onIncomingCall, FALLING); 432 | return sendCheckReply(F("AT+CLIP=1"), ok_reply); 433 | } 434 | 435 | detachInterrupt(interrupt); 436 | return sendCheckReply(F("AT+CLIP=0"), ok_reply); 437 | } 438 | 439 | boolean Adafruit_FONA::incomingCallNumber(char* phonenum) { 440 | //+CLIP: "",145,"",0,"",0 441 | if(!Adafruit_FONA::_incomingCall) 442 | return false; 443 | 444 | readline(); 445 | while(!prog_char_strcmp(replybuffer, (prog_char*)F("RING")) == 0) { 446 | flushInput(); 447 | readline(); 448 | } 449 | 450 | readline(); //reads incoming phone number line 451 | 452 | parseReply(F("+CLIP: \""), phonenum, '"'); 453 | 454 | 455 | DEBUG_PRINT(F("Phone Number: ")); 456 | DEBUG_PRINTLN(replybuffer); 457 | 458 | 459 | Adafruit_FONA::_incomingCall = false; 460 | return true; 461 | } 462 | 463 | /********* SMS **********************************************************/ 464 | 465 | uint8_t Adafruit_FONA::getSMSInterrupt(void) { 466 | uint16_t reply; 467 | 468 | if (! sendParseReply(F("AT+CFGRI?"), F("+CFGRI: "), &reply) ) return 0; 469 | 470 | return reply; 471 | } 472 | 473 | boolean Adafruit_FONA::setSMSInterrupt(uint8_t i) { 474 | return sendCheckReply(F("AT+CFGRI="), i, ok_reply); 475 | } 476 | 477 | int8_t Adafruit_FONA::getNumSMS(void) { 478 | uint16_t numsms; 479 | 480 | // get into text mode 481 | if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return -1; 482 | 483 | // ask how many sms are stored 484 | if (sendParseReply(F("AT+CPMS?"), F(FONA_PREF_SMS_STORAGE ","), &numsms)) 485 | return numsms; 486 | if (sendParseReply(F("AT+CPMS?"), F("\"SM\","), &numsms)) 487 | return numsms; 488 | if (sendParseReply(F("AT+CPMS?"), F("\"SM_P\","), &numsms)) 489 | return numsms; 490 | return -1; 491 | } 492 | 493 | // Reading SMS's is a bit involved so we don't use helpers that may cause delays or debug 494 | // printouts! 495 | boolean Adafruit_FONA::readSMS(uint8_t i, char *smsbuff, 496 | uint16_t maxlen, uint16_t *readlen) { 497 | // text mode 498 | if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 499 | 500 | // show all text mode parameters 501 | if (! sendCheckReply(F("AT+CSDH=1"), ok_reply)) return false; 502 | 503 | // parse out the SMS len 504 | uint16_t thesmslen = 0; 505 | 506 | 507 | DEBUG_PRINT(F("AT+CMGR=")); 508 | DEBUG_PRINTLN(i); 509 | 510 | 511 | //getReply(F("AT+CMGR="), i, 1000); // do not print debug! 512 | mySerial->print(F("AT+CMGR=")); 513 | mySerial->println(i); 514 | readline(1000); // timeout 515 | 516 | //DEBUG_PRINT(F("Reply: ")); DEBUG_PRINTLN(replybuffer); 517 | // parse it out... 518 | 519 | 520 | DEBUG_PRINTLN(replybuffer); 521 | 522 | 523 | if (! parseReply(F("+CMGR:"), &thesmslen, ',', 11)) { 524 | *readlen = 0; 525 | return false; 526 | } 527 | 528 | readRaw(thesmslen); 529 | 530 | flushInput(); 531 | 532 | uint16_t thelen = min(maxlen, (uint16_t)strlen(replybuffer)); 533 | strncpy(smsbuff, replybuffer, thelen); 534 | smsbuff[thelen] = 0; // end the string 535 | 536 | 537 | DEBUG_PRINTLN(replybuffer); 538 | 539 | *readlen = thelen; 540 | return true; 541 | } 542 | 543 | // Retrieve the sender of the specified SMS message and copy it as a string to 544 | // the sender buffer. Up to senderlen characters of the sender will be copied 545 | // and a null terminator will be added if less than senderlen charactesr are 546 | // copied to the result. Returns true if a result was successfully retrieved, 547 | // otherwise false. 548 | boolean Adafruit_FONA::getSMSSender(uint8_t i, char *sender, int senderlen) { 549 | // Ensure text mode and all text mode parameters are sent. 550 | if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 551 | if (! sendCheckReply(F("AT+CSDH=1"), ok_reply)) return false; 552 | 553 | 554 | DEBUG_PRINT(F("AT+CMGR=")); 555 | DEBUG_PRINTLN(i); 556 | 557 | 558 | // Send command to retrieve SMS message and parse a line of response. 559 | mySerial->print(F("AT+CMGR=")); 560 | mySerial->println(i); 561 | readline(1000); 562 | 563 | 564 | DEBUG_PRINTLN(replybuffer); 565 | 566 | 567 | // Parse the second field in the response. 568 | boolean result = parseReplyQuoted(F("+CMGR:"), sender, senderlen, ',', 1); 569 | // Drop any remaining data from the response. 570 | flushInput(); 571 | return result; 572 | } 573 | 574 | boolean Adafruit_FONA::sendSMS(char *smsaddr, char *smsmsg) { 575 | if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 576 | char sendcmd[30] = "AT+CMGS=\""; 577 | strncpy(sendcmd+9, smsaddr, 30-9-2); // 9 bytes beginning, 2 bytes for close quote + null 578 | sendcmd[strlen(sendcmd)] = '\"'; 579 | if (! sendCheckReply(sendcmd, F("> "))) return false; 580 | 581 | DEBUG_PRINT(F("> ")); DEBUG_PRINTLN(smsmsg); 582 | 583 | mySerial->println(smsmsg); 584 | mySerial->println(); 585 | mySerial->write(0x1A); 586 | 587 | DEBUG_PRINTLN("^Z"); 588 | 589 | if ( (_type == FONA3G_A) || (_type == FONA3G_E) ) { 590 | // Eat two sets of CRLF 591 | readline(200); 592 | //DEBUG_PRINT("Line 1: "); DEBUG_PRINTLN(strlen(replybuffer)); 593 | readline(200); 594 | //DEBUG_PRINT("Line 2: "); DEBUG_PRINTLN(strlen(replybuffer)); 595 | } 596 | readline(10000); // read the +CMGS reply, wait up to 10 seconds!!! 597 | //DEBUG_PRINT("Line 3: "); DEBUG_PRINTLN(strlen(replybuffer)); 598 | if (strstr(replybuffer, "+CMGS") == 0) { 599 | return false; 600 | } 601 | readline(1000); // read OK 602 | //DEBUG_PRINT("* "); DEBUG_PRINTLN(replybuffer); 603 | 604 | if (strcmp(replybuffer, "OK") != 0) { 605 | return false; 606 | } 607 | 608 | return true; 609 | } 610 | 611 | 612 | boolean Adafruit_FONA::deleteSMS(uint8_t i) { 613 | if (! sendCheckReply(F("AT+CMGF=1"), ok_reply)) return false; 614 | // read an sms 615 | char sendbuff[12] = "AT+CMGD=000"; 616 | sendbuff[8] = (i / 100) + '0'; 617 | i %= 100; 618 | sendbuff[9] = (i / 10) + '0'; 619 | i %= 10; 620 | sendbuff[10] = i + '0'; 621 | 622 | return sendCheckReply(sendbuff, ok_reply, 2000); 623 | } 624 | 625 | /********* USSD *********************************************************/ 626 | 627 | boolean Adafruit_FONA::sendUSSD(char *ussdmsg, char *ussdbuff, uint16_t maxlen, uint16_t *readlen) { 628 | if (! sendCheckReply(F("AT+CUSD=1"), ok_reply)) return false; 629 | 630 | char sendcmd[30] = "AT+CUSD=1,\""; 631 | strncpy(sendcmd+11, ussdmsg, 30-11-2); // 11 bytes beginning, 2 bytes for close quote + null 632 | sendcmd[strlen(sendcmd)] = '\"'; 633 | 634 | if (! sendCheckReply(sendcmd, ok_reply)) { 635 | *readlen = 0; 636 | return false; 637 | } else { 638 | readline(10000); // read the +CUSD reply, wait up to 10 seconds!!! 639 | //DEBUG_PRINT("* "); DEBUG_PRINTLN(replybuffer); 640 | char *p = prog_char_strstr(replybuffer, PSTR("+CUSD: ")); 641 | if (p == 0) { 642 | *readlen = 0; 643 | return false; 644 | } 645 | p+=7; //+CUSD 646 | // Find " to get start of ussd message. 647 | p = strchr(p, '\"'); 648 | if (p == 0) { 649 | *readlen = 0; 650 | return false; 651 | } 652 | p+=1; //" 653 | // Find " to get end of ussd message. 654 | char *strend = strchr(p, '\"'); 655 | 656 | uint16_t lentocopy = min(maxlen-1, strend - p); 657 | strncpy(ussdbuff, p, lentocopy+1); 658 | ussdbuff[lentocopy] = 0; 659 | *readlen = lentocopy; 660 | } 661 | return true; 662 | } 663 | 664 | 665 | /********* TIME **********************************************************/ 666 | 667 | boolean Adafruit_FONA::enableNetworkTimeSync(boolean onoff) { 668 | if (onoff) { 669 | if (! sendCheckReply(F("AT+CLTS=1"), ok_reply)) 670 | return false; 671 | } else { 672 | if (! sendCheckReply(F("AT+CLTS=0"), ok_reply)) 673 | return false; 674 | } 675 | 676 | flushInput(); // eat any 'Unsolicted Result Code' 677 | 678 | return true; 679 | } 680 | 681 | boolean Adafruit_FONA::enableNTPTimeSync(boolean onoff, FONAFlashStringPtr ntpserver) { 682 | if (onoff) { 683 | if (! sendCheckReply(F("AT+CNTPCID=1"), ok_reply)) 684 | return false; 685 | 686 | mySerial->print(F("AT+CNTP=\"")); 687 | if (ntpserver != 0) { 688 | mySerial->print(ntpserver); 689 | } else { 690 | mySerial->print(F("pool.ntp.org")); 691 | } 692 | mySerial->println(F("\",0")); 693 | readline(FONA_DEFAULT_TIMEOUT_MS); 694 | if (strcmp(replybuffer, "OK") != 0) 695 | return false; 696 | 697 | if (! sendCheckReply(F("AT+CNTP"), ok_reply, 10000)) 698 | return false; 699 | 700 | uint16_t status; 701 | readline(10000); 702 | if (! parseReply(F("+CNTP:"), &status)) 703 | return false; 704 | } else { 705 | if (! sendCheckReply(F("AT+CNTPCID=0"), ok_reply)) 706 | return false; 707 | } 708 | 709 | return true; 710 | } 711 | 712 | boolean Adafruit_FONA::getTime(char *buff, uint16_t maxlen) { 713 | getReply(F("AT+CCLK?"), (uint16_t) 10000); 714 | if (strncmp(replybuffer, "+CCLK: ", 7) != 0) 715 | return false; 716 | 717 | char *p = replybuffer+7; 718 | uint16_t lentocopy = min(maxlen-1, (int)strlen(p)); 719 | strncpy(buff, p, lentocopy+1); 720 | buff[lentocopy] = 0; 721 | 722 | readline(); // eat OK 723 | 724 | return true; 725 | } 726 | 727 | /********* GPS **********************************************************/ 728 | 729 | 730 | boolean Adafruit_FONA::enableGPS(boolean onoff) { 731 | uint16_t state; 732 | 733 | // first check if its already on or off 734 | 735 | if (_type == FONA808_V2) { 736 | if (! sendParseReply(F("AT+CGNSPWR?"), F("+CGNSPWR: "), &state) ) 737 | return false; 738 | } else { 739 | if (! sendParseReply(F("AT+CGPSPWR?"), F("+CGPSPWR: "), &state)) 740 | return false; 741 | } 742 | 743 | if (onoff && !state) { 744 | if (_type == FONA808_V2) { 745 | if (! sendCheckReply(F("AT+CGNSPWR=1"), ok_reply)) // try GNS command 746 | return false; 747 | } else { 748 | if (! sendCheckReply(F("AT+CGPSPWR=1"), ok_reply)) 749 | return false; 750 | } 751 | } else if (!onoff && state) { 752 | if (_type == FONA808_V2) { 753 | if (! sendCheckReply(F("AT+CGNSPWR=0"), ok_reply)) // try GNS command 754 | return false; 755 | } else { 756 | if (! sendCheckReply(F("AT+CGPSPWR=0"), ok_reply)) 757 | return false; 758 | } 759 | } 760 | return true; 761 | } 762 | 763 | 764 | 765 | boolean Adafruit_FONA_3G::enableGPS(boolean onoff) { 766 | uint16_t state; 767 | 768 | // first check if its already on or off 769 | if (! Adafruit_FONA::sendParseReply(F("AT+CGPS?"), F("+CGPS: "), &state) ) 770 | return false; 771 | 772 | if (onoff && !state) { 773 | if (! sendCheckReply(F("AT+CGPS=1"), ok_reply)) 774 | return false; 775 | } else if (!onoff && state) { 776 | if (! sendCheckReply(F("AT+CGPS=0"), ok_reply)) 777 | return false; 778 | // this takes a little time 779 | readline(2000); // eat '+CGPS: 0' 780 | } 781 | return true; 782 | } 783 | 784 | int8_t Adafruit_FONA::GPSstatus(void) { 785 | if (_type == FONA808_V2) { 786 | // 808 V2 uses GNS commands and doesn't have an explicit 2D/3D fix status. 787 | // Instead just look for a fix and if found assume it's a 3D fix. 788 | getReply(F("AT+CGNSINF")); 789 | char *p = prog_char_strstr(replybuffer, (prog_char*)F("+CGNSINF: ")); 790 | if (p == 0) return -1; 791 | p+=10; 792 | readline(); // eat 'OK' 793 | if (p[0] == '0') return 0; // GPS is not even on! 794 | 795 | p+=2; // Skip to second value, fix status. 796 | //DEBUG_PRINTLN(p); 797 | // Assume if the fix status is '1' then we have a 3D fix, otherwise no fix. 798 | if (p[0] == '1') return 3; 799 | else return 1; 800 | } 801 | if (_type == FONA3G_A || _type == FONA3G_E) { 802 | // FONA 3G doesn't have an explicit 2D/3D fix status. 803 | // Instead just look for a fix and if found assume it's a 3D fix. 804 | getReply(F("AT+CGPSINFO")); 805 | char *p = prog_char_strstr(replybuffer, (prog_char*)F("+CGPSINFO:")); 806 | if (p == 0) return -1; 807 | if (p[10] != ',') return 3; // if you get anything, its 3D fix 808 | return 0; 809 | } 810 | else { 811 | // 808 V1 looks for specific 2D or 3D fix state. 812 | getReply(F("AT+CGPSSTATUS?")); 813 | char *p = prog_char_strstr(replybuffer, (prog_char*)F("SSTATUS: Location ")); 814 | if (p == 0) return -1; 815 | p+=18; 816 | readline(); // eat 'OK' 817 | //DEBUG_PRINTLN(p); 818 | if (p[0] == 'U') return 0; 819 | if (p[0] == 'N') return 1; 820 | if (p[0] == '2') return 2; 821 | if (p[0] == '3') return 3; 822 | } 823 | // else 824 | return 0; 825 | } 826 | 827 | uint8_t Adafruit_FONA::getGPS(uint8_t arg, char *buffer, uint8_t maxbuff) { 828 | int32_t x = arg; 829 | 830 | if ( (_type == FONA3G_A) || (_type == FONA3G_E) ) { 831 | getReply(F("AT+CGPSINFO")); 832 | } else if (_type == FONA808_V1) { 833 | getReply(F("AT+CGPSINF="), x); 834 | } else { 835 | getReply(F("AT+CGNSINF")); 836 | } 837 | 838 | char *p = prog_char_strstr(replybuffer, (prog_char*)F("SINF")); 839 | if (p == 0) { 840 | buffer[0] = 0; 841 | return 0; 842 | } 843 | 844 | p+=6; 845 | 846 | uint8_t len = max(maxbuff-1, (int)strlen(p)); 847 | strncpy(buffer, p, len); 848 | buffer[len] = 0; 849 | 850 | readline(); // eat 'OK' 851 | return len; 852 | } 853 | 854 | boolean Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude) { 855 | 856 | char gpsbuffer[120]; 857 | 858 | // we need at least a 2D fix 859 | if (GPSstatus() < 2) 860 | return false; 861 | 862 | // grab the mode 2^5 gps csv from the sim808 863 | uint8_t res_len = getGPS(32, gpsbuffer, 120); 864 | 865 | // make sure we have a response 866 | if (res_len == 0) 867 | return false; 868 | 869 | if (_type == FONA3G_A || _type == FONA3G_E) { 870 | // Parse 3G respose 871 | // +CGPSINFO:4043.000000,N,07400.000000,W,151015,203802.1,-12.0,0.0,0 872 | // skip beginning 873 | char *tok; 874 | 875 | // grab the latitude 876 | char *latp = strtok(gpsbuffer, ","); 877 | if (! latp) return false; 878 | 879 | // grab latitude direction 880 | char *latdir = strtok(NULL, ","); 881 | if (! latdir) return false; 882 | 883 | // grab longitude 884 | char *longp = strtok(NULL, ","); 885 | if (! longp) return false; 886 | 887 | // grab longitude direction 888 | char *longdir = strtok(NULL, ","); 889 | if (! longdir) return false; 890 | 891 | // skip date & time 892 | tok = strtok(NULL, ","); 893 | tok = strtok(NULL, ","); 894 | 895 | // only grab altitude if needed 896 | if (altitude != NULL) { 897 | // grab altitude 898 | char *altp = strtok(NULL, ","); 899 | if (! altp) return false; 900 | *altitude = atof(altp); 901 | } 902 | 903 | // only grab speed if needed 904 | if (speed_kph != NULL) { 905 | // grab the speed in km/h 906 | char *speedp = strtok(NULL, ","); 907 | if (! speedp) return false; 908 | 909 | *speed_kph = atof(speedp); 910 | } 911 | 912 | // only grab heading if needed 913 | if (heading != NULL) { 914 | 915 | // grab the speed in knots 916 | char *coursep = strtok(NULL, ","); 917 | if (! coursep) return false; 918 | 919 | *heading = atof(coursep); 920 | } 921 | 922 | double latitude = atof(latp); 923 | double longitude = atof(longp); 924 | 925 | // convert latitude from minutes to decimal 926 | float degrees = floor(latitude / 100); 927 | double minutes = latitude - (100 * degrees); 928 | minutes /= 60; 929 | degrees += minutes; 930 | 931 | // turn direction into + or - 932 | if (latdir[0] == 'S') degrees *= -1; 933 | 934 | *lat = degrees; 935 | 936 | // convert longitude from minutes to decimal 937 | degrees = floor(longitude / 100); 938 | minutes = longitude - (100 * degrees); 939 | minutes /= 60; 940 | degrees += minutes; 941 | 942 | // turn direction into + or - 943 | if (longdir[0] == 'W') degrees *= -1; 944 | 945 | *lon = degrees; 946 | 947 | } else if (_type == FONA808_V2) { 948 | // Parse 808 V2 response. See table 2-3 from here for format: 949 | // http://www.adafruit.com/datasheets/SIM800%20Series_GNSS_Application%20Note%20V1.00.pdf 950 | 951 | // skip GPS run status 952 | char *tok = strtok(gpsbuffer, ","); 953 | if (! tok) return false; 954 | 955 | // skip fix status 956 | tok = strtok(NULL, ","); 957 | if (! tok) return false; 958 | 959 | // skip date 960 | tok = strtok(NULL, ","); 961 | if (! tok) return false; 962 | 963 | // grab the latitude 964 | char *latp = strtok(NULL, ","); 965 | if (! latp) return false; 966 | 967 | // grab longitude 968 | char *longp = strtok(NULL, ","); 969 | if (! longp) return false; 970 | 971 | *lat = atof(latp); 972 | *lon = atof(longp); 973 | 974 | // only grab altitude if needed 975 | if (altitude != NULL) { 976 | // grab altitude 977 | char *altp = strtok(NULL, ","); 978 | if (! altp) return false; 979 | 980 | *altitude = atof(altp); 981 | } 982 | 983 | // only grab speed if needed 984 | if (speed_kph != NULL) { 985 | // grab the speed in km/h 986 | char *speedp = strtok(NULL, ","); 987 | if (! speedp) return false; 988 | 989 | *speed_kph = atof(speedp); 990 | } 991 | 992 | // only grab heading if needed 993 | if (heading != NULL) { 994 | 995 | // grab the speed in knots 996 | char *coursep = strtok(NULL, ","); 997 | if (! coursep) return false; 998 | 999 | *heading = atof(coursep); 1000 | } 1001 | } 1002 | else { 1003 | // Parse 808 V1 response. 1004 | 1005 | // skip mode 1006 | char *tok = strtok(gpsbuffer, ","); 1007 | if (! tok) return false; 1008 | 1009 | // skip date 1010 | tok = strtok(NULL, ","); 1011 | if (! tok) return false; 1012 | 1013 | // skip fix 1014 | tok = strtok(NULL, ","); 1015 | if (! tok) return false; 1016 | 1017 | // grab the latitude 1018 | char *latp = strtok(NULL, ","); 1019 | if (! latp) return false; 1020 | 1021 | // grab latitude direction 1022 | char *latdir = strtok(NULL, ","); 1023 | if (! latdir) return false; 1024 | 1025 | // grab longitude 1026 | char *longp = strtok(NULL, ","); 1027 | if (! longp) return false; 1028 | 1029 | // grab longitude direction 1030 | char *longdir = strtok(NULL, ","); 1031 | if (! longdir) return false; 1032 | 1033 | double latitude = atof(latp); 1034 | double longitude = atof(longp); 1035 | 1036 | // convert latitude from minutes to decimal 1037 | float degrees = floor(latitude / 100); 1038 | double minutes = latitude - (100 * degrees); 1039 | minutes /= 60; 1040 | degrees += minutes; 1041 | 1042 | // turn direction into + or - 1043 | if (latdir[0] == 'S') degrees *= -1; 1044 | 1045 | *lat = degrees; 1046 | 1047 | // convert longitude from minutes to decimal 1048 | degrees = floor(longitude / 100); 1049 | minutes = longitude - (100 * degrees); 1050 | minutes /= 60; 1051 | degrees += minutes; 1052 | 1053 | // turn direction into + or - 1054 | if (longdir[0] == 'W') degrees *= -1; 1055 | 1056 | *lon = degrees; 1057 | 1058 | // only grab speed if needed 1059 | if (speed_kph != NULL) { 1060 | 1061 | // grab the speed in knots 1062 | char *speedp = strtok(NULL, ","); 1063 | if (! speedp) return false; 1064 | 1065 | // convert to kph 1066 | *speed_kph = atof(speedp) * 1.852; 1067 | 1068 | } 1069 | 1070 | // only grab heading if needed 1071 | if (heading != NULL) { 1072 | 1073 | // grab the speed in knots 1074 | char *coursep = strtok(NULL, ","); 1075 | if (! coursep) return false; 1076 | 1077 | *heading = atof(coursep); 1078 | 1079 | } 1080 | 1081 | // no need to continue 1082 | if (altitude == NULL) 1083 | return true; 1084 | 1085 | // we need at least a 3D fix for altitude 1086 | if (GPSstatus() < 3) 1087 | return false; 1088 | 1089 | // grab the mode 0 gps csv from the sim808 1090 | res_len = getGPS(0, gpsbuffer, 120); 1091 | 1092 | // make sure we have a response 1093 | if (res_len == 0) 1094 | return false; 1095 | 1096 | // skip mode 1097 | tok = strtok(gpsbuffer, ","); 1098 | if (! tok) return false; 1099 | 1100 | // skip lat 1101 | tok = strtok(NULL, ","); 1102 | if (! tok) return false; 1103 | 1104 | // skip long 1105 | tok = strtok(NULL, ","); 1106 | if (! tok) return false; 1107 | 1108 | // grab altitude 1109 | char *altp = strtok(NULL, ","); 1110 | if (! altp) return false; 1111 | 1112 | *altitude = atof(altp); 1113 | } 1114 | 1115 | return true; 1116 | 1117 | } 1118 | 1119 | boolean Adafruit_FONA::enableGPSNMEA(uint8_t i) { 1120 | 1121 | char sendbuff[15] = "AT+CGPSOUT=000"; 1122 | sendbuff[11] = (i / 100) + '0'; 1123 | i %= 100; 1124 | sendbuff[12] = (i / 10) + '0'; 1125 | i %= 10; 1126 | sendbuff[13] = i + '0'; 1127 | 1128 | if (_type == FONA808_V2) { 1129 | if (i) 1130 | return sendCheckReply(F("AT+CGNSTST=1"), ok_reply); 1131 | else 1132 | return sendCheckReply(F("AT+CGNSTST=0"), ok_reply); 1133 | } else { 1134 | return sendCheckReply(sendbuff, ok_reply, 2000); 1135 | } 1136 | } 1137 | 1138 | 1139 | /********* GPRS **********************************************************/ 1140 | 1141 | 1142 | boolean Adafruit_FONA::enableGPRS(boolean onoff) { 1143 | 1144 | if (onoff) { 1145 | // disconnect all sockets 1146 | sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000); 1147 | 1148 | if (! sendCheckReply(F("AT+CGATT=1"), ok_reply, 10000)) 1149 | return false; 1150 | 1151 | // set bearer profile! connection type GPRS 1152 | if (! sendCheckReply(F("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\""), 1153 | ok_reply, 10000)) 1154 | return false; 1155 | 1156 | // set bearer profile access point name 1157 | if (apn) { 1158 | // Send command AT+SAPBR=3,1,"APN","" where is the configured APN value. 1159 | if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"APN\","), apn, ok_reply, 10000)) 1160 | return false; 1161 | 1162 | // send AT+CSTT,"apn","user","pass" 1163 | flushInput(); 1164 | 1165 | mySerial->print(F("AT+CSTT=\"")); 1166 | mySerial->print(apn); 1167 | if (apnusername) { 1168 | mySerial->print("\",\""); 1169 | mySerial->print(apnusername); 1170 | } 1171 | if (apnpassword) { 1172 | mySerial->print("\",\""); 1173 | mySerial->print(apnpassword); 1174 | } 1175 | mySerial->println("\""); 1176 | 1177 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(F("AT+CSTT=\"")); 1178 | DEBUG_PRINT(apn); 1179 | 1180 | if (apnusername) { 1181 | DEBUG_PRINT("\",\""); 1182 | DEBUG_PRINT(apnusername); 1183 | } 1184 | if (apnpassword) { 1185 | DEBUG_PRINT("\",\""); 1186 | DEBUG_PRINT(apnpassword); 1187 | } 1188 | DEBUG_PRINTLN("\""); 1189 | 1190 | if (! expectReply(ok_reply)) return false; 1191 | 1192 | // set username/password 1193 | if (apnusername) { 1194 | // Send command AT+SAPBR=3,1,"USER","" where is the configured APN username. 1195 | if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"USER\","), apnusername, ok_reply, 10000)) 1196 | return false; 1197 | } 1198 | if (apnpassword) { 1199 | // Send command AT+SAPBR=3,1,"PWD","" where is the configured APN password. 1200 | if (! sendCheckReplyQuoted(F("AT+SAPBR=3,1,\"PWD\","), apnpassword, ok_reply, 10000)) 1201 | return false; 1202 | } 1203 | } 1204 | 1205 | // open GPRS context 1206 | if (! sendCheckReply(F("AT+SAPBR=1,1"), ok_reply, 30000)) 1207 | return false; 1208 | 1209 | // bring up wireless connection 1210 | if (! sendCheckReply(F("AT+CIICR"), ok_reply, 10000)) 1211 | return false; 1212 | 1213 | } else { 1214 | // disconnect all sockets 1215 | if (! sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000)) 1216 | return false; 1217 | 1218 | // close GPRS context 1219 | if (! sendCheckReply(F("AT+SAPBR=0,1"), ok_reply, 10000)) 1220 | return false; 1221 | 1222 | if (! sendCheckReply(F("AT+CGATT=0"), ok_reply, 10000)) 1223 | return false; 1224 | 1225 | } 1226 | return true; 1227 | } 1228 | 1229 | boolean Adafruit_FONA_3G::enableGPRS(boolean onoff) { 1230 | 1231 | if (onoff) { 1232 | // disconnect all sockets 1233 | //sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 5000); 1234 | 1235 | if (! sendCheckReply(F("AT+CGATT=1"), ok_reply, 10000)) 1236 | return false; 1237 | 1238 | 1239 | // set bearer profile access point name 1240 | if (apn) { 1241 | // Send command AT+CGSOCKCONT=1,"IP","" where is the configured APN name. 1242 | if (! sendCheckReplyQuoted(F("AT+CGSOCKCONT=1,\"IP\","), apn, ok_reply, 10000)) 1243 | return false; 1244 | 1245 | // set username/password 1246 | if (apnusername) { 1247 | char authstring[100] = "AT+CGAUTH=1,1,\""; 1248 | char *strp = authstring + strlen(authstring); 1249 | prog_char_strcpy(strp, (prog_char *)apnusername); 1250 | strp+=prog_char_strlen((prog_char *)apnusername); 1251 | strp[0] = '\"'; 1252 | strp++; 1253 | strp[0] = 0; 1254 | 1255 | if (apnpassword) { 1256 | strp[0] = ','; strp++; 1257 | strp[0] = '\"'; strp++; 1258 | prog_char_strcpy(strp, (prog_char *)apnpassword); 1259 | strp+=prog_char_strlen((prog_char *)apnpassword); 1260 | strp[0] = '\"'; 1261 | strp++; 1262 | strp[0] = 0; 1263 | } 1264 | 1265 | if (! sendCheckReply(authstring, ok_reply, 10000)) 1266 | return false; 1267 | } 1268 | } 1269 | 1270 | // connect in transparent 1271 | if (! sendCheckReply(F("AT+CIPMODE=1"), ok_reply, 10000)) 1272 | return false; 1273 | // open network (?) 1274 | if (! sendCheckReply(F("AT+NETOPEN=,,1"), F("Network opened"), 10000)) 1275 | return false; 1276 | 1277 | readline(); // eat 'OK' 1278 | } else { 1279 | // close GPRS context 1280 | if (! sendCheckReply(F("AT+NETCLOSE"), F("Network closed"), 10000)) 1281 | return false; 1282 | 1283 | readline(); // eat 'OK' 1284 | } 1285 | 1286 | return true; 1287 | } 1288 | 1289 | uint8_t Adafruit_FONA::GPRSstate(void) { 1290 | uint16_t state; 1291 | 1292 | if (! sendParseReply(F("AT+CGATT?"), F("+CGATT: "), &state) ) 1293 | return -1; 1294 | 1295 | return state; 1296 | } 1297 | 1298 | void Adafruit_FONA::setGPRSNetworkSettings(FONAFlashStringPtr apn, 1299 | FONAFlashStringPtr username, FONAFlashStringPtr password) { 1300 | this->apn = apn; 1301 | this->apnusername = username; 1302 | this->apnpassword = password; 1303 | } 1304 | 1305 | boolean Adafruit_FONA::getGSMLoc(uint16_t *errorcode, char *buff, uint16_t maxlen) { 1306 | 1307 | getReply(F("AT+CIPGSMLOC=1,1"), (uint16_t)10000); 1308 | 1309 | if (! parseReply(F("+CIPGSMLOC: "), errorcode)) 1310 | return false; 1311 | 1312 | char *p = replybuffer+14; 1313 | uint16_t lentocopy = min(maxlen-1, (int)strlen(p)); 1314 | strncpy(buff, p, lentocopy+1); 1315 | 1316 | readline(); // eat OK 1317 | 1318 | return true; 1319 | } 1320 | 1321 | boolean Adafruit_FONA::getGSMLoc(float *lat, float *lon) { 1322 | 1323 | uint16_t returncode; 1324 | char gpsbuffer[120]; 1325 | 1326 | // make sure we could get a response 1327 | if (! getGSMLoc(&returncode, gpsbuffer, 120)) 1328 | return false; 1329 | 1330 | // make sure we have a valid return code 1331 | if (returncode != 0) 1332 | return false; 1333 | 1334 | // +CIPGSMLOC: 0,-74.007729,40.730160,2015/10/15,19:24:55 1335 | // tokenize the gps buffer to locate the lat & long 1336 | char *longp = strtok(gpsbuffer, ","); 1337 | if (! longp) return false; 1338 | 1339 | char *latp = strtok(NULL, ","); 1340 | if (! latp) return false; 1341 | 1342 | *lat = atof(latp); 1343 | *lon = atof(longp); 1344 | 1345 | return true; 1346 | 1347 | } 1348 | /********* TCP FUNCTIONS ************************************/ 1349 | 1350 | 1351 | boolean Adafruit_FONA::TCPconnect(char *server, uint16_t port) { 1352 | flushInput(); 1353 | 1354 | // close all old connections 1355 | if (! sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000) ) return false; 1356 | 1357 | // single connection at a time 1358 | if (! sendCheckReply(F("AT+CIPMUX=0"), ok_reply) ) return false; 1359 | 1360 | // manually read data 1361 | if (! sendCheckReply(F("AT+CIPRXGET=1"), ok_reply) ) return false; 1362 | 1363 | 1364 | DEBUG_PRINT(F("AT+CIPSTART=\"TCP\",\"")); 1365 | DEBUG_PRINT(server); 1366 | DEBUG_PRINT(F("\",\"")); 1367 | DEBUG_PRINT(port); 1368 | DEBUG_PRINTLN(F("\"")); 1369 | 1370 | 1371 | mySerial->print(F("AT+CIPSTART=\"TCP\",\"")); 1372 | mySerial->print(server); 1373 | mySerial->print(F("\",\"")); 1374 | mySerial->print(port); 1375 | mySerial->println(F("\"")); 1376 | 1377 | if (! expectReply(ok_reply)) return false; 1378 | if (! expectReply(F("CONNECT OK"))) return false; 1379 | 1380 | // looks like it was a success (?) 1381 | return true; 1382 | } 1383 | 1384 | boolean Adafruit_FONA::TCPclose(void) { 1385 | return sendCheckReply(F("AT+CIPCLOSE"), ok_reply); 1386 | } 1387 | 1388 | boolean Adafruit_FONA::TCPconnected(void) { 1389 | if (! sendCheckReply(F("AT+CIPSTATUS"), ok_reply, 100) ) return false; 1390 | readline(100); 1391 | 1392 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1393 | 1394 | return (strcmp(replybuffer, "STATE: CONNECT OK") == 0); 1395 | } 1396 | 1397 | boolean Adafruit_FONA::TCPsend(char *packet, uint8_t len) { 1398 | 1399 | DEBUG_PRINT(F("AT+CIPSEND=")); 1400 | DEBUG_PRINTLN(len); 1401 | #ifdef ADAFRUIT_FONA_DEBUG 1402 | for (uint16_t i=0; iprint(F("AT+CIPSEND=")); 1411 | mySerial->println(len); 1412 | readline(); 1413 | 1414 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1415 | 1416 | if (replybuffer[0] != '>') return false; 1417 | 1418 | mySerial->write(packet, len); 1419 | readline(3000); // wait up to 3 seconds to send the data 1420 | 1421 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1422 | 1423 | 1424 | return (strcmp(replybuffer, "SEND OK") == 0); 1425 | } 1426 | 1427 | uint16_t Adafruit_FONA::TCPavailable(void) { 1428 | uint16_t avail; 1429 | 1430 | if (! sendParseReply(F("AT+CIPRXGET=4"), F("+CIPRXGET: 4,"), &avail, ',', 0) ) return false; 1431 | 1432 | 1433 | DEBUG_PRINT (avail); DEBUG_PRINTLN(F(" bytes available")); 1434 | 1435 | 1436 | return avail; 1437 | } 1438 | 1439 | 1440 | uint16_t Adafruit_FONA::TCPread(uint8_t *buff, uint8_t len) { 1441 | uint16_t avail; 1442 | 1443 | mySerial->print(F("AT+CIPRXGET=2,")); 1444 | mySerial->println(len); 1445 | readline(); 1446 | if (! parseReply(F("+CIPRXGET: 2,"), &avail, ',', 0)) return false; 1447 | 1448 | readRaw(avail); 1449 | 1450 | #ifdef ADAFRUIT_FONA_DEBUG 1451 | DEBUG_PRINT (avail); DEBUG_PRINTLN(F(" bytes read")); 1452 | for (uint8_t i=0;i ")); 1481 | DEBUG_PRINT(F("AT+HTTPPARA=\"")); 1482 | DEBUG_PRINT(parameter); 1483 | DEBUG_PRINTLN('"'); 1484 | 1485 | 1486 | mySerial->print(F("AT+HTTPPARA=\"")); 1487 | mySerial->print(parameter); 1488 | if (quoted) 1489 | mySerial->print(F("\",\"")); 1490 | else 1491 | mySerial->print(F("\",")); 1492 | } 1493 | 1494 | boolean Adafruit_FONA::HTTP_para_end(boolean quoted) { 1495 | if (quoted) 1496 | mySerial->println('"'); 1497 | else 1498 | mySerial->println(); 1499 | 1500 | return expectReply(ok_reply); 1501 | } 1502 | 1503 | boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter, 1504 | const char *value) { 1505 | HTTP_para_start(parameter, true); 1506 | mySerial->print(value); 1507 | return HTTP_para_end(true); 1508 | } 1509 | 1510 | boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter, 1511 | FONAFlashStringPtr value) { 1512 | HTTP_para_start(parameter, true); 1513 | mySerial->print(value); 1514 | return HTTP_para_end(true); 1515 | } 1516 | 1517 | boolean Adafruit_FONA::HTTP_para(FONAFlashStringPtr parameter, 1518 | int32_t value) { 1519 | HTTP_para_start(parameter, false); 1520 | mySerial->print(value); 1521 | return HTTP_para_end(false); 1522 | } 1523 | 1524 | boolean Adafruit_FONA::HTTP_data(uint32_t size, uint32_t maxTime) { 1525 | flushInput(); 1526 | 1527 | 1528 | DEBUG_PRINT(F("\t---> ")); 1529 | DEBUG_PRINT(F("AT+HTTPDATA=")); 1530 | DEBUG_PRINT(size); 1531 | DEBUG_PRINT(','); 1532 | DEBUG_PRINTLN(maxTime); 1533 | 1534 | 1535 | mySerial->print(F("AT+HTTPDATA=")); 1536 | mySerial->print(size); 1537 | mySerial->print(","); 1538 | mySerial->println(maxTime); 1539 | 1540 | return expectReply(F("DOWNLOAD")); 1541 | } 1542 | 1543 | boolean Adafruit_FONA::HTTP_action(uint8_t method, uint16_t *status, 1544 | uint16_t *datalen, int32_t timeout) { 1545 | // Send request. 1546 | if (! sendCheckReply(F("AT+HTTPACTION="), method, ok_reply)) 1547 | return false; 1548 | 1549 | // Parse response status and size. 1550 | readline(timeout); 1551 | if (! parseReply(F("+HTTPACTION:"), status, ',', 1)) 1552 | return false; 1553 | if (! parseReply(F("+HTTPACTION:"), datalen, ',', 2)) 1554 | return false; 1555 | 1556 | return true; 1557 | } 1558 | 1559 | boolean Adafruit_FONA::HTTP_readall(uint16_t *datalen) { 1560 | getReply(F("AT+HTTPREAD")); 1561 | if (! parseReply(F("+HTTPREAD:"), datalen, ',', 0)) 1562 | return false; 1563 | 1564 | return true; 1565 | } 1566 | 1567 | boolean Adafruit_FONA::HTTP_ssl(boolean onoff) { 1568 | return sendCheckReply(F("AT+HTTPSSL="), onoff ? 1 : 0, ok_reply); 1569 | } 1570 | 1571 | /********* HTTP HIGH LEVEL FUNCTIONS ***************************/ 1572 | 1573 | boolean Adafruit_FONA::HTTP_GET_start(char *url, 1574 | uint16_t *status, uint16_t *datalen){ 1575 | if (! HTTP_setup(url)) 1576 | return false; 1577 | 1578 | // HTTP GET 1579 | if (! HTTP_action(FONA_HTTP_GET, status, datalen, 30000)) 1580 | return false; 1581 | 1582 | DEBUG_PRINT(F("Status: ")); DEBUG_PRINTLN(*status); 1583 | DEBUG_PRINT(F("Len: ")); DEBUG_PRINTLN(*datalen); 1584 | 1585 | // HTTP response data 1586 | if (! HTTP_readall(datalen)) 1587 | return false; 1588 | 1589 | return true; 1590 | } 1591 | 1592 | /* 1593 | boolean Adafruit_FONA_3G::HTTP_GET_start(char *ipaddr, char *path, uint16_t port 1594 | uint16_t *status, uint16_t *datalen){ 1595 | char send[100] = "AT+CHTTPACT=\""; 1596 | char *sendp = send + strlen(send); 1597 | memset(sendp, 0, 100 - strlen(send)); 1598 | 1599 | strcpy(sendp, ipaddr); 1600 | sendp+=strlen(ipaddr); 1601 | sendp[0] = '\"'; 1602 | sendp++; 1603 | sendp[0] = ','; 1604 | itoa(sendp, port); 1605 | getReply(send, 500); 1606 | 1607 | return; 1608 | 1609 | if (! HTTP_setup(url)) 1610 | 1611 | return false; 1612 | 1613 | // HTTP GET 1614 | if (! HTTP_action(FONA_HTTP_GET, status, datalen)) 1615 | return false; 1616 | 1617 | DEBUG_PRINT("Status: "); DEBUG_PRINTLN(*status); 1618 | DEBUG_PRINT("Len: "); DEBUG_PRINTLN(*datalen); 1619 | 1620 | // HTTP response data 1621 | if (! HTTP_readall(datalen)) 1622 | return false; 1623 | 1624 | return true; 1625 | } 1626 | */ 1627 | 1628 | void Adafruit_FONA::HTTP_GET_end(void) { 1629 | HTTP_term(); 1630 | } 1631 | 1632 | boolean Adafruit_FONA::HTTP_POST_start(char *url, 1633 | FONAFlashStringPtr contenttype, 1634 | const uint8_t *postdata, uint16_t postdatalen, 1635 | uint16_t *status, uint16_t *datalen){ 1636 | if (! HTTP_setup(url)) 1637 | return false; 1638 | 1639 | if (! HTTP_para(F("CONTENT"), contenttype)) { 1640 | return false; 1641 | } 1642 | 1643 | // HTTP POST data 1644 | if (! HTTP_data(postdatalen, 10000)) 1645 | return false; 1646 | mySerial->write(postdata, postdatalen); 1647 | if (! expectReply(ok_reply)) 1648 | return false; 1649 | 1650 | // HTTP POST 1651 | if (! HTTP_action(FONA_HTTP_POST, status, datalen)) 1652 | return false; 1653 | 1654 | DEBUG_PRINT(F("Status: ")); DEBUG_PRINTLN(*status); 1655 | DEBUG_PRINT(F("Len: ")); DEBUG_PRINTLN(*datalen); 1656 | 1657 | // HTTP response data 1658 | if (! HTTP_readall(datalen)) 1659 | return false; 1660 | 1661 | return true; 1662 | } 1663 | 1664 | void Adafruit_FONA::HTTP_POST_end(void) { 1665 | HTTP_term(); 1666 | } 1667 | 1668 | void Adafruit_FONA::setUserAgent(FONAFlashStringPtr useragent) { 1669 | this->useragent = useragent; 1670 | } 1671 | 1672 | void Adafruit_FONA::setHTTPSRedirect(boolean onoff) { 1673 | httpsredirect = onoff; 1674 | } 1675 | 1676 | /********* HTTP HELPERS ****************************************/ 1677 | 1678 | boolean Adafruit_FONA::HTTP_setup(char *url) { 1679 | // Handle any pending 1680 | HTTP_term(); 1681 | 1682 | // Initialize and set parameters 1683 | if (! HTTP_init()) 1684 | return false; 1685 | if (! HTTP_para(F("CID"), 1)) 1686 | return false; 1687 | if (! HTTP_para(F("UA"), useragent)) 1688 | return false; 1689 | if (! HTTP_para(F("URL"), url)) 1690 | return false; 1691 | 1692 | // HTTPS redirect 1693 | if (httpsredirect) { 1694 | if (! HTTP_para(F("REDIR"),1)) 1695 | return false; 1696 | 1697 | if (! HTTP_ssl(true)) 1698 | return false; 1699 | } 1700 | 1701 | return true; 1702 | } 1703 | 1704 | /********* HELPERS *********************************************/ 1705 | 1706 | boolean Adafruit_FONA::expectReply(FONAFlashStringPtr reply, 1707 | uint16_t timeout) { 1708 | readline(timeout); 1709 | 1710 | DEBUG_PRINT(F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1711 | 1712 | return (prog_char_strcmp(replybuffer, (prog_char*)reply) == 0); 1713 | } 1714 | 1715 | /********* LOW LEVEL *******************************************/ 1716 | 1717 | inline int Adafruit_FONA::available(void) { 1718 | return mySerial->available(); 1719 | } 1720 | 1721 | inline size_t Adafruit_FONA::write(uint8_t x) { 1722 | return mySerial->write(x); 1723 | } 1724 | 1725 | inline int Adafruit_FONA::read(void) { 1726 | return mySerial->read(); 1727 | } 1728 | 1729 | inline int Adafruit_FONA::peek(void) { 1730 | return mySerial->peek(); 1731 | } 1732 | 1733 | inline void Adafruit_FONA::flush() { 1734 | mySerial->flush(); 1735 | } 1736 | 1737 | void Adafruit_FONA::flushInput() { 1738 | // Read all available serial input to flush pending data. 1739 | uint16_t timeoutloop = 0; 1740 | while (timeoutloop++ < 40) { 1741 | while(available()) { 1742 | read(); 1743 | timeoutloop = 0; // If char was received reset the timer 1744 | } 1745 | delay(1); 1746 | } 1747 | } 1748 | 1749 | uint16_t Adafruit_FONA::readRaw(uint16_t b) { 1750 | uint16_t idx = 0; 1751 | 1752 | while (b && (idx < sizeof(replybuffer)-1)) { 1753 | if (mySerial->available()) { 1754 | replybuffer[idx] = mySerial->read(); 1755 | idx++; 1756 | b--; 1757 | } 1758 | } 1759 | replybuffer[idx] = 0; 1760 | 1761 | return idx; 1762 | } 1763 | 1764 | uint8_t Adafruit_FONA::readline(uint16_t timeout, boolean multiline) { 1765 | uint16_t replyidx = 0; 1766 | 1767 | while (timeout--) { 1768 | if (replyidx >= 254) { 1769 | //DEBUG_PRINTLN(F("SPACE")); 1770 | break; 1771 | } 1772 | 1773 | while(mySerial->available()) { 1774 | char c = mySerial->read(); 1775 | if (c == '\r') continue; 1776 | if (c == 0xA) { 1777 | if (replyidx == 0) // the first 0x0A is ignored 1778 | continue; 1779 | 1780 | if (!multiline) { 1781 | timeout = 0; // the second 0x0A is the end of the line 1782 | break; 1783 | } 1784 | } 1785 | replybuffer[replyidx] = c; 1786 | //DEBUG_PRINT(c, HEX); DEBUG_PRINT("#"); DEBUG_PRINTLN(c); 1787 | replyidx++; 1788 | } 1789 | 1790 | if (timeout == 0) { 1791 | //DEBUG_PRINTLN(F("TIMEOUT")); 1792 | break; 1793 | } 1794 | delay(1); 1795 | } 1796 | replybuffer[replyidx] = 0; // null term 1797 | return replyidx; 1798 | } 1799 | 1800 | uint8_t Adafruit_FONA::getReply(char *send, uint16_t timeout) { 1801 | flushInput(); 1802 | 1803 | 1804 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN(send); 1805 | 1806 | 1807 | mySerial->println(send); 1808 | 1809 | uint8_t l = readline(timeout); 1810 | 1811 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1812 | 1813 | return l; 1814 | } 1815 | 1816 | uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr send, uint16_t timeout) { 1817 | flushInput(); 1818 | 1819 | 1820 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINTLN(send); 1821 | 1822 | 1823 | mySerial->println(send); 1824 | 1825 | uint8_t l = readline(timeout); 1826 | 1827 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1828 | 1829 | return l; 1830 | } 1831 | 1832 | // Send prefix, suffix, and newline. Return response (and also set replybuffer with response). 1833 | uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, char *suffix, uint16_t timeout) { 1834 | flushInput(); 1835 | 1836 | 1837 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); DEBUG_PRINTLN(suffix); 1838 | 1839 | 1840 | mySerial->print(prefix); 1841 | mySerial->println(suffix); 1842 | 1843 | uint8_t l = readline(timeout); 1844 | 1845 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1846 | 1847 | return l; 1848 | } 1849 | 1850 | // Send prefix, suffix, and newline. Return response (and also set replybuffer with response). 1851 | uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, int32_t suffix, uint16_t timeout) { 1852 | flushInput(); 1853 | 1854 | 1855 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); DEBUG_PRINTLN(suffix, DEC); 1856 | 1857 | 1858 | mySerial->print(prefix); 1859 | mySerial->println(suffix, DEC); 1860 | 1861 | uint8_t l = readline(timeout); 1862 | 1863 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1864 | 1865 | return l; 1866 | } 1867 | 1868 | // Send prefix, suffix, suffix2, and newline. Return response (and also set replybuffer with response). 1869 | uint8_t Adafruit_FONA::getReply(FONAFlashStringPtr prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout) { 1870 | flushInput(); 1871 | 1872 | 1873 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); 1874 | DEBUG_PRINT(suffix1, DEC); DEBUG_PRINT(','); DEBUG_PRINTLN(suffix2, DEC); 1875 | 1876 | 1877 | mySerial->print(prefix); 1878 | mySerial->print(suffix1); 1879 | mySerial->print(','); 1880 | mySerial->println(suffix2, DEC); 1881 | 1882 | uint8_t l = readline(timeout); 1883 | 1884 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1885 | 1886 | return l; 1887 | } 1888 | 1889 | // Send prefix, ", suffix, ", and newline. Return response (and also set replybuffer with response). 1890 | uint8_t Adafruit_FONA::getReplyQuoted(FONAFlashStringPtr prefix, FONAFlashStringPtr suffix, uint16_t timeout) { 1891 | flushInput(); 1892 | 1893 | 1894 | DEBUG_PRINT(F("\t---> ")); DEBUG_PRINT(prefix); 1895 | DEBUG_PRINT('"'); DEBUG_PRINT(suffix); DEBUG_PRINTLN('"'); 1896 | 1897 | 1898 | mySerial->print(prefix); 1899 | mySerial->print('"'); 1900 | mySerial->print(suffix); 1901 | mySerial->println('"'); 1902 | 1903 | uint8_t l = readline(timeout); 1904 | 1905 | DEBUG_PRINT (F("\t<--- ")); DEBUG_PRINTLN(replybuffer); 1906 | 1907 | return l; 1908 | } 1909 | 1910 | boolean Adafruit_FONA::sendCheckReply(char *send, char *reply, uint16_t timeout) { 1911 | if (! getReply(send, timeout) ) 1912 | return false; 1913 | /* 1914 | for (uint8_t i=0; i