This page created with Cool Page.  Click to get your own FREE copy of Cool Page!
MELabs programs
06 Jan '09
You are advised to download all programs from the MeLabs web site so that you will get the latest versions.  This consolidated list is best for searching for keywords in one file so you can see how they were used by MeLabs
EncoderGeek / EncoderGeek
' PicBasic Pro program to read pots on 16F877 ADC

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD pins
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

' Allocate variables
x       var     byte
y       var     byte
z       var     byte

        ADCON1 = 4              ' Set PortA 0, 1, 3 to analog inputs

        Low PORTE.2             ' LCD R/W line low (W)
        Pause 100               ' Wait for LCD to start

        Goto    mainloop        ' Skip subroutines


' Subroutine to read a/d convertor
getad:
        Pauseus 50              ' Wait for channel to setup

        ADCON0.2 = 1            ' Start conversion
        Pauseus 50              ' Wait for conversion

        Return

' Subroutine to get pot x value
getx:
        ADCON0 = $41            ' Set A/D to Fosc/8, Channel 0, On
        Gosub getad
        x = ADRESH
        Return

' Subroutine to get pot y value
gety:
        ADCON0 = $49            ' Set A/D to Fosc/8, Channel 1, On
        Gosub getad
        y = ADRESH
        Return

' Subroutine to get pot z value
getz:
        ADCON0 = $59            ' Set A/D to Fosc/8, Channel 3, On
        Gosub getad
        z = ADRESH
        Return


mainloop:
        Gosub   getx            ' Get x value
        Gosub   gety            ' Get y value
        Gosub   getz            ' Get z value

        Lcdout $fe, 1, "x=", #x, " y=", #y, " z=", #z   ' Send values to LCD
        Pause   100             ' Do it about 10 times a second

        Goto    mainloop        ' Do it forever

        End
0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to display result of
' 8-bit A/D conversion on LCD
'
' Connect analog inputs to channels 0, 1, 3 (RA0, 1, 3)

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

' Define ADCIN parameters
Define  ADC_BITS        8       ' Set number of bits in result
Define  ADC_CLOCK       3       ' Set clock source (3=rc)
Define  ADC_SAMPLEUS    50      ' Set sampling time in uS

advalvarbyte' Create adval to store result


TRISA = %11111111' Set PORTA to all input
ADCON1 = %00000100' Set PORTA analog

        Pause 500                       ' Wait .5 second


mainloop:
Lcdout$fe, 1' Clear the LCD

Adcin0, adval' Read the first ADC channel
Lcdout"0=", #adval' Send it to the LCD

Adcin1, adval' Read the second ADC channel
Lcdout" 1=", #adval' Send it to the LCD

Adcin3, adval' Read the third ADC channel
Lcdout" 3=", #adval' Send it to the LCD

        Pause   200             ' Delay for time to read the display

        Goto    mainloop        ' Do it forever

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to blink all the LEDs connected to PORTD

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

i       var     byte    ' Define loop variable

LEDS    var     PORTD   ' Alias PORTD to LEDS


TRISD = %00000000       ' Set PORTD to all output

loop:   LEDS = 1        ' First LED on
        Pause 500       ' Delay for .5 seconds

        For i = 1 to 7  ' Go through For..Next loop 7 times

                LEDS = LEDS << 1        ' Shift on LED one to left
                Pause 500       ' Delay for .5 seconds

        Next i

        Goto loop       ' Go back to loop and blink LED forever
        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to blink an LED connected to PORTD.0 about once a second

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

LED     var     PORTD.0 ' Alias PORTD.0 to LED

loop:   High LED        ' Turn on LED connected to PORTD.0
        Pause 500       ' Delay for .5 seconds

        Low LED         ' Turn off LED connected to PORTD.0
        Pause 500       ' Delay for .5 seconds

        Goto loop       ' Go back to loop and blink LED forever
        End

0000000000000000000000000000000000000000000000000000000000



' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1


char    var     byte            ' Storage for serial character
mode    var     byte            ' Storage for serial mode
rcv     var     PORTC.7         ' Serial receive pin
baud    var     PORTA.0         ' Baud rate pin - 0 = 2400, 1 = 9600
state   var     PORTA.1         ' Inverted or true serial data - 1 = true


        ADCON1 = 7              ' Set PORTA and PORTE to digital
        Low PORTE.2             ' LCD R/W line low (W)
Pause 500' Wait for LCD to startup

        mode = 0                ' Set mode

        If (baud == 1) Then
                mode = 2        ' Set baud rate
        Endif

        If (state == 0) Then
                mode = mode + 4 ' Set inverted or true
        Endif

        Lcdout $fe, 1           ' Initialize and clear display

loop:   Serin rcv, mode, char   ' Get a char from serial input
        Lcdout char             ' Send char to display
        Goto loop               ' Do it all over again

        End

0000000000000000000000000000000000000000000000000000000000



' LCD clock program using On Interrupt
'  Uses TMR0 and prescaler.  Watchdog Timer should be
'  set to off at program time and Nap and Sleep should not be used.
'  Buttons may be used to set hours and minutes

Define  LCD_DREG        PORTD   ' Define LCD connections
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

hour    var     byte    ' Define hour variable
dhour   var     byte    ' Define display hour variable
minute  var     byte    ' Define minute variable
second  var     byte    ' Define second variable
ticks   var     byte    ' Define pieces of seconds variable
update  var     byte    ' Define variable to indicate update of LCD
i       var     byte    ' Debounce loop variable

        ADCON1 = 7      ' PORTA and E digital
        Low PORTE.2     ' LCD R/W low = write
        Pause 100       ' Wait for LCD to startup

        hour = 0        ' Set initial time to 00:00:00
        minute = 0
        second = 0
        ticks = 0

        update = 1      ' Force first display

' Set TMR0 to interrupt every 16.384 milliseconds
        OPTION_REG = $55        ' Set TMR0 configuration and enable PORTB pullups
        INTCON = $a0            ' Enable TMR0 interrupts
        On Interrupt Goto tickint


