# 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 inputPackets() ;
    00204   u32 outputPackets() ;
    00205
    00211   SFBHWSerial & getHWSerial() { return hwSerial; }
    00212
    00218   bool backgroundProcessingActive() ;
    00219
    00224
    00233   bool available() ;
    00234
    00245   int read();
    00246
    00261   int peek();
    00262
    00267
    00286   u8 * readPacket();
    00287
    00292
    00293   void setPreferredBaudCode(u8 code, bool renegotiateNow = false) ;
    00294
    00295   bool dispatch(DispatchHandler dispatcher = 0, u32 maxPackets = 1) ;
    00296
    00297   void suppress(const char type) ;
    00298   void allow(const char type) ;
    00299
    00300   void reflex(const char type, PacketHandler pfunc) ;
    00301
    00302   void otherwise(PacketHandler pfunc) ;
    00303
    00308
    00318   void putcInterrupt(u8 byte) ;
    00319
    00329   void terpriInterrupt() ;
    00330
    00340   void putcBlocking(u8 byte) ;
    00341
    00350   void terpriBlocking() ;
    00351
    00352   void write(u8 byte) { lowPutc(byte); }
    00353   void write(const char * str) { print(str); }
    00354   void write(u8 * buf, u32 len) { print(buf,len); }
    00355
    00363   void flush() ;
    00364
    00365   SFBSerial(int face) ;
    00366
    00367
    00374   static void startup_initialization() ;
    00375
    00378   //XXX
    00379 private:
    00380
    00381   /* Low-level internal routines so BRN routines can talk before BRN is complete.. */
    00382   void lowPrint(const char * str) ;
    00383   void lowPrintln(const char * str) ;
    00384   void lowPutc(const u8 byte) ;
    00385   void lowTerpri() ;
    00386   void lowPrintOurBRO() ;        /* Print our current baud rate offer */
    00387
    00388   void maybeBlockForOutput() ;  /* Block until output space available, if we're FLAG_BLOCKING */
    00389
    00390   static PacketBuffer sharedBuffer;
    00391
    00392   SFBHWSerial hwSerial;        /* Platform-specific state and methods */
    00393
    00394   u32 baud;
    00395   u32 nextTimeout;             /* when we're next to act */
    00396   SFBAlarmIndexType alarmNumber; /* Our alarm number, if != 0 */
    00397   const u8 face;
    00398   u8 flags;
    00399   u8 state;                    /* Current state in BRN state machine */
    00400   u8 preferredCode;            /* Our current preferred baud rate code */
    00401   u8 selectedCode;             /* negotiated baud rate code */
    00402   bool selectedOdd;            /* negotiated odd parity (else none) */
    00403   bool haveBufferedByte;       /* for ::available() */
    00404   u8 bufferedByte;
    00405   enum {
    00406     STATE_RESET,                /* 0 Entered to send a reset packet */
    00407     STATE_INIT,                 /* 1 Initial state */
    00408     STATE_LISTEN,               /* 2 Sending/waiting for SIM */
    00409     STATE_OFFER,                /* 3 Sent/waiting for SB */
    00410     STATE_CONFIRM,              /* 4 Sent/waiting for SS */
    00411     STATE_WAIT,                 /* 5 Delay after baud changed */
    00412     STATE_DONE,                 /* 6 BRN finished */
    00413     STATE_SHOWTIME,             /* 7 Queueing and dispatching packets */
    00414     STATE_CHECKIN,              /* 8 SRU sent to request SIM */
    00415     MAX_STATES
    00416   };
    00417
    00418   enum {
    00419     FLAG_RUNNING =   0x01,     /* Port is in use (on our side.  This doesn't imply a live connection.) */
    00420     FLAG_ODD_PARITY= 0x02,     /* Port is using odd parity (vs no parity) */
    00421     FLAG_CONSCIOUS = 0x04,     /* Port is under conscious control - no BRN or bkgd packets will be sent */
    00422     FLAG_BRN_DONE  = 0x08,     /* Baud rate negotiation has succeeded or is under conscious control */
    00423     FLAG_BLOCKING_BYTES= 0x10, /* Port is running in byte-by-byte mode, with blocking output */
    00424     FLAG_GPIOS     = 0x20,     /* Port pins are in use as non-UART pins, we can't touch them */
    00425     FLAG_CONNECTED = 0x40,     /* We have received data lately on this face; there's something out there */
    00426     FLAG_RSRVD8    = 0x80      /* Reserved */
    00427   };
    00428
    00429   void start(u32 baud, u8 startFlags) ;
    00430
    00431   void stop() ;
    00432
    00433   void setBaudRate(u32 baud, bool isOddParity = false) ;
    00434
    00435   void setOddParity(bool isOdd) {
    00436     if (isOdd) flags |= FLAG_ODD_PARITY;
    00437     else flags &= ~FLAG_ODD_PARITY;
    00438   }
    00439
    00440   typedef void (*InitHandler)(u8 face);
    00441   static const char backgroundProcessorTypes[];
    00442   static const PacketHandler backgroundProcessorHandlers[];
    00443   static const InitHandler backgroundProcessorInits[];
    00444
    00445   void backgroundProcessingInit() ;
    00446
    00447   static void stateTimeout(u32 when, void * arg) ;
    00448
    00449   void step(u32 when, u8 * spacket) ; /* Step the state machine.  spacket==0 means timeout occurred */
    00450
    00451   bool stepInit(u32 when, u8 * spacket) ; /* step in state INIT */
    00452   bool stepListen(u32 when, u8 * spacket) ; /* step in state LISTEN */
    00453   bool stepOffer(u32 when, u8 * spacket) ; /* step in state OFFER */
    00454   bool stepConfirm(u32 when, u8 * spacket) ; /* step in state CONFIRM */
    00455   bool stepWait(u32 when, u8 * spacket) ; /* step in state WAIT */
    00456   bool stepDone(u32 when, u8 * spacket) ; /* step in state DONE */
    00457   bool stepShowtime(u32 when, u8 * spacket) ; /* step in state SHOWTIME */
    00458   bool stepCheckin(u32 when, u8 * spacket) ; /* step in state CHECKIN */
    00459
    00460   void setState(u8 newState, u32 aboutHowManyMs) ;
    00461
    00462   static void ppacketDispatcher(u8 * packet) ;
    00463
    00464   static void rpacketDispatcher(u8 * packet) ;
    00465
    00466   static void spacketDispatcher(u8 * packet) ;
    00467   static void spacketInit(u8 face) ;
    00468
    00469 };
    00470
    00471 /* The one-time serial startup code */
    00472 extern void serial_startup_initialization() ;
    00473
    00474 /* Some utility functions for packet handling */
    00475 extern bool zPacketPrefix(u8 * p1, const char * to) ;
    00476 extern bool packetPrefix(u8 * p1, const u8 * to, const u32 len) ;
    00477
    00491 extern SFBSerial Faces[FACE_COUNT]; // Declared here but defined in SFBHWSerial(Board|Host)
    00492 #define NorthFace Faces[NORTH]
    00493 #define SouthFace Faces[SOUTH]
    00494 #define EastFace Faces[EAST]
    00495 #define WestFace Faces[WEST]
    00496
    00497 /* Make just plain 'Serial' be the same as 'NorthSerial',
    00498  * so that Arduinoish code will have some place to go.
    00499  *
    00500  * Ditto for 'Serial1', etc, so Arduino Mega examples can fly
    00501  */
    00502 #define Serial NorthFace
    00503 #define Serial1 SouthFace
    00504 #define Serial2 EastFace
    00505 #define Serial3 WestFace
    00506
    00507 #endif  /* SFBSERIAL_H */
    00508