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 

Generated on Mon Sep 28 03:28:40 2009 for SFB by doxygen 1.5.9