Example Library Module

Swordfish libraries include full source code. Not only does this enable you to see how a particular library module works, it can also aid learning and become a code starting point for your own library modules. The following code example is for an interrupt based RX buffer. All you have to do is include this module in your main program and all incoming serial data will be automatically buffered into the MCUs RAM

{
****************************************************************
*  Name    : ISRRX Module                                      *
*  Author  : David John Barker                                 *
*  Notice  : Copyright (c) 2006 Mecanique                      *
*          : All Rights Reserved                               *
*  Date    : 31/03/2006                                        *
*  Version : 1.1                                               *
****************************************************************
}
module ISRRX

// import USART library...
include "USART.bas"

// set interrupt priority level...
#if IsOption(RX_PRIORITY) and not (RX_PRIORITY in (ipLow, ipHigh))
   #error RX_PRIORITY, "Invalid option. Priority must be ipHigh or ipLow."
#endif
#option RX_PRIORITY = ipHigh
const PriorityLevel = RX_PRIORITY

// size of the RX buffer...
#if IsOption(RX_BUFFER_SIZE) and not (RX_BUFFER_SIZE in (1 to 255))
   #error RX_BUFFER_SIZE, "Invalid option. Buffer size must be between 1 and 255 (bytes)."
#endif
#option RX_BUFFER_SIZE = 64      
public const BufferSize = RX_BUFFER_SIZE

type TEvent = event()

// local variables and aliases...
dim 
   FBuffer(BufferSize) as byte,
   FIndexIn as byte,
   FIndexOut as byte,
   FByteRead as byte,
   FProcessByte as boolean,
   FMaybeOverrun as boolean,
   FOnDataEvent as TEvent
 
// public variables and aliases...   
public dim   
   USARTOverrun as USART.Overrun,
   BufferOverrun as boolean,
   DataByte as FByteRead,
   DataChar as FByteRead.AsChar,
   ProcessByte as FProcessByte

{
****************************************************************************
* Name    : OnRX (PRIVATE)                                                 *
* Purpose : Interrupt Service Routine (ISR) to buffer incoming data        *
****************************************************************************
}
interrupt OnRX(PriorityLevel)
   dim FSRSave as word
   FSRSave = FSR0
   BufferOverrun = FMaybeOverrun
   if not USART.Overrun then
      FByteRead = USART.RCRegister
      if not BufferOverrun then
         FProcessByte = true
         
         // execute handler...
         FOnDataEvent
         
         if FProcessByte then
            FBuffer(FIndexIn) = FByteRead
            inc(FIndexIn)
	        if FIndexIn > bound(FBuffer) then
               FIndexIn = 0
            endif
            FMaybeOverrun = (FIndexIn = FIndexOut) 
         endif   
      endif
   endif	     
   FSR0 = FSRSave
end interrupt
{
****************************************************************************
* Name    : Initialize                                                     *
* Purpose : Initialize buffering - with optional OnData event handler      *
****************************************************************************
}
public sub Initialize(pOnDataEvent as TEvent = 0)
   FOnDataEvent = pOnDataEvent
   FIndexIn = 0
   FIndexOut = 0
   FMaybeOverrun = false
   BufferOverrun = false
   USART.ClearOverrun
   #if RX_PRIORITY = ipLow
   USART.RCIPHigh = false
   #endif
   USART.RCIEnable = true
   enable(OnRX)
end sub
{
****************************************************************************
* Name    : Reset                                                          *
* Purpose : Reset module                                                   *
****************************************************************************
}
public sub Reset()
   disable(OnRX)
   Initialize(FOnDataEvent)
end sub	  
{
****************************************************************************
* Name    : Start                                                          *
* Purpose : Start interrupt handling                                       *
****************************************************************************
}
public sub Start()
   enable(OnRX)
end sub
{
****************************************************************************
* Name    : Stop                                                           *
* Purpose : Stop interrupt handling                                        *
****************************************************************************
}
public sub Stop()
   disable(OnRX)
end sub
{
****************************************************************************
* Name    : DataAvailable                                                  *
* Purpose : Check to see if there is data in the buffer                    *
****************************************************************************
}
public function DataAvailable() as boolean
   disable(OnRX)
   Result = FIndexIn <> FIndexOut
   enable(OnRX)
end function
{
****************************************************************************
* Name    : Overrun                                                        *
* Purpose : Returns true if RC register or buffer has overrun, false       *
*         : otherwise                                                      *
****************************************************************************
}
public function Overrun() as boolean
   Result = USART.Overrun or BufferOverrun
end function
{
****************************************************************************
* Name    : GetByte (PRIVATE)                                              *
* Purpose : Get a single byte from the buffer                              *
****************************************************************************
}
function GetByte() as byte
   FMaybeOverrun = false
   Result = FBuffer(FIndexOut)
   inc(FIndexOut)
   if FIndexOut > bound(FBuffer) then
      FIndexOut = 0
   endif   
end function
{
****************************************************************************
* Name    : ReadByte                                                       *
* Purpose : Read a single byte from the buffer                             *
****************************************************************************
}
public function ReadByte() as byte
   disable(OnRX)
   Result = GetByte
   enable(OnRX)
end function
{
****************************************************************************
* Name    : ReadWord                                                       *
* Purpose : Read a word from the buffer                                    *
****************************************************************************
}
public function ReadWord() as word
   disable(OnRX)
   Result.Bytes(0) = GetByte
   Result.Bytes(1) = GetByte
   enable(OnRX)
end function
{
****************************************************************************
* Name    : ReadLongWord                                                   *
* Purpose : Read a long word from the buffer                               *
****************************************************************************
}
public function ReadLongWord() as longword
   disable(OnRX)
   Result.Bytes(0) = GetByte
   Result.Bytes(1) = GetByte
   Result.Bytes(2) = GetByte
   Result.Bytes(3) = GetByte
   enable(OnRX)
end function
{
****************************************************************************
* Name    : ReadFloat                                                      *
* Purpose : Read a floating point number from the buffer                   *
****************************************************************************
}
public function ReadFloat() as float
   disable(OnRX)
   Result.Bytes(0) = GetByte
   Result.Bytes(1) = GetByte
   Result.Bytes(2) = GetByte
   Result.Bytes(3) = GetByte
   enable(OnRX)
end function
{
****************************************************************************
* Name    : ReadStr                                                        *
* Purpose : Read a string from the buffer. Optional parameter pTerminator  *
*         : to specify the input string terminator character. The function *
*         : returns the number of characters read                          *
****************************************************************************
}
public function ReadStr(byref pText as string, pTerminator as char = null) as byte
   dim Ch as char
   dim Text as POSTINC0
   
   disable(OnRX)
   FSR0 = addressof(pText)
   Result = 0
   repeat
      Ch = GetByte
      if Ch <> pTerminator then
         Text = Ch
         inc(Result)
      endif   
   until Ch = pTerminator
   Text = 0
   enable(OnRX)
end function