' Main program loop - in this case, it only updates the LCD with the time
mainloop:
        PORTB = 0       ' PORTB lines low to read buttons
        TRISB = $f0     ' Enable all buttons

        ' Check any button pressed to set time
        If PORTB.7 = 0 Then decmin
        If PORTB.6 = 0 Then incmin      ' Last 2 buttons set minute
        If PORTB.5 = 0 Then dechr
        If PORTB.4 = 0 Then inchr       ' First 2 buttons set hour

        ' Check for time to update screen
chkup:  If update = 1 Then
                Lcdout $fe, 1   ' Clear screen

                ' Display time as hh:mm:ss
                dhour = hour    ' Change hour 0 to 12
                If (hour // 12) = 0 Then
                        dhour = dhour + 12
                Endif

                ' Check for AM or PM
                If hour < 12 Then
                        Lcdout dec2 dhour, ":", dec2 minute, ":", dec2 second, " AM"
                Else
                        Lcdout dec2 (dhour - 12), ":", dec2 minute, ":", dec2 second, " PM"
                Endif

                update = 0      ' Screen updated
        Endif

        Goto mainloop   ' Do it all forever


' Increment minutes
incmin: minute = minute + 1
        If minute >= 60 Then
                minute = 0
        Endif
        Goto debounce

' Increment hours
inchr:  hour = hour + 1
        If hour >= 24 Then
                hour = 0
        Endif
        Goto debounce

' Decrement minutes
decmin: minute = minute - 1
        If minute >= 60 Then
                minute = 59
        Endif
        Goto debounce

' Decrement hours
dechr:  hour = hour - 1
        If hour >= 24 Then
                hour = 23
        Endif

' Debounce and delay for 250ms
debounce: For i = 1 to 25
        Pause 10        ' 10ms at a time so no interrupts are lost
        Next i

        update = 1      ' Set to update screen

        Goto chkup


' Interrupt routine to handle each timer tick
        disable         ' Disable interrupts during interrupt handler
tickint: ticks = ticks + 1      ' Count pieces of seconds
        If ticks < 61 Then tiexit       ' 61 ticks per second (16.384ms per tick)

' One second elasped - update time
        ticks = 0
        second = second + 1
        If second >= 60 Then
                second = 0
                minute = minute + 1
                If minute >= 60 Then
                        minute = 0
                        hour = hour + 1
                        If hour >= 24 Then
                                hour = 0
                        Endif
                Endif
        Endif

        update = 1      ' Set to update LCD

tiexit: INTCON.2 = 0    ' Reset timer interrupt flag
        Resume

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to demonstrate the page-write
' capability of the 24LC256 serial memory.  This program
' will transfer 64 bytes of data to the memory before
' a pause is needed to complete the write.

' Set receive register to receiver enabled
DEFINE HSER_RCSTA       90h
' Set transmit register to transmitter enabled
DEFINE HSER_TXSTA       24h
' Set baud rate
DEFINE HSER_BAUD        9600



scl     VAR     PORTC.3                 ' Clock pin
sda     VAR     PORTC.4                 ' Data pin


addr    VAR     WORD                    ' Memory Address
data_array    VAR     BYTE[64]                ' Data array with location for checksum
i       VAR     BYTE                    ' Loop counter

        ADCON1 = 7                      ' Set PORTA and PORTE to digital
       
       
HSerout ["Programming", 10,13]

For i = 0 to 63' Load the array with test data
data_array[i] = i
Next i


'From the Microchip memory databook: 
'"Page write operations are limited to writing
'bytes within a single physical page,
'regardless of the number of bytes actually
'being written. Physical page boundaries
'start at addresses that are integer
'multiples of the page buffer size (or 'page
'size') and end at addresses that are
'integer multiples of [page size - 1]. If a
'Page Write command attempts to write
'across a physical page boundary, the
'result is that the data wraps around to the
'beginning of the current page (overwriting
'data previously stored there), instead of
'being written to the next page, as might be
'expected. It is, therefore, necessary for the
'application software to prevent page write
'operations that would attempt to cross a
'page boundary."

For addr = 0 To 32767 Step 64        ' Store $00 to all locations (for testing)

I2CWrite sda,scl,$A0,addr,[STR data_array\64]  ' Send a 64-byte page
HSerout ["."]' Indicate progress          
Pause 10' Pause 10mS to let the write complete

Next addr


' Spot-check the data on the terminal screen
i = 0
Hserout [10,13, 10,13, "checking", 10,13]

For addr = 0 to 32767 Step 257' read every 257th address
i = i + 1

I2CRead sda, scl, $A0, addr, [data_array[0]]' Read a single byte from memory

Hserout [HEX2 data_array[0], " "]' To terminal with hex value

If (i & $0007) = 0 Then' Break it into organized lines
Hserout [10,13]' 8 locations to a line
Endif

Next addr' Go get the next test

End

0000000000000000000000000000000000000000000000000000000000




       

' PicBasic Pro program to demonstrate the page-write
' capability of the 24LC256 serial memory.  This program
' will transfer 64 bytes of data to the memory before
' a pause is needed to complete the write.

' Set receive register to receiver enabled
DEFINE HSER_RCSTA       90h
' Set transmit register to transmitter enabled
DEFINE HSER_TXSTA       24h
' Set baud rate
DEFINE HSER_BAUD        9600



scl     VAR     PORTC.3                 ' Clock pin
sda     VAR     PORTC.4                 ' Data pin


addr    VAR     WORD                    ' Memory Address
data_array    VAR     BYTE[64]                ' Data array with location for checksum
i       VAR     BYTE                    ' Loop counter

        ADCON1 = 7                      ' Set PORTA and PORTE to digital
       
       
HSerout ["Programming", 10,13]

For i = 0 to 63' Load the array with test data
data_array[i] = i
Next i


'From the Microchip memory databook: 
'"Page write operations are limited to writing
'bytes within a single physical page,
'regardless of the number of bytes actually
'being written. Physical page boundaries
'start at addresses that are integer
'multiples of the page buffer size (or 'page
'size') and end at addresses that are
'integer multiples of [page size - 1]. If a
'Page Write command attempts to write
'across a physical page boundary, the
'result is that the data wraps around to the
'beginning of the current page (overwriting
'data previously stored there), instead of
'being written to the next page, as might be
'expected. It is, therefore, necessary for the
'application software to prevent page write
'operations that would attempt to cross a
'page boundary."

