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