# 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
    00071 class SFBSerial {
    00072
    00073 public:
    00074
    00077   void begin() ;
    00078
    00079   void begin(u32 baud, bool manual = true) ;
    00080
    00081   void reserve() ;              /* The endless, hideous print routines.. */
    00088   void print(const char * str) {         facePrint(face,str); }
    00089
    00091   void print(const u8 * str, u32 len) {  facePrint(face,str,len); }
    00092
    00094   void print(int decimal) {              facePrint(face,decimal); }
    00095
    00097   void print(unsigned int decimal) {     facePrint(face,decimal); }
    00098
    00100   void print(long decimal) {             facePrint(face,decimal); }
    00101
    00103   void print(unsigned long decimal) {    facePrint(face,decimal); }
    00104
    00106   void print(long decimal, int code) {   facePrint(face,decimal,code); }
    00107
    00109   void print(double val) {               facePrint(face,val); }
    00110
    00112   void println() {                       facePrintln(face); }
    00113
    00115   void println(const char * str) {       facePrintln(face,str); }
    00116
    00118   void println(const u8 * str, u32 len) {facePrintln(face,str,len); }
    00119
    00121   void println(int decimal) {            facePrintln(face,decimal); }
    00122
    00124   void println(unsigned int decimal) {   facePrintln(face,decimal); }
    00125
    00127   void println(long decimal) {           facePrintln(face,decimal); }
    00128
    00130   void println(unsigned long decimal) {  facePrintln(face,decimal); }
    00131
    00133   void println(long decimal, int code) { facePrintln(face,decimal,code); }
    00134
    00136   void println(double val) {             facePrintln(face,val); }
    00137
    00139   void printlnCheckByte() ;
    00144   bool isInUse() ;
    00145
    00146   bool isManualMode() ;
    00147
    00148   bool isReflexMode() ;
    00149
    00150   bool isConsciousMode() ;
    00151
    00152   void switchToBlocking() ;
    00153
    00154   u32 getBaud() { return baud; }
    00155
    00156   bool getOddParity() { return flags&FLAG_ODD_PARITY; }
    00157
    00158   u32 getFace() { return face; }
    00159
    00175   bool ready() ;
    00176
    00177   u32 inputPackets() ;
    00178   u32 outputPackets() ;
    00179
    00185   SFBHWSerial & getHWSerial() { return hwSerial; }
    00186
    00192   bool backgroundProcessingActive() ;
    00193
    00198
    00207   bool available() ;
    00208
    00219   int read();
    00220
    00235   int peek();
    00236
    00241
    00260   u8 * readPacket();
    00261
    00266
    00267   void setPreferredBaudCode(u8 code, bool renegotiateNow = false) ;
    00268
    00269   bool dispatch(DispatchHandler dispatcher = 0, u32 maxPackets = 1) ;
    00270
    00271   void suppress(const char type) ;
    00272   void allow(const char type) ;
    00273
    00274   void reflex(const char type, PacketHandler pfunc) ;
    00275
    00276   void otherwise(PacketHandler pfunc) ;
    00277
    00282
    00292   void putcInterrupt(u8 byte) ;
    00293
    00303   void terpriInterrupt() ;
    00304
    00314   void putcBlocking(u8 byte) ;
    00315
    00324   void terpriBlocking() ;
    00325
    00326   void write(u8 byte) { lowPutc(byte); }
    00327   void write(const char * str) { print(str); }
    00328   void write(u8 * buf, u32 len) { print(buf,len); }
    00329
    00337   void flush() ;
    00338
    00339   SFBSerial(int face) ;
    00340
    00341
    00348   static void startup_initialization() ;
    00349
    00352   //XXX
    00353 private:
    00354
    00355   /* Low-level internal routines so BRN routines can talk before BRN is complete.. */
    00356   void lowPrint(const char * str) ;
    00357   void lowPrintln(const char * str) ;
    00358   void lowPutc(const u8 byte) ;
    00359   void lowTerpri() ;
    00360   void lowPrintOurBRO() ;        /* Print our current baud rate offer */
    00361
    00362   void maybeBlockForOutput() ;  /* Block until output space available, if we're FLAG_BLOCKING */
    00363
    00364   static PacketBuffer sharedBuffer;
    00365
    00366   SFBHWSerial hwSerial;        /* Platform-specific state and methods */
    00367
    00368   u32 baud;
    00369   u32 nextTimeout;             /* when we're next to act */
    00370   SFBAlarmIndexType alarmNumber; /* Our alarm number, if != 0 */
    00371   const u8 face;
    00372   u8 flags;
    00373   u8 state;                    /* Current state in BRN state machine */
    00374   u8 preferredCode;            /* Our current preferred baud rate code */
    00375   u8 selectedCode;             /* negotiated baud rate code */
    00376   bool selectedOdd;            /* negotiated odd parity (else none) */
    00377   bool haveBufferedByte;       /* for ::available() */
    00378   u8 bufferedByte;
    00379   enum {
    00380     STATE_RESET,                /* 0 Entered to send a reset packet */
    00381     STATE_INIT,                 /* 1 Initial state */
    00382     STATE_LISTEN,               /* 2 Sending/waiting for SIM */
    00383     STATE_OFFER,                /* 3 Sent/waiting for SB */
    00384     STATE_CONFIRM,              /* 4 Sent/waiting for SS */
    00385     STATE_WAIT,                 /* 5 Delay after baud changed */
    00386     STATE_DONE,                 /* 6 BRN finished */
    00387     STATE_SHOWTIME,             /* 7 Queueing and dispatching packets */
    00388     STATE_CHECKIN,              /* 8 SRU sent to request SIM */
    00389     MAX_STATES
    00390   };
    00391
    00392   enum {
    00393     FLAG_RUNNING =   0x01,     /* Port is in use (on our side.  This doesn't imply a live connection.) */
    00394     FLAG_ODD_PARITY= 0x02,     /* Port is using odd parity (vs no parity) */
    00395     FLAG_CONSCIOUS = 0x04,     /* Port is under conscious control - no BRN or bkgd packets will be sent */
    00396     FLAG_BRN_DONE  = 0x08,     /* Baud rate negotiation has succeeded or is under conscious control */
    00397     FLAG_BLOCKING_BYTES= 0x10, /* Port is running in byte-by-byte mode, with blocking output */
    00398     FLAG_GPIOS     = 0x20,     /* Port pins are in use as non-UART pins, we can't touch them */
    00399     FLAG_CONNECTED = 0x40,     /* We have received data lately on this face; there's something out there */
    00400     FLAG_RSRVD8    = 0x80      /* Reserved */
    00401   };
    00402
    00403   void start(u32 baud, u8 startFlags) ;
    00404
    00405   void stop() ;
    00406
    00407   void setBaudRate(u32 baud, bool isOddParity = false) ;
    00408
    00409   void setOddParity(bool isOdd) {
    00410     if (isOdd) flags |= FLAG_ODD_PARITY;
    00411     else flags &= ~FLAG_ODD_PARITY;
    00412   }
    00413
    00414   typedef void (*InitHandler)(u8 face);
    00415   static const char backgroundProcessorTypes[];
    00416   static const PacketHandler backgroundProcessorHandlers[];
    00417   static const InitHandler backgroundProcessorInits[];
    00418
    00419   void backgroundProcessingInit() ;
    00420
    00421   static void stateTimeout(u32 when, void * arg) ;
    00422
    00423   void step(u32 when, u8 * spacket) ; /* Step the state machine.  spacket==0 means timeout occurred */
    00424
    00425   bool stepInit(u32 when, u8 * spacket) ; /* step in state INIT */
    00426   bool stepListen(u32 when, u8 * spacket) ; /* step in state LISTEN */
    00427   bool stepOffer(u32 when, u8 * spacket) ; /* step in state OFFER */
    00428   bool stepConfirm(u32 when, u8 * spacket) ; /* step in state CONFIRM */
    00429   bool stepWait(u32 when, u8 * spacket) ; /* step in state WAIT */
    00430   bool stepDone(u32 when, u8 * spacket) ; /* step in state DONE */
    00431   bool stepShowtime(u32 when, u8 * spacket) ; /* step in state SHOWTIME */
    00432   bool stepCheckin(u32 when, u8 * spacket) ; /* step in state CHECKIN */
    00433
    00434   void setState(u8 newState, u32 aboutHowManyMs) ;
    00435
    00436   static void ppacketDispatcher(u8 * packet) ;
    00437
    00438   static void rpacketDispatcher(u8 * packet) ;
    00439
    00440   static void spacketDispatcher(u8 * packet) ;
    00441   static void spacketInit(u8 face) ;
    00442
    00443 };
    00444
    00445 /* The one-time serial startup code */
    00446 extern void serial_startup_initialization() ;
    00447
    00448 /* Some utility functions for packet handling */
    00449 extern bool zPacketPrefix(u8 * p1, const char * to) ;
    00450 extern bool packetPrefix(u8 * p1, const u8 * to, const u32 len) ;
    00451
    00452 extern SFBSerial Faces[FACE_COUNT]; // Declared here but defined in SFBHWSerial(Board|Host)
    00453 #define NorthFace Faces[NORTH]
    00454 #define SouthFace Faces[SOUTH]
    00455 #define EastFace Faces[EAST]
    00456 #define WestFace Faces[WEST]
    00457
    00458 /* Make just plain 'Serial' be the same as 'NorthSerial',
    00459  * so that Arduinoish code will have some place to go.
    00460  *
    00461  * Ditto for 'Serial1', etc, so Arduino Mega examples can fly
    00462  */
    00463 #define Serial NorthFace
    00464 #define Serial1 SouthFace
    00465 #define Serial2 EastFace
    00466 #define Serial3 WestFace
    00467
    00468 #endif  /* SFBSERIAL_H */
    00469