For addr = 0 To 32767 Step 64        ' Store $00 to all locations (for testing)

I2CWrite sda,scl,$A0,addr,[STR data_array\64]  ' Send a 64-byte page
HSerout ["."]' Indicate progress          
Pause 10' Pause 10mS to let the write complete

Next addr


' Spot-check the data on the terminal screen
i = 0
Hserout [10,13, 10,13, "checking", 10,13]

For addr = 0 to 32767 Step 257' read every 257th address
i = i + 1

I2CRead sda, scl, $A0, addr, [data_array[0]]' Read a single byte from memory

Hserout [HEX2 data_array[0], " "]' To terminal with hex value

If (i & $0007) = 0 Then' Break it into organized lines
Hserout [10,13]' 8 locations to a line
Endif

Next addr' Go get the next test

End

0000000000000000000000000000000000000000000000000000000000




       

' PicBasic Pro program to send and receive from the hardware serial port

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1


char    var     byte            ' Storage for serial character
col     var     byte            ' Keypad column
row     var     byte            ' Keypad row
key     var     byte            ' Key value
lastkey var     byte            ' Last key storage


        ADCON1 = 7              ' Set PORTA and PORTE to digital
        Low PORTE.2             ' LCD R/W line low (W)
Pause 500' Wait for LCD to startup

        OPTION_REG.7 = 0        ' Enable PORTB pullups

        key = 0                 ' Initialize vars
        lastkey = 0


        Lcdout $fe, 1           ' Initialize and clear display

loop:   Hserin 1, tlabel, [char]        ' Get a char from serial port
        Lcdout char             ' Send char to display
tlabel: Gosub getkey            ' Get a keypress if any
        If (key != 0) and (key != lastkey) Then
                Hserout [key]   ' Send key out serial port
        Endif
        lastkey = key           ' Save last key value
        Goto loop               ' Do it all over again

' Subroutine to get a key from keypad
getkey:
        key = 0                 ' Preset to no key
        For col = 0 to 3        ' 4 columns in keypad
                PORTB = 0       ' All output pins low
                TRISB = (dcd col) ^ $ff ' Set one column pin to output
                row = PORTB >> 4        ' Read row
                If row != $f Then gotkey        ' If any keydown, exit
        Next col

        Return                  ' No key pressed

gotkey: ' Change row and column to ASCII key number
        key = (col * 4) + (ncd (row ^ $f)) + "0"
        Return                  ' Subroutine over

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to read and write to I2C SEEPROMs
'
' Write to the first 16 locations of an external serial EEPROM
' Read first 16 locations back and send to LCD repeatedly
' Note: for SEEPROMs with byte-sized address

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

SCL     var     PORTC.3                 ' Clock pin
SDA     var     PORTC.4                 ' Data pin

B0      var     byte                    ' Address
B1      var     byte                    ' Data 1
B2      var     byte                    ' Data 2

        ADCON1 = 7                      ' Set PORTA and PORTE to digital
        Low PORTE.2                     ' LCD R/W line low (W)
        Pause 100                       ' Wait for LCD to start up


        For B0 = 0 To 15                ' Loop 16 times
                B1 = B0 + 100           ' B1 is data for SEEPROM
                I2CWRITE SDA,SCL,$A0,B0,[B1]    ' Write each location
                Pause 10                ' Delay 10ms after each write
        Next B0

loop:   For B0 = 0 To 15 Step 2         ' Loop 8 times
                I2CREAD SDA,SCL,$A0,B0,[B1,B2]  ' Read 2 locations in a row
                Lcdout $fe,1,#B0,": ",#B1," ",#B2," "   ' Display 2 locations
                Pause 1000
        Next B0

        Goto loop

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to read and write to I2C SEEPROMs
' that require a word-sized address
'
' Write to the first 16 locations of an external serial EEPROM
' Read first 16 locations back and send to LCD repeatedly
'

' Define LCD registers and bits
DEFINE  LCD_DREG        PORTD
DEFINE  LCD_DBIT        4
DEFINE  LCD_RSREG       PORTE
DEFINE  LCD_RSBIT       0
DEFINE  LCD_EREG        PORTE
DEFINE  LCD_EBIT        1

SCL     VAR     PORTC.3                 ' Clock pin
SDA     VAR     PORTC.4                 ' Data pin

address VAR     WORD                    ' Address
B1      VAR     BYTE                    ' Data 1
B2      VAR     BYTE                    ' Data 2

        ADCON1 = 7                      ' Set PORTA and PORTE to digital
        Low PORTE.2                     ' LCD R/W line low (W)
        Pause 100                       ' Wait for LCD to start up


        For address = 0 TO 15                ' Loop 16 times
                B1 = address + 100           ' B1 is data for SEEPROM
                I2CWrite SDA,SCL,$A0,address,[B1]    ' Write each location
                Pause 10                ' Delay 10ms after each write
        Next address

loop:   For address = 0 TO 15 STEP 2         ' Loop 8 times
                I2CRead SDA,SCL,$A0,address,[B1,B2]  ' Read 2 locations in a row
                LCDOut $fe,1,#address,": ",#B1," ",#B2," "   ' Display 2 locations
                Pause 1000
        Next address

        GoTo loop

        End

0000000000000000000000000000000000000000000000000000000000



' LCD clock program using JRC6355 RTC

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

        Include "MODEDEFS.BAS"  ' Include Shiftin/out modes

Define  LCD_DREG        PORTD   ' Define LCD connections
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

' Alias pins
CE      var     PORTA.2
CLK     var     PORTC.1
SDATA   var     PORTC.3
IO      var     PORTC.5

' Allocate variables
rtcyear var     byte
rtcmonth var    byte
rtcdate var     byte
rtcday  var     byte
rtchr   var     byte
rtcmin  var     byte
rtcsec  var     byte


        Low CE          ' Disable RTC
        Low CLK
        High IO

        ADCON1 = 7      ' PORTA and E digital
        Low PORTE.2     ' LCD R/W low = write
        Pause 100       ' Wait for LCD to startup

        ' Set initial time to 8:00:00AM 07/16/99
        rtcyear = $99
        rtcmonth = $07
        rtcdate = $16
        rtcday = 6
        rtchr = $08
        rtcmin = 0
        rtcsec = 0
        Gosub settime   ' Set the time

        Goto mainloop   ' Skip subroutines


