-
Notifications
You must be signed in to change notification settings - Fork 5
/
POST_S76G.ino
400 lines (308 loc) · 10.4 KB
/
POST_S76G.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
/*
* POST_S76G(.ino) firmware
* Copyright (C) 2019-2021 Linar Yusupov
*
* Author: Linar Yusupov, [email protected]
*
* Web: http:/lyusupov/SoftRF
*
* Credits:
* Arduino Core for STM32 is developed by Frederic Pillon
* U8g2 monochrome LCD, OLED and eInk library is developed by Oliver Kraus
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wire.h>
#include <SPI.h>
#include <U8x8lib.h>
#define SX1276_RegVersion 0x42
#define SSD1306_OLED_I2C_ADDR 0x3C
#define BMP085_I2CADDR 0x77
#define BMP280_ADDRESS 0x77
#define BMP280_ADDRESS_ALT 0x76 /* GY-91, SA0 is NC */
#define ICM20948_ADDRESS 0x69
#define BMP280_REGISTER_CHIPID 0xD0
#define BMP280_CHIPID (0x58)
#define BME280_CHIPID (0x60)
#if !defined(USBD_USE_CDC) || defined(DISABLE_GENERIC_SERIALUSB)
#define Serial Serial1
#endif
/* Peripherals */
#define SOC_GPIO_PIN_CONS_RX PA10
#define SOC_GPIO_PIN_CONS_TX PA9
#define SOC_GPIO_PIN_GNSS_RX PC11
#define SOC_GPIO_PIN_GNSS_TX PC10
#define SOC_GPIO_PIN_GNSS_RST PB2
#define SOC_GPIO_PIN_GNSS_LS PC6
#define SOC_GPIO_PIN_GNSS_PPS PB5
/* SPI0 */
#define SOC_GPIO_PIN_MOSI PB15
#define SOC_GPIO_PIN_MISO PB14
#define SOC_GPIO_PIN_SCK PB13
#define SOC_GPIO_PIN_SS PB12
/* SX1276 */
#define SOC_GPIO_PIN_RST PB10
#define SOC_GPIO_PIN_DIO0 PB11
#define SOC_GPIO_PIN_DIO1 PC13
#define SOC_GPIO_PIN_DIO2 PB9
#define SOC_GPIO_PIN_DIO3 PB4
#define SOC_GPIO_PIN_DIO4 PB3
#define SOC_GPIO_PIN_DIO5 PA15
/* RF antenna switch */
#define SOC_GPIO_PIN_ANT_RXTX PA1 // 1:Rx, 0:Tx
/* I2C */
#define SOC_GPIO_PIN_SDA PB7
#define SOC_GPIO_PIN_SCL PB6
#define TTGO_TIMPULSE_OLED_PIN_RST PA8
#define TTGO_TIMPULSE_GPIO_PAD_OUT PA0
#define TTGO_TIMPULSE_GPIO_PAD_PWR PA2
#define TTGO_TIMPULSE_SENSOR_INT PB1
#define TTGO_TIMPULSE_GPIO_CHRG PB8
#define TTGO_TIMPULSE_VDD_1V8_EN PB0
#define TTGO_TIMPULSE_GPS_PWR_EN PA3
/* button */
#define SOC_GPIO_PIN_BUTTON TTGO_TIMPULSE_GPIO_PAD_OUT
#define GNSS_BAUD_RATE 115200
HardwareSerial Serial1(SOC_GPIO_PIN_CONS_RX, SOC_GPIO_PIN_CONS_TX);
HardwareSerial Serial3(SOC_GPIO_PIN_GNSS_RX, SOC_GPIO_PIN_GNSS_TX);
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8_i2c(U8X8_PIN_NONE);
static U8X8_SSD1306_128X64_NONAME_HW_I2C *u8x8 = NULL;
const char SoftRF_text1[] = "SoftRF";
const char SoftRF_text2[] = "and";
const char SoftRF_text3[] = "LilyGO";
static boolean GNSS_probe() {
unsigned long startTime = millis();
char c1, c2;
c1 = c2 = 0;
// clean any leftovers
Serial3.flush();
// Timeout if no valid response in 3 seconds
while (millis() - startTime < 3000) {
if (Serial3.available() > 0) {
c1 = Serial3.read();
if ((c1 == '$') && (c2 == 0)) { c2 = c1; continue; }
if ((c2 == '$') && (c1 == 'G')) {
/* got $G */
/* leave the function with GNSS port opened */
return true;
} else {
c2 = 0;
}
}
delay(1);
}
return false;
}
static bool bmp_probe()
{
#if 1
Wire.beginTransmission(BMP280_ADDRESS);
if (Wire.endTransmission() == 0) return true;
Wire.beginTransmission(BMP280_ADDRESS_ALT);
if (Wire.endTransmission() == 0) return true;
#else
Wire.beginTransmission(BMP280_ADDRESS);
Wire.write(BMP280_REGISTER_CHIPID);
Wire.endTransmission();
Wire.requestFrom(BMP280_ADDRESS, (byte)1);
if (Wire.read() == BMP280_CHIPID) return true;
Wire.beginTransmission(BMP280_ADDRESS_ALT);
Wire.write(BMP280_REGISTER_CHIPID);
Wire.endTransmission();
Wire.requestFrom(BMP280_ADDRESS_ALT, (byte)1);
if (Wire.read() == BMP280_CHIPID) return true;
Wire.beginTransmission(BMP280_ADDRESS);
Wire.write(BMP280_REGISTER_CHIPID);
Wire.endTransmission();
Wire.requestFrom(BMP280_ADDRESS, (byte)1);
if (Wire.read() == BME280_CHIPID) return true;
Wire.beginTransmission(BMP280_ADDRESS_ALT);
Wire.write(BMP280_REGISTER_CHIPID);
Wire.endTransmission();
Wire.requestFrom(BMP280_ADDRESS_ALT, (byte)1);
if (Wire.read() == BME280_CHIPID) return true;
#endif
return false;
}
static bool imu_probe()
{
Wire.beginTransmission(ICM20948_ADDRESS);
if (Wire.endTransmission() == 0) return true;
return false;
}
void setup() {
bool has_SX1276 = false;
bool has_GNSS = false;
bool has_OLED = false;
bool has_BMP280 = false;
bool has_IMU = false;
Serial.begin(115200);
#if defined(USBD_USE_CDC) && !defined(DISABLE_GENERIC_SERIALUSB)
/* Let host's USB and console drivers to warm-up */
delay(2000);
#else
delay(500);
#endif
pinMode(TTGO_TIMPULSE_VDD_1V8_EN, INPUT_PULLUP);
delay(150);
pinMode(TTGO_TIMPULSE_GPS_PWR_EN, INPUT_PULLUP);
delay(50);
Wire.setSCL(SOC_GPIO_PIN_SCL);
Wire.setSDA(SOC_GPIO_PIN_SDA);
Wire.begin();
has_IMU = imu_probe();
if (has_IMU) {
pinMode(TTGO_TIMPULSE_GPIO_PAD_PWR, INPUT_PULLUP);
pinMode(TTGO_TIMPULSE_OLED_PIN_RST, INPUT_PULLDOWN);
delay(200);
pinMode(TTGO_TIMPULSE_OLED_PIN_RST, INPUT_PULLUP);
pinMode(TTGO_TIMPULSE_SENSOR_INT, INPUT);
} else {
pinMode(TTGO_TIMPULSE_VDD_1V8_EN, INPUT_ANALOG);
pinMode(TTGO_TIMPULSE_GPS_PWR_EN, INPUT_ANALOG);
}
Serial.println();
Serial.print(F("TTGO "));
Serial.print(has_IMU ? F("T-Impulse") : F("T-Motion"));
Serial.println(F(" (S76G) Power-on Self Test"));
Serial.println();
Serial.flush();
/* SSD1306 I2C OLED probing */
Wire.beginTransmission(SSD1306_OLED_I2C_ADDR);
has_OLED = (Wire.endTransmission() == 0 ? true : false);
if (has_OLED) {
u8x8 = &u8x8_i2c;
}
if (u8x8) {
u8x8->begin();
u8x8->setFont(u8x8_font_chroma48medium8_r);
if (has_IMU) {
u8x8->draw2x2Glyph(4, 4, SoftRF_text3[0]);
u8x8->draw2x2Glyph(6, 4, SoftRF_text3[1]);
u8x8->draw2x2Glyph(8, 4, SoftRF_text3[2]);
u8x8->draw2x2Glyph(10, 4, SoftRF_text3[3]);
u8x8->draw2x2Glyph(6, 6, SoftRF_text3[4]);
u8x8->draw2x2Glyph(8, 6, SoftRF_text3[5]);
delay(2000);
u8x8->clear();
u8x8->draw2x2String( 5, 5, SoftRF_text2);
delay(2000);
u8x8->clear();
u8x8->draw2x2Glyph(4, 4, SoftRF_text1[0]);
u8x8->draw2x2Glyph(6, 4, SoftRF_text1[1]);
u8x8->draw2x2Glyph(8, 4, SoftRF_text1[2]);
u8x8->draw2x2Glyph(10, 4, SoftRF_text1[3]);
u8x8->draw2x2Glyph(6, 6, SoftRF_text1[4]);
u8x8->draw2x2Glyph(8, 6, SoftRF_text1[5]);
} else {
u8x8->draw2x2String(2, 1, SoftRF_text1);
u8x8->drawString (6, 4, SoftRF_text2);
u8x8->draw2x2String(2, 6, SoftRF_text3);
}
delay(3000);
}
SPI.setMISO(SOC_GPIO_PIN_MISO);
SPI.setMOSI(SOC_GPIO_PIN_MOSI);
SPI.setSCLK(SOC_GPIO_PIN_SCK);
SPI.begin();
digitalWrite(SOC_GPIO_PIN_SS, HIGH);
pinMode(SOC_GPIO_PIN_SS, OUTPUT);
digitalWrite(SOC_GPIO_PIN_RST, HIGH);
pinMode(SOC_GPIO_PIN_RST, OUTPUT);
// manually reset radio
digitalWrite(SOC_GPIO_PIN_RST, LOW); // drive RST pin low
delay(5);
digitalWrite(SOC_GPIO_PIN_RST, HIGH); // drive RST pin high
delay(5);
digitalWrite(SOC_GPIO_PIN_SS, LOW);
SPI.transfer(SX1276_RegVersion & 0x7F);
uint8_t r_ver = SPI.transfer(0x00);
has_SX1276 = (r_ver == 0x12 || r_ver == 0x13);
digitalWrite(SOC_GPIO_PIN_SS, HIGH);
SPI.end();
pinMode(SOC_GPIO_PIN_SS, INPUT);
pinMode(SOC_GPIO_PIN_RST, INPUT);
Serial.println(F("Built-in components:"));
Serial.print(F("RADIO - ")); Serial.println(has_SX1276 ? F("PASS") : F("FAIL"));
if (u8x8) {
u8x8->clear();
if (has_IMU) {
u8x8->draw2x2Glyph( 4, 4, 'R');
u8x8->draw2x2Glyph( 6, 4, has_SX1276 ? '+' : '-');
} else {
u8x8->draw2x2String( 0, 0, "RADIO");
u8x8->draw2x2String(14, 0, has_SX1276 ? "+" : "-");
}
}
Serial3.begin(GNSS_BAUD_RATE);
/* drive GNSS RST pin low */
pinMode(SOC_GPIO_PIN_GNSS_RST, OUTPUT);
digitalWrite(SOC_GPIO_PIN_GNSS_RST, LOW);
/* activate 1.8V<->3.3V level shifters */
pinMode(SOC_GPIO_PIN_GNSS_LS, OUTPUT);
digitalWrite(SOC_GPIO_PIN_GNSS_LS, HIGH);
/* keep RST low to ensure proper IC reset */
delay(200);
/* release */
digitalWrite(SOC_GPIO_PIN_GNSS_RST, HIGH);
/* give Sony GNSS few ms to warm up */
delay(100);
/* hot start */
Serial3.write("@GSR\r\n"); delay(250);
has_GNSS = GNSS_probe();
Serial.print(F("GNSS - ")); Serial.println(has_GNSS ? F("PASS") : F("FAIL"));
if (u8x8) {
if (has_IMU) {
u8x8->draw2x2Glyph( 8, 4, 'G');
u8x8->draw2x2Glyph( 10, 4, has_GNSS ? '+' : '-');
} else {
u8x8->draw2x2String( 0, 2, "GNSS");
u8x8->draw2x2String(14, 2, has_GNSS ? "+" : "-");
}
}
if (!has_IMU) {
Serial.println();
Serial.println(F("External components:"));
}
Serial.print(F("OLED - ")); Serial.println(has_OLED ? F("PASS") : F("FAIL"));
if (u8x8) {
if (has_IMU) {
u8x8->draw2x2Glyph(4, 6, 'O');
u8x8->draw2x2Glyph(6, 6, has_OLED ? '+' : '-');
} else {
u8x8->draw2x2String( 0, 4, "OLED");
u8x8->draw2x2String(14, 4, has_OLED ? "+" : "-");
}
}
if (has_IMU) {
Serial.print(F("IMU - ")); Serial.println(has_IMU ? F("PASS") : F("FAIL"));
} else {
has_BMP280 = bmp_probe();
Serial.print(F("BMx280 - ")); Serial.println(has_BMP280 ? F("PASS") : F("FAIL"));
}
if (u8x8) {
if (has_IMU) {
u8x8->draw2x2Glyph( 8, 6, 'I');
u8x8->draw2x2Glyph( 10, 6, has_IMU ? '+' : '-');
} else {
u8x8->draw2x2String( 0, 6, "BMx280");
u8x8->draw2x2String(14, 6, has_BMP280 ? "+" : "-");
}
}
Wire.end();
Serial.println();
Serial.println(F("POST is completed."));
}
void loop() {
}