# SFBSerial.h

Go to the documentation of this file.

    00001 /*                                       -*- mode:C++; fill-column: 100 -*-
    00002   SFBSerial.h - 'Platform-independent' serial port support
    00003   Copyright (C) 2008 The Regents of the University of New Mexico.  All rights reserved.
    00004
    00005   This library is free software; you can redistribute it and/or
    00006   modify it under the terms of the GNU Lesser General Public
    00007   License as published by the Free Software Foundation; either
    00008   version 2.1 of the License, or (at your option) any later version.
    00009
    00010   This library is distributed in the hope that it will be useful,
    00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013   Lesser General Public License for more details.
    00014
    00015   You should have received a copy of the GNU General Public License
    00016   along with this library; if not, write to the Free Software
    00017   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
    00018   USA
    00019
    00020   $Id$
    00021 */
    00022
    00029 #ifndef SFBSERIAL_H
    00030 #define SFBSERIAL_H
    00031
    00032 #include "SFBConstants.h"       /* For FACE_COUNT */
    00033 #include "SFBAlarm.h"           /* For SFBAlarmIndexType */
    00034 #include "SFBReactor.h"         /* For PacketHandler, DispatchHandler, Body */
    00035 #include "SFBHWSerial.h"        /* For hardware-specific serial support */
    00036 #include "SFBPrint.h"           /* For facePrint* */
    00037
    00045 enum StandardBaudRateCodes {
    00046   SFBAUD300 = 0,
    00047   SFBAUD1200 = 1,
    00048   SFBAUD9600 = 2,
    00049   SFBAUD57600 = 3,
    00050   SFBAUD115200 = 4,
    00051   SFBAUD230400 = 5,
    00052   SFBAUD500000 = 6,
    00053   SFBAUD1000000 = 7,
    00054   SFBAUD2000000 = 8,
    00055   SFBAUD3000000 = 9,
    00056
    00057   SFBAUD_RENDEZVOUS = 2
    00058
    00059
    00060
    00061
    00062
    00063 };
    00064
    00074 extern int getStandardBaudCode(u32 baudCodeOrRate) ;
    00075
    00084 extern u32 getStandardBaudRate(u32 baudCode) ;
    00085
    00092 class SFBSerial {
    00093
    00094 public:
    00095
    00098   void begin() ;
    00099
    00100   void begin(u32 baud, bool manual = true) ;
    00101
    00102   void reserve() ;              /* The endless, hideous print routines.. */
    00109   void print(const char * str) {         facePrint(face,str); }
    00110
    00112   void print(const u8 * str, u32 len) {  facePrint(face,str,len); }
    00113
    00115   void print(int decimal) {              facePrint(face,decimal); }
    00116
    00118   void print(unsigned int decimal) {     facePrint(face,decimal); }
    00119
    00121   void print(long decimal) {             facePrint(face,decimal); }
    00122
    00124   void print(unsigned long decimal) {    facePrint(face,decimal); }
    00125
    00127   void print(long decimal, int code) {   facePrint(face,decimal,code); }
    00128
    00130   void print(double val) {               facePrint(face,val); }
    00131
    00133   void println() {                       facePrintln(face); }
    00134
    00136   void println(const char * str) {       facePrintln(face,str); }
    00137
    00139   void println(const u8 * str, u32 len) {facePrintln(face,str,len); }
    00140
    00142   void println(int decimal) {            facePrintln(face,decimal); }
    00143
    00145   void println(unsigned int decimal) {   facePrintln(face,decimal); }
    00146
    00148   void println(long decimal) {           facePrintln(face,decimal); }
    00149
    00151   void println(unsigned long decimal) {  facePrintln(face,decimal); }
    00152
    00154   void println(long decimal, int code) { facePrintln(face,decimal,code); }
    00155
    00157   void println(double val) {             facePrintln(face,val); }
    00158
    00160   void printlnCheckByte() ;
    00165   bool isInUse() ;
    00166
    00167   bool isManualMode() ;
    00168
    00169   bool isReflexMode() ;
    00170
    00171   bool isConsciousMode() ;
    00172
    00173   void switchToBlocking() ;
    00174
    00175   u32 getBaud() { return baud; }
    00176
    00177   bool getOddParity() { return flags&FLAG_ODD_PARITY; }
    00178
    00179   u32 getFace() { return face; }
    00180
    00196   bool ready() ;
    00197
    00198   u32 inputPackets() ;
    00199   u32 outputPackets() ;
    00200
    00206   SFBHWSerial & getHWSerial() { return hwSerial; }
    00207
    00213   bool backgroundProcessingActive() ;
    00214
    00219
    00228   bool available() ;
    00229
    00240   int read();
    00241
    00256   int peek();
    00257
    00262
    00281   u8 * readPacket();
    00282
    00287
    00288   void setPreferredBaudCode(u8 code, bool renegotiateNow = false) ;
    00289
    00290   bool dispatch(DispatchHandler dispatcher = 0, u32 maxPackets = 1) ;
    00291
    00292   void suppress(const char type) ;
    00293   void allow(const char type) ;
    00294
    00295   void reflex(const char type, PacketHandler pfunc) ;
    00296
    00297   void otherwise(PacketHandler pfunc) ;
    00298
    00303
    00313   void putcInterrupt(u8 byte) ;
    00314
    00324   void terpriInterrupt() ;
    00325
    00335   void putcBlocking(u8 byte) ;
    00336
    00345   void terpriBlocking() ;
    00346
    00347   void write(u8 byte) { lowPutc(byte); }
    00348   void write(const char * str) { print(str); }
    00349   void write(u8 * buf, u32 len) { print(buf,len); }
    00350
    00358   void flush() ;
    00359
    00360   SFBSerial(int face) ;
    00361
    00362
    00369   static void startup_initialization() ;
    00370
    00373   //XXX
    00374 private:
    00375
    00376   /* Low-level internal routines so BRN routines can talk before BRN is complete.. */
    00377   void lowPrint(const char * str) ;
    00378   void lowPrintln(const char * str) ;
    00379   void lowPutc(const u8 byte) ;
    00380   void lowTerpri() ;
    00381   void lowPrintOurBRO() ;        /* Print our current baud rate offer */
    00382
    00383   void maybeBlockForOutput() ;  /* Block until output space available, if we're FLAG_BLOCKING */
    00384
    00385   static PacketBuffer sharedBuffer;
    00386
    00387   SFBHWSerial hwSerial;        /* Platform-specific state and methods */
    00388
    00389   u32 baud;
    00390   u32 nextTimeout;             /* when we're next to act */
    00391   SFBAlarmIndexType alarmNumber; /* Our alarm number, if != 0 */
    00392   const u8 face;
    00393   u8 flags;
    00394   u8 state;                    /* Current state in BRN state machine */
    00395   u8 preferredCode;            /* Our current preferred baud rate code */
    00396   u8 selectedCode;             /* negotiated baud rate code */
    00397   bool selectedOdd;            /* negotiated odd parity (else none) */
    00398   bool haveBufferedByte;       /* for ::available() */
    00399   u8 bufferedByte;
    00400   enum {
    00401     STATE_RESET,                /* 0 Entered to send a reset packet */
    00402     STATE_INIT,                 /* 1 Initial state */
    00403     STATE_LISTEN,               /* 2 Sending/waiting for SIM */
    00404     STATE_OFFER,                /* 3 Sent/waiting for SB */
    00405     STATE_CONFIRM,              /* 4 Sent/waiting for SS */
    00406     STATE_WAIT,                 /* 5 Delay after baud changed */
    00407     STATE_DONE,                 /* 6 BRN finished */
    00408     STATE_SHOWTIME,             /* 7 Queueing and dispatching packets */
    00409     STATE_CHECKIN,              /* 8 SRU sent to request SIM */
    00410     MAX_STATES
    00411   };
    00412
    00413   enum {
    00414     FLAG_RUNNING =   0x01,     /* Port is in use (on our side.  This doesn't imply a live connection.) */
    00415     FLAG_ODD_PARITY= 0x02,     /* Port is using odd parity (vs no parity) */
    00416     FLAG_CONSCIOUS = 0x04,     /* Port is under conscious control - no BRN or bkgd packets will be sent */
    00417     FLAG_BRN_DONE  = 0x08,     /* Baud rate negotiation has succeeded or is under conscious control */
    00418     FLAG_BLOCKING_BYTES= 0x10, /* Port is running in byte-by-byte mode, with blocking output */
    00419     FLAG_GPIOS     = 0x20,     /* Port pins are in use as non-UART pins, we can't touch them */
    00420     FLAG_CONNECTED = 0x40,     /* We have received data lately on this face; there's something out there */
    00421     FLAG_RSRVD8    = 0x80      /* Reserved */
    00422   };
    00423
    00424   void start(u32 baud, u8 startFlags) ;
    00425
    00426   void stop() ;
    00427
    00428   void setBaudRate(u32 baud, bool isOddParity = false) ;
    00429
    00430   void setOddParity(bool isOdd) {
    00431     if (isOdd) flags |= FLAG_ODD_PARITY;
    00432     else flags &= ~FLAG_ODD_PARITY;
    00433   }
    00434
    00435   typedef void (*InitHandler)(u8 face);
    00436   static const char backgroundProcessorTypes[];
    00437   static const PacketHandler backgroundProcessorHandlers[];
    00438   static const InitHandler backgroundProcessorInits[];
    00439
    00440   void backgroundProcessingInit() ;
    00441
    00442   static void stateTimeout(u32 when, void * arg) ;
    00443
    00444   void step(u32 when, u8 * spacket) ; /* Step the state machine.  spacket==0 means timeout occurred */
    00445
    00446   bool stepInit(u32 when, u8 * spacket) ; /* step in state INIT */
    00447   bool stepListen(u32 when, u8 * spacket) ; /* step in state LISTEN */
    00448   bool stepOffer(u32 when, u8 * spacket) ; /* step in state OFFER */
    00449   bool stepConfirm(u32 when, u8 * spacket) ; /* step in state CONFIRM */
    00450   bool stepWait(u32 when, u8 * spacket) ; /* step in state WAIT */
    00451   bool stepDone(u32 when, u8 * spacket) ; /* step in state DONE */
    00452   bool stepShowtime(u32 when, u8 * spacket) ; /* step in state SHOWTIME */
    00453   bool stepCheckin(u32 when, u8 * spacket) ; /* step in state CHECKIN */
    00454
    00455   void setState(u8 newState, u32 aboutHowManyMs) ;
    00456
    00457   static void ppacketDispatcher(u8 * packet) ;
    00458
    00459   static void rpacketDispatcher(u8 * packet) ;
    00460
    00461   static void spacketDispatcher(u8 * packet) ;
    00462   static void spacketInit(u8 face) ;
    00463
    00464 };
    00465
    00466 /* The one-time serial startup code */
    00467 extern void serial_startup_initialization() ;
    00468
    00469 /* Some utility functions for packet handling */
    00470 extern bool zPacketPrefix(u8 * p1, const char * to) ;
    00471 extern bool packetPrefix(u8 * p1, const u8 * to, const u32 len) ;
    00472
    00486 extern SFBSerial Faces[FACE_COUNT]; // Declared here but defined in SFBHWSerial(Board|Host)
    00487 #define NorthFace Faces[NORTH]
    00488 #define SouthFace Faces[SOUTH]
    00489 #define EastFace Faces[EAST]
    00490 #define WestFace Faces[WEST]
    00491
    00492 /* Make just plain 'Serial' be the same as 'NorthSerial',
    00493  * so that Arduinoish code will have some place to go.
    00494  *
    00495  * Ditto for 'Serial1', etc, so Arduino Mega examples can fly
    00496  */
    00497 #define Serial NorthFace
    00498 #define Serial1 SouthFace
    00499 #define Serial2 EastFace
    00500 #define Serial3 WestFace
    00501
    00502 #endif  /* SFBSERIAL_H */
    00503