' Subroutine to write time to RTC
settime:
        IO = 1          ' Set RTC to input
        CE = 1          ' Enable transfer

        ' Write all 7 RTC registers
        Shiftout SDATA, CLK, LSBFIRST, [rtcyear, rtcmonth, rtcdate, rtcday\4, rtchr, rtcmin]

        CE = 0          ' Disable RTC
        Return

' Subroutine to read time from RTC
gettime:
        IO = 0          ' Set RTC to output
        CE = 1          ' Enable transfer

        ' Read all 7 RTC registers
        Shiftin SDATA, CLK, LSBPRE, [rtcyear, rtcmonth, rtcdate, rtcday\4, rtchr, rtcmin, rtcsec]

        CE = 0          ' Disable RTC
        Return

' Main program loop - in this case, it only updates the LCD with the time
mainloop:
        Gosub gettime   ' Read the time from the RTC

        ' Display time on LCD
        Lcdout $fe, 1, hex2 rtcmonth, "/", hex2 rtcdate, "/" , hex2 rtcyear,_
        "  ", hex2 rtchr, ":", hex2 rtcmin, ":", hex2 rtcsec

        Pause 300       ' Do it about 3 times a second

        Goto mainloop   ' Do it forever

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to display key number on LCD

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD connections
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1


' Define program variables
col     var     byte            ' Keypad column
row     var     byte            ' Keypad row
key     var     byte            ' Key value


        OPTION_REG.7 = 0        ' Enable PORTB pullups

        ADCON1 = 7              ' Make PORTA and PORTE digital
        Low PORTE.2             ' LCD R/W low (write)

        Pause 100               ' Wait for LCD to start

        Lcdout $fe, 1, "Press any key"  ' Display sign on message

loop:   Gosub getkey            ' Get a key from the keypad
        Lcdout $fe, 1, #key     ' Display ASCII key number
        Goto loop               ' Do it forever


' Subroutine to get a key from keypad
getkey:
        Pause 50                ' Debounce

getkeyu:
        ' Wait for all keys up
        PORTB = 0               ' All output pins low
        TRISB = $f0             ' Bottom 4 pins out, top 4 pins in
        If ((PORTB >> 4) != $f) Then getkeyu    ' If any keys down, loop

        Pause 50                ' Debounce

getkeyp:
        ' Wait for keypress
        For col = 0 to 3        ' 4 columns in keypad
                PORTB = 0       ' All output pins low
                TRISB = (dcd col) ^ $ff ' Set one column pin to output
                row = PORTB >> 4        ' Read row
                If row != $f Then gotkey        ' If any keydown, exit
        Next col

        Goto getkeyp            ' No keys down, go look again

gotkey: ' Change row and column to key number 1 - 16
        key = (col * 4) + (ncd (row ^ $f))
        Return                  ' Subroutine over

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to display "hello world" on LCD,
' then use LCDIN to read the first letter of each line and
' change it to upper case.

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DEFINELOADER_USED1

' Define LCD registers and bits
DEFINE  LCD_DREG        PORTD
DEFINE  LCD_DBIT        4
DEFINE  LCD_RSREG       PORTE
DEFINE  LCD_RSBIT       0
DEFINE  LCD_EREG        PORTE
DEFINE  LCD_EBIT        1
DEFINELCD_RWREGPORTE
DEFINELCD_RWBIT2

characterVARBYTE


        ADCON1 = 7      ' Set PORTA and PORTE to digital
        Low PORTE.2     ' LCD R/W line low (W)
        Pause 100       ' Wait for LCD to start up


loop:   LCDOut $FE, 1   ' Clear screen
        Pause 500       ' Wait .5 second

        LCDOut "hello"  ' Display "hello"
        Pause 500       ' Wait .5 second

        LCDOut $fe, $C0, "world"' Move to line 2  and display "world"
        Pause 500       ' Wait .5 second

LCDIN $80, [character]' Read value of first character, first line
LCDOut $FE, $80, (character - $20)' Change character to upper case
Pause 500' Wait .5 second

LCDIN $C0, [character]' Read value of first character, second line
LCDOut $FE, $C0, (character - $20)' Change character to upper case
Pause 500' Wait .5 second

        GoTo loop       ' Do it forever
        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to display "Hello World" on LCD

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1


        ADCON1 = 7      ' Set PORTA and PORTE to digital
        Low PORTE.2     ' LCD R/W line low (W)
        Pause 100       ' Wait for LCD to start up


loop:   Lcdout $fe, 1   ' Clear screen
        Pause 500       ' Wait .5 second

        Lcdout "Hello"  ' Display "Hello"
        Pause 500       ' Wait .5 second

        Lcdout $fe, $c0, "World"        ' Move to line 2  and display "World"
        Pause 500       ' Wait .5 second

        Goto loop       ' Do it forever
        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to read LTC1298 ADC

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD pins
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

        include "modedefs.bas"

' Alias pins
CS      var     PORTC.5         ' Chip select
CK      var     PORTC.3         ' Clock
DI      var     PORTA.2         ' Data in
DO      var     PORTC.1         ' Data out

' Allocate variables
addr    var     byte            ' Channel address / mode
result  var     word
x       var     word
y       var     word
z       var     word

        High CS                 ' Chip select inactive

        ADCON1 = 7              ' Set PORTA, PORTE to digital

        Low PORTE.2             ' LCD R/W line low (W)
        Pause 100               ' Wait for LCD to start

        Goto    mainloop        ' Skip subroutines


' Subroutine to read a/d convertor
getad:
        CS = 0                  ' Chip select active

        ' Send address / mode - Start bit, 3 bit addr, null bit]
        Shiftout DI, CK, MSBFIRST, [1\1, addr\3, 0\1]

        Shiftin DO, CK, MSBPRE, [result\12]  ' Get 12-bit result

        CS = 1                  ' Chip select inactive
        Return

