# 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_CODE_COUNT = 10,
    00058
    00059   SFBAUD_RENDEZVOUS = 2
    00060
    00061
    00062
    00063
    00064
    00065 };
    00066
    00076 extern int getStandardBaudCode(u32 baudCodeOrRate) ;
    00077
    00086 extern u32 getStandardBaudRate(u32 baudCode) ;
    00087
    00094 class SFBSerial {
    00095
    00096 public:
    00097
    00100   void begin() ;
    00101
    00102   void begin(u32 baud, bool manual = true) ;
    00103
    00104   void reserve() ;
    00105
    00106   void end() ;
    00107   /* The endless, hideous print routines.. */
    00114   void print(const char * str) {         facePrint(face,str); }
    00115
    00117   void print(const u8 * str, u32 len) {  facePrint(face,str,len); }
    00118
    00120   void print(int decimal) {              facePrint(face,decimal); }
    00121
    00123   void print(unsigned int decimal) {     facePrint(face,decimal); }
    00124
    00126   void print(long decimal) {             facePrint(face,decimal); }
    00127
    00129   void print(unsigned long decimal) {    facePrint(face,decimal); }
    00130
    00132   void print(long decimal, int code) {   facePrint(face,decimal,code); }
    00133
    00135   void print(double val) {               facePrint(face,val); }
    00136
    00138   void println() {                       facePrintln(face); }
    00139
    00141   void println(const char * str) {       facePrintln(face,str); }
    00142
    00144   void println(const u8 * str, u32 len) {facePrintln(face,str,len); }
    00145
    00147   void println(int decimal) {            facePrintln(face,decimal); }
    00148
    00150   void println(unsigned int decimal) {   facePrintln(face,decimal); }
    00151
    00153   void println(long decimal) {           facePrintln(face,decimal); }
    00154
    00156   void println(unsigned long decimal) {  facePrintln(face,decimal); }
    00157
    00159   void println(long decimal, int code) { facePrintln(face,decimal,code); }
    00160
    00162   void println(double val) {             facePrintln(face,val); }
    00163
    00165   void printlnCheckByte() ;
    00170   bool isInUse() ;
    00171
    00172   bool isManualMode() ;
    00173
    00174   bool isReflexMode() ;
    00175
    00176   bool isConsciousMode() ;
    00177
    00178   void switchToBlocking() ;
    00179
    00180   u32 getBaud() { return baud; }
    00181
    00182   bool getOddParity() { return flags&FLAG_ODD_PARITY; }
    00183
    00184   u32 getFace() { return face; }
    00185
    00201   bool ready() ;
    00202
    00203   u32 inputBufferUsed() ;
    00204   u32 outputBufferUsed() ;
    00205   u32 inputBufferFree() ;
    00206   u32 outputBufferFree() ;
    00207   u32 brokenPackets() { return brokenPacketCount; }
    00208   void incrBrokenPacketCount() { ++brokenPacketCount; }
    00209
    00215   SFBHWSerial & getHWSerial() { return hwSerial; }
    00216
    00222   bool backgroundProcessingActive() ;
    00223
    00228
    00237   bool available() ;
    00238
    00249   int read();
    00250
    00265   int peek();
    00266
    00271
    00290   u8 * readPacket();
    00291
    00296
    00297   void setPreferredBaudCode(u8 code, bool renegotiateNow = false) ;
    00298
    00299   bool dispatch(DispatchHandler dispatcher = 0, u32 maxPackets = 1) ;
    00300
    00301   void suppress(const char type) ;
    00302   void allow(const char type) ;
    00303
    00304   void reflex(const char type, PacketHandler pfunc) ;
    00305
    00306   void otherwise(PacketHandler pfunc) ;
    00307
    00312
    00322   void putcInterrupt(u8 byte) ;
    00323
    00333   void terpriInterrupt() ;
    00334
    00344   void putcBlocking(u8 byte) ;
    00345
    00354   void terpriBlocking() ;
    00355
    00356   void write(u8 byte) { lowPutc(byte); }
    00357   void write(const char * str) { print(str); }
    00358   void write(u8 * buf, u32 len) { print(buf,len); }
    00359
    00367   void flush() ;
    00368
    00369   SFBSerial(int face) ;
    00370
    00371
    00378   static void startup_initialization() ;
    00379
    00382   //XXX
    00383 private:
    00384
    00385   /* Low-level internal routines so BRN routines can talk before BRN is complete.. */
    00386   void lowPrint(const char * str) ;
    00387   void lowPrintln(const char * str) ;
    00388   void lowPutc(const u8 byte) ;
    00389   void lowTerpri() ;
    00390   void lowPrintOurBRO() ;        /* Print our current baud rate offer */
    00391
    00392   void maybeBlockForOutput() ;  /* Block until output space available, if we're FLAG_BLOCKING */
    00393
    00394   static PacketBuffer sharedBuffer;
    00395
    00396   SFBHWSerial hwSerial;        /* Platform-specific state and methods */
    00397
    00398   u32 baud;
    00399   u32 nextTimeout;             /* when we're next to act */
    00400   u32 brokenPacketCount;       /* how many inbound packets were dead */
    00401   SFBAlarmIndexType alarmNumber; /* Our alarm number, if != 0 */
    00402   const u8 face;
    00403   u8 flags;
    00404   u8 state;                    /* Current state in BRN state machine */
    00405   u8 preferredCode;            /* Our current preferred baud rate code */
    00406   u8 selectedCode;             /* negotiated baud rate code */
    00407   bool selectedOdd;            /* negotiated odd parity (else none) */
    00408   bool haveBufferedByte;       /* for ::available() */
    00409   u8 bufferedByte;
    00410   enum {
    00411     STATE_RESET,                /* 0 Entered to send a reset packet */
    00412     STATE_INIT,                 /* 1 Initial state */
    00413     STATE_LISTEN,               /* 2 Sending/waiting for SIM */
    00414     STATE_OFFER,                /* 3 Sent/waiting for SB */
    00415     STATE_CONFIRM,              /* 4 Sent/waiting for SS */
    00416     STATE_WAIT,                 /* 5 Delay after baud changed */
    00417     STATE_DONE,                 /* 6 BRN finished */
    00418     STATE_SHOWTIME,             /* 7 Queueing and dispatching packets */
    00419     STATE_CHECKIN,              /* 8 SRU sent to request SIM */
    00420     MAX_STATES
    00421   };
    00422
    00423   enum {
    00424     FLAG_RUNNING =   0x01,     /* Port is in use (on our side.  This doesn't imply a live connection.) */
    00425     FLAG_ODD_PARITY= 0x02,     /* Port is using odd parity (vs no parity) */
    00426     FLAG_CONSCIOUS = 0x04,     /* Port is under conscious control - no BRN or bkgd packets will be sent */
    00427     FLAG_BRN_DONE  = 0x08,     /* Baud rate negotiation has succeeded or is under conscious control */
    00428     FLAG_BLOCKING_BYTES= 0x10, /* Port is running in byte-by-byte mode, with blocking output */
    00429     FLAG_GPIOS     = 0x20,     /* Port pins are in use as non-UART pins, we can't touch them */
    00430     FLAG_CONNECTED = 0x40,     /* We have received data lately on this face; there's something out there */
    00431     FLAG_RSRVD8    = 0x80      /* Reserved */
    00432   };
    00433
    00434   void start(u32 baud, u8 startFlags) ;
    00435
    00436   void stop() ;
    00437
    00438   void setBaudRate(u32 baud, bool isOddParity = false) ;
    00439
    00440   void setOddParity(bool isOdd) {
    00441     if (isOdd) flags |= FLAG_ODD_PARITY;
    00442     else flags &= ~FLAG_ODD_PARITY;
    00443   }
    00444
    00445   typedef void (*InitHandler)(u8 face);
    00446   static const char backgroundProcessorTypes[];
    00447   static const PacketHandler backgroundProcessorHandlers[];
    00448   static const InitHandler backgroundProcessorInits[];
    00449
    00450   void backgroundProcessingInit() ;
    00451
    00452   static void stateTimeout(u32 when, void * arg) ;
    00453
    00454   void step(u32 when, u8 * spacket) ; /* Step the state machine.  spacket==0 means timeout occurred */
    00455
    00456   bool stepInit(u32 when, u8 * spacket) ; /* step in state INIT */
    00457   bool stepListen(u32 when, u8 * spacket) ; /* step in state LISTEN */
    00458   bool stepOffer(u32 when, u8 * spacket) ; /* step in state OFFER */
    00459   bool stepConfirm(u32 when, u8 * spacket) ; /* step in state CONFIRM */
    00460   bool stepWait(u32 when, u8 * spacket) ; /* step in state WAIT */
    00461   bool stepDone(u32 when, u8 * spacket) ; /* step in state DONE */
    00462   bool stepShowtime(u32 when, u8 * spacket) ; /* step in state SHOWTIME */
    00463   bool stepCheckin(u32 when, u8 * spacket) ; /* step in state CHECKIN */
    00464
    00465   void setState(u8 newState, u32 aboutHowManyMs) ;
    00466
    00467   static void ppacketDispatcher(u8 * packet) ;
    00468
    00469   static void rpacketDispatcher(u8 * packet) ;
    00470
    00471   static void spacketDispatcher(u8 * packet) ;
    00472   static void spacketInit(u8 face) ;
    00473
    00474 };
    00475
    00476 /* The one-time serial startup code */
    00477 extern void serial_startup_initialization() ;
    00478
    00479 /* Some utility functions for packet handling */
    00480 extern bool zPacketPrefix(u8 * p1, const char * to) ;
    00481 extern bool packetPrefix(u8 * p1, const u8 * to, const u32 len) ;
    00482
    00496 extern SFBSerial Faces[FACE_COUNT]; // Declared here but defined in SFBHWSerial(Board|Host)
    00497 #define NorthFace Faces[NORTH]
    00498 #define SouthFace Faces[SOUTH]
    00499 #define EastFace Faces[EAST]
    00500 #define WestFace Faces[WEST]
    00501
    00502 /* Make just plain 'Serial' be the same as 'NorthSerial',
    00503  * so that Arduinoish code will have some place to go.
    00504  *
    00505  * Ditto for 'Serial1', etc, so Arduino Mega examples can fly
    00506  */
    00507 #define Serial NorthFace
    00508 #define Serial1 SouthFace
    00509 #define Serial2 EastFace
    00510 #define Serial3 WestFace
    00511
    00512 #endif  /* SFBSERIAL_H */
    00513