source: rtos_arduino/trunk/arduino_lib/libraries/GSM/src/GSM3SoftSerial.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 12.8 KB
RevLine 
[136]1/*
2This file is part of the GSM3 communications library for Arduino
3-- Multi-transport communications platform
4-- Fully asynchronous
5-- Includes code for the Arduino-Telefonica GSM/GPRS Shield V1
6-- Voice calls
7-- SMS
8-- TCP/IP connections
9-- HTTP basic clients
10
11This library has been developed by Telefónica Digital - PDI -
12- Physical Internet Lab, as part as its collaboration with
13Arduino and the Open Hardware Community.
14
15September-December 2012
16
17This library is free software; you can redistribute it and/or
18modify it under the terms of the GNU Lesser General Public
19License as published by the Free Software Foundation; either
20version 2.1 of the License, or (at your option) any later version.
21
22This library is distributed in the hope that it will be useful,
23but WITHOUT ANY WARRANTY; without even the implied warranty of
24MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25Lesser General Public License for more details.
26
27You should have received a copy of the GNU Lesser General Public
28License along with this library; if not, write to the Free Software
29Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30
31The latest version of this library can always be found at
32https://github.com/BlueVia/Official-Arduino
33*/
34#include "GSM3SoftSerial.h"
35#include "GSM3IO.h"
36#include <avr/interrupt.h>
37#include <avr/pgmspace.h>
38#include "pins_arduino.h"
39#include <HardwareSerial.h>
40#include <Arduino.h>
41
42#define __XON__ 0x11
43#define __XOFF__ 0x13
44
45#define _GSMSOFTSERIALFLAGS_ESCAPED_ 0x01
46#define _GSMSOFTSERIALFLAGS_SENTXOFF_ 0x02
47
48//
49// Lookup table
50//
51#define __PARAGRAPHGUARD__ 50
52typedef struct _DELAY_TABLE
53{
54 long baud;
55 unsigned short rx_delay_centering;
56 unsigned short rx_delay_intrabit;
57 unsigned short rx_delay_stopbit;
58 unsigned short tx_delay;
59} DELAY_TABLE;
60
61#if F_CPU == 16000000
62
63static const DELAY_TABLE PROGMEM table[] =
64{
65 // baud rxcenter rxintra rxstop tx
66 { 115200, 1, 17, 17, 12, },
67 { 57600, 10, 37, 37, 33, },
68 { 38400, 25, 57, 57, 54, },
69 { 31250, 31, 70, 70, 68, },
70 { 28800, 34, 77, 77, 74, },
71 { 19200, 54, 117, 117, 114, },
72 { 14400, 74, 156, 156, 153, },
73 { 9600, 114, 236, 236, 233, },
74 { 4800, 233, 474, 474, 471, },
75 { 2400, 471, 950, 950, 947, },
76 { 1200, 947, 1902, 1902, 1899, },
77 { 300, 3804, 7617, 7617, 7614, },
78};
79
80const int XMIT_START_ADJUSTMENT = 5;
81
82#elif F_CPU == 8000000
83
84static const DELAY_TABLE table[] PROGMEM =
85{
86 // baud rxcenter rxintra rxstop tx
87 { 115200, 1, 5, 5, 3, },
88 { 57600, 1, 15, 15, 13, },
89 { 38400, 2, 25, 26, 23, },
90 { 31250, 7, 32, 33, 29, },
91 { 28800, 11, 35, 35, 32, },
92 { 19200, 20, 55, 55, 52, },
93 { 14400, 30, 75, 75, 72, },
94 { 9600, 50, 114, 114, 112, },
95 { 4800, 110, 233, 233, 230, },
96 { 2400, 229, 472, 472, 469, },
97 { 1200, 467, 948, 948, 945, },
98 { 300, 1895, 3805, 3805, 3802, },
99};
100
101const int XMIT_START_ADJUSTMENT = 4;
102
103#elif F_CPU == 20000000
104
105// 20MHz support courtesy of the good people at macegr.com.
106// Thanks, Garrett!
107
108static const DELAY_TABLE PROGMEM table[] =
109{
110 // baud rxcenter rxintra rxstop tx
111 { 115200, 3, 21, 21, 18, },
112 { 57600, 20, 43, 43, 41, },
113 { 38400, 37, 73, 73, 70, },
114 { 31250, 45, 89, 89, 88, },
115 { 28800, 46, 98, 98, 95, },
116 { 19200, 71, 148, 148, 145, },
117 { 14400, 96, 197, 197, 194, },
118 { 9600, 146, 297, 297, 294, },
119 { 4800, 296, 595, 595, 592, },
120 { 2400, 592, 1189, 1189, 1186, },
121 { 1200, 1187, 2379, 2379, 2376, },
122 { 300, 4759, 9523, 9523, 9520, },
123};
124
125const int XMIT_START_ADJUSTMENT = 6;
126
127#else
128
129#error This version of GSM3SoftSerial supports only 20, 16 and 8MHz processors
130
131#endif
132
133GSM3SoftSerial* GSM3SoftSerial::_activeObject=0;
134
135GSM3SoftSerial::GSM3SoftSerial():
136 _rx_delay_centering(0),
137 _rx_delay_intrabit(0),
138 _rx_delay_stopbit(0),
139 _tx_delay(0),
140 cb(this)
141{
142 setTX();
143 setRX();
144 //comStatus=0;
145 //waitingAnswer=false;
146}
147
148int GSM3SoftSerial::begin(long speed)
149{
150 _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
151
152 for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i)
153 {
154 long baud = pgm_read_dword(&table[i].baud);
155 if (baud == speed)
156 {
157 _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
158 _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
159 _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
160 _tx_delay = pgm_read_word(&table[i].tx_delay);
161 break;
162 }
163 }
164
165 if (_rx_delay_stopbit)
166 {
167 if (digitalPinToPCICR(__RXPIN__))
168 {
169 *digitalPinToPCICR(__RXPIN__) |= _BV(digitalPinToPCICRbit(__RXPIN__));
170 *digitalPinToPCMSK(__RXPIN__) |= _BV(digitalPinToPCMSKbit(__RXPIN__));
171 }
172 tunedDelay(_tx_delay); // if we were low this establishes the end
173 }
174
175 _activeObject=this;
176
177}
178
179void GSM3SoftSerial::close()
180 {
181 _activeObject=0;
182 }
183
184size_t GSM3SoftSerial::write(uint8_t c)
185{
186 if (_tx_delay == 0)
187 return 0;
188
189 // Characters to be escaped under XON/XOFF control with Quectel
190 if(c==0x11)
191 {
192 this->finalWrite(0x77);
193 return this->finalWrite(0xEE);
194 }
195
196 if(c==0x13)
197 {
198 this->finalWrite(0x77);
199 return this->finalWrite(0xEC);
200 }
201
202 if(c==0x77)
203 {
204 this->finalWrite(0x77);
205 return this->finalWrite(0x88);
206 }
207
208 return this->finalWrite(c);
209}
210
211size_t GSM3SoftSerial::finalWrite(uint8_t c)
212{
213
214 uint8_t oldSREG = SREG;
215 cli(); // turn off interrupts for a clean txmit
216
217 // Write the start bit
218 tx_pin_write(LOW);
219 tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
220
221 // Write each of the 8 bits
222 for (byte mask = 0x01; mask; mask <<= 1)
223 {
224 if (c & mask) // choose bit
225 tx_pin_write(HIGH); // send 1
226 else
227 tx_pin_write(LOW); // send 0
228 tunedDelay(_tx_delay);
229 }
230
231 tx_pin_write(HIGH); // restore pin to natural state
232
233 SREG = oldSREG; // turn interrupts back on
234 tunedDelay(_tx_delay);
235
236 return 1;
237}
238
239/*inline*/ void GSM3SoftSerial::tunedDelay(uint16_t delay) {
240 uint8_t tmp=0;
241
242 asm volatile("sbiw %0, 0x01 \n\t"
243 "ldi %1, 0xFF \n\t"
244 "cpi %A0, 0xFF \n\t"
245 "cpc %B0, %1 \n\t"
246 "brne .-10 \n\t"
247 : "+r" (delay), "+a" (tmp)
248 : "0" (delay)
249 );
250}
251
252void GSM3SoftSerial::tx_pin_write(uint8_t pin_state)
253{
254 // Direct port manipulation is faster than digitalWrite/Read
255 if (pin_state == LOW)
256 *_transmitPortRegister &= ~_transmitBitMask;
257 else
258 *_transmitPortRegister |= _transmitBitMask;
259}
260
261void GSM3SoftSerial::setTX()
262{
263 pinMode(__TXPIN__, OUTPUT);
264 digitalWrite(__TXPIN__, HIGH);
265 // For digital port direct manipulation
266 _transmitBitMask = digitalPinToBitMask(__TXPIN__);
267 uint8_t port = digitalPinToPort(__TXPIN__);
268 _transmitPortRegister = portOutputRegister(port);
269}
270
271void GSM3SoftSerial::setRX()
272{
273 pinMode(__RXPIN__, INPUT);
274 digitalWrite(__RXPIN__, HIGH); // pullup for normal logic!
275 // For digital port direct manipulation
276 _receiveBitMask = digitalPinToBitMask(__RXPIN__);
277 uint8_t port = digitalPinToPort(__RXPIN__);
278 _receivePortRegister = portInputRegister(port);
279
280#ifdef __AVR_ATmega32U4__
281//#define __RXINT__ 1
282 attachInterrupt(__RXINT__, GSM3SoftSerial::handle_interrupt, FALLING);
283#endif
284 // This line comes from the High Middle Ages...
285 // attachInterrupt(__RXINT__, GSM3SoftSerial::handle_interrupt, FALLING);
286}
287
288void GSM3SoftSerial::handle_interrupt()
289{
290 if(_activeObject)
291 _activeObject->recv();
292}
293
294uint8_t GSM3SoftSerial::rx_pin_read()
295{
296 // Digital port manipulation
297 return *_receivePortRegister & _receiveBitMask;
298}
299
300void GSM3SoftSerial::recv()
301{
302
303#if GCC_VERSION < 40302
304// Work-around for avr-gcc 4.3.0 OSX version bug
305// Preserve the registers that the compiler misses
306// (courtesy of Arduino forum user *etracer*)
307 asm volatile(
308 "push r18 \n\t"
309 "push r19 \n\t"
310 "push r20 \n\t"
311 "push r21 \n\t"
312 "push r22 \n\t"
313 "push r23 \n\t"
314 "push r26 \n\t"
315 "push r27 \n\t"
316 ::);
317#endif
318
319 bool firstByte=true;
320 byte thisHead;
321
322 uint8_t d = 0;
323 bool morebytes=false;
324 //bool fullbuffer=(cb.availableBytes()<3);
325 bool fullbuffer;
326 bool capturado_fullbuffer = 0;
327 int i;
328 byte oldTail;
329
330 // If RX line is high, then we don't see any start bit
331 // so interrupt is probably not for us
332 if (!rx_pin_read())
333 {
334 do
335 {
336 oldTail=cb.getTail();
337 // Wait approximately 1/2 of a bit width to "center" the sample
338 tunedDelay(_rx_delay_centering);
339
340 fullbuffer=(cb.availableBytes()<6);
341
342
343 if(fullbuffer&&(!capturado_fullbuffer))
344 tx_pin_write(LOW);
345
346
347 // Read each of the 8 bits
348 for (uint8_t i=0x1; i; i <<= 1)
349 {
350 tunedDelay(_rx_delay_intrabit);
351 uint8_t noti = ~i;
352 if (rx_pin_read())
353 d |= i;
354 else // else clause added to ensure function timing is ~balanced
355 d &= noti;
356
357 if(fullbuffer&&(!capturado_fullbuffer))
358 {
359 if((uint8_t)__XOFF__ & i)
360 tx_pin_write(HIGH);
361 else
362 tx_pin_write(LOW);
363 }
364 }
365
366 if(fullbuffer&&(!capturado_fullbuffer))
367 {
368 tunedDelay(_rx_delay_intrabit);
369 tx_pin_write(HIGH);
370 }
371
372 // So, we know the buffer is full, and we have sent a XOFF
373 if (fullbuffer)
374 {
375 capturado_fullbuffer =1;
376 _flags |=_GSMSOFTSERIALFLAGS_SENTXOFF_;
377 }
378
379
380 // skip the stop bit
381 if (!fullbuffer) tunedDelay(_rx_delay_stopbit);
382
383 if(keepThisChar(&d))
384 {
385 cb.write(d);
386 if(firstByte)
387 {
388 firstByte=false;
389 thisHead=cb.getTail();
390 }
391 }
392
393
394 // This part is new. It is used to detect the end of a "paragraph"
395 // Caveat: the old fashion would let processor a bit of time between bytes,
396 // that here is lost
397 // This active waiting avoids drifting
398 morebytes=false;
399 // TO-DO. This PARAGRAPHGUARD is empyric. We should test it for every speed
400 for(i=0;i<__PARAGRAPHGUARD__;i++)
401 {
402 tunedDelay(1);
403 if(!rx_pin_read())
404 {
405 morebytes=true;
406 break;
407 }
408 }
409 }while(morebytes);
410 // If we find a line feed, we are at the end of a paragraph
411 // check!
412
413 if (fullbuffer)
414 {
415 // And... go handle it!
416 if(mgr)
417 mgr->manageMsg(thisHead, cb.getTail());
418 }
419 else if(d==10)
420 {
421 // And... go handle it!
422 if(mgr)
423 mgr->manageMsg(thisHead, cb.getTail());
424 }
425 else if (d==32)
426 {
427 // And... go handle it!
428 if(mgr)
429 mgr->manageMsg(thisHead, cb.getTail());
430 }
431 }
432
433#if GCC_VERSION < 40302
434// Work-around for avr-gcc 4.3.0 OSX version bug
435// Restore the registers that the compiler misses
436 asm volatile(
437 "pop r27 \n\t"
438 "pop r26 \n\t"
439 "pop r23 \n\t"
440 "pop r22 \n\t"
441 "pop r21 \n\t"
442 "pop r20 \n\t"
443 "pop r19 \n\t"
444 "pop r18 \n\t"
445 ::);
446#endif
447}
448
449bool GSM3SoftSerial::keepThisChar(uint8_t* c)
450{
451 // Horrible things for Quectel XON/XOFF
452 // 255 is the answer to a XOFF
453 // It comes just once
454 if((*c==255)&&(_flags & _GSMSOFTSERIALFLAGS_SENTXOFF_))
455 {
456 _flags ^= _GSMSOFTSERIALFLAGS_SENTXOFF_;
457 return false;
458 }
459
460 // 0x77, w, is the escape character
461 if(*c==0x77)
462 {
463 _flags |= _GSMSOFTSERIALFLAGS_ESCAPED_;
464 return false;
465 }
466
467 // and these are the escaped codes
468 if(_flags & _GSMSOFTSERIALFLAGS_ESCAPED_)
469 {
470 if(*c==0xEE)
471 *c=0x11;
472 else if(*c==0xEC)
473 *c=0x13;
474 else if(*c==0x88)
475 *c=0x77;
476
477 _flags ^= _GSMSOFTSERIALFLAGS_ESCAPED_;
478 return true;
479 }
480
481 return true;
482}
483
484void GSM3SoftSerial::spaceAvailable()
485{
486 // If there is spaceAvailable in the buffer, lets send a XON
487 finalWrite((byte)__XON__);
488}
489
490
491// This is here to avoid problems with Arduino compiler
492void GSM3SoftSerialMgr::manageMsg(byte from, byte to){};
493
494//#define PCINT1_vect _VECTOR(2)
495//#undef PCINT1_vect
496
497#if defined(PCINT0_vect)
498ISR(PCINT0_vect)
499{
500 GSM3SoftSerial::handle_interrupt();
501}
502#endif
503
504#if defined(PCINT1_vect)
505ISR(PCINT1_vect)
506{
507 GSM3SoftSerial::handle_interrupt();
508}
509#endif
510
511#if defined(PCINT2_vect)
512ISR(PCINT2_vect)
513{
514 GSM3SoftSerial::handle_interrupt();
515}
516#endif
517
518#if defined(PCINT3_vect)
519ISR(PCINT3_vect)
520{
521 GSM3SoftSerial::handle_interrupt();
522}
523#endif
524
Note: See TracBrowser for help on using the repository browser.