' Subroutine to get x value (channel 0)
getx:
        addr = $05              ' Single ended, channel 0, MSBF high
        Gosub getad
        x = result
        Return

' Subroutine to get y value (channel 1)
gety:
        addr = $07              ' Single ended, channel 1, MSBF high
        Gosub getad
        y = result
        Return

' Subroutine to get z value (differential)
getz:
        addr = $01              ' Differential (ch0 = +, ch1 = -), MSBF high
        Gosub getad
        z = result
        Return


mainloop:
        Gosub   getx            ' Get x value
        Gosub   gety            ' Get y value
        Gosub   getz            ' Get z value

        Lcdout $fe, 1, "x=", #x, " y=", #y, " z=", #z   ' Send values to LCD
        Pause   100             ' Do it about 10 times a second

        Goto    mainloop        ' Do it forever

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to read and write to Microwire SEEPROM 93LC56A
'
' Write to the first 16 locations of an external serial EEPROM
' Read first 16 locations back and send to LCD repeatedly
' Note: for SEEPROMs with byte-sized address

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

        include "modedefs.bas"

CS      var     PORTA.5                 ' Chip select pin
CLK     var     PORTC.3                 ' Clock pin
DI      var     PORTC.4                 ' Data in pin
DO      var     PORTC.5                 ' Data out pin

addr    var     byte                    ' Address
B0      var     byte                    ' Data

        Low CS                          ' Chip select inactive

        ADCON1 = 7                      ' Set PORTA and PORTE to digital
        Low PORTE.2                     ' LCD R/W line low (W)
        Pause 100                       ' Wait for LCD to start up


        Gosub eewriteen                 ' Enable SEEPROM writes
       
        For addr = 0 To 15              ' Loop 16 times
                B0 = addr + 100         ' B0 is data for SEEPROM
                Gosub eewrite           ' Write to SEEPROM
                Pause 10                ' Delay 10ms after each write
        Next addr

loop:   For addr = 0 To 15              ' Loop 16 times
                Gosub eeread            ' Read from SEEPROM
                Lcdout $fe,1,#addr,": ",#B0     ' Display
                Pause 1000
        Next addr

        Goto loop

' Subroutine to read data from addr in serial EEPROM
eeread: CS = 1                          ' Enable serial EEPROM
        Shiftout DI, CLK, MSBFIRST, [%1100\4, addr]     ' Send read command and address
        Shiftin DO, CLK, MSBPOST, [B0]  ' Read data
        CS = 0                          ' Disable
        Return

' Subroutine to write data at addr in serial EEPROM
eewrite: CS = 1                         ' Enable serial EEPROM
        Shiftout DI, CLK, MSBFIRST, [%1010\4, addr, B0] ' Send write command, address and data
        CS = 0                          ' Disable
        Return

' Subroutine to enable writes to serial EEPROM
eewriteen: CS = 1                       ' Enable serial EEPROM
        Shiftout DI, CLK, MSBFIRST, [%10011\5, 0\7]     ' Send write enable command and dummy clocks
        CS = 0                          ' Disable
        Return

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to receive HEX file from PC and write
' data to I2C memory. Writes data in page mode, 16 bytes at one
' time.  Memory device must be addressed with 16 bits and capable
' of receiving 16 bytes at once.

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Set receive register to receiver enabled
DEFINE HSER_RCSTA       90h
' Set transmit register to transmitter enabled
DEFINE HSER_TXSTA       20h
' Set baud rate
DEFINE HSER_BAUD        2400



scl     VAR     PORTC.3                 ' Clock pin
sda     VAR     PORTC.4                 ' Data pin
pinin   VARPORTC.7                 ' Serial receive pin
pinout  VAR     PORTC.6                 ' Serial transmit pin


addr    VAR     WORD                    ' Memory Address
dta1    VAR     BYTE[17]                ' Data array with location for checksum
bb      VAR     BYTE                    ' Byte count
tt      VAR     BYTE                    ' Record type
i       VAR     WORD                    ' Loop counter
cs      VAR     BYTE                    ' Checksum
ln      VAR     BYTE                    ' Line count

        Clear                           ' Clear RAM data



        ADCON1 = 7                      ' Set PORTA and PORTE to digital
       
        ln = 0                          ' Clear line count
       
        HSerout ["Erasing"]
       
        For i = 0 To 8192 Step 8        ' Store $00 to all locations (for testing)
               
                I2CWrite sda,scl,$A0,i,[STR dta1\8]
                If i//256 = 0 Then
                        HSerout ["."]          
                EndIf                                  
                Pause 6
               
Next i

       
        HSerout [13,10,"Ready",13,10]' Notify: ready for file
       
loop:   cs = 0                          ' Reset checksum byte
       
        HSerin [WAIT(":"),HEX2 bb,HEX4 addr,HEX2 tt]    ' Receive line and parse
       
        cs = bb + addr.lowbyte + addr.highbyte + tt' Begin checksum calculation
       
        If (tt = 1) Then eof            ' Check for end of file
       
        For i = 0 To bb                ' Loop for each expected data-byte and checksum
                HSerin [HEX2 dta1[i]]   ' Store each byte to location in array
                cs = cs + dta1[i]       ' Add each byte to checksum calculation
        Next i

        ln = ln + 1                     ' Count line received
       
        If (cs <> 0) Then sume          ' Check for checksum error
       
I2CWrite sda,scl,$A0,addr,[STR dta1\bb] ' Write data to device, checksum is dropped
            
        Goto loop' Go get another line
       

sume:   HSerout ["Checksum Error: line ",DEC ln,13,10]  ' Notify: checksum error

               
eof:    HSerout [DEC ln," lines received",13,10]        ' Notify: Confirm line count


        For i = 0 To (ln*16)            ' Loop 16 times for each line received

                I2CRead sda,scl,$A0,i,[cs]' Read back each character
                HSerout [HEX2 cs]' Send each character

                If (i+1)//16 = 0 Then
                        HSerout [13,10]' New line every 16 characters
                EndIf                                  

        Next i

        HSerout [13,10,13,10]           ' New Lines

        End

0000000000000000000000000000000000000000000000000000000000




' PicBasic Pro program to receive HEX file from PC and write
' data to I2C memory. Writes data in page mode, 8 bytes at one
' time.  Memory device must be addressed with 8 bits and capable
' of receiving 8 bytes at once.

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

' Set receive register to receiver enabled
DEFINE HSER_RCSTA       90h
' Set transmit register to transmitter enabled
DEFINE HSER_TXSTA       20h
' Set baud rate
DEFINE HSER_BAUD        2400


scl     VAR     PORTC.3                 ' Clock pin
sda     VAR     PORTC.4                 ' Data pin
pinin   VARPORTC.7' Serial receive pin
pinout  VARPORTC.6                 ' Serial transmit pin


addr    VARBYTE                     ' Memory Address
dta1    VARBYTE[9]                  ' Data array with location for checksum
bb      VARBYTE                     ' Byte count
ttVARBYTE                     ' Record type
iVARBYTE                     ' Loop counter
csVARBYTE                     ' Checksum
lnVARBYTE                     ' Line count

Clear                            ' Clear RAM data


        ADCON1 = 7                      ' Set PORTA and PORTE to digital
       
        ln = 0                          ' Clear line count
       
        For i = 0 To 255 Step 8         ' Store $00 to first 256 locations (for testing)
               
                I2CWrite sda,scl,$A0,i,[STR dta1\8]
                Pause 10
               
        Next i

       
        HSerout ["Ready",13,10]' Notify: ready for file
       
loop:   cs = 0                          ' Reset checksum byte
       
        HSerin [WAIT(":"),HEX2 bb,HEX4 addr,HEX2 tt]    ' Receive line and parse
       
        cs = bb + addr + tt             ' Begin checksum calculation
       
        If (tt = 1) Then eof            ' Check for end of file
       
        If (bb>8) Then                  ' Write twice if more that 8 bytes of data on line
       
                For i = 0 To 7          ' Loop for first 8 bytes of data
                        HSerin [HEX2 dta1[i]]   ' Store each byte to location in array
                        cs = cs + dta1[i]' Add each byte to checksum calculation
                Next i

                I2CWrite sda,scl,$A0,addr,[STR dta1\8]  ' Write 8 bytes of data to device
                       
                bb = bb - 8
                addr = addr + 8
       
                For i = 0 To (bb)' Loop for remaining expected data-bytes and checksum
                        HSerin [HEX2 dta1[i]]   ' Store each byte to location in array
                        cs = cs + dta1[i]       ' Add each byte to checksum calculation
                Next i

                If (cs <> 0) Then sume  ' Check for checksum error

                I2CWrite sda,scl,$A0,addr,[STR dta1\bb] ' Write remaining data to device

Else                    ' Write once if 8 or less bytes of data
      
                For i = 0 To bb         ' Loop for each expected data-byte and checksum
                        HSerin [HEX2 dta1[i]]   ' Store each byte to location in array
                        cs = cs + dta1[i]       ' Add each byte to checksum calculation
                Next i
       
                If (cs <> 0) Then sume  ' Check for checksum error

                I2CWrite sda,scl,$A0,addr,[STR dta1\bb] ' Write data to device
               
EndIf
           
        ln = ln + 1                     ' Count line received
        Goto loop                       ' Go get another line
       

sume:   HSerout ["Checksum Error: line ",DEC ln,13,10]  ' Notify: checksum error

               
eof:    HSerout [DEC ln," lines received",13,10]' Notify: Confirm line count


        For i = 0 To (ln*16)' Loop 16 times for each line received

I2CRead sda,scl,$A0,i,[cs]' Read back each character
        HSerout [HEX2 cs]       ' Send each character

        If (i+1)//16 = 0 Then
        HSerout [13,10]' New line every 16 characters
               EndIf                                  

        Next i

HSerout [13,10,13,10]           ' New Lines

        End

0000000000000000000000000000000000000000000000000000000000




' LCD clock program using Dallas1202/1302 RTC

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
DefineLOADER_USED1

        Include "MODEDEFS.BAS"  ' Include Shiftin/out modes

Define  LCD_DREG        PORTD   ' Define LCD connections
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

' Alias pins
RST     var     PORTA.2
IO      var     PORTC.1
SCLK    var     PORTC.3

' Allocate variables
rtcyear var     byte
rtcday  var     byte
rtcmonth var    byte
rtcdate var     byte
rtchr   var     byte
rtcmin  var     byte
rtcsec  var     byte
rtccontrol var  byte


        Low RST         ' Reset RTC
        Low SCLK

        ADCON1 = 7      ' PORTA and E digital
        Low PORTE.2     ' LCD R/W low = write
        Pause 100       ' Wait for LCD to startup

        ' Set initial time to 8:00:00AM 07/16/99
        rtcyear = $99
        rtcday = $06
        rtcmonth = $07
        rtcdate = $16
        rtchr = $08
        rtcmin = 0
        rtcsec = 0
        Gosub settime   ' Set the time

        Goto mainloop   ' Skip subroutines


' Subroutine to write time to RTC
settime:
        RST = 1         ' Ready for transfer

        ' Enable write
        Shiftout IO, SCLK, LSBFIRST, [$8e, 0]

        RST = 0         ' Reset RTC

        RST = 1         ' Ready for transfer

        ' Write all 8 RTC registers in burst mode
        Shiftout IO, SCLK, LSBFIRST, [$be, rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, 0]

        RST = 0         ' Reset RTC
        Return

' Subroutine to read time from RTC
gettime:
        RST = 1         ' Ready for transfer

        Shiftout IO, SCLK, LSBFIRST, [$bf]      ' Read all 8 RTC registers in burst mode
        Shiftin IO, SCLK, LSBPRE, [rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, rtccontrol]

        RST = 0         ' Reset RTC
        Return

' Main program loop - in this case, it only updates the LCD with the time
mainloop:
        Gosub gettime   ' Read the time from the RTC

        ' Display time on LCD
        Lcdout $fe, 1, hex2 rtcmonth, "/", hex2 rtcdate, "/" , hex2 rtcyear,_
        "  ", hex2 rtchr, ":", hex2 rtcmin, ":", hex2 rtcsec

        Pause 300       ' Do it about 3 times a second

        Goto mainloop   ' Do it forever

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to read and write to code space
' Flash Program Write must be enabled on your programmer
'
' Write to 8 locations of code space beginning at $1800
' Read 8 locations back and send to LCD repeatedly

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1


I    var     byte                ' Loop count
D    var     byte                ' Data
A    var     word                ' Address

        ADCON1 = 7                      ' Set PORTA and PORTE to digital
        Low PORTE.2                     ' LCD R/W line low (W)
        Pause 100                       ' Wait for LCD to start up

        For I = 0 To 7         ' Loop 8 times, once for each address $1800 to $1807
A = $1800 + I' Increment Address
                D = I + $A0          ' Change Data
Writecode A,D ' Send value in D to code space location A
        Next I

loop:   For I = 0 To 7          ' Loop 8 times, once for each address $1800 to $1807
A = $1800 + I' Increment Address
Readcode A,D' Get data in location A

                Lcdout $fe,1,hex A,": ",hex D   ' Display the location and data
                Pause 1000
        Next I

        Goto loop

        End

0000000000000000000000000000000000000000000000000000000000



' PicBasic Pro program to demonstrate an interrupt-driven
' input buffer for hardware USART receive using Assembly
' language interrupt.
' Pin definitions compatible with LAB-X1 and PIC16F877


' Defines for LCD
DEFINE  LCD_DREG        PORTD
DEFINE  LCD_DBIT        4
DEFINE  LCD_RSREG       PORTE
DEFINE  LCD_RSBIT       0
DEFINE  LCD_EREG        PORTE
DEFINE  LCD_EBIT        1

' Define interrupt handler
DEFINE INTHAND myint

' Configure internal registers
ADCON1 = 7' Set PortA and E to digital operation
RCSTA = $90' Enable USART receive
TXSTA = $24' Set USART parameters
SPBRG = 25' Set baud rate to 9600

LEDVARPORTD.0' Alias LED to PORTD.0
CRENVAR RCSTA.4' Alias CREN (Serial receive enable)

'Variables for saving state in interrupt handler
wsaveVARBYTE $70 system' Saves W
ssaveVARBYTE bank0 system' Saves STATUS
psaveVARBYTE bank0 system' Saves PCLATH
fsaveVARBYTE bank0 system' Saves FSR

buffer_sizeCON32' Sets size of ring buffer
bufferVARBYTE[buffer_size]' Array variable for holding received characters
index_inVARBYTE bank0' Pointer - next empty location in buffer
index_outVARBYTE bank0' Pointer - location of oldest character in buffer
errflagVARBYTE bank0 ' Error flag

bufcharVARBYTE' Stores the character retrieved from the buffer
colVARBYTE' Stores location on LCD for text wrapping
iVARBYTE' Loop counter


GoTo start' Skip around interrupt handler


' Assembly language INTERRUPT handler
Asm
myint

; Uncomment the following if the device has less than 2k of code space
;movwfwsave; Save W
;swapfSTATUS, W; Swap STATUS to W (swap avoids changing STATUS)
;clrfSTATUS; Clear STATUS
;movwfssave; Save swapped STATUS
;movfPCLATH, W; Move PCLATH to W
;movwfpsave; Save PCLATH

; Save the FSR value for later
movfFSR, W; Move FSR to W
movwffsave; Save FSR

; Check for hardware overrun error
btfscRCSTA,OERR; Check for usart overrun
GoTo usart_err; jump to assembly error routine

; Find in which bank the compiler put buffer, and set IRP
IF (_buffer > 0FFh); Find the bank where buffer is located
bsfSTATUS,IRP; If bank 2 or 3 set IRP
Else
bcfSTATUS,IRP; If bank 0 or 1 clear IRP
EndIF

; Test for buffer overrun
incf_index_in, W; Increment index_in to W
subwf_index_out, W; Subtract indexes to test for buffer overrun
btfscSTATUS,Z; check for zero (index_in = index_out)
GoTobuffer_err; jump to error routine if zero

; Increment the index_in pointer and reset it if it's outside the ring buffer
incf_index_in, F; Increment index_in to index_in
movf_index_in, W; Move new index_in to W
sublw_buffer_size-1; Subtract index_in from buffer_size-1
btfssSTATUS,C; If index_in => buffer_size
clrf_index_in; Clear index_in

; Set FSR with the location of the next empty location in buffer
movlwLow _buffer; Get the location of buffer[0]
addwf_index_in, W; Add index_in to point to next empty slot
movwfFSR; Store pointer in FSR

; Read and store the character from the USART
movf    RCREG, W; Read the received character
movwfINDF; Put the received character in FSR location


; Restore FSR, PCLATH, STATUS and W registers
finished
movffsave, W; retrieve FSR value
movwfFSR; Restore it to FSR
movfpsave, W; Retrieve PCLATH value
movwfPCLATH; Restore it to PCLATH
swapfssave, W; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
movwfSTATUS; Restore it to STATUS
swapfwsave, F; Swap the stored W value
swapfwsave, W; Restore it to W (swap to avoid changing STATUS)
retfie; Return from the interrupt

; Error routines
buffer_err; Jump here on buffer error
bsf_errflag,1; Set the buffer flag
usart_err; Jump here on USART error
bsf_errflag,0; Set the USART flag
movfRCREG, W; Trash the received character
GoTofinished; Restore state and return to program

EndAsm


start:

' Initialize variables
index_in = 0
index_out = 0
col = 1
errflag = 0

INTCON = %11000000' Enable interrupts
PIE1.5 = 1' Enable interrupt on USART

Low PORTE.2             ' LCD R/W line low (W)
Pause 100               ' Wait for LCD to start

LCDOut $fe,1' Clear LCD


' Main program starts here - blink an LED at 1Hz

loop:  
High LED        ' Turn on LED connected to PORTD.0
Pause 500   ' Pause 500mS
Low LED     ' Turn off LED connected to PORTD.0
Pause 500' Pause 500mS

display:' dump the buffer to the LCD
IF errflag Then error' Goto error routine if needed
IF index_in = index_out Then loop' loop if nothing in buffer

GoSub getbuf' Get a character from buffer
LCDOut bufchar' Send the character to LCD

col = col + 1' Increment LCD location
IF col > 20 Then' Check for end of line
col = 1' Reset LCD location
LCDOut $fe,$c0,REP " "\20' Clear any error on line-2 of LCD
LCDOut $FE,2' Tell LCD to return home
EndIF

GoTo display' Check for more characters in buffer


' Subroutines

' Get a character from the buffer
getbuf:' Move the next character in buffer to bufchar
intcon = 0' Disable interrupts while reading buffer
index_out = index_out + 1' Increment index_out pointer (0 to 63)
IF index_out => buffer_size Then index_out = 0' Reset pointer if outside buffer
bufchar = buffer[index_out]' Read buffer location(index_out)
INTCON = %11000000' Enable interrupts
Return

' Display an error
error:' Display error message
INTCON = 0' Disable interrupts while in the error routine
IF errflag.1 Then' Determine the error
LCDOut $FE,$c0,"Buffer Overrun"' Display buffer error on line-2
Else
LCDOut $FE,$c0,"USART Overrun"' Display usart error on line_2
EndIF

LCDOut $fe,2' Send the LCD cursor back to line-1 home
For i = 2 TO col' Loop for each column beyond 1
LCDOut $fe,$14' Put the cursor back where it was
Next i

errflag = 0' Reset the error flag
CREN = 0' Disable continuous receive to clear hardware error
CREN = 1' Enable continuous receive
INTCON = %11000000' Enable interrupts

GoTo display' Carry on

End

0000000000000000000000000000000000000000000000000000000000




' PicBasic Pro program to demonstrate an interrupt-driven
' input buffer for Hserin using On Interrupt.
' Pin definitions compatible with LAB-X1 and PIC16F877


' Defines for LCD and USART

DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 9600

DEFINE  LCD_DREG        PORTD
DEFINE  LCD_DBIT        4
DEFINE  LCD_RSREG       PORTE
DEFINE  LCD_RSBIT       0
DEFINE  LCD_EREG        PORTE
DEFINE  LCD_EBIT        1


ADCON1 = 7' Set PortA and E to digital operation

RCIFVARPIR1.5' Alias RCIF (USART Receive Interrupt Flag)
OERRVARRCSTA.1' Alias OERR (USART Overrun Error Flag)
CRENVARRCSTA.4' Alias CREN (USART Continuous Receive Enable)
LED     VARPORTD.0 ' Alias LED to PORTD.0

buffer_sizeCON32' Sets the size of the ring buffer
bufferVARBYTE[buffer_size]' Array variable for holding received characters
index_inVARBYTE' Pointer - next empty location in buffer
index_outVARBYTE' Pointer - location of oldest character in buffer
bufcharVARBYTE' Stores the character retrieved from the buffer
iVARBYTE' loop counter
colVARBYTE' Stores location on LCD for text wrapping
errflagVARBYTE' Holds error flags

' Initialize variables

index_in = 0
index_out = 0
i = 0
col = 1


Low PORTE.2             ' LCD R/W line low (W)
Pause 100               ' Wait for LCD to start

LCDOut $fe,1' Clear LCD


INTCON = %11000000' Enable interrupts
ON INTERRUPT GoTo serialin' Declare interrupt handler routine
PIE1.5 = 1' Enable interrupt on USART



' Main program starts here - blink an LED at 1Hz

loop:   High LED        ' Turn on LED connected to PORTD.0
        For i = 0 to 250' Delay for .5 seconds (250*2mS)
    Pause 2   ' Use a short pause within a loop
Next i' instead of one long pause
        Low LED     ' Turn off LED connected to PORTD.0
        For i = 0 to 250' Delay for .5 seconds (250*2mS)
        Pause 2   ' Use a short pause within a loop
Next i' instead of one long pause

display:' dump the buffer to the LCD
IF errflag Then error' Handle error if needed
IF index_in = index_out Then loop' loop if nothing in buffer

GoSub getbuf' Get a character from buffer
LCDOut bufchar' Send the character to LCD

col = col + 1' Increment LCD location
IF col > 20 Then' Check for end of line
col = 1' Reset LCD location
LCDOut $fe,$c0,REP " "\20' Clear line-2 of LCD
LCDOut $FE,2' Tell LCD to return home
EndIF

GoTo display' Check for more characters in buffer



' Subroutines

Disable' Don't check for interrupts in this section

getbuf:' move the next character in buffer to bufchar
index_out = (index_out + 1)' Increment index_out pointer (0 to 63)
IF index_out > (buffer_size-1) Then index_out = 0' Reset pointer if outside of buffer
bufchar = buffer[index_out]' Read buffer location
Return


error:' Display error message if buffer has overrun
IF errflag.1 Then' Determine the error
LCDOut $FE,$c0,"Buffer Overrun"' Display buffer error on line-2
Else
LCDOut $FE,$c0,"USART Overrun"' Display usart error on line-2
EndIF

LCDOut $fe,2' Send the LCD cursor back to line-1 home
For i = 2 to col' Loop for each column beyond 1
LCDOut $fe,$14' Move the cursor right to the right column
Next i

errflag = 0' Reset the error flag
CREN = 0' Disable continuous receive to clear overrun flag
CREN = 1' Enable continuous receive

GoTo display' Carry on


' Interrupt handler

serialin:' Buffer the character received
IF OERR Then usart_error' Check for USART errors
index_in = (index_in + 1)' Increment index_in pointer (0 to 63)
IF index_in > (buffer_size-1) Then index_in = 0'Reset pointer if outside of buffer
IF index_in = index_out Then buffer_error' Check for buffer overrun
HSerin [buffer[index_in]]' Read USART and store character to next empty location
IF RCIF Then serialin' Check for another character while we're here

Resume' Return to program

buffer_error:
errflag.1 = 1' Set the error flag for software
' Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer.
index_in = (index_in - 1) MIN (buffer_size - 1)
HSerin [buffer[index_in]]' Overwrite the last character stored (resets the interrupt flag)
usart_error: