Gcbasic

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 543

Great Cow BASIC documentation

The Great Cow BASIC development team @ 2017


Introducing Great Cow BASIC
Hello, and welcome to Great Cow BASIC help. This help file is intended to provide you insights and
knowledge to use Great Cow BASIC.

For information on installing Great Cow BASIC and several other programs that may be helpful, please
see Getting Started with Great Cow BASIC.

If you are new to programming, you should try the Great Cow BASIC demonstration programs these
explains everything in a step-by-step manner, and assumes no prior knowledge.

If you have programmed in another language, then the demonstration files and this command
reference may be the best place to turn.

If there is anything else that you need help on, please visit the Great Cow BASIC forum.

Using Great Cow BASIC


Need to compile a program with Great Cow BASIC, but don’t know where to begin? Try these simple
instructions:

- Complete the installation using the default values - select all the programmers but not the portable
mode.

- The installer will automatically start the IDE.

- When a Great Cow BASIC sourcefile is opened, check out the IDE Tools menu - through this menu you
can access the oneclick commands. Try right mousebutton - this will access the same options.

- The IDE Tools… commands (function keys F5 - F8) starts a Great Cow BASIC utility which calls the
(1)
batchfiles for compiling sourcecode and programming ("flashing") the target microcontroller. By
default these batchfiles are called flashAVR.bat (when the chipmodel is an AVR) and flashPIC.bat (when
the chipmodel is a PIC) and a batch file to create and program your microcontroller called
makeHEX.bat. The chipmodel is autodetected by the IDE.

- By editing these batchfiles you can configure the programmer software for your own needs. All the
programmers are located in the G+Stools subfolder.

- If there is a batchfile "FlashThis.bat" present in the same folder as the sourcefile, this batchfile is
used for flashing. This may be useful for project-specific flashing.

- Included programmer software is:


— Avrdude for AVR,
— PICPgm for PIC,

1
— PicKit2 and PicKit3
— TinyBootLoader+
— Microchip Xpress Board and many, many more.

(1)
You need a suitable programmer to do this, and instructions should be included with the
programmer on how to download to the microcontroller.

2
Changes
Formal Release of <>

Reference Time Stamp

ASCIIDOCs rendered 2017-05-14


23:38:36 GMT Daylight Time

Master ToC information 2017-05-12


07:56:38 GMT Daylight Time

Updates to HELP are as follows


• Updated #define USART_TX_BLOCKING examples

• Updated Conditions page with the known constraints of using functions as test conditions

• Updated SPI section, adding FastHWSPITransfer method

• Revised GLCD section to support SSD1306 128 * 32 pixels

• Updated ADC section to support all three read options for ReadAD, ReadAD10 and ReadAD12

• Updated Input/Output section to clarify AVR support.

• Added ILI9341 GLCD section.

• Added ILI9486L GLCD section.

• Updated Lookup Table section.

• Updated OtherDirectives section and added improved information on ChipFamily

Release 0.97.00
• #Startup section revised to document latest changes to priority of startup subroutines

• Added maintenance section

• Revised inittimer 1,3,5 and 7 to reflect additional clock sources

• Updated all PPS sections to reflect #startup as the recommended method

• Revised Pulsein and added PulseInInv

• Added PORTCHANGE to OnInterrupt section.

• Updated compiler insights for TRISIO cache.

3
• Updated HSerGetNum to support Longs and added an example.

• Revised LCD_IO 2_74xx164 to add the link to the circuit diagram

• Added output usage to other Directives

• Added SDD1306 support for SPI to GLCD section

• Added GetUserID section

• Added Software Serial (optimised) section

Release 0.96.00
• Revised String usage and String examples to show use of quote marks within a string

• Revised OtherDirectives to include missing constants

• Added DisplaySegment and revised DisplayChar

• Revised initimer2/4 and 6 to show revised prescalers

• Restore Bitwise operations and SetWith to Help

Release 0.95.010
• Added improvements to SerSend and SerPrint

• Revised 7 Segment Section to provide clarity, improve code and remove errors.

• Revised CCP and PWM section to include need capabilities

• Revised ADC section and add ADReadPreReadCommand constant

Release 0.95.009
• Added SH1106 GLCD driver

Release 0.95.008
• Updated version number only.

Release 0.95.007a
• Added #option explicit.

• Added variable lifecycle explanation.

• Revised and Improved PlayRTTTL section.

• Revised Wait and SPIMode sections.

Release 0.95.007

4
• Added new capabilities to support 16F1885x range of Microcontrollers.

• New PMW commands - support for hardware PWM

• New Initimer0 option to support 8bit and 16bit timer modules.

• New constants available ChipADC and ChipIO.

• New commands to support PPS. LOCKPPS and UNLOCKPPS.

• Added I2CStartoccurred command. Missing from Help.

• Additional information for Scripts.

• General removal of typos in Help files.

• Updated FnLSL section removing error.

• Removal of SetWith, FnEQUBit and FnNOTBit should now be replaced by built-in compiler
operations. Bits are now correctly handled by built-in Not operator.

• New command #option volatile. Sensitive pins can be marked as volatile, and native assignment
operators will set without glitching, replacing SetWith.

• Added new sections on ADC and PWM code optimisation

• Added new I2C command for software I2C - use_i2c_timeout

Release 0.95.006
• Completed rewrite of the Help File.

• New Help File in PDF.

• New Help File in XML.

• New Help File in HTML5.

• New Help File in HTML for Web.

• Revised Linux section

• Revised SPIMode section

Release 0.95.005a
• Revised RS232 Hardware section to improve readability

Release 0.95.005
• Added LeftPad

Release 0.95.004
• Updated HSerial commands to support AVR 1, 2, 3 and 4.

5
Release 0.95
• Added weak pullup command set

• Added RAM usage when defining Array

• Added new method to use a Constant to define an Array

• Added information on how to set address on mjkdz I2C LCD 1602 Modules

• Added new constants ChipWords and ChipEEPROM

• Added new Table definition method

• Added new capabilities to Lookup Tables

• Added new capability to READAD for AVR microcomputers

• Added instructions to compile Great Cow BASIC under Linux

• Added new command to invert an KS0108 GLCD display

• Added new example code - FLASH_LED

• Added how to set chip speed to non standard speeds

• Added new command parameter to hardware USART command set

• Added new command set for second hardware I2C port. The HI2C2 command set

• Added new command set for second USART port

• Added new ILI9340 GLCD driver command set

• Added SDD1289 GLCD driver command set

• Added example code


Measuring Pulse Width To Sub-Microsecond Resolution
Generating Accurate Pulses using a Macro
How to pass a Port address to routine using a Macro

• Added .NET support section

• Revised SPIMode command parameters

• Added #option NoContextSave

• Added On Intterupt: The default handler

• Added new sub-section Compiler Options, moved options from Compiler Directives

• Added new fonts support for GLCD

• Added new color support for GLCD

• Added LCD_IO_1 and changes LCD_IO_2 to support 74xx164 and 74xx174

• Revised most of the Timer section to support correct information.

• Added ADS7843 Touch Screen Controller support

• Added Play and PlayRTTL command set

6
• Added DIFFerence command

• Added three bitwise methods. FnNotBit, FnLSL and FnLSR

• Updated FAQ with 'how to set a bit'

• Added bitwise method FnequBit

• Added Timer6, Timer7, Timer8, Timer10 and Timer12 details to On Interrupt.

• Added new On Interrupt Example

• Added command line /WX

• Added HI2CWaitMSSP and HI2CWaitMSSPTimeout to the Hardware I2C section.

• Updated command line parameters

• Added Fill command

• Revised Arrays section

• Added ReadAD12 command

• Added divide and division explanation

• Added Str32 and Val32

• Added Support for USART2. HSerReceive1 and HSerReceive2

• Added HSerRecieveFrom

• Added HSerGetNum.HSertGetString

• Added Single channel measurement mode and Differential Channel Measurement mode to ADC
overview.

Release 0.94b
• Added HEFM support

• Added SSD 1306 GLCD Driver support

Release v0.91
• Added USART_TX_BLOCKING

• Added LCD_SPEED

• Improved LCD section

Release v0.9ho
• Updated parameter passing to Sub routines

• New and revised LCD section to include LCD_IO 10 and 12

• Remove of LAT where appropiate

7
• LAT has been deprecated. The compiler will redirect all I/O pin writes from PORTx to LATx
registers on PIC 16F1/18F.

• Use #option nolatch if problems occur.

• ADFormat changed to deprecated.

• Add default action to #CHIP when no frequency is specified.

Release v0.9hm
• Correct errors in PWM section and improved examples.

Release v0.9hn
• Changes to Arrays. Number of elements is now limited to 10,000 for 12F and 16F devices, or, the
available RAM.

• Lookup tables updated to reflect new methods of populating tables.

1. a single value on each line

2. multiple elements on a single line separated by commas

3. constants and calculations within the single line data table entries are permitted

• Repeat loop changed to support EXIT REPEAT

• New Pad command. The Pad method is used to create string to a specific length that is extended
with a specific character

• Added DS18B20 command set.

v0.9hm
• Updated I2C - software and hardware. Demonstration code now uses Chipino demonstration
board. Changed to Serial I2C section with these new examples.

• New Functional Commands:


LCDDisplayOn
LCDDisplayOff
LCDBackLight ( On | Off )

• New Defines to support LCD functionality are:


LCD_SPEED FAST
LCD_SPEED MEDIUM
LCD_SPEED SLOW

• Revised Functionality LCDHex now supports printing of leading zeros when the HEX number is
less than 0x10. call LCDHex as follows to ensure leading zeros are present.
LCDHex byte_value, LeadingZeroActive ; parameter called LeadingZeroActive

• New support for GLCD PCD8544 devices.

8
Changed GLCD section of the help to support the new device.

v0.9hl
• HSERPRINTCLRF - Added parameter to repeat the number of CRLF sent.

• Hardware I2C command set added. This is revised functionality to provide support the MSSP
module.

@0.9hk
• Help file updated to correct Power entry, it was in the incorrect section. Moved to Maths section
and other minors typos.

• Correct Timer0 information. Revised to show constants and the timer code was corrected.

@v0.9hj
• This information relates to the Hot Release 11 May 2014. Where functionality is not supported
by earlier versions of GCB please upgrade. Some functions will not work in the earlier releases
of Great Cow Basic.

• New Functional Commands


Circle. Draws a circle on the GLCD screen.
FilledCircle. Fills a circle on the GLCD screen
Log function(s)
Power function.

• Revised Functional Commands


Line. Now draws lines between any two points on the GLCD display.
#define GLCD_PROTECTOVERRUN . Controls drawing of circles to prevent overdraw of the circle at
display extremes.
#define Line OldLine. Adding this define will revert to the old line drawing routines. This has
been added for backward compatibility.

• Help File Revisions


Added PulseIn
Added IR_Remote header example
Added revised GLCD demonstration example
Added RGB LED Control example
Added section to show inline documentation method, see Code Documentation

@ v0.9hk
• Documented method for GCGB documentation.
Added MATHS.H
Added SQRT function.

9
@ v0.9hi
• Support for ST7735 documented. Functionality added to GLCD.h

• Support for ST7920 Graphical LCD 128 * 64 device.

• Revised GLCD section to include the one new and one undocumented device.

• New GLCD commands for support of ST7920 GLCD


ST7920GLCDEnableGraphics
ST7920GLCDDisableGraphics
ST7920GLCDClearGraphics
ST7920Locate
ST7920gTile
ST7920Tile
ST7920cTile
ST7920SetIcon
ST7920GraphicTest
ST7920LineHs
ST7920gLocate
ST7920lineh
ST7920linev

• Documented support for ST7735 GLCD.

• Revise GLCD commands with backwards compatibility:


GLCDCLS
GLCDPrint - supports LCD and GLCD modes
GLCDDrawString - support for string handling
GLCDDrawChar - Optional Colour
Box
FilledBox
Line
PSet
GLCDReady

• InitGLCD, includes fix for startup routine for KS0108 devices


Private ST7920 functions but can be used as needed..
ST7920WriteCommand
ST7920WriteData
ST7920WriteByte
ST7920gReaddata
ST7920GLCDReadByte
GLCDTimeDelay

• Updated conditional test information.

• Updated KeyPad information.

• Updated Lookup table information.

10
• Added Macro information.

• Added new Trig maths section.

• Added two new Circle examples

• Added Other Directive information.

• Added example programs

• Mid Point Circles

• Trigonometry Circles

@v0.9hg
• Corrected GLCD Common Anode display pages

@v0.9hf
• Revised 7 Segment section to support Common Cathode. Split 7 Segment entry to show the two
options available.

@v0.9he
• New commands. Required post March 2014 LCD.h:
LCDHOME, LCDSPACE, LCDCreateGraph, LCDCursor, LCDCmd

• Added Concatenation

• Updated DisplayValue to show the support for HEX values. Required post March 2014
7Segment.h

• Updated GLCD example code to ensure the example compiled without external files.

• Added Trigonometry and the example application

• Updated the LCD Overview to include the LATx support for higher clock speed. Required post
March 2014 LCD.h

@v0.9hd
• Revised Rotate to clarify type supported byte types.

@v0.9hc Mar 2014


• Revised HSERPRINT to show Integers and Longs are supported and changed the text to be
correct.

• Added HserPrintByteCRLF and HserPrintCRLF

• Added Sine Table Example

11
• Revised TABLE to show the limitation with respect to using WORDS when placing TABLES in
EEPROM

@v0.9hb Mar 2014


• Added PulseOutInv

• I2CRestart

• Add new variants to use of Comments

• Added Assembler Section

Jan 14
• New item(s):
Len, Asc, Chr, Trim, Ltrim, Rtrim, Swap4, Swap, Abs, Average, Trim, Ltrim, Rtrim, Wordtobin, Bytetobin,
GLCD, DectoBCD, BCDtoDec
Using variables
More on constants and variables
Acknowledgements

• Changes to:
Str, Hex, Poke, Else, Readtable, Exit (was exitsub)
Command line parameters Frequently asked questions

• Fixed typos.

• Updated REPEAT maximum repeat value.

• Updated most pages for layout.


Fixed links to external pages, again. This time downloaded as full html pages, for POT and LC.
Added LABEL, Bootloader and revise Select, add READAD10
Fix Double SWAP

@v0.9hg
• Corrected GLCD Common Anode display pages

@v0.9hf
• Revised 7 Segment section to support Common Cathode. Split 7 Segment entry to show the two
options available.

@v0.9he
• New commands. Required post March 2014 LCD.h:
LCDHOME, LCDSPACE, LCDCreateGraph, LCDCursor, LCDCmd

• Added Concatenation

12
• Updated DisplayValue to show the support for HEX values. Required post March 2014
7Segment.h

• Updated GLCD example code to ensure the example compiled without external files.

• Added Trigonometry and the example application

• Updated the LCD Overview to include the LATx support for higher clock speed. Required post
March 2014 LCD.h

@v0.9hd
• Revised Rotate to clarify type supported byte types.

@v0.9hc Mar 2014


• Revised HSERPRINT to show Integers and Longs are supported and changed the text to be
correct.

• Added HserPrintByteCRLF and HserPrintCRLF

• Added Sine Table Example

• Revised TABLE to show the limitation with respect to using WORDS when placing TABLES in
EEPROM

@v0.9hb Mar 2014


• Added PulseOutInv

• I2CRestart

• Add new variants to use of Comments

• Added Assembler Section

Jan 14
• New item(s):
Len, sc, Chr, Trim, Ltrim, Rtrim, Swap4, Swap, Abs, Average, Trim, Ltrim, Rtrim, Wordtobin, Bytetobin,
GLCD, DectoBCD, BCDtoDec
Using variables
More on constants and variables
Acknowledgements

• Changes to:
Str, Hex, Poke, Else, Readtable, Exit (was exitsub)
Command line parameters Frequently asked questions

• Fixed typos.

• Updated REPEAT maximum repeat value.

13
• Updated most pages for layout.
Fixed links to external pages, again. This time downloaded as full html pages, for POT and LC.
Added LABEL, Bootloader and revise Select, add READAD10
Fix Double SWAP

Command Line Parameters


About the Command Line Parameters

GCBASIC [/O:output.asm] [/A:assembler] [/P:programmer] [/K:\{C|A}] [/V] [/L] [/NP]


filename

GCBASIC [/O:output.asm] [/A:assembler] [/P:programmer] [/K:{C|A}] [/V] [/L] [/WX]


[/NP] filename

GCBASIC /version

Switch Description Default

/O:filen Sets the name of the assembly file generated to Same name as the input file, but
ame filename. with a .asm extension.

/A:assem Batch file used to call assembler(1). If /A:GCASM is given, The program will not be assembled
bler Great Cow BASIC will use its internal assembler.

/P:progr Batch file used to call programmer(1). This parameter is The program will not be
ammer ignored if the program is not assembled. downloaded.

/K:{C|A} Keep original code in assembly output. /K:C will save No original code left in output.
comments, /K:A will preserve all input code.

/V Verbose mode - compiler gives more detailed -


information about its activities.

/L Show license and exit. -

/NP Do not pause on errors. Use with IDEs. Pause when an error occurs, and
wait for the user to press a key.

/WX Force compiler to ensure all include files are valid.

/version Shown build date and version of the compiler.

/S Load the settings from a specified file, rather than use


the defaults.

filename The file to compile. -

14
(1)
For the /A: and /P: switches, there are special options available. If %FILENAME% is present, it will be
replaced by the name of the .asm file. %FN_NOEXT% will be replaced by the name of the .asm file but
without an extension, and %CHIPMODEL% will be replaced with the name of the chip. The name of the chip
will be the same as that on the chip data file.

A batch file to load the ASM from Great Cow BASIC into MPASM. Command line should be like this:

C:\progra~1\microc~1\mpasms~1\MPASMWIN /c- /o- /q+ /l- /x- /w1 %code%.asm

A batch file to compile in Great Cow BASIC then load the ASM from Great Cow BASIC into GPASM.
Command line should be like this:

gcbasic.exe %1 /NP /K:A /A:"..\gputils\bin\gpasm.exe %~d1%~p1%~n1.asm"

To instruct MAKEHEX.BAT to use GPASM. You have GPUTILS installed. The batch file should be edited
as follows:

REM Create the ASM


gcbasic.exe /NP /K:A %1
REM Use GPASM piping to the GCB error log
gpasm.exe "%~d1%~p1%~n1.asm" -k -i -w1 >> errors.txt

To summarise, you can use any of the following:

gcbasic.exe filetocompile.gcb /A:GCASM /P:"icprog -L%FILENAME%" /V /O:compiled.asm

Great Cow BASIC will compile the file, then assemble the program, and run this command:

`icprog -Lcompiled.hex`

You can also create/edit the gcbasic.ini file :

'Assembler settings
Assembler = C:\Program Files\Microchip\MPASM Suite\mpasmwin
AssemblerParams = /c- /o- /q+ /l+ /x- /w1 "%FileName%"

'Programmer settings
Programmer = C:\Program Files\WinPic\Winpic.exe
ProgrammerParams = /device=PIC%ChipModel% /p "%FileName%"

15
This example will use MPASM to assemble the program. It will run the program specified in the
assembler = line, and give it these parameters:

`/c- /o- /q+ /l+ /x- /w1 "compiled.asm"`

Then, it will run the programmer, and give it these parameters when it calls it:

`/device=PIC16F88 /p "compiled.hex"`

%ChipModel% will get replaced with the chip you are using, so this the chip Great Cow BASIC will pass to
WinPIC.

16
Frequently Asked Questions
Why doesn’t anything come up when I run GCBASIC.exe?

Great Cow BASIC is a command line compiler. To compile a file, you can drag and drop it onto the
GCBASIC.exe icon. There are also several Integrated Development Environments, or IDEs, available for
Great Cow BASIC. These will give you an area where you can edit your program and a button to send
the program to the chip. Several are listed on the Great Cow BASIC website.

What Microchip PIC and Atmel AVR microcontrollers does Great Cow BASIC support?

Hopefully, all 8 bit Microchip PIC and Atmel AVR microcontrollers (those in the PIC10, PIC12, PIC16 and
PIC18 families). If you find one that Great Cow BASIC does not work with properly, please post about it
in the Compiler Problems section of the Great Cow BASIC forum.

Is Great Cow BASIC case sensitive?

No! For example, Set, SET, set, SeT, etc are all treated exactly the same way by Great Cow BASIC.

Can I specify the bit of a variable to alter using another variable?

Setting a variable with other variable will expected. Great Cow BASIC support bitwise assignments. As
follows:

portc.0 = !porta.1

You can also use a shift function. As in other languages, by using the Shift Function FnLSL. AN
example is:

MyVar = FnLSL( 1, BitNum)` is Equivalent to `MyVar = 1<<BitNum`

To set a bit of a port prevent glitches during the output update, use this method.

'add this option for a specific port.


#option volatile portc.0

'then in your code


portc.0 = !porta.1

You can use this method to set a bit of a port. Encapsulate it in the SetWith method, this also eliminates
any glitches during the update, use this method.

17
SetWith(MyPORT, MyPORT OR FnLSL( 1, BitNum))

To clear a bit of a port, use this method.

MyPORT = MyPORT AND NOT FnLSL( 1, BitNum))

To set a bit within an array, use this method.

video_buffer_A1(video_adress) = video_buffer_A1(video_adress) OR FnLSL( 1, BitNum)

See also Set, FnLSL, FnLSR and Rotate

Why is x feature not implemented?

Because it hasn’t been thought of, or no-one has been able to implement it! If there are any features
that you would like to see in Great Cow BASIC, please post them in the "Open Discussion" section of the
Great Cow BASIC forum. Or, if you can, have a go at adding the feature yourself!

When using an include file does this use lots of memory?

When using include files, in this instance the <ds3231.h> include, if you are not using all the functions
of the include file, does GCB know not to include the non used functions within the include file when
compiling, or does everything get included anyway. For instance, if I am not using the hardware I2C,
does all the code related to hardware I2C still get compiled in the code?

Great Cow BASIC only compiles functions and subroutines if they are called. Great Cow BASIC starts by
compiling the main routine, then anything called from there. Each time it finds a new subroutine that
is called, it compiles it and anything that it calls. If a subroutine is not needed, it does not get compiled.

My LCD will not operate as expected?

Try adding. #define LCD_SPEED SLOW

This will slow the writing to the LCD.

Atmel AVR memory usage displayed is incorrect?

Atmel AVR memory values are specified in WORDS in Great Cow BASIC. The Great Cow BASIC compiler
uses words, not bytes, for consistency between Microchip PIC and Atmel AVR microcontrollers. This
keeps parts of the compiler simpler.

I cannot open the Window Help File?

See http://digital.ni.com/public.nsf/allkb/B59D2B24D624B823862575FC0056F3D0

18
Troubleshooting
Problem Common Causes More Assistance

There is an error in the program. Is Great Cow BASIC Forums


Great Cow BASIC complaining about
a particular line of code?

Cannot compile a Great Cow BASIC has not been Great Cow BASIC Forums
program installed correctly - reinstall it.

There is a bug in Great Cow BASIC Post on the Great Cow BASIC Forums.
Ensure you state the version of your
compiler and attach your code as a ZIP.

A program compiles Oscillator not selected. Configuration


and downloads fine,
but will not run

19
Compiler Insights
This section will provide some insights into what the compiler does

How does the compiler cope with read only registers in the Chip Family 12 range?

Within this chip range the Option register is a write only register. Reading the register is not permitted.

Great Cow BASIC needs to update this when the user wants to change the configuration - the Sleep
process is an example of a user change.

The compiler handles this by the creation of the Option_reg byte variable. This byte is created by the
compiler to manage the required write process.

The Option_reg variable is a cache that compiler will create if any bits of option_reg have been set
manually.

If the user changes any of the bits in a program, then the compiler will find any uses of the option
instruction and insert a "movwf OPTION_REG" immediately before the option instruction to cache the
value in the buffer.

If Option_reg bits aren’t set individually anywhere, then option_reg doesn’t get created, and nothing
special is done with the option instruction.

Essentially the compiler maintains a special variable and manages the whole process without the user
being aware.

How does the compiler cope with the TRIS register in the 10f products?

The compiler ensures that a TRIS cache matches the actual TRIS register. The TRIS cache is a byte
variable called TRISIO. The TRISIO cache is required as TRIS is a write-only register.

All ports default to input ( where all TRIS bits to 1) on reset. Therefore, this is assummed to be the
value 255.

TRISIO is updated when required by the user code and then used in the writing to the correct register.

The example user code and the assiocated assembly shows TRISIO cache in use. This method complies
with datasheet.

User Code

20
'set as input
dir gpio.0 in
gpio0State = gpio.0
'set as output this will require TRIS GPIO to be set using the TRISIO cache.
dir gpio.0 out
gpio.0 = 1

ASM

;dir gpio.0 in
bsf TRISIO,0
movf TRISIO,W
tris GPIO
;gpio0State = gpio.0
clrf GPIO0STATE
btfsc GPIO,0
incf GPIO0STATE,F
;dir gpio.0 out
bcf TRISIO,0
movf TRISIO,W
tris GPIO
;gpio.0 = 1
bsf GPIO,0

Anywhere that an individual TRIS bit is set/cleared by change the port direction, the bit in the cache is
changed and then that gets written to the TRIS register.

21
Libraries Overview
About Libraries

Great Cow BASIC (as with most other microcontroller programming languages) supports libraries.

You can create you own device specific library, you are not limited to those shown below. If you create
a new device specific library - please submit for inclusion in the next release via the Great Cow BASIC
forum.

Maintenance of these libraries is completed by the Great Cow BASIC development team. If you wish to
adapt these libraries you should create a local copy, edit and save within your development file
structure. The development team may update these libraries as part of a release and we do not want
you to lose your local changes.

To use a library, simple inlcude the following in your user code

#include <3PI.H> 'this will include the 3PI capabilities within your program

To use a local copy of a library, simple inlcude the following in your user code

#include "C:\mydev\library\3pi.h" 'this will include a local copy of the the 3PI
capabilities within your program

Great Cow BASIC supports the following device libraries.

Library Class Usage

3PI Polulu 3pi robot A library that interfaces the switch and the motors.

ALPS-EC11 Rotary Encoder A device specific library for a rotary encoder.

ADS7843 Touch Shield A library that interfaces with the ADS7843 touch screen.

CHIPINO Shield A library that interfaces the Chipino board with Arduino
like port addresses.

DHT Temperature and A library that supports the DHT22 and the DHT11
Humidity Temperature and Humidity sensors.

DS1307 Clock A library that supports the timer clock and NVRAM
functions.

DS1672 Clock A library that supports the timer clock and NVRAM
functions.

DS18B20 Temperature A library that supports the temperature functions.

22
Library Class Usage

DS18S20 Temperature A library that supports the temperature functions.

DS2482 Clock A library that supports the I2C to Dallas OneWire


functions.

DS3231 Clock A library that supports the timer clock and NVRAM
functions.

DUEMILANOVE Shield A library that interfaces the Duemilanove board with


Arduino like port addresses.

EMC1001 Temperature A library that supports the temperature functions and


the other device capabilities.

FRAM I2C Eeprom A library that supports memory functions.

GETUSERID Microchip read ID A library that supports the identification of Microchip


microcontrollers.

GLCD Graphical LCD A core library for Graphical LCD support.

GLCD_ILI9340 Graphical LCD A device specific library for an Graphical LCD.

GLCD_ILI9341 Graphical LCD A device specific library for an Graphical LCD.

GLCD_ILI9486L Graphical LCD A device specific library for an Graphical LCD.

GLCD_IMAGESANDFON Graphical LCD A library to increase the capabilities of the Graphical


TS_ADDIN3 LCDs.

GLCD_KS0108 Graphical LCD A device specific library for an Graphical LCD.

GLCD_PCD8544 Graphical LCD A device specific library for an Graphical LCD.

GLCD_SH1106 Graphical LCD A device specific library for an Graphical LCD.

GLCD_SSD1289 Graphical LCD A device specific library for an Graphical LCD.

GLCD_SSD1306 Graphical LCD A device specific library for an Graphical LCD.

GLCD_ST7735 Graphical LCD A device specific library for an Graphical LCD.

GLCD_ST7920 Graphical LCD A device specific library for an Graphical LCD.

HEFLASH HEF Memory A library that supports the HEF memory functions.
Driver

HMC5883L Triple-axis A library that supports the magnetometer functions.


Magnetometer

HWI2C_ISR_HANDLER I2C Slave Driver A library that supports the use of a Microchip
microcontroller as an I2C slave.

HWI2C_MESSAGEINTE I2C Slave A support library that supports the use of a Microchip
RFACE microcontroller as an I2C slave.

23
Library Class Usage

I2CEEPROM I2C EEProm A library that supports memory functions.

LCD2SERIALREDIRECT LCD to Serial A library that supports the use of a serial and PC
Handler terminal as a psuedo LCD.

LEGO-PF Lego Mindstorms A library that supports the Lego Mindstorms robot
shield

LEGO Lego Mindstorms A library that supports the Lego Mindstorms robot
shield

MATHS Maths routines A library that supports maths functions such as logs,
power and atan.

MAX6675 Temperature A library that supports the temperature functions.

MCP23008 i2C to serial A library that supports the I2C to serial functions.

MCP23017 i2C to serial A library that supports the I2C to serial functions.

MCP4XXXDIGITALPOT Digital Pot A library that supports the MCPxxxx range of digital
potentiometers.

MCP7940N Clock A library that supports the timer clock and NVRAM
functions.

NUNCHUCK Game controller A library that supports the NunChuck game controller.

PCF8574 GLCD A device specific library for an Graphical LCD.

SD SD Card A device specific library for an SD Card.

SOFTSERIAL Serial A library for software serial.

SOFTSERIALCH1 Serial A library for software serial.

SOFTSERIALCH2 Serial A library for software serial.

SOFTSERIALCH3 Serial A library for software serial.

SONGLAY Music A library for play music. Supports QBASIC and RTTTL
format.

SONYREMOTE Infrared A library that supports the functions of a Sony remote


control.

SRF02 Distance Sensor A library that supports the SRF02 ultrasonic sensor.

SRF04 Distance Sensor A library that supports the SRF04 ultrasonic sensor.

TEA5767 I2C Radio A library that supports the TEA5767 radio.

TRIG2PLACES Maths functions A maths library that supports trignometry to two places.

24
Library Class Usage

TRIG3PLACES Maths functions A maths library that supports trignometry to three


places

TRIG4PLACES Maths functions A maths library that supports trignometry to four places

UNO_MEGA328P Shield A library that interfaces the shield with Arduino like port
addresses.

Great Cow BASIC supports the following core libraries. These libraries are automatically included in
your user program therefore you do not need to use '#include' to access the libraries capabilities.

Library Class Usage

7SEGME 7 Segment LED A library that interfaces the device.


NT display

A-D Analog to Digital A library that supports the ADC functionality.

EEPRO EEProm A library that supports I2C eeprom devices.


M

HWI2C I2C A library that supports the MSSP and TWI hardware modules of I2C

HWI2C2 I2C A library that supports the MSSP and TWI hardware modules of I2C on
channel two

HWSPI SPI A library that supports the MSSP and TWI hardware modules of SPI

HWI2C I2C A library that supports software I2C

KEYPAD KeyPad A library that supports a keypad.

HWI2C I2C A library that supports keyboard functionality

LCD LCD A library that supports LCD functionality, library supports many
different communications methods.

PWM Pulse Width A library supports PWM functionality.


Modulation

RANDO Random A library supports random number functionality.


M Numbers

REMOT Infrared A library that supports the functions of a NEC remote control.
E

RS232 Serial A library for serial communications.

SOUND Tones A library for sound and tone generation

25
Library Class Usage

STDBASI Utility Functions The library that contains many of the utility methods.
C

STRING String The library that contains the string methods.

SYSTEM System The library that contains the system methods.

TIMER Timers The library that contains the timer methods.

USART Serial The library that contains the hardware serial methods that use the MSSP
or AVR equivilent hardware module.

26
Acknowledgements
Developers and Contributors:

Hugh Considine - Main developer of Great Cow BASIC

Stefano Bonomi - Two-wire LCD subroutines

Geordie Millar - Swap and Swap4 subroutines

Jacques Nilo - HEFM and help file conversion to asciidoc

Finn Stokes - 8-bit multiply routine, program memory access code

Evan Venn - Utilities, revised I2C routines, this help file and generally everything else!

Translation Contributors:

Stefano Delfiore - Italian

Pablo Curvelo - Spanish

Murat Inceer - Turkish

Other Contributors:

Russ Hensel - Great Cow BASIC Notes.

Chuck Hellebuyck - His documentation for the GLCD and other pieces, see http://www.elproducts.com.

Frank Steinberg - GCB@SYN IDE for Great Cow BASIC, see


http://sourceforge.net/projects/gcbasic/files/IDE/GCB%40Syn/GCB%40Syn.zip.

Alexy T. - SynWrite IDE used for GCB IDE, see http://www.uvviewsoft.com/synwrite.

Thomas Henry for the Select Case and the Sine Table examples.

William Roth for the LCD code and supporting diagrams.

Theo Loermans for the revised LCD sections and the library.

Chris Roper for the bitwise methods including the library including FnEquBit, FnNotBit, FnlslBit,
FnlsrBit and SetWith.

Conversion of asciidoctor documentation files:

See the asciidoctor Web site and the support forum.

27
Microcontroller Fundamentals
Inputs/Outputs
About Inputs and Outputs

Most general purpose pins on a microcontroller can function in one of two modes: input mode, or
output mode.

When acting as an input, the general purpose input/output pin will be placed in a high impedance
state. The microcontroller will then sense the general purpose input/output pin, and the program can
read the state of the general purpose input/output pin and make decisions based on it.

When in output mode, the microcontroller will connect the general purpose input/output pin to either
Vcc (the positive supply), or Vss (ground, or the negative supply). The program can then set the state of
the general purpose input/output pin to either high or low.

Great Cow BASIC will attempt to determine the direction of each general purpose input/output pin, and
set it appropriately, when possible. Great Cow BASIC will try to set the direction of the general purpose
input/output pin. However, if the general purpose input/output pin is read from and written to in your
program, then the general purpose input/output pin must be configured to input or output mode by the
program, using the appropriate Dir commands.

Example of dir commands.

'The port address is microcontroller specific. Portx.x is a general case for PICs
and AVRs
dir portb.0 in
dir portb.1 out

'The port address is microcontroller specific. gpiox.x is a general case for some
PICs
dir gpio.0 in
dir gpio.1 Out

'Set the whole port as an output


dir portb out
dir gpio out

'Set the whole port as an input


dir portc in
dir gpio in

Microchip specifics for read/write operations

28
For the specific ports and general purpose input/output pins available for a specific microcontroller
please refer to the datasheet.

Port Purpose Example

PORTx maps to the microcontrollers Read: PORTx the port data register for a read uservar=PORTA
digital pins 0 to 7. Where x can be operation. uservar=PORTA
a,b,c,d,e,f or g .1

PORTx maps to microcontrollers Write: PORTx the port data register for a PORTA=255
digital pins 0 to 7. Where x can be write operation, and, where LATx is not PORTA.1=1
a,b,c,d,e,f or g required as Great Cow BASIC will implement
LATx when needed. See Option NoLatch for
more information on LAT registers and how
to disable this automatic function.

To read a general purpose input/output pin, you need to ensure the direction is correct DIR Portx IN is
set (default is IN) or a specific set of port bits. Where uservar = PORTx.n can be used.

Examples:

uservar = PORTb.0
uservar = PORTb

To write to a general purpose input/output pin, you need to ensure the direction is correct DIR Portx
OUT for port or a specific set of port bits. Where PORTx.n = uservar can be used.

Examples:

PORTb.0 = uservar
PORTb = uservar

ATMEL specifics for read/write operations

Using a Mega328p as a general the following provides insights for the AVR devices. For the specific
ports and general purpose input/output pins available for a specific microcontroller please refer to the
datasheet.

Port Write operation Read operation

PORTD maps to Mega328p (and, the AVR PORTD - The Port D Data Register - write PIND - The Port D
microcontrollers) digital pins 0 to 7 operation (a read operation to a port Input Pins Register
will provide the pull-up status) - read only

29
Port Write operation Read operation

PORTB maps to Mega328p (and, the AVR PORTB - The Port B Data Register - write PINB - The Port B
microcontrollers) digital pins 8 to 13. operation (a read operation to a port Input Pins Register
The two high bits (6 & 7) map to the will provide the pull-up status) - read only
crystal pins and are not usable

PORTC maps to Mega328p (and, the AVR PORTC - The Port C Data Register - write PINC - The Port C
microcontrollers) analog pins 0 to 5. operation (a read operation to a port Input Pins Register
Pins 6 & 7 are only accessible on the will provide the pull-up status) - read only
Mega328p (and, the AVR
microcontrollers) Mini

To read a general purpose input/output pin, you need to ensure the direction is correct DIR Portx IN is
set (default is IN) or a specific set of port bits. Where uservar = PINx.n can be used and therefore to
read data port use uservar = PINx.

Examples:

uservar = PINb.0
uservar = PINb

To write to a general purpose input/output pin you need to ensure the direction is correct DIR Portx
OUT for port or a specific set of port bits. Where PORTx.n = uservar can be used and therefore to write to
a data port use PORTx = uservar.

Examples:

PORTb.0 = uservar
PORTb = uservar

Setting Ports and Port.bit

You can set a port as shown above with a variable, or, you can set with a constant or any combination
using the bitwise and logical operators.

#define InitStateofPort 0b11110000


PORTb = InitStateofPort 'will unconditionally set bits 4:7

PORTb = 0b11110000 'will unconditionally set bits 4:7

PORTb = uservar OR 0b11110000 'will OR bits 4:7 to ensure bits 4:7 are set

30
The following is also valid - read a port.bit and then set port.bit with a variable or port value. As shown
below.

dir portb out

portb.0 = NOT portb.0

The user code above may cause issues with glitches when the read and write operations occurs. Let us
look at the generated assembler.

;portb.0 = NOT portb.0


banksel SYSTEMP1
clrf SysTemp1
btfsc PORTB,0
incf SysTemp1,F
comf SysTemp1,F
bcf PORTB,0
btfsc SysTemp1,0
bsf PORTB,0

To resolve any glitches add #option Volatile to your user code.

#option Volatile portb.0

dir portb out

portb.0 = NOT portb.0

This option provides the following assembler resolving the glitch issue.

;portb.0 = NOT portb.0


banksel SYSTEMP1
clrf SysTemp1
btfsc PORTB,0
incf SysTemp1,F
comf SysTemp1,F
btfsc SysTemp1,0
bsf PORTB,0
btfss SysTemp1,0
bcf PORTB,0

31
See also Dir, #Option Volatile

Configuration
About Configuration

(Note: This section does not apply to Atmel AVR microcontrollers. Atmel AVR microcontrollers do have a
similar configuration settings, but they are controlled through "Configuration Fuses". Great Cow BASIC
cannot set these - you MUST use the programmer software.)

Every Microchip PIC has a CONFIG word. This is an area of memory on the chip that stores settings
which govern the operation of the chip.

The following asects of the chip are governed by the CONFIG word:

• Oscillator selection - will the chip run from an internal oscillator, or is an external one attached?

• Automatic resets - should the chip reset if the power drops too low? If it detects it is running the
same piece of code over and over?

• Code protection - what areas of memory must be kept hidden once written to?

• Pin usage - which pins are available for programming, resetting the chip, or emitting PWM signals?

The exact configuration settings vary amongst chips. To find out a list of valid settings, please consult
the datasheet for the microcontrollers that you wish to use.

This can all be rather confusing - hence, Great Cow BASIC will automatically set some config settings,
unless told otherwise:

• Low Voltage Programming (LVP) is turned off. This enables the PGM pin (usually B3 or B4) to be
used as a normal I/O pin.

• Watchdog Timer (WDT) is turned off. The WDT resets the chip if it runs the same piece of code
over and over - this can cause trouble with some of the longer delay routines in Great Cow BASIC.

• Master Clear (MCLR) is disabled where possible. On many newer chips this allows the MCLR pin
(often PORTA.5) to be used as a standard input port. It also removes the need for a pull-up resistor
on the MCLR pin.

• An oscillator mode will be selected, based on the following rules:

◦ If the microcontroller has an internal oscillator, and the internal oscillator is capable of
generating the speed specified in the #chip line, then the internal oscillator will be used.

◦ If the clock speed is over 4 Mhz, the external HS oscillator is selected

◦ If the clock speed is 4 MHz or less, then the external XT oscillator mode is selected.

32
Note that these settings can easily be individually overridden whenever needed. For example, if the
Watchdog Timer is needed, adding the line

#config WDT = ON

This will enable the watchdog timer, without affecting any other configuration settings.

Using Configuration

Once the necessary CONFIG options have been determined, adding them to the program is easy. On a
new line type "#config" and then list the desired options separated by commas, such as in this line:

#config OSC = RC, BODEN = OFF

Great Cow BASIC also supports this format on 10/12/16 series chips:

#config INTOSC_OSC_NOCLKOUT, BODEN_OFF

However, for upwards compatibility with 18F chips, you should use the = style config settings.

It is possible to have several #config lines in a program - for instance, one in the main program, and
one in each of several #include files. However, care must then be taken to ensure that the settings in
one file do not conflict with those in another.

For more help, see #config Directive

33
Syntax
Arrays
About Arrays

An array is a special type of variable - one which can store several values at once. It is essentially a list
of byte numbers in which each one can be addressed individually through the use of an "index". The
index is a value in brackets immediately after the name of the array.

Examples of array names are:

Array/Index Meaning

Fish(10) Element 10 of an array called Fish

DataLog(2) The second number in an array named


DataLog
ButtonList(Temp) An element in the array ButtonList that
is selected according to the value in the
variable Temp

Defining an array

Use the DIM command to define an array.

DIM array_title ( number_of_elements )

The number of elements can be number, a variable or a constant.

Setting an entire array at once

It is possible to set several elements of an array with a single line of code. This short example shows
how:

Dim TestVar(10)
TestVar = 1, 2, 3, 4, 5, 6, 7, 8, 9

When using the method above element 0 of the array TestVar will be set to the number of items in the
list, which in this case is 9. Each element of the array will then be loaded with the corresponding value
in the list - so in the example, TestVar(1) will be set to 1, TestVar(2) to 2, and so on. Element 0 will only
be set to number of items in the array when using this method up to 48 data elements.

Array Length Element 0 should not be used to obtain the length of the array. Element 0 will only be a

34
consistent with respect to the length of the array when the array is set as shown above.

The correct method is to use a constant to set the array size and use the constant within your code to
obtain the array length.

#Define ArraySizeConstant 500


Dim TestVar( ArraySizeConstant )

SerPrint ArraySizeConstant 'or, other usage

Using Arrays

To use an array, its name is specified, then the index. Arrays can be used everywhere that a normal
variable can be used.

The limit on array size varies dependent on the chip type.

1. The 12F/16F series of chips the array limit is the physical RAM less a few bytes for array handling.

2. For the Atmel AVR or an 18F there is not limit other than free RAM.

3. However, Great Cow BASIC limits the array size of any array to 10,000 elements.

Get the most from the available memory

Array RAM usage is determined by the architecture of the chip type. Getting most out of the available
memory is determined by the allocation of the array within the available banks of memory.

An example is an array of 6 or 7 bytes when there is only 24 bytes of RAM and the 24 bytes is split
across multiple memory banks. Assume in this example that 18 bytes have allocated to other variables
and there is 29 bytes total available. An array of 6 bytes will fit into the free space in one bank, but the
array of 7 will not.

Great Cow BASIC currently cannot split an array over banks, so if there are 6 bytes free in one bank
and 5 in another, you cannot have an array of 7 bytes. This would be very hard to do efficiently on
12F/16F as there would be a series of special function registers in the middle of the array when using a
12F or 16F. This constraint is not the case on 16F1/18F as linear addressing makes it easy to span
banks because the SFRs are not making the problem (as with 12F/16F).

Using Tables as an alternative.

If there are many items in the array, it may be better to use a Lookup Table to store the items, and then
copy some of the data items into a smaller array as needed.

For more help, see Declaring arrays with DIM

35
Comments
About Comments

Adding comments to your Great Cow BASIC program is done with an apostrophe before the comment
line. You can also comment out sections of code if you want just by placing an apostrophe, a semi-colon
or use the statement REM at the beginning of each line. The SynGCB IDE has a feature to do this
automatically.

Warning: Great Cow Graphical BASIC uses semi-colons to mark comments that it has inserted
automatically. It does not read these comments when opening a file, so any comments in a Great Cow
BASIC program starting with a semi-colon will be deleted if the program is opened using Great Cow
Graphical BASIC.

Example:

' The number of pins to flash


#define FlashPins 2

REM You can create a header using an apostrophe before each line
REM This is a great way to describe your program
REM You can also use it to describe the hardware connections.

' You can place comments above the command or on the same line
Dir PORTB Out ' Initialise PORTB to all Outputs

; The Main loop


do
PORTB = 0 ' All Pins off
Wait 1 S ' Delay 1 second
PORTB = 0xFF ' All pins on
Wait 1 s ' Delay 1 second
Loop

Conditions
About Conditions

In Great Cow BASIC (and most other programming languages) a condition is a statement that can be
either true or false. Conditions are used when the program must make a decision. A condition is
generally given as a value or variable, a relative operator (such as = or >), and another value or
variable. Several conditions can be combined to form one condition through the use of logical
operators such as AND and OR.

Great Cow BASIC supports these relative operators:

36
Symbol Meaning

= Equal

<> Not Equal

< Less Than

> Greater Than

⇐ Less than or equal to

>= Equal to or greater than

In addition, these logical operators can be used to combine several conditions into one:

Name Abbreviation Condition true if

AND & both conditions are true

OR | at least one condition is


true

XOR # one condition is true

NOT ! the condition is not true

NOT is slightly different to the other logical operators, in that it only needs one other condition. Other
arithmetic operators may be combined in conditions, to change values before they are compared, for
example.

Great Cow BASIC has two built in conditions - TRUE, which is always true, and FALSE, which is always
false. These can be used to create infinite loops.

It is also possible to test individual bits in conditions. To do this, specify the bit to test, then 1 or 0 (or
ON and OFF respectively). Presently there is no way to combine bit tests with other conditions - NOT,
AND, OR and XOR will not work.

Example conditions:

Condition Comments

Temp = 0 Condition is true if Temp = 0

Sensor <> 0 Condition is true if Sensor is not 0

Reading1 > Reading2 True if Reading1 is more than Reading2

Mode = 1 AND Time > 10 True if Mode is 1 and Time is more than
10

Heat > 5 OR Smoke > 2 True if Heat is more than 5 or Smoke is


more than 2

37
Condition Comments

Light >= 10 AND (NOT Time > 7) True if Light is 10 or more, and Time is
7 or less

Temp.0 ON True if Temp bit 0 is on

Constraints when using Conditional Test

As Great Cow BASIC is very flexible with the use of variables type this can cause issues when testing
constants and/or functions.

A few simple rules. Always put the function or constant first, or, always call the function with the
addition of the braces.

The example code below shows the correct method and an example that does compile but will not
work as expected.

'Example A - works
'Call the function by adding the braces
'
Do
Loop While HSerReceive() <> 62

'Example B - works
'Please the constant first - this is the general rule - put the constant first.
'
Do
Loop While 62 <> HSerReceive

This fails as the function will not be called

'Example C - compiles but does not operate as expected


Do
Loop While HSerReceive <> 62

Constants
About Constants

38
A constant tells the compiler to find a given word, and replace it with another word or number. Define
directives create constants.

Constants are useful for situations where a routine needs to be easily altered. For example, a define
could be used to specify the amount of time to run an alarm for once triggered.

It is also possible to use defines to specify ports - thus defines can be used to aid in the creation of code
that can easily be adapted to run on a different microcontroller with different ports.

Great Cow BASIC makes considerable use of defines internally. For instance, the LCD code uses defines
to set the ports that it must use to communicate with the LCD.

About Defines

To create a define is a matter of using the #define directive. Here are some examples of defines:

#define Line 34
#define Light PORTB.0
#define LightOn Set PORTB.0 on

Line is a simple constant - Great Cow BASIC will find Line in the program, and replace it with the
number 34. This could be used in a line following program, to make it easier to calibrate the program
for different lighting conditions.

Light is a port - it represents a particular pin on the microcontroller. This would be of use if the
program had many lines of code that controlled the light, and there was a possibility that the port the
light was attached to would need to change in the future.

LightOn is a define used to make the program more readable. Rather than typing Set PORTB.0 on over
and over, it would then be made possible to type LightOn, and have the compiler do the hard work.

Great Cow BASIC Defined constants

#define ON 1
#define OFF 0
#define TRUE 255
#define FALSE 0

'Names for symbols


#define AND &
#define OR |
#define XOR #
#define NOT !
#define MOD %

39
Great Cow BASIC special constant

Forever is a special constant. For Great Cow BASIC Graphical users think of this as 'false'. For those not
using Great Cow BASIC Graphical think of this as a non numeric value that has no value. You can use
in a DO-LOOP but not in a REPEAT-END REPEAT loop, as the in the later case the REPEAT will have no
value and you will create an error condition.

Precedence of Constants within Great Cow BASIC.

The #define command creates constants, and, a script can creates constants.

The precedence is as follows:

#define in the main program are read first,

then, the #define in the include files. Constants defined in the include files will be ignored if they
conflict or are different to another constant in the main program,

then, the scripts are processed. Scripts that create constants always override any constant value
previously defined.

Scripts are highest priority, then constants in the main program, then constants in include files from
the main program, then constants in the standard libraries.

See #define

Functions
About Functions

Functions are a special type of subroutine that can return a value. This means that when the name of
the function is used in the place of a variable, Great Cow BASIC will call the function, get a value from
it, and then put the value into the line of code in the place of the variable.

Functions may also have parameters - these are treated in exactly the same way as parameters for
subroutines. The only exception is that brackets are required around any parameters when calling a
function.

Using Functions

This program uses a function called AverageAD to take two analog readings, and then make a decision
based on the average:

40
'Select chip
#chip 16F88, 20

'Define ports
#define LED PORTB.0
#define Sensor AN0

'Set port directions


dir LED out
dir PORTA.0 in

'Main code
Do
Set PORTB.0 Off
If AverageAD > 128 Then Set PORTB.0 On
wait 10 ms
Loop

Function AverageAD
'Get 2 readings, divide by 2, store in AverageAD
'Note the cast, the result of ReadAD needs to be converted to
'a word before adding, or the result may overflow.
AverageAD = ([word]ReadAD(Sensor) + ReadAD(Sensor)) / 2
end function

See Also Subroutines, Exit

Labels
About Labels

Labels are used as markers throughout the program. Labels are used to mark a position in the program
to ‘jump to’ from another position using a goto, gosub or other command.

Labels can be any word (that is not already a reserved keyword) and may contain digits and the
underscore character. Labels must start with a letter or underscore (not digit), and are followed
directly by a colon (:) at the marker position. The colon is not required within the actual commands.

The compiler is not case sensitive. Lower and/or upper case may be used at any time.

Example:

41
'This program will flash the light until the button is pressed
'off. Notice the label named SWITCH_OFF.

#chip 16F628A, 4

#define BUTTON PORTB.0


#define LIGHT PORTB.1
Dir BUTTON In
Dir BUTTON Out

Do
PulseOut LIGHT, 500 ms
If BUTTON = 1 Then Goto SWITCH_OFF
Wait 500 ms
If BUTTON = 1 Then Goto SWITCH_OFF
Loop

SWITCH_OFF:
Set LIGHT Off
'Chip will enter low power mode when program ends

For more help, see Goto, Gosub

Lookup Tables
About Lookup Tables

A lookup table is a list of values that are stored in the program memory of the chip, which can be
accessed using the ReadTable command.

The advantage of lookup tables is that they are memory efficient, compared to an equivalent set of IF
statements.

Data tables are defined as

1. a single value on each line

2. byte, word, longs and integer values are valid (no strings or decimals!)

3. multiple elements on a single line separated by commas

4. constants and calculations within the single line data table entries are permitted

5. an external data source file

Defining Tables

A single value on each line

42
Table TestDataSource as Integer
12
24
36
48
60
72
End Table

Multiple elements on a single line separated by commas:

Table TestDataSource as Integer


12, 24, 36
48, 60, 72
End Table

Constants and calculations within the single line:

#define calculation_constant 2

Table TestDataSource as Integer


1 * calculation_constant
2 * calculation_constant
4 * calculation_constant
8 * calculation_constant
16 * calculation_constant
32 * calculation_constant
End Table

Data tables can now be loaded directly from a file. The source file will be read as a hexidecimal raw
file.

Table TestDataSource from "sourcefile.raw"

Using Lookup Tables

First, the table must be created. The code to create a lookup table is simple - a line that has Table and
then the name of the table, a list of numbers (up to 10,000 elements), and then End Table.

For tables with more than 255 elements it is mandated to used a WORD variable to read the size of the
table. See below.

Once the table is created, the ReadTable command is used to read data from it. The ReadTable command

43
requires the name of the table it is to read, the location of the item to retrieve, and a variable to store
the retrieved number in.

Lookup tables can store byte, word, longs and integer values. Great Cow BASIC will automatically
detect the type of the table depending on the values in it. Great Cow BASIC can be explicitly instructed
to cast the table to a variable type, as follows:

Table TestDataSource as Integer


12
24
36
48
60
72
End Table

Item 0 of a lookup table stores the size of the table. If the ReadTable command attempts to read beyond
the end of the table, the value 0 will be returned.

For tables with more than 255 elements it is mandatory to use a WORD variable to read the size of the
table. See below.

dim lengthoftable word


readtable TestDataSource , 0, lengthoftable
print lengthoftable ; will print the size as a word

table TestDataSource
'a table with more than 255 elements
end table

For tables that are defined using an external file the table data will be read into the TestDataSource
table from the external file.

An example file is shown below:

The following program will import the external data file.

44
#chip 16f877a

Table TestDataSource from "sourcefile.raw"

for nn = 1 to 10
ReadTable TestDataSource, nn, inc
HSerPrint inc
next

And the program will out the following:

Advanced use of Lookup Tables

You can use the Table statement to store the data table in EEPROM. If the compiler is told to store a data
table in "Data" memory, it will store it in the EEPROM.

NOTE The limitation of of using EPPROM tables is that you can only store BYTEs. You cannot store
WORD values in the EEPROM tables.

Here is some example code:

45
#chip 16F628

'Read table item


'Must use ReadTable and a variable for the index, or the table won't be
downloaded to EEPROM

TableLoc = 2
ReadTable TestDataSource, TableLoc, SomeVar

'Write to table , this is not required


EPWrite 1, 45

'Table of values to write to EEPROM


'EEPROM location 0 will store length of table
'Subsequent locations will each store a value

Table TestDataSource Store Data


12
24
36
48
60
72
End Table

For more help, see ReadTable

Miscellaneous
About Miscellaneous things….

It is possible to combine multiple instructions on a single line, by separating them with a colon. For
example, this code:

Set PORTB.0 On
Set PORTB.1 On
Wait 1 sec
Set PORTB.0 Off
Set PORTB.0 Off

could also be written as:

46
Set PORTB.0 On: Set PORTB.1 On
Wait 1 sec
Set PORTB.0 Off: Set PORTB.0 Off

In most cases, it will make no difference if commands share a line or not. However, special care should
be taken with If commands, as this code:

Set PORTB.0 Off


Set PORTB.1 Off
If Temp > 10 Then Set PORTB.0 On: Set PORTB.1 On
Wait 1 s

Will be equivalent to this:

Set PORTB.0 Off


Set PORTB.1 Off
If Temp > 10 Then
Set PORTB.0 On
Set PORTB.1 On
End If
Wait 1 s

Also, the commands used to start and end subroutines, data tables and functions must be alone on a
line. For example, this is WRONG:

Sub Something: Set PORTB.0 Off: End Sub

ReadTable
About ReadTable

The ReadTable command is used to read information from lookup tables. TableName is the name of the
table that is to be read, Item is the line of the table to read, and Output is the variable to write the
retrieved value in to.

Syntax:

ReadTable TableName, Item, Output

Command Availability:

47
Available on all microcontrollers.

Explanation:

Item is 1 for the first line of the table, 2 for the second, and so on. Item 0 gives the size of the table. Care
must be taken to ensure that the program is not told to read beyond the end of the table, or strange
effects will be observed.

The type of Output should match the type of data stored in the table. For example, if the table contains
Word values then Output should be a Word variable. If the type does not match, Great Cow BASIC will
attempt to convert the value.

Example:

'Chip Settings
#chip 16F88, 20

'Hardware Settings
#define LED PORTB.0
Dir LED Out

'Main Routine
ReadTable TimesTwelve, 4, Temp
Set LED Off
If Temp = 48 Then Set LED On

'Lookup table named "TimesTwelve"


Table TimesTwelve
12
24
36
48
60
72
84
96
108
120
132
144
End Table

For more help, see Lookup Tables

48
Scripts
About Scripts

A script is a small section of code that Great Cow BASIC runs when it starts to compile a program. Uses
include performing calculations that are required to adjust the program for different chip frequencies.

Scripts are not compiled or downloaded to the microcontroller - Great Cow BASIC reads them, executes
them, then removes them from the program and then the results calculated can be used as constants in
the user program.

Inside a script, constants are treated like variables. Scripts can read the values of constants, and set
them to contain new values.

Using Scripts

Scripts start with #script and end with #endscript. Inside, they can consist of the following commands:

If
Assignment (=)
Error
Warning
Int()

If is similar to the If command in normal Great Cow BASIC code, except that it does not have an Else
clause. It is used to compare the values of the script constants.

The = sign is identical to that in Great Cow BASIC programs. The constant that is to be set goes on the
left side of the = and the new value goes to the right of the =.

Error is used to display an error message. Anything after the Error command is displayed at the end of
compilation, and is saved in the error log for the program.

Warning is used to display a warning message. Anything after the Warning command is displayed at the
end of compilation but warning does not halt compilation.

Int() will calculate the integer value of a calculation. Using Int() is critical to set the constant to the
integer component of the calculation.

Notes:

Use Warning to display constant values when creating and debugging scripts.

Scripts have a limited syntax and limited error checking when compiling. The compiler may halt if
you get something wrong.

Scripts that are incorrectly formatted may also halt the compiler or return unrelated error.

49
Scripts used for calculations should use the Int( expression ) where you may have a floating point
numbers returned.
Scripts do use floating point for all calculations and a failure to use Int() may set the script constant
and the resulting constant to 0.

Scripts may require that complex math expressions may require definition in multiple steps/line to
simplify the calculation.
The returned value could be incorrect if simplification is not implemented.

Scripts can only access existing constants both user and system defined.

User defines variables are not accessible within the scope of a script.

Scripts has precendence over #define. A #define constant statements are read first, then scripts run.
So, a script will always overwrite a constant that was set with #define.

Use Warning to display constants values when creating and debugging scripts.

Example Script

This script is used in the pwm.h file. It takes the values of the user defined constants PWM_Freq,
PWM_Duty and system constant ChipMHz and calculates the results using the equations. These
calculation are based on information from a Microchip PIC datasheet to calculate the correct values to
setup Pulse Width Modulation (PWM).

#script
PR2Temp = INT((1/PWM_Freq)/(4*(1/(ChipMHz*1000))))
T2PR = 1
If PR2Temp > 255 Then
PR2Temp = INT((1 / PWM_Freq) / (16 * (1 / (ChipMHz * 1000))))
T2PR = 4
If PR2Temp > 255 Then
PR2Temp = INT(( 1 / PWM_Freq) / (64 * (1 / (ChipMHz * 1000))))
T2PR = 16
If PR2Temp > 255 Then
Error Invalid PWM Frequency value
End If
End If
End If

DutyCycle = (PWM_Duty * 10.24) * PR2Temp / 1024


DutyCycleH = (DutyCycle AND 1020) / 4
DutyCycleL = DutyCycle AND 3
#endscript

During the execution of the script the calculations and assignment uses the constants in the script.

50
After this script has completed the constants PR2Temp, DutyCycleH and DutyCycleL are set using the
constants and/or the calculations.

The constants assigned in this script, PR2Temp, DutyCycleH and DutyCycleL, are made available as
constants in the user program.

Subroutines
About Subroutines

A subroutine is a small program inside of the main program. Subroutines are typically used when a
task needs to be repeated several times in different parts of the main program.

There are two main uses for subroutines:

• Keeping programs neat and easy to read

• Reducing the size of programs by allowing common sections of code to be reused.

When the microcontroller comes to a subroutine it saves its location in the current program before
jumping to the start of, or calling, the subroutine. Once it reaches the end of the subroutine it returns
to the main program, and continues to run the code where it left off previously.

Normally, it is possible for subroutines to call other subroutines. There are limits to the number of
times that a subroutine can call another sub, which vary from chip to chip:

Microcontroller Family Instruction Width Number of subs called

10F*, 12C5*, 12F5*, 16C5*, 16F5* 12 1

12C*, 12F*, 16C*, 16F*, except those above 14 7

18F*, 18C* 16 31

These limits are due to the amount of memory on the microcontroller which saves its location before it
jumps to a new subroutine. Some Great Cow BASIC commands are subroutines, so you should always
allow for 2 or 3 subroutine calls more than your program has.

Atmel AVR microcontrollers have no fixed limit on how many subroutines can be called at a time, but
if too many are called then some variables on the chip may be corrupted. To check if there are too
many subroutines, work out the most that will be called at once, then multiply that number by 2 and
create an array of that size. If an out of memory error message comes up, there are too many calls.

Another feature of subroutines is that they are able to accept parameters. These are values that are
passed from the main program to the subroutine when it is called, and then passed back when the
subroutine ends.

Using Subroutines

51
To call a subroutine is very simple - all that is needed is the name of the sub, and then a list of
parameters. This code will call a subroutine named "Buzz" that has no parameters:

Buzz

If the sub has parameters, then they should be listed after the name of the subroutine. This would be
the command to call a subroutine named "MoveArm" that has three parameters:

MoveArm NewX, NewY, 10

Or, you may choose to put brackets around the parameters, like so:

MoveArm (NewX, NewY, 10)

All that this does is change the appearance of the code - it doesn’t make any difference to what the code
does. Decide which one meets your own personal preference, and then stick with it.

Creating subroutines

To create a subroutine is almost as simple as using one. There must be a line at the start which has sub,
and then the name of the subroutine. Also, there needs to be a line at the end of the subroutine which
reads end sub. To create a subroutine called Buzz, this is the required code:

sub Buzz

'code for the subroutine goes here

end sub

If the subroutine has parameters, then they need to be listed after the name. For example, to define the
MoveArm sub used above, use this code:

sub MoveArm(ArmX, ArmY, ArmZ)

'code for the subroutine goes here

end sub

In the above sub, ArmX, ArmY and ArmZ are all variables. If the call from above is used, the variables will
have these values at the start of the subroutine:

52
ArmX = NewX
ArmY = NewY
ArmZ = 10

When the subroutine has finished running, Great Cow BASIC will copy the values back where possible.
NewX will be assigned to ArmX, and NewY will be assigned to ArmY. Great Cow BASIC will not attempt to set
the number 10 to ArmZ.

Controlling the direction data moves in

It is possible to instruct Great Cow BASIC not to copy the value back after the subroutine is called. If a
subroutine is defined like this:

sub MoveArm(In ArmX, In ArmY, In ArmZ)


'code for the subroutine goes here

end sub

Then Great Cow BASIC will copy the values to the subroutine, but will not copy them back.

Great Cow BASIC can also be prevented from copying the values back, by adding Out before the
parameter name. This is used in the EEPROM reading routines - there is no point copying a data value
into the read subroutine, so Out has been used to avoid wasting time and memory. The EPRead routine
is defined as Sub EPRead(In Address, Out Data).

Many older sections of code use #NR at the end of the line where the parameters are specified. The #NR
means "No Return", and when used has the same effect as adding In before every parameter. Use of #NR
is not recommended, as it does not give the same level of control.

Using different data types for parameters

It is possible to use any type of variable a as parameter for a subroutine. Just add As and then the data
type to the end of the parameter name. For example, to make all of the parameters for the MoveArm
subroutine word variables, use this code:

sub MoveArm(ArmX As Word, ArmY As Word, ArmZ As Word)


...
end sub

Optional parameters

Sometimes, the same value may be used over and over again for a parameter, except in a particular
case. If this occurs, a default value may be specified for the parameter, and then a value for that
parameter only needs to be given in a call if it is different to the default.

53
For example, suppose a subroutine to create an error beep is required. Normally it emits ! 440 Hz tone,
but sometimes a different tone is required. To create the sub, this code would be use:

Sub ErrorBeep(Optional OutTone As Word = 440)


Tone OutTone, 100
End Sub

Note the Optional before the parameter, and the = 440 after it. This tells Great Cow BASIC that if no
parameter is supplied, then set the OutTone parameter to 440.

If called using this line:

ErrorBeep

then a 440 Hz beep will be emitted. If called using this line:

ErrorBeep 1000

then the sub will produce a 1000 Hz tone.

When using several parameters, it is possible to make any number of them optional. If the optional
parameter/s are at the end of the call, then no value needs to be specified. If they are at the start or in
the middle, then you must insert commas to allow Great Cow BASIC to tell where the optional
parameters are.

Overloading

It is possible to have 2 subroutines with the same name, but different parameters. This is known as
overloading, and Great Cow BASIC will automatically select the most appropriate subroutine for each
call.

An example of this is the Print routine in the LCD routines. There are actually several Print
subroutines; for example, one has a byte parameter, one a word parameter, and one a string
parameter. If this command is used:

Print 100

Then the Print (byte) subroutine will be called. However, if this command is used:

Print 30112

54
Then the Print (word) subroutine will be called. If there is no exact match for a particular call, Great
Cow BASIC will use the option that requires the least conversion of variable types. For example, if this
command is used:

Print PORTB.0

The byte print will be used. This is because byte is the closest type to the single bit parameter.

See Also Functions, Exit

Variables
About Variables

A variable is an area of memory on the microcontroller that can be used to store a number or a series
of letters. This is useful for many purposes, such as taking a sensor reading and acting on it, or
counting the number of times the robot has performed a particular task.

Each variable must be given a name, such as "MyVariable" or "PieCounter". Choosing a name for a
variable is easy - just don’t include spaces or any symbols (other than _), and make sure that the name
is at least 2 characters (letters and/or numbers) long.

Variable Types

There are several different types of variable, and each type can store a different sort of information.
These are the variable types that Great Cow BASIC can currently use:

Variable Information that this variable can Example uses for this type of variable
type store

Bit A bit (0 or 1) Flags to track whether or not a piece of code


has run

Byte A whole number between 0 and 255 General purpose storage of data, such as
counters

Word A whole number between 0 and 65535 Storage of extra large numbers

Integer A whole number between -32768 and Anything where a negative number will
32767 occur
32
Long A whole number between 0 and 2 (4.29 Storing very, very big numbers
billion)

Array A list of whole numbers ranging from 0 to Logs of sensor readings


255

String A series of letters, numbers and symbols. Messages that are to be shown on a screen

55
Using Variables

Byte variables do not need any special commands to set them up - just put the name of the variable in
to the command where the variable is needed.

Other types of variable can be used in a very similar way, except that they must be "dimensioned" first.
This involves using the DIM command, to tell Great Cow BASIC that it is dealing with something other
than a byte variable.

A key feature of variables is that it is possible the have the microcontroller check a variable, and only
run a section of code if it is a given value. This can be done with the IF command.

String Variables

Strings are defined as follows:

'Create buffer variables to store received messages

Dim Buffer As String

String variables default to the following rules and the RAM constraints of a specific chip.

• 10 bytes for chips with less than 16 bytes of RAM.

• 20 bytes for chips with 16 to 367 bytes of RAM.

• 40 bytes for devices with more RAM than 367 bytes.

• For chips that have less RAM then the required RAM to support the user define strings the strings
(and therefore the RAM) will be NOT be allocated. Please reduce string size.

You cannot store a string 20 characters long in a chip with 16 bytes of RAM.

To change the default string size handled internally by the Great Cow BASIC compiler you add
increase/decrease the default string size

'To define the default string size as the follows constant.


#define STRINGSIZE 24

Defining a length for the string is the best way to limit memory usage. It is good practice if you need a
string of a certain size to set the length of a strings, since the default length for a string variable
changes depending on the amount of memory in the microcontroller (see above).

To set the length of a string, see the example below:

56
'Create buffer variables to store received messages as 16 bytes long
Dim OutBuffer As String * 16

To place quotation marks (" ") in a string of text. For example:

She said, "You deserve a treat!"

Use the following method to show the string with the insertion of two quotation marks in a row as an
embedded quotation mark. These two examples apply to all output methods like HerPrint, Print etc.

hserprint "She said, ""You deserve a treat!"" "

dim myString as string * 39


myString = "She said, ""You deserve another treat!"" "
hserprint myString

Variable Aliases

Some variables are aliases, which are used to refer to memory locations used by other variables. These
are useful for joining predefined byte variable together to form word variables.

Alias are not like pointers in many languages - they must always refer to the same variable or variables
and cannot be changed.

Casting

Casting changes the type of a variable or value. Placing the type that the value should be converted to
in square brackets will tell the compiler to convert it. For example, this will cause two byte variables to
be treated as word variables by the addition code:

Dim MyWord As Word


MyWord = [word]ByteVar + AnotherByteVar

Why do this? If there are no casts, then Great Cow BASIC will add the two values using the byte
addition code, and then convert the result to a word to store in MyWord. Suppose that ByteVar is 150, and
AnotherByteVar is 231. When added, this will come to 381 - which will overflow, leaving 125 in the
result. However, when the cast is added, Great Cow BASIC will treat ByteVar as if it were a word, and so
will use the word addition code. This will cause the correct result to be calculated.

Often, a cast will be used when calculating an average:

57
MyAverage = ([word]Value1 + Value2) / 2

It’s also possible to cast the second value:

MyAverage = (Value1 + [word]Value2) / 2

The result will be exactly the same.

For more help, see: Declaring variables with DIM, Setting Variables

Doing things to individual bits of variables see, Set, Rotate

Checking variables and doing different things based on their value, see If, Do, For, Conditions

Converters
About Converters

Converters allow Great Cow BASIC to read files that have been created by other programs. A converter
can convert these files into Great Cow BASIC libraries or any Great Cow BASIC instruction or a Great
Cow BASIC dataset.

A typical use case is when you have a data source file from another computer system and you want to
consume the data within your Great Cow BASIC program. The data source file could be database,
graphic, reference data or music file. The converter will read these source files and convert them into a
format that can be processed by Great Cow BASIC. The conversion process is completed by external
application which can be written by the developer or you can use one of the converters provided with
the Great Cow BASIC release.

The Great Cow BASIC release includes the converter for BMP files and standard Text files.

With an appropriate Converter installed, and an associated #include to these non-Great Cow BASIC
files, Great Cow BASIC will detect that the file extension and hand the processing to the external
converting program. When the external converting program had complete, Great Cow BASIC will then
continue with the converted source file as a Great Cow BASIC source file.

An example of a converter is to read an existing picture file, convert the picture file to a GCB table and
then refer to the picture file table to display the picture file on a GLCD.

Conversion is achieved by including a command within the source program to transform external
data. The command used is the instruction #include followed by the data source. An example:

58
'Convert ManLooking.BMP to a Great Cow BASIC usable format.

#include <..\converters\ManLooking.BMP>

The inclusion of the #include line within a Great Cow BASIC program will enable the commencement
of the following process:

1. Great Cow BASIC will examine the ..\converters folder structure for a configuration file that will
handle the file extension specified in the include statement.

2. Great Cow BASIC will examine the configuration file(s) *.INI for command line instructions.

3. Great Cow BASIC will at stage examine the folder structure for the source file and the target
transformed file. If the source file is older than the transformed file the next step will not be
executed, goto step 6.

4. Great Cow BASIC will execute the command as specified within the configuration file to transform
the source file to the target file.

The Conversion program must create the output file extension as specified in the configuration file.
If the include statement as an extension of .TXT and the configuration files states the input file
extension as .TXT and the output as .GCB the converted file must have the extension of .GCB.

#include <..\converters\ManLooking.BMP>

Init file is input file as BMP and output as GCB, then the file expected is
..\converters\ManLooking.GCB

5. Great Cow BASIC will attempt to include the transformed target file (with the file extension as
specified in the configuration file) within the Great Cow BASIC program.

6. Great Cow BASIC will resume normal processing of the Great Cow BASIC program including the
transformed target file, therefore, with normal compiling and errors handling.

For example programs see here.

More about Converters

1. The configuration file

The configuration file MUST have the extension of .INI. No leading spaces are permitted in the
configuration file. Specification of the configuration file. The file has four items: desc, in, out and
exe. Where:

59
desc : Is the description shown in GCGB
in : Is the source file extension to be transformed
out : Is the target transformed file extension.
exe : Is the executable to be run for this specific configuration file.
params : Optional, is the required parameter to be passed from the compiler.
Example: params = %filename% %chipmodel%
purge : Optional, will always recreate the target transformed file. The default is
to retain the target transformed file unless source has changed.

You can have multiple configuration files within the ..\converters folder structure.

Great Cow BASIC will examine all configuration file to match the extension as specified in the
#include command.

Example 1 :

BMP (Black and White) conversion configuration file is called BMP2GCBasic.ini. The source
extension is .bmp, the transformed file extension is .GCB, and the executable is called
BMP2GCBASIC.exe.

desc = BMP file (*.bmp)


in = bmp
out = GCB
exe = BMP2GCBASIC .exe

An example :

#include <..\converters\ManLooking.BMP>

Will be converted by the BMP2GCBASIC .EXE to ..\converters\ManLooking.GCB

Example 2 :

60
Data file conversion configuration file is called TXT2GCB.ini. The source extension is .TXT, the
transformed file extension is .GCB, and the command line called AWKRUN.BAT .

desc = Infrared Patterns (*.txt)


in = txt
out = GCB
exe = awkrun.bat

An example :

#include <..\converters\InfraRedPatterns.TXT>

Will be converted by the AWKRUN.BAT to ..\converters\ InfraRedPatterns.GCB

The example would require a supporting batch file and a script process to complete the
transformation.

2. Conversion Executable

The conversion executable may be written in any language (compiled or interpreted).

The conversion executable MUST create the converted file with the correct file extension as
specified in the configuration file.

The conversion executable will be passed one parameter - the source file name. Using example #1
the conversion executable would be passed ..\converters\ManLooking.BMP

The conversion executable MUST create a Great Cow BASIC compatible source file. Any valid
commands/instruction are permitted.

3. Installation

The INI file, the source file and the conversion executable MUST be located in the ..\converters
folder. The converters folder is relative to the GCBASIC.EXE compiler folder.

Example 3 : Converter Program

61
This program converts the InfraRedPatterns.TXT into InfraRedPatterns.GCB that will have a Great
Cow BASIC table called DataSource. This example is located in the converter folder of the Great
Cow BASIC installation.

#chip16f877a, 16
#include <..\converters\InfraRedPatterns.TXT>

dir portb out

' These must be WORDs as this could be large table.


dim TableReadPosition, TableLen as word

dir portb out

' Read the table length


TableReadPosition = 0
ReadTable DataSource, TableReadPosition, TableLen

Do Forever
For TableReadPosition = 1 to TableLen step 2
ReadTable DataSource, TableReadPosition, TransmissionPattern
ReadTable DataSource, TableReadPosition+1 , PulseDelay
portb = TransmissionPattern
wait PulseDelay ms
next
Loop

Example 4 : Dynamic Import

62
This program converts a chip specific configuration file into manifest.GCB that will have a Great
Cow BASIC functions called DataIn and DataOut. This example is located in the converter folder of
the Great Cow BASIC installation.

#chip 16f18326

#include <..\converters\manifest.mcc>

DataOut ( TX, RA0 ) 'this method is created during the convert process. They do
not exist withiut the converter.
DataIn ( Rx, RC6 ) 'this method is created during the convert process. They do
not exist withiut the converter.

This example would use the optional parameters of params and purge in the converter
configuration file as follows:

desc = PPS file (*.PPS)


params = %filename% %chipmodel%
in = mcc
out = GCB
exe = DataHandler.exe
purge = on

63
Command References

64
Analog/Digital conversion
This is the Analog/Digital conversion section of the Help file. Please refer the sub-sections for details
using the contents/folder view.

Analog/Digital Conversion Overview

About Analog to Digital Conversion

The analog to digital converter (ADC or A/D) module support is implemented by Great Cow BASIC to
provide 8-bit, 10-bit and 12-bit Single channel measurement mode and Differential Channel
Measurement mode.

Great Cow BASIC configures the analog to digital converter clock source, the programmed acquisition
time and justification of the response byte, word or integer (as defined in the Great Cow BASIC
method).

Normal or Single channel measurement mode

The Single channel measurement mode is the default method for reading the ADC port. The positive
input is attached to suitable device (a light sensor or adjustable resistor) and the command ReadADC,
ReadADC10, ReadADC12 with return a byte, word or word value respectively.

The A/D module on most microcontrollers only supports single-ended mode. Single channel mode uses
a single A/D port and the returned Value represents the difference between the voltage on the analog
pin and a fixed negative reference which is usually ground or Vss.

The syntax for single-ended A/D is Returned_Value = ReadAD(Port)

Example

Print ReadAD10(AN3)

65
Differential channel measurement mode

Some of the in the Microchip PIC family of devices also support differential analog to digital
conversion. With differential conversion, the differential voltage between two channels is measured
and converted to a digital value. The returned value can be either positive or negative (therefore an
integer value).

When configured to differential channel measurement mode, the positive channel is connected to the
defined positive analog pin (ANx), and the negative channel is connected to the defined negative
analog pin. These two pins are internally connected (within the microcontroller) to a unity gain
differential amplifier and once the amplifier has completed the comparison the result is returned as an
integer.

The positive channel Input is selected using the CHSx bits and the negative channel input is selected
using the CHSNx bits. These bits are managed by Great Cow BASIC. The programmer only needs to
supply the correct analog pin designators in the ReadADx commands.

The 12-bit returned result is available on the ADRESH and ADRESL registers which is returned by the
Great Cow BASIC methods as an integer variable.

Some Microchip PIC microcontrollers have differential A/D modules and support differential Mode as
well as 12-Bit A/D. With DIfferential mode the returned value can be either a positive or negative
number that represents the voltage differential between the two A/D ports.

The syntax for differential A/D is ReadAD( PositiveANPort , NegativeANPort ). Note: if "negative port"
is omitted readAd() will perform a single-ended read on the positive AN port.

Example

66
Print ReadAD12( AN3, An4 )

Optimising Great Cow BASIC Code

Great Cow BASIC supports a wide range of A/D modules and the supporting library addresses up to 34
channels. To reduce the size of the code produced you can define which channels are specifically
supported. See Optimising ADC code for more details.

See also ReadAD, ReadAD10 and ReadAD12

The Microchip PIC microcontrollers that support Differential and 12-bit A/D are listed below. Dated
December 2015.

16f1782 16lf1782
16f1783 16lf1783
16f1784 16lf1784
16f1786 16lf1786
16f1787 16lf1787
16f1788 16lf1788
16f1789 16lf1789

18f65k22
18f66k22
18f67k22
18f85k22
18f86k22
18f86k22

18f25k80 18lf25k80
18f26k80 18lf26k80
18f45k80 18lf45k80
18f46k80 18lf46k80
18f65k80 18lf65k80
18f66k80 18lf66k80

18f65k90
18f66k90
18f67k90
18f85k90
18f86k90
18f87k22
18f87k90

67
ADFormat (Deprecated - Do not use)

Syntax:

ADFormat ( Format_Left | Format_Right )

Command Availability:

Available only on Microchip PIC microcontrollers.

Explanation:

Left justified means 8 bits in the high byte, 2 in the low. Right justified means 2 in the high byte, and
the remaining 8 in the low byte. It’s only supported on Microchip PIC microcontrollers.

ADOff

This command is obsolete. There should be no need to call it. Great Cow BASIC will automatically
disable the A/D converter and set all pins to digital mode when starting the program, and after every
use of the ReadAD function.

It is recommended that this command be removed from all programs.

ReadAD

Syntax:

For a normal ( also called a Single Channel ) read use.

var = ReadAD_port( ANX )

For a Differential Channel read use the following. Where ANpX is the positive port, and ANnY is the
negative port.

user_variable = ReadAD( ANpX , ANnY )

To obtain a byte value from an AD Channel use the following to force an 8 bit AD Channel to respond
with a byte value [0 to 255].

user_variable = ReadAD( ANX , TRUE )

Command Availability:

68
When using ReadAD ( ANx ) the returned value is an 8 bit number [0- 255]. The user variable assigned
by the function can be a byte, word, integer or long.

When using ReadAD ( ANpX , ANnY ) the returned value is an integer, as negative values can be
returned.

When using ReadAD ( ANpX , TRUE ) the returned value is an integer, but you should treat as a byte.

ReadAD is a function that can be used to read the built-in analog to digital converter that many
microcontroller chips include. port should be specified as AN0, AN1, AN2, etc., up to the number of
analog inputs available on the chip that is in use. Those familiar with Atmel AVR microcontrollers can
also refer to the ports as ADC0, ADC1, etc. Refer to the datasheet for the microcontroller chip to find the
number of ports available. (Note: it’s perfectly acceptable to use ANx on AVR, or ADCx on the
microcontroller)

Another function, ReadAD10, is similar to ReadAD. The only difference is that it returns a full value of
the ADC either 8bits or 10 bits.

The constant AD_Delay controls is the acquisition delay. The default value is 20 us. This can be
changed by adding the following constant.

#define AD_Delay 2 10us

ADSpeed controls the source of the clock for the ADC module. It varies from one chip to another.
InternalClock is a Microchip PIC microcontroller only option that will drive the ADC from an internal
RC oscillator. The default value is 128.

Using ADSPEED

'default value
#define ADSpeed MediumSpeed

'pre-defined constants
#define HighSpeed 255
#define MediumSpeed 128
#define LowSpeed 0

AD_VREF_DELAY controls the charging time for VRef capacitor on Atmel AVR microcontrollers only.
This therefore controls the charge from internal VRef. ReadAD will not be accurate for internal
reference without this.

AD_Acquisition_Time_Select_bits also controls the Acquisition Time Select bits. Acquisition time is
the duration that the AD charge holding capacitor remains connected to AD channel from the instant
the read is commenced is set until conversions begins.

69
The default value of AD_Acquisition_Time_Select_bits is 0b100 or decimal 4, where all three ACQT bits
will be set. To change use the following.

'change the default value


#define AD_Acquisition_Time_Select_bits 0b001 'this will only set ACQT bit 0, ACQT
bits 1 and 2 will be cleared.

Example 1

This example reads the ADC port and writes the output to the EEPROM.

#chip 16F819, 8
#config osc = int

'Set the input pin direction


Dir PORTA.0 In

'Loop to take readings until the EEPROM is full


For CurrentAddress = 0 to 255

'Take a reading and log it


EPWrite CurrentAddress, ReadAD(AN0)

'Wait 10 minutes before getting another reading


Wait 10 min
Next

Example 2

This example reads the ADC port and writes the output to the EEPROM. The output value will be in the
range of [0-255].

70
#chip 16F1789, 8

'Set the input pin direction


Dir PORTA.0 In

'Loop to take readings until the EEPROM is full


For CurrentAddress = 0 to 255

'Take a reading and log it


EPWrite CurrentAddress, ReadAD(AN0, TRUE)

'Wait 10 minutes before getting another reading


Wait 10 min
Next

Example 3

This example used the diffential capabilities of ADC port and writes the output to the EEPROM. The
output value will be in the range of [-255 to 255].

AN0 and AN2 are used for the diffential ADC reading.

#chip 16F1789, 8

'Set the input pin direction


Dir PORTA.0 In
Dir PORTA.2 In

'Loop to take readings until the EEPROM is full


For CurrentAddress = 0 to 255

'Take a reading and log it


EPWrite CurrentAddress, ReadAD( AN0, AN2 )

'Wait 10 minutes before getting another reading


Wait 10 min
Next

See Also ReadAD10, ReadAD12

ReadAD10

Syntax:

71
For a normal ( also called a Single Channel ) read use.

user_variable = ReadAD10( ANX )

For a Differential Channel read use the following. Where ANpX is the positive port, and ANnY is the
negative port.

user_variable = ReadAD10( ANpX , ANnY )

To obtain a 10-bit value from an AD Channel use the following to force a 10 bit AD Channel to respond
with the correct value, in terms of the range [0 to 1023]

user_variable = ReadAD10( ANX , TRUE )

Command Availability:

When using ReadAD10 ( ANX ) the returned value is the full range of the ADC module. Therefore, the
method will return an 8 bit value [0-255], or an 10 bit value [0-1023] or an 12 bit value [0-4095]. This is
dependent on the microcontrollers capabilities. For a 10 bit value [0-1023] always to be returned use
user_variable = ReadAD10( ANX , TRUE )

The user variable can be a word, integer or long.

When using ReadAD10 ( ANpX , ANnY ), for differential ADC reading, the returned value is an integer
as negative values can be returned.

ReadAD10 is a function that can be used to read the built-in analog to digital converter that many
microcontroller chips include. The port should be specified as AN0, AN1, AN2, etc., up to the number of
analog inputs available on the chip that is in use. Those familiar with Atmel AVR microcontrollers can
also refer to the ports as ADC0, ADC1, etc. Refer to the datasheet for the microcontroller chip to find the
number of ports available. (Note: it’s perfectly acceptable to use ANx on AVR, or ADCx on the
microcontroller.)

Another function, ReadAD is similar to ReadAD10. The only difference is that the ReadAD method
returns a byte variable.

AD_Delay controls is the acquisition delay. The default value is 20 us. This can be changed to a longer
acquisition delay by adding the following constant.

#define AD_Delay 4 10us

ADSpeed( controls the source of the clock for the ADC module. It varies from one chip to another.

72
InternalClock is a microcontroller only option that will drive the ADC from an internal RC oscillator.
The default value is 128.

'default value
#define ADSpeed MediumSpeed

'pre-defined constants
#define HighSpeed 255
#define MediumSpeed 128
#define LowSpeed 0

AD_Acquisition_Time_Select_bits also controls the Acquisition Time Select bits. Acquisition time is
the duration that the AD charge holding capacitor remains connected to AD channel from the instant
the read is commenced is set until conversions begins.

The default value of AD_Acquisition_Time_Select_bits is 0b100 or decimal 4, where all three ACQT bits
will be set. To change use the following.

'change the default value


#define AD_Acquisition_Time_Select_bits 0b001 'this will only set ACQT bit 0, ACQT
bits 1 and 2 will be cleared.

Example 1 - Read 10-bit ADC

#chip 16F819, 8

'Set the input pin direction


Dir PORTA.0 In

'Print 255 reading


For CurrentAddress = 0 to 255

'Take a reading and show it


Print str(ReadAD10(AN0))

'Wait 10 minutes before getting another reading


Wait 10 min
Next

Example 2 - Reading Reference Voltages:

When selecting the reference source for ADC on ATmega328 Great Cow BASIC will overwrite anything

73
that you put into te ADMUX register - but this option allow you change the ADC reference source on
Atmel AVR microcontrollers. You can set the AD_REF_SOURCE constant to whatever you want to use.
It defaults to the VCC pin, as example you can set the Atmel AVR to use the 1.1V reference with this:
#define AD_REF_SOURCE AD_REF_256 where 256 refers to the 2.56V reference on some older AVRs,
but the same code will select the 1.1V reference on an ATmega328p

' Dynamically switching reference.


#define AD_REF_SOURCE ADRefSource
#define AD_VREF_DELAY 5 ms
AdRefSource = AD_REF_AVCC
HSerPrint ReadAD10(AN1)
HSerPrint ", "
AdRefSource = AD_REF_256
HSerPrint ReadAD10(AN1)

The example above sets the AD_REF_SOURCE to a variable, and then changes the value of the variable
to select the source. With this approach, we also need to allow time to charge the reference capacitor
to the correct voltage.

Example 3 - Read 10-bit ADC forcing a 10-bit value to be returned

#chip 16F1789, 8

'Set the input pin direction


Dir PORTA.0 In

'Print 255 reading


For CurrentAddress = 0 to 255

'Take a reading and show it


Print str(ReadAD10(AN0), TRUE)

'Wait 10 minutes before getting another reading


Wait 10 min
Next

Example 4

This example used the diffential capabilities of ADC port and writes the output to the EEPROM. The
output value will be in the range of [-1023 to 1023].

AN0 and AN2 are used for the diffential ADC reading.

74
#chip 16F1789, 8

'USART settings
#define USART_BAUD_RATE 9600 'Initializes USART port with 9600 baud
#define USART_TX_BLOCKING ' wait for tx register to be empty
wait 100 ms

'Set the input pin direction


Dir PORTA.0 In
Dir PORTA.2 In

'Loop to take readings until the EEPROM is full


For CurrentAddress = 0 to 255

'Take a reading and log it


HSerPrint ReadAD10( AN0, AN2 )
HserPrintCRLF
'Wait 10 minutes before getting another reading
Wait 10 min

Next

See Also ReadAD, ReadAD12

ReadAD12

Syntax:

For a normal ( also called a Single Channel ) read use.

user_variable = ReadAD12( ANX )

For a Differential Channel read use the following. Where ANpX is the positive port, and ANnY is the
negative port.

user_variable = ReadAD12( ANpX , ANnY )

To obtain a 12-bit value from an AD Channel use the following to force a 12 bit AD Channel to respond
with the correct value, in terms of the range of [0 to 4095]

user_variable = ReadAD12( ANX , TRUE )

Command Availability:

75
When using ReadAD12 ( ANX ) the returned value is an 12 bit number [0-4095]. The user variable can
be a word, integer or long.

When using ReadAD12 ( ANpX , ANnY ) the returned value is an integer as negative values can be
returned.

ReadAD12 is a function that can be used to read the built-in analog to digital converter that many
microcontroller chips include. Port should be specified as AN0, AN1, AN2, etc., up to the number of
analog inputs available on the chip that is in use. Those familiar with Atmel AVR microcontrollers can
also refer to the ports as ADC0, ADC1, etc. Refer to the datasheet for the microcontroller chip to find the
number of ports available. (Note: it’s perfectly acceptable to use ANx on AVR, or ADCx on the
microcontroller.)

Another function, ReadAD10 is similar to ReadAD12. The only difference is that it returns a 10 bit
number.

AD_Delay controls is the acquisition delay. The default value is 20 us. This can be changed to a longer
acquisition delay by adding the following constant.

#define AD_Delay 4 10us

ADSpeed( controls the source of the clock for the ADC module. It varies from one microcontroller to
another. InternalClock is a Microchip PIC microcontroller only option that will drive the ADC from an
internal RC oscillator. The default value is 128.

'default value
#define ADSpeed MediumSpeed

'pre-defined constants
#define HighSpeed 255
#define MediumSpeed 128
#define LowSpeed 0

AD_Acquisition_Time_Select_bits also controls the Acquisition Time Select bits. Acquisition time is
the duration that the AD charge holding capacitor remains connected to AD channel from the instant
the read is commenced is set until conversions begins.

The default value of AD_Acquisition_Time_Select_bits is 0b100 or decimal 4, where all three ACQT bits
will be set. To change use the following.

76
'change the default value
#define AD_Acquisition_Time_Select_bits 0b001 'this will only set ACQT bit 0, ACQT
bits 1 and 2 will be cleared.

Example 1 - Read 12-bit ADC

#chip 16F1788, 8
#config osc = int

'Set the input pin direction


Dir PORTA.0 In

'Print 255 readings


For CurrentAddress = 0 to 255

'Take a reading and show it


Print str(ReadAD12(AN0))

'Wait 10 minutes before getting another reading


Wait 10 min
Next

Example 2 - Force a 12-bit value to be returned

#chip 16F1788, 8

'Set the input pin direction


Dir PORTA.0 In

'Print 255 readings


For CurrentAddress = 0 to 255

'Take a reading and show it


Print str(ReadAD12(AN0), TRUE)

'Wait 10 minutes before getting another reading


Wait 10 min
Next

Example 3

77
This example used the diffential capabilities of ADC port and writes the output to the EEPROM. The
output value will be in the range of [-4095 to 4095].

AN0 and AN2 are used for the diffential ADC reading.

#chip 16F1789, 8

'USART settings
#define USART_BAUD_RATE 9600 'Initializes USART port with 9600 baud
#define USART_TX_BLOCKING ' wait for tx register to be empty
wait 100 ms

'Set the input pin direction


Dir PORTA.0 In
Dir PORTA.2 In

'Loop to take readings until the EEPROM is full


For CurrentAddress = 0 to 255

'Take a reading and log it


HSerPrint ReadAD12( AN0, AN2 )
HserPrintCRLF
'Wait 10 minutes before getting another reading
Wait 10 min

Next

See Also ReadAD, ReadAD10

Analog/Digital Conversion Code Optimisation

About Analog/Digital Conversion Code Optimisation

The analog to digital converter (ADC or A/D) module support is implemented by Great Cow BASIC to
provide 8-bit, 10-bit and 12-bit Single channel measurement mode and Differential Channel
Measurement with support up to 34 channels. For compatibility all channels are supported.

There are two methods to optimise the code.

1. To mimise the code, use the contstants to disable support for a specfic channels

2. To adapt the ADC configuration by inserting specfic commands to set registers or register bits.

1. Minimise the code

The example below would disable support for ADC port 0 (AD0).

78
#define USE_AD0 FALSE

The following tables show the #defines that can be used to reduce the code size - these are the defines
for the standard microcontrollers. For 16f1688x and similar microcontrollers please see the second
table.

Channe Optimisation Default


l Value Value

USE_AD0 FALSE TRUE


USE_AD1 FALSE TRUE
USE_AD2 FALSE TRUE
USE_AD3 FALSE TRUE
USE_AD4 FALSE TRUE
USE_AD5 FALSE TRUE
USE_AD6 FALSE TRUE
USE_AD7 FALSE TRUE
USE_AD8 FALSE TRUE
USE_AD9 FALSE TRUE
USE_AD10 FALSE TRUE
USE_AD11 FALSE TRUE
USE_AD12 FALSE TRUE
USE_AD13 FALSE TRUE
USE_AD14 FALSE TRUE
USE_AD15 FALSE TRUE
USE_AD16 FALSE TRUE
USE_AD17 FALSE TRUE
USE_AD18 FALSE TRUE
USE_AD19 FALSE TRUE
USE_AD20 FALSE TRUE
USE_AD21 FALSE TRUE
USE_AD22 FALSE TRUE
USE_AD23 FALSE TRUE
USE_AD24 FALSE TRUE
USE_AD25 FALSE TRUE
USE_AD26 FALSE TRUE

79
Channe Optimisation Default
l Value Value

USE_AD27 FALSE TRUE


USE_AD28 FALSE TRUE
USE_AD29 FALSE TRUE
USE_AD30 FALSE TRUE
USE_AD31 FALSE TRUE
USE_AD32 FALSE TRUE
USE_AD33 FALSE TRUE
USE_AD34 FALSE TRUE

For 16f1688x devices see the table below.

Channe Optimisation Default


l Value Value

USE_ADA0 FALSE TRUE


USE_ADA1 FALSE TRUE
USE_ADA2 FALSE TRUE
USE_ADA3 FALSE TRUE
USE_ADA4 FALSE TRUE
USE_ADA5 FALSE TRUE
USE_ADA6 FALSE TRUE
USE_ADA7 FALSE TRUE
USE_ADC0 FALSE TRUE
USE_ADC1 FALSE TRUE
USE_ADC2 FALSE TRUE
USE_ADC3 FALSE TRUE
USE_ADC4 FALSE TRUE
USE_ADC5 FALSE TRUE
USE_ADC6 FALSE TRUE
USE_ADC7 FALSE TRUE
USE_ADD0 FALSE TRUE
USE_ADD1 FALSE TRUE
USE_ADD2 FALSE TRUE
USE_ADD3 FALSE TRUE

80
Channe Optimisation Default
l Value Value

USE_ADD4 FALSE TRUE


USE_ADD5 FALSE TRUE
USE_ADD6 FALSE TRUE
USE_ADD7 FALSE TRUE
USE_ADE0 FALSE TRUE
USE_ADE1 FALSE TRUE
USE_ADE2 FALSE TRUE

This is a example - disables every channel except the specified channel by defining every channel
except USE_AD0 as FALSE.

This will save 146 bytes of program memory.

; ----- Configuration
#chip 16F1939

'USART settings
#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Set the input pin direction


Dir PORTA.0 In

'Print 255 reading


For CurrentAddress = 0 to 255

'Take a reading and show it


HSerPrint str(ReadAD10(AN0))

'Wait 10 minutes before getting another reading


Wait 10 min
Next

#define USE_AD0 TRUE


#define USE_AD1 FALSE
#define USE_AD2 FALSE
#define USE_AD2 FALSE
#define USE_AD3 FALSE
#define USE_AD4 FALSE
#define USE_AD5 FALSE
#define USE_AD6 FALSE

81
#define USE_AD7 FALSE
#define USE_AD8 FALSE
#define USE_AD9 FALSE
#define USE_AD10 FALSE
#define USE_AD11 FALSE
#define USE_AD12 FALSE
#define USE_AD13 FALSE
#define USE_AD14 FALSE
#define USE_AD15 FALSE
#define USE_AD16 FALSE
#define USE_AD17 FALSE
#define USE_AD18 FALSE
#define USE_AD19 FALSE
#define USE_AD20 FALSE
#define USE_AD21 FALSE
#define USE_AD22 FALSE
#define USE_AD23 FALSE
#define USE_AD24 FALSE
#define USE_AD25 FALSE
#define USE_AD26 FALSE
#define USE_AD27 FALSE
#define USE_AD28 FALSE
#define USE_AD29 FALSE
#define USE_AD30 FALSE
#define USE_AD31 FALSE
#define USE_AD32 FALSE
#define USE_AD33 FALSE
#define USE_AD34 FALSE

For 16f18855 family of microcontrollers this is a example. This will save 149 bytes of program
memory.

''' PIC: 16F18855


''' Compiler: GCB
''' IDE: GCB@SYN
'''
''' Board: Xpress Evaluation Board
''' Date: 13.3.2016
'''

'Chip Settings.
#chip 16f18855,32
#Config FEXTOSC_OFF, RSTOSC_HFINT32
#Config WRT_OFF, CPD_ON, MCLRE_ON

'' -------------------LATA-----------------

82
'' Bit#: -7---6---5---4---3---2---1---0---
'' LED: ---------------|D5 |D4 |D3 |D1 |-
''-----------------------------------------
''

#define USART_BAUD_RATE 19200


#define USART_TX_BLOCKING

#define LEDD2 PORTA.0


#define LEDD3 PORTA.1
#define LEDD4 PORTA.2
#define LEDD5 PORTA.3
Dir LEDD2 OUT
Dir LEDD3 OUT
Dir LEDD4 OUT
Dir LEDD5 OUT

#define SWITCH_DOWN 0
#define SWITCH_UP 1

#define SWITCH PORTA.5

'Setup an Interrupt event when porta.5 goes negative.


IOCAN5 = 1
On Interrupt PORTBChange Call InterruptHandler

do

'Read the value from the EEPROM from register Zero in the EEPROM
EPRead ( 0, OutValue )

'Leave the Top Bytes alone and set the lower four bits
PortA = ( PortA & 0XF0 ) OR ( OutValue / 16 )
Sleep

loop

sub InterruptHandler

if IOCAF5 = 1 then 'S2 was just pressed


IOCAN5 = 0 'Prevent the event from reentering the
InterruptHandler routine
IOCAF5 = 0 'We must clear the flag in software

wait 5 ms 'debounce by waiting and seeing if


still held down

83
if ( SWITCH = DOWN ) then
'Read the ADC
adc_value = readad ( AN4 )
'Write the value to register Zero in the EEPROM
EPWrite ( 0, adc_value )
end if
IOCAN5 = 1 'ReEnable the InterruptHandler
routine

end if

end sub

#define USE_ADA0 FALSE


#define USE_ADA1 FALSE
#define USE_ADA2 FALSE
#define USE_ADA3 FALSE
#define USE_ADA4 TRUE
#define USE_ADA5 FALSE
#define USE_ADA6 FALSE
#define USE_ADA7 FALSE
#define USE_ADB0 FALSE
#define USE_ADB1 FALSE
#define USE_ADB2 FALSE
#define USE_ADB3 FALSE
#define USE_ADB4 FALSE
#define USE_ADB5 FALSE
#define USE_ADB6 FALSE
#define USE_ADB7 FALSE
#define USE_ADC0 FALSE
#define USE_ADC1 FALSE
#define USE_ADC2 FALSE
#define USE_ADC3 FALSE
#define USE_ADC4 FALSE
#define USE_ADC5 FALSE
#define USE_ADC6 FALSE
#define USE_ADC7 FALSE
#define USE_ADD0 FALSE
#define USE_ADD1 FALSE
#define USE_ADD2 FALSE
#define USE_ADD3 FALSE
#define USE_ADD4 FALSE
#define USE_ADD5 FALSE
#define USE_ADD6 FALSE
#define USE_ADD7 FALSE
#define USE_ADE0 FALSE
#define USE_ADE1 FALSE
#define USE_ADE2 FALSE

84
2. Adapt the ADC configuration

The following example will set the specific register bits. The instruction will be added to the compiled
code.

#define ADReadPreReadCommand ADCON.2=0:ANSELA.0=1

The constant ADReadPreReadCommand can be used to adapt the ADC methods. The constant can
enable registers or register bit(s) that are required to managed for a specfic solution.

In the example above the following ASM will be added to your code. This WILL be added just before
the ADC is enabled and the setting of the acquisition delay.

;ADReadPreReadCommand
banksel ADCON
bcf ADCON,2
banksel ANSELA
bsf ANSELA,0

85
Bitwise
This is the Bitwise section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Bitwise Operations Overview

About Bitwise Operations

Great Cow BASIC (as with most other microcontroller programming languages) supports bitwise
operations.

Bitwise operations are performed on one or more bit patterns at the level of their individual bits.

Great Cow BASIC supports the following methods.

Method Meaning

Set Assigns a Bit value of On or Off

SetWith Evaluates an expression and assigns the result

FnLSL Performs a Bitwise LEFT shift

FnLSR Performs a Bitwise RIGHT shift

Rotate Performs a rotation of a variable of one bit in a specified direction

For more help, see: Set, SetWith, FnLSL, FnLSR and Rotate

FnLSL

Syntax:

BitsOut = FnLSL(BitsIn, NumBits)

Command Availability:

Available on all microcontrollers.

Explanation:

FnLSL (Logical Shift Left) will perform a Bitwise left shift. FnLSL will return BitsIn shifted NumBits to the
left, it is equivalent to the 'C' operation:

BitsOut = BitsIn << NumBits

86
Each left shift is the equivalent of multiplying BitsIn by 2. BitsIn and NumBits may be may be a
variable and of type: Bit, Byte, Word, Long, Constant or another Function. Zeros are shifted in from the
right, Bits that are shifted out are lost.

It is useful for mathematical and logical operations, as well as creating serial data streams or
manipulating I/O ports.

Example:

' This program will shift the LEDs on the Microchip PIC Low Pin
' Count Demo Board from Right to Left, that is DS1(RC0) to
' DS4(RC3) and repeat

#chip 16f690 ' declare the target Device

#define LEDPORT PORTC ' LEDs on pins 16, 15, 14 and 7

Dim LEDMask as Byte ' Pattern to be displayed


LEDMask = 0b0001 ' Initialise the Patten
Dir LEDPORT Out ' Enable the LED Port.

Do
LEDMask = FnLSL(LEDMask, 1) & 0x0F ' Mask the lower 4 bits
if LEDPORT.3 then LEDMask.0 = 1 ' Restart the sequence
LEDPORT = LEDMask ' Display the Pattern
wait 500 ms
Loop
End

See Also Bitwise Operations Overview and Conditions

FnLSR

Syntax:

BitsOut = FnLSR(BitsIn, NumBits)

Command Availability:

Available on all microcontrollers.

Explanation:

FnLSR (Logical Shift Right) will perform a Bitwise right shift. FnLSR will return BitsIn shifted NumBits to
the right, it is equivalent to the 'C' operation:

87
BitsOut = BitsIn >> NumBits

Each right shift is the equivalent of dividing BitsIn by 2.

BitsIn and NumBits may be may be a variable and of type: Bit, Byte, Word, Long, Constant or another
Function.

Zeros are shifted in from the left, Bits that are shifted out are lost.

It is useful for mathematical and logical operations, as well as creating serial data streams or
manipulating I/O ports.

Example:

' This program will shift the LEDs on the Microchip PIC Low Pin Count Demo Board
' from Right to Left, that is DS4(RC3) to DS1(RC0) and repeat.

#chip 16f690 ' declare the target Device

#define LEDPORT PORTC ' LEDs on pins 16, 15, 14 and 7

Dim LEDMask as Byte ' Pattern to be displayed


LEDMask = 0b1000 ' Initialise the Patten
Dir LEDPORT Out ' Enable the LED Port.

Do
LEDPORT = LEDMask ' Display the Pattern
wait 500 ms
LEDMask = FnLSR(LEDMask, 1) & 0x0F ' Mask the lower 4 bits
if LEDPORT.0 then LEDMask.3 = 1 ' Restart the sequence
Loop
End

See Also Bitwise Operations Overview and Conditions

SetWith

Syntax:

SetWith(TargetBit, Source)

Command Availability:

Available on all microcontrollers.

88
Explanation:

SetWith is an extended version of SET, it allows a Bit Field to be set or cleared by evaluating the content
of Source. SetWith should always be used when TargetBit is an I/O Bit and Source is a Function, in order
to avoid the possibility of I/O jitter.

Source may be a variable and of type: Bit, Byte, Word or Long, a Constant, an expression or a Function.

It will SET TargetBit to 1 if Source evaluates to anything other than zero. TargetBit will always be a 1
or a 0 regardless of the variable type of TargetBit.

Example:

' This program will reflect the state of SW1(RA3) on LED DS1(RC0) of the Microchip
' Low Pin Count Demo Board. Notice that because SW1 is normally High the state has to
' be inverted to turn on the LED (DS1) when SW1 is pressed.

#chip 16f690 ' declare the target Device

#Define SW1 PORTA.3


#Define DS1 PORTC.0

DIR DS1 Out


DIR SW1 In

Do
' set the Bit DS1 to equal the Bit SW1
SetWith( DS1, !SW1 )
Loop
END

See Also Bitwise Operations Overview and Conditions

89
Eeprom
This is the Eeprom section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

EPRead

Syntax:

EPRead location, store

Command Availability:

Available on all Microchip PIC and Atmel AVR microcontrollers with EEPROM data memory.

Explanation:

EPRead is used to read information from the EEPROM data storage that many microcontroller chips are
equipped with. location represents the location to read data from, and varies from one chip to
another. store is the variable in which to store the data after it has been read from EEPROM.

Example:

90
'Program to turn a light on and off
'Will remember the last status

#chip tiny2313, 1
#define Button PORTB.0
#define Light PORTB.1

Dir Button In
Dir Light Out

'Load saved status


EPRead 0, LightStatus

If LightStatus = 0 Then
Set Light Off
Else
Set Light On
End If

Do
'Wait for the button to be pressed
Wait While Button = On
Wait While Button = Off
'Toggle value, record
LightStatus = !LightStatus
EPWrite 0, LightStatus

'Update light
If LightStatus = 0 Then
Set Light Off
Else
Set Light On
End If
Loop

For more help, see EPWrite

EPWrite

Syntax:

EPWrite location, data

Command Availability:

91
Available on all Microchip PIC and Atmel AVR microcontrollers with EEPROM data memory.

Explanation:

EPWrite is used to write information to the EEPROM data storage, so that it can be accessed later by a
programmer on the PC, or by the EPRead command. location represents the location to read data from,
and varies from one chip to another. data is the data that is to be written to the EEPROM, and can be a
value or a variable.

Example:

#chip 16F819, 8
#config osc = int

'Set the input pin direction


Dir PORTA.0 In

'Loop to take readings until the EEPROM is full


For CurrentAddress = 0 to 255

'Take a reading and log it


EPWrite CurrentAddress, ReadAD(AN0)

'Wait 10 minutes before getting another reading


Wait 10 min

Next

For more help, see EPRead

ProgramErase

Syntax:

ProgramErase (location)

Command Availability:

Available on all Microchip PIC microcontrollers with self write capability. Not available on Atmel AVR
at present.

Explanation:

ProgramErase erases information from the program memory on chips that support this feature. The
largest value possible for location depends on the amount of program memory on the Microchip PIC

92
microcontroller, which is given on the datasheet.

This command must be called before writing to a block of memory. It is slow in comparison to other
Great Cow BASIC commands. Note that it erases memory in 32-byte blocks - see the relevant Microchip
PIC microcontroller datasheet for more information.

This is an advanced command which should only be used by advanced developers. Care must be taken
with this command, as it can easily erase the program that is running on the microcontroller.

For more help, see ProgramRead and ProgramWrite

ProgramRead

Syntax:

ProgramRead (location, store)

Command Availability:

Available on all Microchip PIC microcontrollers with self write capability. Not available on Atmel AVR
at present.

Explanation:

ProgramRead reads information from the program memory on chips that support this feature. location
and store are both word variables, meaning that they can store values over 255.

The largest value possible for location depends on the amount of program memory on the Microchip
PIC microcontroller, which is given on the datasheet. store is 14 bits wide, and thus can store values up
to 16383.

This is an advanced command which should only be used by advanced developers.

Example:

For more help, see ProgramErase and ProgramWrite

ProgramWrite

Syntax:

ProgramWrite (location, value)

Command Availability:

Available on all Microchip PIC microcontrollers with self write capability. Not available on Atmel AVR

93
at present.

Explanation:

ProgramWrite writes information to the program memory on chips that support this feature. location
and value are both word variables.

The largest value possible for location depends on the amount of program memory on the
microcontroller , which is given on the datasheet. value is 14 bits wide, and thus can store values up to
16383.

This is an advanced command which should only be used by advanced developers. ProgramErase must
be used to clear a block of memory BEFORE ProgramWrite is called.

Example:

For more help, see ProgramErase and ProgramRead

94
Hefm
This is the Hefm section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

HEFM Overview

Introduction:

Several members of the Microchip PIC microcontroller family, including the 16F14xx, 16F15xx and
16F17xx have replaced the data EEPROM present on older models with a block of Flash memory that is
designed to provide the same high endurance (100K erase/write cycles).

This high endurance flash memory (HEFM) is a block of 128 locations found at the top of the Flash
program memory. Each location can only be used to hold a byte variable (whereas the standard Flash
memory for a mid-range Microchip PIC microcontroller will typically hold 14 bits of information).

The main difference between EEPROM and HEFM is that the former does allow byte-by-byte erase
whereas the latter does not. With HEFM data must be erased before a write and this can only be
performed in blocks (also referred to as rows) of a fixed size associated with the chip design.

The heflash.h library uses as an input the following variables which are available from the chips *.dat
files supporting HEFM.

Variable Name Type Content

HEFLASH_ROWSIZE Byte Size of an HEFM block in words

HEFLASH_START Word Starting address of HEFM

HEFLASH_END Word Ending address of HEFM

Caution

Whenever you update the hex file of your Microchip PIC microcontroller with your programmer you
will erase the data that are stored in HEFM. If you want to avoid that you will have to flash your
Microchip PIC microcontroller with software that allows memory exclusion when flashing. This is the
case with Microchip PIC MPLAB IPE (Go to Advanced Mode/Enter password/Select Memory/Tick “Preserve
Flash on Program”/ Enter Start and End address of your HEFM).

HEFreadBlock

Syntax:

HEFreadBlock(buffer(), Flash_row, count)

95
Command availability:

Available on specific Microchip PIC microcontrollers only. Check your datasheet.

Explanation:

Buffer() is the destination byte array (must be sufficiently large)


Flash_row is the HEFM relative location (i.e. the row number)
Count is the number of bytes to be retrieved

HEFreadBlock reads information from the HEFM on chips that support this feature. buffer is a byte
array of length equal to count. Reading starts at the beginning of given row number.

Example:

#chip 16F1509, 8
'The following example reads a byte vector
'from row 0 of the HEFM of the 16F1509
dim data(32)
HEFreadBlock(data,0,HEFLASH_ROWSIZE)

HEFRead

Syntax:

HEFRead(HEFaddress, HEFDataValue)

Command availability:

Available on specific Microchip PIC microcontrollers only. Check your datasheet.

Explanation:

HEFaddress is the HEFM relative location in the whole HEFM area (i.e. a number generally comprised
between 0 and 127)
HEFDataValue is the byte data being retrieved

This subroutine reads information from the HEFM given its relative number in the whole HEFM area.
It is the equivalent of the EPRead subroutine for EEPROM. The subroutine will compute the row
number and the offset in the row from HEFaddress and HEFLASH_ROWSIZE. It will then call the
HEFreadBlock subroutine to retrieve the byte data.

Example:

96
#chip 16F1509, 8
'The following example stores in the byte variable “value” the
'HEFM byte variable located in row 1 at offset 2
HEFRead(34,value)

HEFwriteBlock

Syntax:

HEFwriteBlock(Flash_row, buffer(), count)

Command availability:

Available on specific Microchip PIC microcontrollers only. Check your datasheet.

Explanation:

Flash_row is the HEFM relative location (i.e. the row number)


Buffer() is the source byte array
Count is the number of bytes to be copied

HEFwriteBlock writes information to the HEFM on chips that support this feature. buffer is a byte
array of length equal to count. Writing starts at the beginning of the given row number.

WARNING:

Be aware that this subroutine will first erase whatever data are present on the destination row. If you
want to preserve them check the HEFwrite subroutine.

Example:

#chip 16F1509, 8
'The following example generates a byte vector and stores it
'in row 0 of the HEFM of the 16F1509
dim data(32)
for index = 1 to 32
data(index)=index
next
HEFwriteBlock(0,data,HEFLASH_ROWSIZE)

'Now we store a string in row 1


Dim Hello as String
Hello="Hello GCB World!"
HEFwriteBlock(1,Hello,len(Hello))

97
HEFWrite

Syntax:

HEFWrite(HEFaddress, HEFDataValue)

Command availability:

Available on specific Microchip PIC microcontrollers only. Check your datasheet.

Explanation:

HEFaddress is the HEFM relative location in the whole HEFM area (i.e. a number generally comprised
between 0 and 127)
HEFDataValue is the byte data being retrieved

This subroutine writes information to the HEFM given its relative number in the whole HEFM area. It
is the equivalent of the EPWrite subroutine for EEPROM. The subroutine will compute the row number
and the offset in the row from HEFaddress and HEFLASH_ROWSIZE. It will then call the HEFWriteBlock
subroutine to store the byte data.

Example:

#chip 16F1509, 8
'The following example stores in the byte variable “value” the
'HEFM byte variable located in row 1 at offset 2
HEFWrite(34,value)

98
Flow control
This is the Flow control section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Do

Syntax:

Do [{While | Until} condition]


...
program code
...
<condition> Exit Do
...
Loop [{While | Until} condition]

Command Availability:

Available on all microcontrollers.

Explanation:

The Do command will cause the code between the Do and the Loop to run repeatedly while condition is
true or until condition is true, depending on whether While or Until has been specified.

Note that the While or Until and the condition can only be specified once, or not at all. If they are not
specified, then the code will repeat endlessly.

Optionally, you can specify a condition to EXIT the Do-Loop immediately.

Example 1:

99
'This code will flash a light until the button is pressed
#chip 12F629, 4
#config osc = int

#define BUTTON GPIO.3


#define LIGHT GPIO.5

Dir BUTTON In
Dir LIGHT Out

Do Until BUTTON = 1
PulseOut LIGHT, 1 s
Wait 1 s
Loop

Example 2:

This code will also flash a light until the button is pressed. This example uses EXIT DO within a
continuous loop.

#chip 12F629, 4
#config osc = int

#define BUTTON GPIO.3


#define LIGHT GPIO.5

Dir BUTTON In
Dir LIGHT Out

Do
PulseOut LIGHT, 1 s
Wait 1 s
if BUTTON = 1 then EXIT DO
Loop

For more help, see Conditions

End

Syntax:

End

Command Availability:

100
Available on all microcontrollers.

Explanation:

When the End command is used, the program will immediately stop running. There are very few cases
where this command is needed - generally, the program should be an endless loop.

Example:

'This program will turn on the red light, but not the green light
Set RED On
End
Set GREEN On

Exit

Syntax options:

Exit Sub | Exit Function | Exit Do | Exit For | Exit Repeat

Command Availability:

Available on all microcontrollers.

Explanation:

This command will make the program exit the routine it is currently in, as it would if it came to the end
of the routine.

Applies to Subroutines, Functions, For-Next loops, Do-Loop loops and Repeat loops.

Example:

101
#chip tiny13, 1

#define SENSOR PORTB.0


#define BUZZER PORTB.1
#define LIGHT PORTB.2
Dir SENSOR In
Dir BUZZER Out
Dir LIGHT Out

Do
Burglar
Loop

'Burglar Alarm subroutine


Sub Burglar
If SENSOR = 0 Then
Set BUZZER Off
Set LIGHT Off
Exit Sub
End If
Set BUZZER On
Set LIGHT On
End Sub

For more help, see Do, For, Sub, Functions and Repeat

For

Syntax:

For counter = start To end [Step increment]


...
program code
...
<condition> Exit For
...
Next

Command Availability:

Available on all microcontrollers.

Explanation:

The For command is ideal for situations where a piece of code needs to be run a set number of times,

102
and where it is necessary to keep track of how many times the code has run. When the For command is
first executed, counter is set to start. Then, each successive time the program loops, increment is added
to counter, until counter is equal to end. Then, the program continues beyond the Next.

Step and increment are optionals. If Step is not specified, Great Cow BASIC will increment counter by 1
each time the code is run.

The Exit For is optional and can be used to exit the loop upon a specific condition.

Example 1:

'This code will flash a green light 6 times.

#chip 16F88, 8
#config Osc = Int

#define LED PORTB.0


Dir LED Out

For LoopCounter = 1 to 6
PulseOut Led, 1 s
Wait 1 s
Next

Example 2:

103
'This code will flash alternate LEDS until the switch is pressed.

#chip 16F88, 8
#config Osc = Int

#define LED1 PORTB.0


Dir LED1 Out
#define LED2 PORTB.2
Dir LED2 Out

#define SWITCH1 PORTA.0


Dir SWITCH1 In
main:
PulseOut LED1, 1 s
For LoopCounterOut = 1 to 250
PulseOut LED2, 4 Ms
if switch = On then Exit For
Next
Set LED2 OFF
goto main

For more help, see Repeat

Gosub

Syntax:

Gosub label

Command Availability:

Available on all microcontrollers.

Explanation:

The Gosub command is used to jump to a label as a subroutine, in a similar way to Goto. The difference
is that Return can then be used to return to the line of code after the Goto.

NOTE

Gosub should NOT be used if it can be avoided. It is not required to call a subroutine that has been
defined using Sub, just write the name of the subroutine.

Example:

104
'This program will flash an LED on portb bit 0 and play a beep on
'porta bit 4. until the robot is turned off.

#chip 16F628A, 4 'Change this to suit your circuit

#define SOUNDOUT PORTA.4


#define LIGHT PORTB.0
Dir LIGHT Out

Do
'Flash Light
PulseOut LIGHT, 1 s
Wait 1 s
'Beep
Gosub PlayBeep
Loop

PlayBeep:
Tone 200, 10
Tone 100, 10
Return

For more help, see Goto and Labels

Goto

Syntax:

Goto label

Command Availability:

Available on all microcontrollers.

Explanation:

The Goto command will make the robot jump to the line specified, and continue running the program
from there. The Goto command is mainly useful for exiting out of loops - if you need to create an
infinite loop, use the Do command instead.

Be careful how you use Goto. If used too much, it can make programs very hard to read.

To define a label, put the name of the label alone on a line, with just a colon (:) after it.

Example:

105
'This program will flash the light until the button is pressed
'off. Notice the label named SWITCH_OFF.

#chip 16F628A, 4 'Change this line to suit your circuit

#define BUTTON PORTB.0


#define LIGHT PORTB.1
Dir BUTTON In
Dir BUTTON Out

Do
PulseOut LIGHT, 500 ms
If BUTTON = 1 Then Goto SWITCH_OFF
Wait 500 ms
If BUTTON = 1 Then Goto SWITCH_OFF
Loop

SWITCH_OFF:
Set LIGHT Off
'Chip will enter low power mode when program ends

For more help, see Gosub and Labels

If

Syntax:

106
Short form:

If condition Then command

Long form:

If condition Then
...
program code
...
End If

Using Else:

If condition Then
code to run if true
Else
code to run if false
End If

Command Availability:

Available on all microcontrollers.

Explanation:

The If command is the most common command used to make decisions. If condition is true, then
command (short) or program code (long) will be run. If it is false, then the robot will skip to the code
located on the next line (short) or after the End If (long form).

If Else is used, then the condition between If and Else will run if the condition is true, and the code
between Else and End If will run if the condition is false.

Note: Else must be on a separate line in the source code.

Supported:

<instruction> 'is supported


Else
<instruction>

<instruction> Else 'Not Supported, but will compile


<instruction>

107
Example:

'Turn a light on or off depending on a light sensor

#chip 12F683, 8
#config osc = int

#define LIGHT GPIO.1


#define SENSOR AN3
#define SENSOR_PORT GPIO.4

Dir LIGHT Out


Dir SENSOR_PORT In

Do
If ReadAD(SENSOR) > 128 Then
Set LIGHT Off
Else
Set LIGHT On
End If
Loop

For more help, see Conditions

IndCall

Syntax:

IndCall Address

Command Availability:

Available on all microcontrollers.

Explanation:

IndCall provides a basic implementation of function pointers. Address is the program memory location
of the subroutine that is to be called. There are two ways to specify this - either by providing a direct
reference to the subroutine using the @ operator, or by specifying a word variable that contains the
address.

This command is useful for callbacks. For example, a particular subroutine might read bytes from a
serial connection, but different actions may need to be taken at different times. A different subroutine
could be created for each action, and then the subroutine for the appropriate action could be passed to
the serial connection reading routine each time it is called.

108
Note: Calling subroutines that have parameters using IndCall is not supported. Errors may occur. If
data needs to be passed, use a variable instead.

Example:

'Flash an LED using an indirect call


#chip 12F683

'Create a word variable, and set it to the memory location of the


'Blink subroutine.
Dim FlashingSub As Word
FlashingSub = @Blink

'Main loop
Do
'Indirect call to subroutine at location FlashingSub
IndCall FlashingSub
Loop

'LED flashing subroutine


Sub Blink
PulseOut GPIO.0, 500 ms
Wait 500 ms
End Sub

Pause

Syntax:

Fixed Length Delay:


Pause time_ms

Command Availability:

Available on all microcontrollers.

Explanation:

The Pause command will cause the program to pause for a specified time in milliseconds. The only unit
of time permitted is milliseconds.

Please use the wait command to use other units of time.

For more help, see Wait

109
Repeat

Syntax:

Repeat times
...
program code
...
<condition> Exit Repeat
...
End Repeat

Command Availability:

Available on all microcontrollers.

Explanation:

The Repeat command is ideal for situations where a piece of code needs to be run a set number of
times. It uses less memory and runs faster than the For command, and should be used wherever it is
not necessary to count how many times the code has run.

Optionally, you can specify a condition to Exit the Repeat-Loop immediately.

Repeat has a maximum repeat value of 65535.

Example:

'This code will flash a green light 6 times.

#chip 16F88, 20

#define LED PORTB.0


dir LED out

Repeat 6
PulseOut LED, 1 s
Wait 1 s
End Repeat

See Also For

Select

Syntax:

110
Select Case var

Case value1
code1

Case value2
code2

Case Else
code3

End Select

Command Availability:

Available on all microcontrollers.

Explanation:

The Select Case control structure is used to select and run a particular section of code, based on the
value of var. If var equals value1 then code1 will be run. Once code1 has run, the chip will jump to the
End Select command and continue running the program. If none of the other conditions are true, then
the code under the Case Else section will be run.

Case Else is optional, and the program will function correctly without it.

If there is only one line of code after the Case, the code may look neater if the line is placed after the
Case. This is shown below in the example, for cases 3, 4 and 5.

It is important to note that only one section of code will be run when using Select Case.

There are two examples shown below.

Example 1:

111
'Program to read a value from a potentiometer, and display a
'different word based on the result

#chip 18F4550, 20

'LCD connection settings


#define LCD_IO 4
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

DIR PORTA.0 IN
Do
Temp = ReadAD(AN0) / 20
CLS
Select Case Temp
Case 0
Print "None!"
Case 1
Print "One"
Case 2
Print "Two"
Case 3: Print "Three"
Case 4: Print "Four"
Case 5: Print "Five"
Case Else
Print "A lot!"
End Select
Wait 250 ms
Loop

Example 2:

This code demonstrates how to receive codes from a handheld remote control unit. This has been
tested and supports a Sony TV remote and also a universal remote set to Sony TV mode.

The program gets both the device number and the key number, and also translates the key number to
English. The received results are displayed on an LCD.

The circuit for the IR receiver and the chip is shown below.

'A program to receive IR codes sent by a Sony

112
'compatible handheld remote control.

#chip 16F88, 8 'PIC16F88 running at 8 MHz


#config mclr=off 'reset handled internally
#config osc=int 'use internal clock

'----- Constants

#define LCD_IO 4 '4-bit mode


#define LCD_RS PortB.2 'pin 8 is Register Select
#define LCD_Enable PortB.3 'pin 9 is Enable
#define LCD_DB4 PortB.4 'DB4 on pin 10
#define LCD_DB5 PortB.5 'DB5 on pin 11
#define LCD_DB6 PortB.6 'DB6 on pin 12
#define LCD_DB7 PortB.7 'DB7 on pin 13
#define LCD_NO_RW 1 'ground RW line on LCD
#define IR PortA.0 'sensor on pin 17

'----- Variables

dim device, cmd, count, i as byte


dim pulse(12) 'pulse count array
dim button as string 'ASCII for button label

'----- Program

dir PortA in 'A.0 is IR input


dir PortB out 'B.2 - B.6 for LCD

cls 'clear the LCD


print "Dev: Cmd:" 'logo for top line
locate 1,0
print "Button:" 'logo for second line

do
getIR, cmd 'wait for IR signal
printCmd 'show device and command
printKey 'show key label
wait 10 mS 'ignore any repeats
loop 'repeat forever

'----- Subroutines

sub getIR
tarry1:
count = 0 'wait for start bit
do while IR = 0 'measure width (active low)
wait 100 uS '24 X 100 uS = 2.4 mS

113
count += 1
loop
if count < 20 then goto tarry1 'less than this so wait

for i=1 to 12 'read/store the 12 pulses


tarry2:
count = 0
do while IR = 0 'zero = 6 units = 0.6 mS
wait 100 uS 'one = 12 units = 1.2 mS
count += 1
loop
if count < 4 then goto tarry2 'too small to be legit
pulse(i) = count 'else store pulse width
next

cmd = 0 'command built up here


for i = 1 to 7 '1st seven bits are the cmd
cmd = cmd / 2 'shift into place
if pulse(i) > 10 then 'longer than 10 mS
cmd = cmd + 64 'so call it a one
end if
next

device = 0 'device number built up here


for i=8 to 12 'next 5 bits are device number
device = device / 2
if pulse(i) > 10 then
device = device + 16
end if
next
end sub

sub printCmd 'print device number


locate 0,5
print " "
locate 0,5
print device

locate 0,13 'print raw command number


print " "
locate 0,13
print cmd
end sub

sub PrintKey 'print translated button


locate 1,9
print " "
locate 1,9

114
select case cmd 'translate command code
case 0
button = "One"
case 1
button = "Two"
case 2
button = "Three"
case 3
button = "Four"
case 4
button = "Five"
case 5
button = "Six"
case 6
button = "Seven"
case 7
button = "Eight"
case 8
button = "Nine"
case 9
button = "Zero"
case 10
button = "#####"
case 11
button = "Enter"
case 12
button = "#####"
case 13
button = "#####"
case 14
button = "#####"
case 15
button = "#####"
case 16
button = "Chan+"
case 17
button = "Chan-"
case 18
button = "Vol+"
case 19
button = "Vol-"
case 20
button = "Mute"
case 21
button = "Power"
case else
button = " "

115
end select
print button
end sub

Wait

Syntax:

Fixed Length Delay:

Wait time units

Conditional Delay:

Wait {While | Until} condition

Command Availability:

Available on all microcontrollers.

Explanation:

The Wait command will cause the program to wait for either a specified amount of time (such as 1

116
second), or while/until a condition is true.

When using the fixed-length delay, there is a variety of units that are available:

Unit Length of unit Delay range

us 1 microsecond 1 us - 65535 us

10us 10 microseconds 10 us - 2.55 ms

ms 1 millisecond 1 ms - 65535 ms

10ms 10 milliseconds 10 ms - 2.55 s

s 1 second 1 s - 255 s

m 1 minute 1 min - 255 min

h 1 hour 1 hour - 255 hours

At one stage, Great Cow BASIC variables could not hold more than 255. The 10us and 10ms units were
added as a way to work around this limit. There is now no such limit (Wait 1000 ms will work for
example), so these are not really needed. However, you may see them in some older examples or
programs, and the 10us units are sometimes the shortest delay that will work accurately.

Example:

117
'This code will wait until a button is pressed, then it will flash
'a light every half a second and produce a 440 Hz tone.

#chip 16F819, 8
#config osc = int

#define BUTTON PORTB.0


#define SPEAKER PORTB.1
#define LIGHT PORTB.2
Dir BUTTON In
Dir SPEAKER Out
Dir LIGHT Out

'Assumes Button switches on when pressed


Wait Until BUTTON = 1
Wait Until BUTTON = 0

Do
'Flash the light
Set LIGHT On
Wait 500 ms
Set LIGHT Off

'Produce the tone


'440 Hz = 880 changes = tone on for 1.14 ms
Repeat 440
PulseOut SPEAKER, 1140 us
Wait 114 10us 'Wait for 114 x 10 us (1.14 ms)
End Repeat
Loop

For more help, see Conditions

118
Interrupts
This is the Interrupt section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Interrupts overview

Introduction

Interrupts are a feature of many microcontrollers. They allow the microcontroller to temporarily
pause (interrupt) the code it is running and then start running another piece of code when some event
occurs. Once it has dealt with the event, it will return to where it was and continue running the
program.

Many events can trigger an interrupt, such as a timer reaching its limit, a serial message being
received, or a special pin on the microcontroller receiving a signal.

Using Interrupts

There are two ways to use interrupts in Great Cow BASIC. The first way is to use the On Interrupt
command. This will automatically enable a given interrupt, and run a particular subroutine when the
interrupt occurs.

The other way to deal with interrupts is to create a subroutine called Interrupt. Great Cow BASIC will
call this subroutine whenever an interrupt occurs, and then your code can check the "flag" bits to
determine which interrupt has occured, and what should be done about it. If you use this approach,
then you’ll need to enable the desired interrupts manually. It is also essential that your code clears the
flag bits, or else the interrupt routine will be called repeatedly.

Some combination of these two methods is also possible - the code generated by On Interrupt with
check to see if the interrupt is one it recognises. If the interrupt is recognised, On Interrupt will deal
with it - if not, the Interrupt subroutine will be called to deal with the interrupt.

The recommended way is to use On Interrupt, as it is both more efficient and easier to set up.

During some sections of code, it is desirable not to have any interrupts occur. If this is the case, then
use the IntOff command to disable interrupts at the start of the section, and IntOn to re-enable them at
the end. If any interrupt events occur while interrupts are disabled, then they will be processed as
soon as interrupts are re-enabled. If the program does not use interrupts, IntOn and IntOff will be
removed automatically by Great Cow BASIC.

See Also IntOff, IntOn, On Interrupt

IntOff

Syntax:

119
IntOff

Command Availability:

Available on Microchip PIC and Atmel AVR microcontrollers with interrupt support. Will be
automatically removed on chips without interrupts.

Explanation:

IntOff is used to disable interrupts on the microcontroller. It should be used at the start of code which
is timing-sensitive, and which would not function correctly if paused and restarted.

It is essential that IntOn is used to turn interrupts on again after the timing-sensitive code has finished
running. If not, no interrupts will be handled.

It is recommended that IntOff be placed before all code that is timing sensitive, in case interrupts are
implemented later.

IntOff will be removed from the assembler if no interrupts are used.

See also IntOn, Interrupts

IntOn

Syntax:

IntOn

Command Availability:

Available on Microchip PIC and Atmel AVR microcontrollers with interrupt support. Will be
automatically removed on chips without interrupts.

Explanation:

IntOn is used to enable interrupts on the microcontroller after IntOff has disabled them. It should be
used at the end of code which is timing-sensitive.

IntOn will be removed from the assembler if no interrupts are used.

See also IntOff, Interrupts

On Interrupt

Syntax:

120
On Interrupt event Call handler
On Interrupt event Ignore

Command Availability:

Available on Microchip PIC and Atmel AVR microcontrollers with interrupt support.

Explanation:

On Interrupt will add code to call the subroutine handler whenever the interrupt event occurs. When
Call is specified, Great Cow BASIC will enable the interrupt, and call the interrupt handler when it
occurs. When Ignore is specified, Great Cow BASIC will disable the interrupt handler and prevent it
from being called when the event occurs. If the event occurs while the handler is disabled, then the
handler will be called as soon as it is re-enabled. The only way to prevent this from happening is to
manually clear the flag bit for the interrupt.

There are many possible interrupt events that can occur, and the events vary greatly from chip to chip.
Great Cow BASIC will display an error if a given chip cannot support the specified event.

In some cases, On Interrupt will not be able to set or clear the interrupt flag and/or enable bits. If this is
the case, Great Cow BASIC will display a warning. You will need to consult the chip datasheet and use
the Set command to manually set/clear the flag and enable bits, both at the start of the program and
inside the interrupt handler subroutine. If On Interrupt is used to handle an event, then the Interrupt
subroutine will not be called for that event. However, it will still be called for any events not dealt with
by On Interrupt.

Events:

Great Cow BASIC supports the events shown on the table below. Some events are only implemented on
a few specialised chips. Events in grey are supported by Microchip PIC and Atmel AVR
microcontrollers, events in blue are only supported by some Microchip PIC microcontrollers, and
events in red are only supported by Atmel AVR microcontrollers.

Note that Great Cow BASIC doesn’t fully support all of the hardware which can generate interrupts -
some work may be required with various system variables to control the unsupported peripherals.

Event Name Description Supported

ADCReady The analog/digital converter has finished a conversion Microchip&


AVR

BatteryFail The battery has failed in some way. This is only implemented on the AVR
ATmega406

CANActivity CAN bus activity is taking place Microchip

121
Event Name Description Supported

CANBadMessag A bad CAN message has been received Microchip


e

CANError Some CAN error has occured Microchip&


AVR

CANHighWater CAN high watermark reached Microchip


mark

CANRx0Ready New message present in buffer 0 Microchip

CANRx1Ready New message present in buffer 1 Microchip

CANRx2Ready New message present in buffer 2 Microchip

CANRxReady New message present Microchip

CANTransferCo Transfer of data has been completed AVR


mplete

CANTx0Ready Buffer 0 has been sent Microchip

CANTx1Ready Buffer 1 has been sent Microchip

CANTx2Ready Buffer 2 has been sent Microchip

CANTxReady Sending has completed Microchip

CCADCAccRead CC ADC accumulate conversion finished (ATmega406 only) AVR


y

CCADCReady CC ADC instantaneous conversion finished (ATmega406 only) AVR

CCADCRegular CC ADC regular conversion finished (ATmega406 only) AVR

CCP1 The CCP1 module has captured an event Microchip

CCP2 The CCP2 module has captured an event Microchip

CCP3 The CCP3 module has captured an event Microchip

CCP4 The CCP4 module has captured an event Microchip

CCP5 The CCP5 module has captured an event Microchip

Comp0Change The output of comparator 0 has changed Microchip&


AVR

Comp1Change The output of comparator 1 has changed Microchip&


AVR

Comp2Change The output of comparator 2 has changed Microchip&


AVR

Crypto The KEELOQ module has generated an interrupt Microchip

122
Event Name Description Supported

EEPROMReady An EEPROM write has finished Microchip&


AVR

Ethernet The Ethernet module has generated an interrupt. This must be dealt Microchip
within the handler.

ExtInt0 External Interrupt pin 0 has been ed Microchip&


AVR

ExtInt1 External Interrupt pin 1 has been ed Microchip&


AVR

ExtInt2 External Interrupt pin 2 has been ed Microchip&


AVR

ExtInt3 External Interrupt pin 3 has been ed Microchip&


AVR

ExtInt4 External Interrupt pin 4 has been ed AVR

ExtInt5 External Interrupt pin 5 has been ed AVR

ExtInt6 External Interrupt pin 6 has been ed AVR

ExtInt7 External Interrupt pin 7 has been ed AVR

GPIOChange The pins on port GPIO have changed Microchip

LCDReady The LCD is about to draw a segment Microchip&


AVR

LPWU The Low Power Wake Up has been ed Microchip

OscillatorFail The external oscillator has failed, and the microcontroller is running Microchip
from an internal oscillator.

PinChange Logic level of PCINT pin has changed AVR

PinChange0 Logic level of PCINT0 pin has changed AVR

PinChange1 Logic level of PCINT1 pin has changed AVR

PinChange2 Logic level of PCINT2 pin has changed AVR

PinChange3 Logic level of PCINT3 pin has changed AVR

PinChange4 Logic level of PCINT4 pin has changed AVR

PinChange5 Logic level of PCINT5 pin has changed AVR

PinChange6 Logic level of PCINT6 pin has changed AVR

PinChange7 Logic level of PCINT7 pin has changed AVR

PMPReady A Parallel Master Port read or write has finished Microchip

123
Event Name Description Supported

PORTChange The pins on ports ABCEDEF have changed. This is generic port change Microchip
interrupt. You must inspect the source to ensure you are handlign the
correct interrupt.

PORTAChange The pins on port A have changed Microchip

PORTABChange The pins on port A and/or B have changed Microchip

PORTBChange The pins on port B have changed Microchip&


AVR

PSC0Capture The counter for Power Stage Controller 0 matches the value in a AVR
compare register, the value of the counter has been captured, or a
synchronisation error has occurred

PSC0EndCycle Power Stage Controller 0 has reached the end of its cycle AVR

PSC1Capture The counter for Power Stage Controller 1 matches the value in a AVR
compare register, the value of the counter has been captured, or a
synchronisation error has occurred

PSC1EndCycle Power Stage Controller 1 has reached the end of its cycle AVR

PSC2Capture The counter for Power Stage Controller 2 matches the value in a AVR
compare register, the value of the counter has been captured, or a
synchronisation error has occurred

PSC2EndCycle Power Stage Controller 2 has reached the end of its cycle AVR

PSPReady A Parallel Slave Port read or write has finished Microchip

PWMTimeBase The PWM time base matches the PWM Time Base Period register Microchip
(PTPER)

SPIReady The SPI module has finished the previous transfer AVR

SPMReady A write to program memory by the spm instruction has finished AVR

SPPReady A SPP read or write has finished Microchip

SSP1Collision SSP1 has detected a bus collision Microchip

SSP1Ready The SSP/SSP1/MSSP1 module has finished sending or receiving Microchip

SSP2Collision SSP2 has detected a bus collision Microchip

SSP2Ready The SSP2/MSSP2 module has finished sending or receiving Microchip

Timer0Capture An input event on the pin ICP0 has caused the value of Timer 0 to be AVR
captured in the ICR0 register

Timer0Match1 Timer 0 matches the Timer 0 output compare register A (OCR0A) AVR

Timer0Match2 Timer 0 matches the Timer 0 output compare register B (OCR0B) AVR

124
Event Name Description Supported

Timer0Overflo Timer 0 has overflowed Microchip&


w AVR

Timer1Capture An input event on the pin ICP1 has caused the value of Timer 1 to be AVR
captured in the ICR1 register

Timer1Error The Timer 1 Fault Protection unit has been ed by an input on the INT0 AVR
pin

Timer1Match1 Timer 1 matches the Timer 1 output compare register A (OCR1A) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer1Match2 Timer 1 matches the Timer 1 output compare register B (OCR1B) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer1Match3 Timer 1 matches the Timer 1 output compare register C (OCR1C) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer1Match4 Timer 1 matches the Timer 1 output compare register D (OCR1D) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer1Overflo Timer 1 has overflowed Microchip&


w AVR

Timer2Match Timer 2 matches the Timer 2 output compare register (PR2) Microchip
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer2Match1 Timer 2 matches the Timer 2 output compare register A (OCR2A) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer2Match2 Timer 2 matches the Timer 2 output compare register B (OCR2B) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer2Overflo Timer 2 has overflowed AVR


w

Timer3Capture An input event on the pin ICP3 has caused the value of Timer 3 to be AVR
captured in the ICR3 register

Timer3Match1 Timer 3 matches the Timer 3 output compare register A (OCR3A) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

125
Event Name Description Supported

Timer3Match2 Timer 3 matches the Timer 3 output compare register B (OCR3B) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer3Match3 Timer 3 matches the Timer 3 output compare register C (OCR3C) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer3Overflo Timer 3 has overflowed Microchip&


w AVR

Timer4Capture An input event on the pin ICP4 has caused the value of Timer 4 to be AVR
captured in the ICR4 register

Timer4Match Timer 4 matches the Timer 4 output compare register (PR4) Microchip
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer4Match1 Timer 4 matches the Timer 4 output compare register A (OCR4A) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer4Match2 Timer 4 matches the Timer 4 output compare register B (OCR4B) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer4Match3 Timer 4 matches the Timer 4 output compare register C (OCR4C) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer4Overflo Timer 4 has overflowed AVR


w

Timer5CAP1 An input on the CAP1 pin has caused the value of Timer 5 to be Microchip
captured in CAP1BUF

Timer5CAP2 An input on the CAP2 pin has caused the value of Timer 5 to be Microchip
captured in CAP2BUF

Timer5CAP3 An input on the CAP3 pin has caused the value of Timer 5 to be Microchip
captured in CAP3BUF

Timer5Capture An input event on the pin ICP5 has caused the value of Timer 5 to be AVR
captured in the ICR5 register

Timer5Match1 Timer 5 matches the Timer 5 output compare register A (OCR5A) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer5Match2 Timer 5 matches the Timer 5 output compare register B (OCR5B) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

126
Event Name Description Supported

Timer5Match3 Timer 5 matches the Timer 5 output compare register C (OCR5C) AVR
Within the Interrupt handling sub routine ensure the timer reset and
cleartimer is set appropriately.

Timer5Overflo Timer 5 has overflowed Microchip&


w AVR

Timer6Match Timer 6 matches the Timer 6 output compare register (PR6) Microchip

Timer7Overflo Timer 7 has overflowed Microchip


w

Timer8Match Timer 8 matches the Timer 8 output compare register (PR8) Microchip

Timer10Match Timer 10 matches the Timer 10 output compare register (PR10) Microchip

Timer12Match Timer 12 matches the Timer 12 output compare register (PR12) Microchip

TWIConnect The Atmel AVR has been connected to or disconnected from the TWI Microchip&
(I2C) bus AVR

TWIReady The TWI has finished the previous transmission and is ready to send or Microchip&
receive more data AVR

UsartRX1Ready UART/USART 1 has received data Microchip&


AVR

UsartRX2Ready UART/USART 2 has received data Microchip&


AVR

UsartRX3Ready UART/USART 3 has received data AVR

UsartRX4Ready UART/USART 4 has received data AVR

UsartTX1Ready UART/USART 1 is ready to send data Microchip&


AVR

UsartTX1Sent UART/USART 1 has finished sending data AVR

UsartTX2Ready UART/USART 2 is ready to send data Microchip&


AVR

UsartTX2Sent UART/USART 2 has finished sending data AVR

UsartTX3Ready UART/USART 3 is ready to send data AVR

UsartTX3Sent UART/USART 3 has finished sending data AVR

UsartTX4Ready UART/USART 4 is ready to send data AVR

UsartTX4Sent UART/USART 4 has finished sending data AVR

USBEndpoint A USB endpoint has generated an interrupt AVR

127
Event Name Description Supported

USB The USB module has generated an interrupt. This must be dealt with in Microchip&
the handler. AVR

USIOverflow The USI counter has overflowed from 15 to 0 AVR

USIStart The USI module has detected a start condition AVR

VoltageFail The input voltage has dropped too low Microchip

VoltageRegulat An interrupt has been generated by the voltage regulator AVR


or (ATmega16HVA only)

WakeUp The Wake-Up timer has overflowed AVR

WDT An interrupt has been generated by the Watchdog Timer AVR

Example:

128
'This program increments a counter every time Timer1 overflows
#chip 16F877A, 20

'LCD connection settings


#define LCD_IO 4
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

InitTimer1 Osc, PS1_1/8


StartTimer 1
CounterValue = 0

Wait 100 ms
Print "Int Test"

On Interrupt Timer1Overflow Call IncCounter

Do
CLS
Print CounterValue
Wait 100 ms
Loop

Sub IncCounter
CounterValue ++
End Sub

For more help, see InitTimer0 article contains an example of using Timer 0 and On Interrupt to
generate a Pulse Width Modulation signal to control a motor.

See also IntOff, IntOn

On Interrupt: The default handler

Introduction

Great Cow BASIC supports a default interrupt handler in two modes:

1. You can define the interrupt flags and the default handler (a sub routine) will executed

2. You can define an On Interrupt event Call handler where the handler is executed that matches the
event and where all other define/valid events are handled by the default handler (a sub routine),

129
The easiest way to write an interrupt handler is to write it in Great Cow BASIC in conjunction with
the On Interrupt statement. On Interrupt tells microcontroller to activate its internal interrupt
handling and to jump to a predetermined interrupt handler (a sub routine that has been defined)
when the interrupt handler (the sub routine) has completed processing returns to correct address
in the program. See On Interrupt.

This method of supports the handling interrupts by enabling a default interrupt subroutine.

Example 1

This example shows if an event occurs the microcontroller will be program to jump to the interrupt
vector and the program will not know the event type, it will simple execute the Interrupt subroutine.
This code is not intended as a meaningful solution and intended to show the functionality only. An LED
is attached to PORTB.1 via a suitable resistor. It will light up when the Interrupt event has occurred.

#chip 16f877a, 4
dir PORTB.1 out
Set PORTB.1 Off

'Note: there is NO On Interrupt handler


InitTimer1 Osc, PS1_8
SetTimer 1, 1
StartTimer 1
'Manually set Timer1Overflow to the overflow event
'this will event will be handled by the Interrupt sub routine
TMR1IE = 1
end

Sub Interrupt
Set PORTB.1 On
TMR1IF = 0
End Sub

Example 2

Any events that are not dealt with by On Interrupt will result in the code in the Interrupt subroutine
executing. This example shows the operation of two interrupt handlers - is not intended as a
meaningful solution.

LEDs are attached to PORTB.1 and PORTB.2 via suitable resistors. They will light up when the
Interrupt events occur.

130
#chip 16f877a, 4
On Interrupt Timer1Overflow call Overflowed

dir PORTB.1 out


Set PORTB.1 Off

dir PORTB.2 out


Set PORTB.2 Off

InitTimer1 Osc, PS1_8


SetTimer 1, 1
StartTimer 1

InitTimer2 PS2_16, PS2_16


SetTimer 2, 255
StartTimer 2

'Manually set Timer2Overflow to create a second event


'this will event will be handled by the Interrupt sub routine
TMR2IE = 1
end

Sub Interrupt
Set PORTB.2 On
TMR2IF = 0
End Sub

Sub Overflowed
Set PORTB.1 On
TMR1IF = 0
End Sub

131
Keypad
This is the Keypad section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Keypad Overview

Introduction

The keypad routines allow for a program to read from a 4 x 4 matrix keypad.

There are two ways that the keypad routines can be set up. One option is to connect the wires from the
keypad in a particular order, and then to set the KeypadPort constant. The other option is to connect
the keypad in whatever way is easiest, and then set the KEYPAD_ROW_x and KEYPAD_COL_x constants. The
option (setting KeypadPort) will generate slightly more efficient code.

Configuration using KEYPAD_ROW_x and KEYPAD_COL_x:

These constants must be set:

Constant Controls Default


Name Value

KEYPAD_ROW_1 The pin on the microcontroller that connects to the Row 1 pin on the N/A
keypad

KEYPAD_ROW_2 The pin on the microcontroller that connects to the Row 2 pin on the N/A
keypad

KEYPAD_ROW_3 The pin on the microcontroller that connects to the Row 3 pin on the N/A
keypad

KEYPAD_ROW_4 The pin on the microcontroller that connects to the Row 4 pin on the N/A
keypad

KEYPAD_COL_1 The pin on the microcontroller that connects to the Col 1 pin on the N/A
keypad

KEYPAD_COL_2 The pin on the microcontroller that connects to the Col 2 pin on the N/A
keypad

KEYPAD_COL_3 The pin on the microcontroller that connects to the Col 3 pin on the N/A
keypad

KEYPAD_COL_4 The pin on the microcontroller that connects to the Col 4 pin on the N/A
keypad

If using a 3 x 3 keypad, do not set the KEYPAD_ROW_4 or KEYPAD_COL_4 constants.

Configuration using KeypadPort:

132
When setting up the keypad code using the KeypadPort constant, only KeypadPort needs to be set.

Pull-ups or pull-downs go on the columns only, and are typically 4.7k to 10k in value.

Constant Name Controls Default Value

KeypadPort The port on the microcontroller chip that the keypad is connected to. N/A

Configuration when using Pull down resistors

The keypad routine has a feature when using pull-down resistors, simply add the constant to your
program and the and the scan logic will be inverted appropriately.

Constant Name Controls Default Value

KEYPAD_PULLDOWN Support pull down resistors. N/A

For this to work, the keypad must be connected as follows:

Microcontroller port pin Keypad connector

0 Row 1

1 Row 2

2 Row 3

3 Row 4

4 Column 1

5 Column 2

6 Column 3

7 Column 4

Note: To use a 3 x 3 keypad in this mode, the pins on the microcontroller for any unused columns must
be pulled up.

KeypadData

Syntax:

var = KeypadData

Command Availability:

Available on all microcontrollers.

133
Explanation:

This function will return a value corresponding to the key that is pressed on the keypad. Note that if
two or more keys are pressed, then only one value will be returned. var can have one of the following
values:

Value Constant Name Key Pressed

0 0

1 1

2 2

3 3

4 4

5 5

6 6

7 7

8 8

9 9

10 KEY_A A

11 KEY_B B

12 KEY_C C

13 KEY_D D

14 KEY_STAR Asterisk/Star (*)

15 KEY_HASH Hash (#)

255 KEY_NONE None

Example:

134
'Program to show the value of the last pressed key on the LCD
#chip 18F4550, 20

'LCD connection settings


#define LCD_IO 4
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

'Keypad connection settings


#define KeypadPort PORTB

'Main loop
Do
'Get key
Temp = KeypadData

'If a key is pressed, then display it


If Temp <> KEY_NONE Then
CLS
Print Temp
Wait 100 ms
End If
Loop

For more help, see Keypad Overview

KeypadRaw

Syntax:

largevar = KeypadRaw

Command Availability:

Available on all microcontrollers.

Explanation:

This function will return a 16 bit value, in which each bit corresponds to a key on the keypad. If the key
is pressed its bit will hold 1, and if it is released its bit will contain a 0.

135
This table shows the key that each bit corresponds to:

Bit Key Position (row, col) Common Key Symbol

15 1,1 1

14 1,2 2

13 1,3 3

12 1,4 A

11 2,1 4

10 2,2 5

9 2,3 6

8 2,4 B

7 3,1 7

6 3,2 8

5 3,3 9

4 3,4 C

3 4,1 *

2 4,2 0

1 4,3 #

0 4,4 D

Example:

136
'Program to show the keypad status using LEDs
#chip 16F877A, 20

'Keypad connection settings


#define KeypadPort PORTB

'LEDs
#define LED1 PORTC
#define LED2 PORTD
Dir LED1 Out
Dir LED2 Out

'Declare a 16 bit variable for the key value


Dim KeyStatus As Word

'Main loop
Do
'Get key
KeyStatus = KeypadRaw

'Display
LED1 = KeyStatus_H 'High Byte
LED2 = KeyStatus 'Low Byte
Loop

For more help, see Keypad Overview

137
Graphical LCD
This is the GLCD section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

GLCD Overview

The GLCD commands are used to control a Graphical Liquid Crystal Display (GLCD) based on the a
number of GLCD chipsets. These are often 128x64 pixel displays but the size can vary. GLCD devices
draw graphical elements by enabling or disabling pixels.

A GLCD is an upgrade from the popular 16x2 LCDs (see Liquid Crystal Display Overview ) but the GLCD
allows full graphical control of the display.

Typical displays are

• Color or mono displays

• Low power white LED, OLED with or without back-light

• Driven by on-board interface chipsets or SPI interface controllers

• The GLCDs are very common and well documente

• Typically with viewing area is 71mmx39mm (2.8" x 1.5")

• Typically requires a 36-pin 0.1" header and 10K contrast pot

• Typically have back-lit pixels.

Great Cow BASIC makes this type of device easier to control with the commands for the GLCD.

Setup:

You must include the glcd.h file at the top of your program. The file needs to be in brackets as shown
below.

#include <GLCD.h>

Defines:

There are several connections that must be defined to use the GLCD commands with a GLCD display.
The I/O pin is the pin on the Microchip PIC or the Atmel AVR microcontroller that is connected to that
specific pin on the graphical LCD.

Example: KS0108 connectivity

138
#define GLCD_RW _I/O pin_ ‘Read/Write pin connection
#define GLCD_RESET _I/O pin_ ‘Reset pin connection
#define GLCD_CS1 _I/O pin_ ‘CS1 pin connection
#define GLCD_CS2 _I/O pin_ ‘CS2 pin connection
#define GLCD_RS _I/O pin_ ‘RS pin connection
#define GLCD_ENABLE _I/O pin_ ‘Enable pin Connection
#define GLCD_DB0 _I/O pin_ ‘Data pin 0 Connection
#define GLCD_DB1 _I/O pin_ ‘Data pin 1 Connection
#define GLCD_DB2 _I/O pin_ ‘Data pin 2 Connection
#define GLCD_DB3 _I/O pin_ ‘Data pin 3 Connection
#define GLCD_DB4 _I/O pin_ ‘Data pin 4 Connection
#define GLCD_DB5 _I/O pin_ ‘Data pin 5 Connection
#define GLCD_DB6 _I/O pin_ ‘Data pin 6 Connection
#define GLCD_DB7 _I/O pin_ ‘Data pin 7 Connection
#define GLCD_PROTECTOVERRUN 'prevent screen overdrawing 'SSD1306 GLCD only
#define GLCDDirection 'Invert GLCD Y axis 'KS0108 GCD only

Common commands supported across the range of supported GLCDs are:

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition,


t GCB font set Stringvariable )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific size Box ( Xposition1, Yposition1, Xposition2,
Yposition2, [Optional In LineColour as 0 or 1]
)
FilledBo Draw a box on the GLCD to a specific size FilledBox (Xposition1, Yposition1, Xposition2,
x that is filled with the foreground colour. Yposition2, [Optional In LineColour 0 or 1] )

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or
position that is set with the specific 1)
attribute.

139
Public variable supported across the range of supported GLCDs are shown in the table below. These
variables control the user definable parameters of a specific GLCD.

Variable Purpose Type

GLCDBackgrou Color of GLCD Can be monochrome or color.


nd background. For mono GLCDs the default is White or 0x0001. For color GLCDs
the default is White or 0xFFFF.

GLCDForegrou Color of GLCD Can be monochrome or color.


nd foreground. For mono GLCDs the default is non-white or 0x0000. For color
GLCDs the default is Black or 0x0000.

GLCDFontWidt Width of the current Default is 6 pixels.


h GLCD font.

GLCDfntDefau Size of the current Default is 0.+ This equates to the standard GCB font set.
lt GLCD font.

GLCDfntDefau Size of the current Default is 1.+ This equates to the 8 pixel high.
ltsize GLCD font.

For more help, see KS 0108 controllers, ST7735 Controllers and ST7920 Controllers

This example shows how to drive a KS0108 based Graphic LCD module with the built in commands of
Great Cow BASIC. See Graphic LCD for details, this is an external web site.

Example:

140
;Chip Settings
#chip 16F886,16
'#config MCLRE = on 'enable reset switch on CHIPINO
#include <GLCD.h>

;Defines (Constants)
#define GLCD_RW PORTB.1 'D9 to pin 5 of LCD
#define GLCD_RESET PORTB.5 'D13 to pin 17 of LCD
#define GLCD_CS1 PORTB.3 'D12 to actually since CS1, CS2 can be inverted
#define GLCD_CS2 PORTB.4 'D11 to actually since CS1, CS2 can be inverted
#define GLCD_RS PORTB.0 'D8 to pin 4 D/I pin on LCD
#define GLCD_ENABLE PORTB.2 'D10 to Pin 6 on LCD
#define GLCD_DB0 PORTC.7 'D0 to pin 7 on LCD
#define GLCD_DB1 PORTC.6 'D1 to pin 8 on LCD
#define GLCD_DB2 PORTC.5 'D2 to pin 9 on LCD
#define GLCD_DB3 PORTC.4 'D3 to pin 10 on LCD
#define GLCD_DB4 PORTC.3 'D4 to pin 11 on LCD
#define GLCD_DB5 PORTC.2 'D5 to pin 12 on LCD
#define GLCD_DB6 PORTC.1 'D6 to pin 13 on LCD
#define GLCD_DB7 PORTC.0 'D7 to pin 14 on LCD

Start:
GLCDCLS
GLCDPrint 0,10,"Hello" 'Print Hello
wait 5 s
GLCDPrint 0,10, "ASCII #:" 'Print ASCII #:
Box 18,30,28,40 'Draw Box Around ASCII Character
for char = 15 to 129 'Print 0 through 9
GLCDPrint 17, 20 , Str(char)+" "
GLCDdrawCHAR 20,30, char
wait 125 ms
next
line 0,50,127,50 'Draw Line using line command
for xvar = 0 to 80 'Draw line using Pset command
pset xvar,63,on '
next '
Wait 1 s
GLCDPrint 0,10,"End " 'Print Hello
wait 1 s
Goto Start

For more help, see Graphical LCD Demonstration, GLCDCLS, GLCDDrawChar, GLCDPrint,
GLCDReadByte, GLCDWriteByte, Pset

141
ILI9340 Controllers

This section covers GLCD devices that use the ILI9340 graphics controller. The ILI9340 is a TFT LCD
Single Chip Driver with 240RGBx320 Resolution and 262K colors.

The Great Cow BASIC constants shown below control the configuration of the ILI9340 controller.
Great Cow BASIC supports SPI hardware and software connectivity - this is shown in the tables
below.

To use the ILI9340 driver simply include the following in your user code. This will initialise the driver.

#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_ILI9340

'Pin mappings for ILI9340 - these MUST be specified


#define GLCD_DC porta.0 'example port setting
#define GLCD_CS porta.1 'example port setting
#define GLCD_RESET porta.2 'example port setting
#define GLCD_DI porta.3 'example port setting
#define GLCD_DO porta.4 'example port setting

The Great Cow BASIC constants for the interface to the controller are shown in the table below.

Constan Controls Option


ts s

GLCD_TYP GLCD_TYPE_ILI9340
E
GLCD_DC Specifies the output pin that is connected to Data/Command IO pin on the GLCD. Require
d

GLCD_CS Specifies the output pin that is connected to Chip Select (CS) on the GLCD. Require
d

GLCD_Res Specifies the output pin that is connected to Reset pin on the GLCD. Require
et d

GLCD_DI Specifies the output pin that is connected to Data In (GLCD out) pin on the GLCD. Require
d

GLCD_DO Specifies the output pin that is connected to Data Out (GLCD in) pin on the GLCD. Require
d

GLCD_SCK Specifies the output pin that is connected to Clock (CLK) pin on the GLCD. #define Require
GLCD_SCK porta.5 'example port setting d

The Great Cow BASIC constants for control display characteristics are shown in the table below.

142
Constants Controls Default

GLCD_WIDTH The width parameter of the GLCD 320+ Cannot be changed.

GLCD_HEIGHT The height parameter of the GLCD 240+ Cannot be changed.

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition, Stringvariable
t GCB font set )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific Box ( Xposition1, Yposition1, Xposition2,
size Yposition2, [Optional In LineColour as 0 or 1]

FilledBo Draw a box on the GLCD to a specific FilledBox (Xposition1, Yposition1, Xposition2,
x size that is filled with the foreground Yposition2, [Optional In LineColour 0 or 1] )
colour.

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or 1)
position that is set with the specific
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte ( LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, bytevariable = GLCDReadByte


Byte see the datasheet for usage.

GLCDRota Rotate the display LANDSCAPE, PORTRAIT_REV, LANDSCAPE_REV and


te PORTRAIT are supported

143
Comma Purpose Example
nd

ILI9340_ Specify color as a parameter for many Color constants for this device are shown in the
[color] GLCD commands list below.
Any color can be defined using a valid
hexidecimal word value between 0x0000 to
0xFFFF.

ILI9340_BLACK 'hexidecimal value 0x0000


ILI9340_RED 'hexidecimal value 0xF800
ILI9340_GREEN 'hexidecimal value 0x07E0
ILI9340_BLUE 'hexidecimal value 0x001F
ILI9340_WHITE 'hexidecimal value 0xFFFF
ILI9340_PURPLE 'hexidecimal value 0xF11F
ILI9340_YELLOW 'hexidecimal value 0xFFE0
ILI9340_CYAN 'hexidecimal value 0x07FF
ILI9340_D_GRAY 'hexidecimal value 0x528A
ILI9340_L_GRAY 'hexidecimal value 0x7997
ILI9340_SILVER 'hexidecimal value 0xC618
ILI9340_MAROON 'hexidecimal value 0x8000
ILI9340_OLIVE 'hexidecimal value 0x8400
ILI9340_LIME 'hexidecimal value 0x07E0
ILI9340_AQUA 'hexidecimal value 0x07FF
ILI9340_TEAL 'hexidecimal value 0x0410
ILI9340_NAVY 'hexidecimal value 0x0010
ILI9340_FUCHSIA 'hexidecimal value 0xF81F

For a ILI9340 datasheet, please refer here.

This example shows how to drive a ILI9340 based Graphic LCD module with the built in commands of
Great Cow BASIC.

Example:

144
;Chip Settings
#chip 16F1937,32
#config Osc = INT, VCAPEN_OFF, MCLRE_ON, PLLEN_ON, CLKOUTEN_OFF 'microcontroller
specific configuration

#include <glcd.h>

'Defines for ILI9340


#define GLCD_TYPE GLCD_TYPE_ILI9340

'Pin mappings for ILI9340


#define GLCD_DC porta.0
#define GLCD_CS porta.1
#define GLCD_RESET porta.2
#define GLCD_DI porta.3
#define GLCD_DO porta.4
#define GLCD_SCK porta.5

GLCDPrint(0, 0, "Test of the ILI9340 Device")


end

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

ILI9341 Controllers

This section covers GLCD devices that use the ILI9341 graphics controller. The ILI9341 is a TFT LCD
Single Chip Driver with 240RGBx320 Resolution and 262K colors.

The Great Cow BASIC constants shown below control the configuration of the ILI9341 controller.
Great Cow BASIC supports SPI hardware and software connectivity - this is shown in the tables
below.

To use the ILI9341 driver simply include the following in your user code. This will initialise the driver.

145
#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_ILI9341

'Pin mappings for ILI9341 - these MUST be specified


#define GLCD_DC porta.0 'example port setting
#define GLCD_CS porta.1 'example port setting
#define GLCD_RESET porta.2 'example port setting
#define GLCD_DI porta.3 'example port setting
#define GLCD_DO porta.4 'example port setting
#define GLCD_SCK porta.5 'example port setting

The Great Cow BASIC constants for the interface to the controller are shown in the table below.

Constants Controls Options

GLCD_TYPE GLCD_TYPE_ILI9341
GLCD_DC Specifies the output pin that is connected to Data/Command IO pin on the GLCD. Required

GLCD_CS Specifies the output pin that is connected to Chip Select (CS) on the GLCD. Required

GLCD_Reset Specifies the output pin that is connected to Reset pin on the GLCD. Required

GLCD_DI Specifies the output pin that is connected to Data In (GLCD out) pin on the Required
GLCD.

GLCD_DO Specifies the output pin that is connected to Data Out (GLCD in) pin on the Required
GLCD.

GLCD_SCK Specifies the output pin that is connected to Clock (CLK) pin on the GLCD. Required

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Defaul


t

GLCD_WIDTH The width parameter of the GLCD 320

GLCD_HEIGHT The height parameter of the GLCD 240

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

146
Comma Purpose Example
nd

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition, Stringvariable
t GCB font set )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific Box ( Xposition1, Yposition1, Xposition2,
size Yposition2, [Optional In LineColour as 0 or 1]

FilledBo Draw a box on the GLCD to a specific FilledBox (Xposition1, Yposition1, Xposition2,
x size that is filled with the foreground Yposition2, [Optional In LineColour 0 or 1] )
colour.

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or 1)
position that is set with the specific
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte ( LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, bytevariable = GLCDReadByte


Byte see the datasheet for usage.

GLCDRota Rotate the display LANDSCAPE, PORTRAIT_REV, LANDSCAPE_REV and


te PORTRAIT are supported

ILI9341_ Specify color as a parameter for many Color constants for this device are shown in the
[color] GLCD commands list below.
Any color can be defined using a valid
hexidecimal word value between 0x0000 to
0xFFFF.

147
ILI9341_BLACK 'hexidecimal value 0x0000
ILI9341_RED 'hexidecimal value 0xF800
ILI9341_GREEN 'hexidecimal value 0x07E0
ILI9341_BLUE 'hexidecimal value 0x001F
ILI9341_WHITE 'hexidecimal value 0xFFFF
ILI9341_PURPLE 'hexidecimal value 0xF11F
ILI9341_YELLOW 'hexidecimal value 0xFFE0
ILI9341_CYAN 'hexidecimal value 0x07FF
ILI9341_D_GRAY 'hexidecimal value 0x528A
ILI9341_L_GRAY 'hexidecimal value 0x7997
ILI9341_SILVER 'hexidecimal value 0xC618
ILI9341_MAROON 'hexidecimal value 0x8000
ILI9341_OLIVE 'hexidecimal value 0x8400
ILI9341_LIME 'hexidecimal value 0x07E0
ILI9341_AQUA 'hexidecimal value 0x07FF
ILI9341_TEAL 'hexidecimal value 0x0410
ILI9341_NAVY 'hexidecimal value 0x0010
ILI9341_FUCHSIA 'hexidecimal value 0xF81F

For a ILI9341 datasheet, please refer here.

This example shows how to drive a ILI9341 based Graphic LCD module with the built in commands of
Great Cow BASIC.

Example:

148
;Chip Settings
#chip 16F1937,32
#config Osc = INT, VCAPEN_OFF, MCLRE_ON, PLLEN_ON, CLKOUTEN_OFF 'microcontroller
specific configuration

#include <glcd.h>

'Defines for ILI9341


#define GLCD_TYPE GLCD_TYPE_ILI9341

'Pin mappings for ILI9341


#define GLCD_DC porta.0
#define GLCD_CS porta.1
#define GLCD_RESET porta.2
#define GLCD_DI porta.3
#define GLCD_DO porta.4
#define GLCD_SCK porta.5

GLCDPrint(0, 0, "Test of the ILI9341 Device")


end

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

ILI9481 Controllers

This section covers GLCD devices that use the ILI9481 graphics controller.

ILI9481 is a 262,144-color single-chip SoC driver for a-TFT liquid crystal display with resolution of
320RGBx480 dots, comprising a 960-channel source driver, a 480-channel gate driver, 345,600 bytes
GRAM for graphic data.

The Great Cow BASIC constants shown below control the configuration of the ILI9481 controller. The
Great Cow BASIC constants for control of the connectivity are shown in the table below. The only
connectivity option the 8-bit mode where 8 pins are connected between the microcontroller and the
GLCD to control the data bus.

To use the ILI9481 driver simply include the following in your user code. This will initialise the driver.

149
#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_ILI9481

'Pin mappings for SPI - this GLCD driver supports Hardware SPI and Software SPI
#define GLCD_RD ANALOG_0 ' read command line
#define GLCD_WR ANALOG_1 ' write command line
#define GLCD_RS ANALOG_2 ' Command/Data line
#define GLCD_CS ANALOG_3 ' Chip select line
#define GLCD_RST ANALOG_4 ' Reset line

#define GLCD_DB0 DIGITAL_8 'Data port'


#define GLCD_DB1 DIGITAL_9 'Data port'
#define GLCD_DB2 DIGITAL_2 'Data port'
#define GLCD_DB3 DIGITAL_3 'Data port'
#define GLCD_DB4 DIGITAL_4 'Data port'
#define GLCD_DB5 DIGITAL_5 'Data port'
#define GLCD_DB6 DIGITAL_6 'Data port'
#define GLCD_DB7 DIGITAL_7 'Data port'

The Great Cow BASIC constants for the interface to the controller are shown in the table below.

Constants Controls Options

GLCD_TYPE GLCD_TYPE_ILI9481
GLCD_DB0.. Specifies the pin that is connected to DB0..7 IO pin on the GLCD. Require
7 d

GLCD_RST Specifies the output pin that is connected to Reset IO pin on the GLCD. Require
d

GLCD_CS Specifies the output pin that is connected to Chip Select (CS) on the GLCD. Require
d

GLCD_RS Specifies the output pin that is connected to Data/Command pin on the GLCD. Require
d

GLCD_RW Specifies the output pin that is connected to Data In (RW or WDR) pin on the Require
GLCD. d

GLCD_RD Specifies the output pin that is connected to Data Out (RD or RDR) pin on the Require
GLCD. d

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Defaul


t

GLCD_WIDTH The width parameter of the GLCD 320

150
Constants Controls Defaul
t

GLCD_HEIGHT The height parameter of the GLCD 240

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition, Stringvariable
t GCB font set )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific Box ( Xposition1, Yposition1, Xposition2,
size Yposition2, [Optional In LineColour as 0 or 1]

FilledBo Draw a box on the GLCD to a specific FilledBox (Xposition1, Yposition1, Xposition2,
x size that is filled with the foreground Yposition2, [Optional In LineColour 0 or 1] )
colour.

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or 1)
position that is set with the specific
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte ( LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, bytevariable = GLCDReadByte


Byte see the datasheet for usage.

GLCDRota Rotate the display LANDSCAPE, PORTRAIT_REV, LANDSCAPE_REV and


te PORTRAIT are supported

ILI9481_ Specify color as a parameter for many Color constants for this device are shown in the
[color] GLCD commands list below.
Any color can be defined using a valid
hexidecimal word value between 0x0000 to
0xFFFF.

151
ILI9481_BLACK 'hexidecimal value 0x0000
ILI9481_RED 'hexidecimal value 0xF800
ILI9481_GREEN 'hexidecimal value 0x07E0
ILI9481_BLUE 'hexidecimal value 0x001F
ILI9481_WHITE 'hexidecimal value 0xFFFF
ILI9481_PURPLE 'hexidecimal value 0xF11F
ILI9481_YELLOW 'hexidecimal value 0xFFE0
ILI9481_CYAN 'hexidecimal value 0x07FF
ILI9481_D_GRAY 'hexidecimal value 0x528A
ILI9481_L_GRAY 'hexidecimal value 0x7997
ILI9481_SILVER 'hexidecimal value 0xC618
ILI9481_MAROON 'hexidecimal value 0x8000
ILI9481_OLIVE 'hexidecimal value 0x8400
ILI9481_LIME 'hexidecimal value 0x07E0
ILI9481_AQUA 'hexidecimal value 0x07FF
ILI9481_TEAL 'hexidecimal value 0x0410
ILI9481_NAVY 'hexidecimal value 0x0010
ILI9481_FUCHSIA 'hexidecimal value 0xF81F

This example shows how to drive a ILI9481 based Graphic LCD module with the built in commands of
Great Cow BASIC. This example uses a UNO shield, this can easily adapted to Microchip architecture.

Example:

152
#include <glcd.h>
#include <UNO_mega328p.h >

#define GLCD_TYPE GLCD_TYPE_ILI9481

'Pin mappings for SPI - this GLCD driver supports Hardware SPI and Software SPI
#define GLCD_RD ANALOG_0 ' read command line
#define GLCD_WR ANALOG_1 ' write command line
#define GLCD_RS ANALOG_2 ' Command/Data line
#define GLCD_CS ANALOG_3 ' Chip select line
#define GLCD_RST ANALOG_4 ' Reset line

#define GLCD_DB0 DIGITAL_8


#define GLCD_DB1 DIGITAL_9
#define GLCD_DB2 DIGITAL_2
#define GLCD_DB3 DIGITAL_3
#define GLCD_DB4 DIGITAL_4
#define GLCD_DB5 DIGITAL_5
#define GLCD_DB6 DIGITAL_6
#define GLCD_DB7 DIGITAL_7

GLCDPrint(0, 0, "Test of the ILI9481 Device")


end

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

ILI9486L Controllers

This section covers GLCD devices that use the ILI9486L graphics controller.

The ILI9486L is a 262,144-color single-chip SoC driver for a-Si TFT liquid crystal display with resolution
of 320RGBx480 dots, comprising a 960-channel source driver, a 480-channel gate driver, 345,600bytes
GRAM for graphic data of 320RGBx480 dots.

The Great Cow BASIC constants shown below control the configuration of the ILI9486L controller.
Great Cow BASIC supports SPI hardware and software connectivity - this is shown in the tables
below.

To use the ILI9486L driver simply include the following in your user code. This will initialise the
driver.

#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_ILI9486L

153
The Great Cow BASIC constants for the interface to the controller are shown in the table below.

Constants Controls Options

GLCD_TYPE GLCD_TYPE_ILI9486L
GLCD_DC Specifies the output pin that is connected to Data/Command IO pin on the GLCD. Required

GLCD_CS Specifies the output pin that is connected to Chip Select (CS) on the GLCD. Required

GLCD_Reset Specifies the output pin that is connected to Reset pin on the GLCD. Required

GLCD_DI Specifies the output pin that is connected to Data In (GLCD out) pin on the Required
GLCD.

GLCD_DO Specifies the output pin that is connected to Data Out (GLCD in) pin on the Required
GLCD.

GLCD_SLK Specifies the output pin that is connected to Clock (CLK) pin on the GLCD. Required

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Defaul


t

GLCD_WIDTH The width parameter of the GLCD 320

GLCD_HEIGHT The height parameter of the GLCD 480

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition, Stringvariable
t GCB font set )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific Box ( Xposition1, Yposition1, Xposition2,
size Yposition2, [Optional In LineColour as 0 or 1]

FilledBo Draw a box on the GLCD to a specific FilledBox (Xposition1, Yposition1, Xposition2,
x size that is filled with the foreground Yposition2, [Optional In LineColour 0 or 1] )
colour.

154
Comma Purpose Example
nd

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or 1)
position that is set with the specific
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte ( LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, bytevariable = GLCDReadByte


Byte see the datasheet for usage.

GLCDRota Rotate the display LANDSCAPE, PORTRAIT_REV, LANDSCAPE_REV and


te PORTRAIT are supported

ILI9486L Specify color as a parameter for many Color constants for this device are shown in the
_[color] GLCD commands list below.
Any color can be defined using a valid
hexidecimal word value between 0x0000 to
0xFFFF.

ILI9486L_BLACK 'hexidecimal value 0x0000


ILI9486L_RED 'hexidecimal value 0xF800
ILI9486L_GREEN 'hexidecimal value 0x07E0
ILI9486L_BLUE 'hexidecimal value 0x001F
ILI9486L_WHITE 'hexidecimal value 0xFFFF
ILI9486L_PURPLE 'hexidecimal value 0xF11F
ILI9486L_YELLOW 'hexidecimal value 0xFFE0
ILI9486L_CYAN 'hexidecimal value 0x07FF
ILI9486L_D_GRAY 'hexidecimal value 0x528A
ILI9486L_L_GRAY 'hexidecimal value 0x7997
ILI9486L_SILVER 'hexidecimal value 0xC618
ILI9486L_MAROON 'hexidecimal value 0x8000
ILI9486L_OLIVE 'hexidecimal value 0x8400
ILI9486L_LIME 'hexidecimal value 0x07E0
ILI9486L_AQUA 'hexidecimal value 0x07FF
ILI9486L_TEAL 'hexidecimal value 0x0410
ILI9486L_NAVY 'hexidecimal value 0x0010
ILI9486L_FUCHSIA 'hexidecimal value 0xF81F

For a ILI9486L datasheet, please refer to Google.

This example shows how to drive a ILI9486L based Graphic LCD module with the built in commands of
Great Cow BASIC.

155
Example:

#chip mega328p, 16
#option explicit

#include <glcd.h>
#include <UNO_mega328p.h >

#define GLCD_TYPE GLCD_TYPE_ILI9486L

'Pin mappings for SPI - this GLCD driver supports Hardware SPI and Software SPI
#define GLCD_DC DIGITAL_8 ' Data command line
#define GLCD_CS DIGITAL_10 ' Chip select line
#define GLCD_RESET DIGITAL_9 ' Reset line

#define GLCD_DI DIGITAL_12 ' Data in | MISO


#define GLCD_DO DIGITAL_11 ' Data out | MOSI
#define GLCD_SCK DIGITAL_13 ' Clock Line

#define ILI9486L_HardwareSPI ' Remove/comment out if you want to use


software SPI.

GLCDPrint(0, 0, "Test of the ILI9486L Device")


end

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

KS0108 Controllers

This section covers GLCD devices that use the KS0108 graphics controller.

The KS0108 is an LCD is driven by on-board 5V parallel interface chipset KS0108 and KS0107. They are
extremely common and well documented

The Great Cow BASIC constants shown below control the configuration of the KS0108 controller. The
only connectivity option is the 8-bit mode where 8 connections (for the data) are required between the
microcontroller and the GLCD to control the data bus.

The SH1106 is a monochrome device.

To use the KS0108 driver simply include the following in your user code. This will initialise the driver.

156
#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_KS0108

#define GLCD_RW PORTB.1 'chip specific configuration


#define GLCD_RESET PORTB.5 'chip specific configuration
#define GLCD_CS1 PORTB.3 'chip specific configuration
#define GLCD_CS2 PORTB.4 'chip specific configuration
#define GLCD_RS PORTB.0 'chip specific configuration
#define GLCD_ENABLE PORTB.2 'chip specific configuration
#define GLCD_DB0 PORTC.7 'chip specific configuration
#define GLCD_DB1 PORTC.6 'chip specific configuration
#define GLCD_DB2 PORTC.5 'chip specific configuration
#define GLCD_DB3 PORTC.4 'chip specific configuration
#define GLCD_DB4 PORTC.3 'chip specific configuration
#define GLCD_DB5 PORTC.2 'chip specific configuration
#define GLCD_DB6 PORTC.1 'chip specific configuration
#define GLCD_DB7 PORTC.0 'chip specific configuration

The Great Cow BASIC constants for the interface to the controller are shown in the table below.

Consta Controls Options


nts

GLCD_TY GLCD_TYPE_KS0108
PE
GLCD_RS Specifies the output pin that is connected to Required
Register Select on the GLCD.

GLCD_RW Specifies the output pin that is connected to Must be defined (unless R/W is disabled)
Read/Write on the GLCD. The R/W pin can be see GLCD_NO_RW
disabled.

GLCD_CS Specifies the output pin that is connected to Required


1 CS1 on the GLCD.

GLCD_CS Specifies the output pin that is connected to Required


2 CS2 on the GLCD.

GLCD_EN Specifies the output pin that is connected to Required


ABLE Enable on the GLCD.

GLCD_DB Specifies the output pin that is connected to Required


0 DB0 on the GLCD.

GLCD_DB Specifies the output pin that is connected to Required


1 DB1 on the GLCD.

157
Consta Controls Options
nts

GLCD_DB Specifies the output pin that is connected to Required


2 DB2 on the GLCD.

GLCD_DB Specifies the output pin that is connected to Required


3 DB3 on the GLCD.

GLCD_DB Specifies the output pin that is connected to Required


4 DB4 on the GLCD.

GLCD_DB Specifies the output pin that is connected to Required


5 DB5 on the GLCD.

GLCD_DB Specifies the output pin that is connected to Required


6 DB6 on the GLCD.

GLCD_DB Specifies the output pin that is connected to Required


7 DB7 on the GLCD.

GLCD_NO Disables read/write inspection of the device Optional, but recommend NOT to set. The R/W
_RW during read/write operations pin can be disabled by setting the GLCD_NO_RW
constant. If this is done, there is no need for
the R/W to be connected to the chip, and no
need for the LCD_RW constant to be set. Ensure
that the R/W line on the LCD is connected to
ground if not used.

GLCD_DA Not Available for this controller. Not applicable.


TA_PORT

The Great Cow BASIC constants defined for the controller type are shown in the table below.

Constants Controls Default

GLCD_WIDTH The width parameter of the 128 This constant cannot be changed
GLCD

GLCD_HEIGHT The height parameter of the 64 This constant cannot be changed


GLCD

GLCDDirection Defining this will invert the Y Not defined


Axis

KS0108ReadDelay Read delay Default is 9 Can be set to improve overall


performance.

KS0108WriteDela Write delay Default is 1 Can be set to improve performance.


y
KS0108ClockDela Clock Delay Default is 1 Can be set to improve performance.
y

158
The Great Cow BASIC constants for control display characteristics are shown in the table below.

Variables Controls Default

GLCDFontWidth Width of the current GLCD Default is 6 pixels.


font.

GLCDfntDefault Size of the current GLCD font. Default is 0. This equates to the standard GCB font
set.

GLCDfntDefaultsiz Size of the current GLCD font. Default is 1. This equates to the 8 pixel high.
e

The Great Cow BASIC commands supported for this GLCD are shown in the table below.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition,


t GCB font set Stringvariable )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific size Box ( Xposition1, Yposition1, Xposition2,
Yposition2, [Optional In LineColour as 0 or 1]
)
FilledBo Draw a box on the GLCD to a specific size FilledBox (Xposition1, Yposition1, Xposition2,
x that is filled with the foreground colour. Yposition2, [Optional In LineColour 0 or 1] )

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or
position that is set with the specific 1)
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte ( LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, see bytevariable = GLCDReadByte
Byte the datasheet for usage.

For a KS0108 datasheet, please refer here.

This example shows how to drive a KS0108 based Graphic LCD module with the built in commands of
Great Cow BASIC. See Graphic LCD for details, this is an external web site.

159
;Chip Settings
#chip 16F886,16
'#config MCLRE = on 'enable reset switch on CHIPINO
#include <GLCD.h>

;Defines (Constants)
#define GLCD_RW PORTB.1 'D9 to pin 5 of LCD
#define GLCD_RESET PORTB.5 'D13 to pin 17 of LCD
#define GLCD_CS1 PORTB.3 'D12 to actually since CS1, CS2 can be reversed on some
devices
#define GLCD_CS2 PORTB.4 'D11 to actually since CS1, CS2 can be reversed on some
devices
#define GLCD_RS PORTB.0 'D8 to pin 4 D/I pin on LCD
#define GLCD_ENABLE PORTB.2 'D10 to Pin 6 on LCD
#define GLCD_DB0 PORTC.7 'D0 to pin 7 on LCD
#define GLCD_DB1 PORTC.6 'D1 to pin 8 on LCD
#define GLCD_DB2 PORTC.5 'D2 to pin 9 on LCD
#define GLCD_DB3 PORTC.4 'D3 to pin 10 on LCD
#define GLCD_DB4 PORTC.3 'D4 to pin 11 on LCD
#define GLCD_DB5 PORTC.2 'D5 to pin 12 on LCD
#define GLCD_DB6 PORTC.1 'D6 to pin 13 on LCD
#define GLCD_DB7 PORTC.0 'D7 to pin 14 on LCD

Do forever
GLCDCLS
GLCDPrint 0,10,"Hello" 'Print Hello
wait 5 s
GLCDPrint 0,10, "ASCII #:" 'Print ASCII #:
Box 18,30,28,40 'Draw Box Around ASCII Character
for char = 15 to 129 'Print 0 through 9
GLCDPrint 17, 20 , Str(char)+" "
GLCDdrawCHAR 20,30, char
wait 125 ms
next
line 0,50,127,50 'Draw Line using line command
for xvar = 0 to 80 'draw line using Pset command
pset xvar,63,on '
next '
Wait 1 s
GLCDPrint 0,10,"End " 'Print Hello
wait 1 s
Loop

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

160
PCD8544 Controllers

This section covers GLCD devices that use the PCD844 graphics controller.

The PCD8544 is a low power CMOS LCD controller/driver, designed to drive a graphic display of 48
rows and 84 columns. All necessary functions for the display are provided in a single chip, including
on-chip generation of LCD supply and bias voltages, resulting in a minimum of external components
and low power consumption. The PCD8544 interfaces to microcontrollers through a serial bus
interface.

The Great Cow BASIC constants shown below control the configuration of the PCD844 controller.
Great Cow BASIC supports SPI software connectivity only - this is shown in the tables below.

The SH1106 is a monochrome device.

To use the PCD844 driver simply include the following in your user code. This will initialise the driver.

#include <glcd.h>
#define GLCD_TYPE GLCD_TYPE_PCD8544

' Pin mappings for software SPI for Nokia 3310 Device
#define GLCD_DO portc.5 'example port setting
#define GLCD_SCK portc.3 'example port setting
#define GLCD_DC portc.2 'example port setting
#define GLCD_CS portc.1 'example port setting
#define GLCD_RESET portc.0 'example port setting

The Great Cow BASIC constants for the interface to the controller are shown in the table below.

Constants Controls Options

GLCD_TYPE GLCD_TYPE_PCD8544
GLCD_DC Specifies the output pin that is connected to Data/Command IO pin on the GLCD. Required

GLCD_CS Specifies the output pin that is connected to Chip Select (CS) on the GLCD. Required

GLCD_Reset Specifies the output pin that is connected to Reset pin on the GLCD. Required

GLCD_D0 Specifies the output pin that is connected to Data Out (GLCD in) pin on the Required
GLCD.

GLCD_SCK Specifies the output pin that is connected to Clock (CLK) pin on the GLCD. Required

The Great Cow BASIC constants for control display characteristics are shown in the table below.

161
Constants Controls Default

GLCD_TYPE_PCD8544_CHA Specifies that the display controller will operate in text Optional
RACTER_MODE_ONLY mode and BMP draw mode only.
For microcontrollers with less then 1kb of RAM this will
be set be default.

PCD8544ClockDelay Specifies the clock delay, if required for slower Optional. Set to 0 as
microcontroller, the default value

PCD8544WriteDelay Specifies the write delay, if required for slower Optional. Set to 0 as
microcontroller, the default value

GLCD_WIDTH The width parameter of the GLCD 160


This cannot be
changed

GLCD_HEIGHT The height parameter of the GLCD 128


This cannot be
changed

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition,


t GCB font set Stringvariable )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific size Box ( Xposition1, Yposition1, Xposition2,
Yposition2, [Optional In LineColour as 0 or 1]
)
FilledBo Draw a box on the GLCD to a specific size FilledBox (Xposition1, Yposition1, Xposition2,
x that is filled with the foreground colour. Yposition2, [Optional In LineColour 0 or 1] )

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or
position that is set with the specific 1)
attribute.

162
Comma Purpose Example
nd

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte ( LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, see bytevariable = GLCDReadByte
Byte the datasheet for usage.

*For a PCD8544 datasheet, please refer here

This example shows how to drive a PCD8544 based Graphic LCD module with the built in commands of
Great Cow BASIC.

Example:

#chip 16lf1939,32
#config Osc = INT, MCLRE_ON, PLLEN_Off, CLKOUTEN_OFF

#include <glcd.h>

#DEFINE GLCD_TYPE GLCD_TYPE_PCD8544

' Pin mappings for software SPI for Nokia 3310 Device
#define GLCD_DO portc.5
#define GLCD_SCK portc.3
#define GLCD_DC portc.2
#define GLCD_CS portc.1
#define GLCD_RESET portc.0

GLCDCLS

DO forever
for CCount = 31 to 127
GLCDPrint (0, 0, "PrintStr")
GLCDDrawString (0, 9, "DrawStr")
GLCDPrint ( 44 , 21, " ")
GLCDPrint ( 44 , 29, " ") ' word value
GLCDPrint ( 44 , 37, " ") ' Byte value

outstring = hex( longNumber_U)


GLCDPrint ( 44 , 21,outstring )
outstring = hex( longNumber_H)
GLCDPrint ( 55 , 21, outstring)
outstring = hex( longNumber)
GLCDPrint ( 67 , 21, outstring )
GLCDPrint ( 44 , 29, mid( str(wordNumber),1, 6))

163
GLCDPrint ( 44 , 37, byteNumber)

box 46,9,57,19
GLCDDrawChar(48, 9, CCount )
outString = str( CCount )
' draw a box to overwrite existing strings
FilledBox(58,9,GLCD_WIDTH-1,17,GLCDBackground )
GLCDDrawString(58, 9, outString )

box 0,0,GLCD_WIDTH-1, GLCD_HEIGHT-1


box GLCD_WIDTH-5, GLCD_HEIGHT-5,GLCD_WIDTH- 1, GLCD_HEIGHT-1
filledbox 2,30,6,38, wordNumber
Circle( 25,30,8,1) ;center
FilledCircle( 25,30,4,longNumber xor 1) ;center

line 0, GLCD_HEIGHT-1 , GLCD_WIDTH/2, (GLCD_HEIGHT /2) +1


line GLCD_WIDTH/2, (GLCD_HEIGHT /2) +1 ,0, (GLCD_HEIGHT /2) +1

longNumber = longNumber + 7
wordNumber = wordNumber + 3
byteNumber++
NEXT
LOOP

end

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H> and <glcd_PCD8544.h>

SDD1289 Controllers

This section covers GLCD devices that use the SDD1289 graphics controller. The SDD1289 is a 240 x 320
single chip controller driver IC for 262k color (RGB) amorphous TFT LCD.

The Great Cow BASIC constants shown below control the configuration of the SDD1289 controller.
Great Cow BASIC supports SPI hardware and software connectivity - this is shown in the tables
below.

To use the SDD1289 driver simply include the following in your user code. This will initialise the
driver.

164
#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_SDD1289
'Pin mappings for SDD1289
#define GLCD_DC porta.0 'example port setting
#define GLCD_CS porta.1 'example port setting
#define GLCD_RESET porta.2 'example port setting
#define GLCD_DI porta.3 'example port setting
#define GLCD_DO porta.4 'example port setting
#define GLCD_SCK porta.5 'example port setting

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Default

GLCD_TYPE GLCD_TYPE_SDD1289
GLCD_DC Specifies the output pin that is connected to Data/Command IO pin on the GLCD. Required

GLCD_CS Specifies the output pin that is connected to Chip Select (CS) on the GLCD. Required

GLCD_Reset Specifies the output pin that is connected to Reset pin on the GLCD. Required

GLCD_DI Specifies the output pin that is connected to Data In (GLCD out) pin on the Required
GLCD.

GLCD_DO Specifies the output pin that is connected to Data Out (GLCD in) pin on the Required
GLCD.

GLCD_SCK Specifies the output pin that is connected to Clock (CLK) pin on the GLCD. Required

The Great Cow BASIC constants for control display characteristics are shown in the table below.

GLCD_WIDTH The width parameter of the GLCD

GLCD_HEIGHT The height parameter of the GLCD

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition, Stringvariable
t GCB font set )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

165
Comma Purpose Example
nd

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific Box ( Xposition1, Yposition1, Xposition2,
size Yposition2, [Optional In LineColour as 0 or 1]

FilledBo Draw a box on the GLCD to a specific FilledBox (Xposition1, Yposition1, Xposition2,
x size that is filled with the foreground Yposition2, [Optional In LineColour 0 or 1] )
colour.

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or 1)
position that is set with the specific
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte ( LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, bytevariable = GLCDReadByte


Byte see the datasheet for usage.

SDD1289_ Specify color as a parameter for many Color constants for this device are shown in the
[color] GLCD commands list below.
Any color can be defined using a valid
hexidecimal word value between 0x0000 to
0xFFFF.

166
SSD1289_BLACK 'hexidecimal value 0x0000
SSD1289_RED 'hexidecimal value 0xF800
SSD1289_GREEN 'hexidecimal value 0x07E0
SSD1289_BLUE 'hexidecimal value 0x001F
SSD1289_WHITE 'hexidecimal value 0xFFFF
SSD1289_PURPLE 'hexidecimal value 0xF11F
SSD1289_YELLOW 'hexidecimal value 0xFFE0
SSD1289_CYAN 'hexidecimal value 0x07FF
SSD1289_D_GRAY 'hexidecimal value 0x528A
SSD1289_L_GRAY 'hexidecimal value 0x7997
SSD1289_SILVER 'hexidecimal value 0xC618
SSD1289_MAROON 'hexidecimal value 0x8000
SSD1289_OLIVE 'hexidecimal value 0x8400
SSD1289_LIME 'hexidecimal value 0x07E0
SSD1289_AQUA 'hexidecimal value 0x07FF
SSD1289_TEAL 'hexidecimal value 0x0410
SSD1289_NAVY 'hexidecimal value 0x0010
SSD1289_FUCHSIA 'hexidecimal value 0xF81F

For a SDD1289 datasheet, please refer here.

This example shows how to drive a SDD1289 based Graphic LCD module with the built in commands of
Great Cow BASIC.

Example:

;Chip Settings
#chip 16F1937,32
#config Osc = INT, VCAPEN_OFF, MCLRE_ON, PLLEN_ON, CLKOUTEN_OFF

#include <glcd.h>

'Defines for SDD1289


#define GLCD_TYPE GLCD_TYPE_SDD1289
'Pin mappings for SDD1289
#define GLCD_DC porta.0
#define GLCD_CS porta.1
#define GLCD_RESET porta.2
#define GLCD_DI porta.3
#define GLCD_DO porta.4
#define GLCD_SCK porta.5

GLCDPrint(0, 0, "Test of the SDD1289 Device")


end

167
For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte OR Pset

Supported in <GLCD.H>

SH1106 Controllers

This section covers GLCD devices that use the SH1106 graphics controller. THe SH1106 is a single-chip
CMOS OLED/PLED driver with controller for organic/polymer light emitting diode dot-matrix graphic
display system. SH1106 consists of 132 segments, 64 commons that can support a maximum display
resolution of 132 X 64. It is designed for Common Cathode type OLED panel.

The Great Cow BASIC constants shown below control the configuration of the SH1106 controller.
Great Cow BASIC supports i2C hardware and software connectivity - this is shown in the tables
below.

The SH1106 is a monochrome device.

To use the SH1106 driver simply include the following in your user code. This will initialise the driver.

#include <glcd.h>

; ----- Define GLCD Hardware settings


#define GLCD_TYPE GLCD_TYPE_SH1106
#define GLCD_I2C_Address 0x78

; ----- Define Hardware settings


' Define I2C settings
#define HI2C_BAUD_RATE 400
#define HI2C_DATA
HI2CMode Master

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Options

GLCD_TYPE GLCD_TYPE_SH1106 Required

GLCD_I2C_Address I2C address of the GLCD. Required

HI2C_BAUD_RATE HI2C_BAUD_RATE 400 or 100

HI2C_DATA HI2C_DATA Mandated, plus


HI2CMode Master is required.

The Great Cow BASIC constants for control display characteristics are shown in the table below.

168
Constants Controls Default

GLCD_WIDTH The width parameter of the GLCD 128

GLCD_HEIGHT The height parameter of the GLCD 64

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition,


t GCB font set Stringvariable )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific size Box ( Xposition1, Yposition1, Xposition2,
Yposition2, [Optional In LineColour as 0 or 1]
)
FilledBo Draw a box on the GLCD to a specific size FilledBox (Xposition1, Yposition1, Xposition2,
x that is filled with the foreground colour. Yposition2, [Optional In LineColour 0 or 1] )

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or
position that is set with the specific 1)
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte (LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, see bytevariable = GLCDReadByte
Byte the datasheet for usage.

The additional Great Cow BASIC commands for this GLCD are shown in the table below.

Command Purpose

GLCDSetDisplayInver Inverts the display


tMode

169
Command Purpose

GLCDSetDisplayNorma Set the display to normal mode


lMode
SetContrast ( Sets the constrast to select 1 out of 256 contrast steps. Contrast increases as the
dim_state ) value increases.
Parameter is dim value

For a SH1106 datasheet, please refer here.

This example shows how to drive a SH1106 based Graphic LCD module with the built in commands of
Great Cow BASIC.

; ----- Configuration
#chip mega328p,16
#include <glcd.h>

; ----- Define Hardware settings


' Define I2C settings
#define HI2C_BAUD_RATE 400
#define HI2C_DATA
HI2CMode Master

; ----- Define GLCD Hardware settings


#define GLCD_TYPE GLCD_TYPE_SH1106
#define GLCD_I2C_Address 0x78

GLCDCLS
GLCDPrint 0, 0, "Great Cow BASIC"
GLCDPrint (0, 16, "Anobium 2016")

wait 3 s
GLCDCLS

' Prepare the static components of the screen


GLCDPrint ( 0, 0, "PrintStr") ; Print some text
GLCDPrint ( 64, 0, "@")
; Print some more text
GLCDPrint ( 72, 0, ChipMhz) ; Print chip speed
GLCDPrint ( 86, 0, "Mhz") ; Print some text
GLCDDrawString( 0,8,"DrawStr") ; Draw some text
box 0,0,GLCD_WIDTH-1, GLCD_HEIGHT-1 ; Draw a box
box GLCD_WIDTH-5, GLCD_HEIGHT-5,GLCD_WIDTH-1, GLCD_HEIGHT-1 ; Draw a box
Circle( 44,41,15) ; Draw a circle
line 64,31,0,31 ; Draw a line

DO forever

170
for CCount = 31 to 127
GLCDPrint ( 64 , 36, hex(longNumber_E ) ) ; Print a HEX string
GLCDPrint ( 76 , 36, hex(longNumber_U ) ) ; Print a HEX string
GLCDPrint ( 88 , 36, hex(longNumber_H ) ) ; Print a HEX string
GLCDPrint ( 100 , 36, hex(longNumber ) ) ; Print a HEX string
GLCDPrint ( 112 , 36, "h" ) ; Print a HEX string

GLCDPrint ( 64 , 44, pad(str(wordNumber), 5 ) ) ; Print a padded string


GLCDPrint ( 64 , 52, pad(str(byteNumber), 3 ) ) ; Print a padded string

box (46,9,56,19) ; Draw a Box


GLCDDrawChar(48, 9, CCount ) ; Draw a character
outString = str( CCount ) ; Prepare a string
GLCDDrawString(64, 9, pad(outString,3) ) ; Draw a string

filledbox 3,43,11,51, wordNumber ; Draw a filled box

FilledCircle( 44,41,9, longNumber xor 1) ; Draw a filled box


line 0,63,64,31 ; Draw a line

; Do some simple maths


longNumber = longNumber + 7 : wordNumber = wordNumber + 3 : byteNumber++
NEXT
LOOP
end

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

SSD1306 Controllers

This section covers GLCD devices that use the SSD1306 graphics controller.

The SSD1306 is a single-chip CMOS OLED/PLED driver with controller for organic / polymer light
emitting diode dot-matrix graphic display system. It consists of 128 segments and 64 commons. This IC
is designed for Common Cathode type OLED panel.

The SSD1306 embeds with contrast control, display RAM and oscillator, which reduces the number of
external components and power consumption. It has 256-step brightness control. Data/Commands are
sent from general MCU through the hardware selectable 6800/8000 series compatible Parallel
Interface, I2C interface or Serial Peripheral Interface. It is suitable for many compact portable
applications, such as mobile phone sub-display, MP3 player and calculator, etc.

The Great Cow BASIC constants shown below control the configuration of the SSD1306 controller.
Great Cow BASIC supports SPI and I2C hardware & software connectivity - this is shown in the tables
below.

171
To use the SSD1306 driver simply include the following in your user code. This will initialise the
driver.

The SSD1306 library supports 128 * 64 pixels or 128 * 32 pixels. The default is 128 * 64 pixels.

The SH1106 is a monochrome device.

To use the SSD1306 drivers simply include one of the following configuration requirements:

'An I2C configuration


#include <glcd.h>

; ----- Define GLCD Hardware settings


#define GLCD_TYPE GLCD_TYPE_SSD1306
#define GLCD_I2C_Address 0x78

; ----- Define Hardware settings


' Define I2C settings
#define HI2C_BAUD_RATE 400
#define HI2C_DATA
HI2CMode Master

or,

'An SPI configuration'


#include <glcd.h>

; ----- Define GLCD Hardware settings


#define GLCD_TYPE GLCD_TYPE_SSD1306

; ----- Define Hardware settings


#define S4Wire_DATA

#define MOSI_SSD1306 PortB.1


#define SCK_SSD1306 PortB.2
#define DC_SSD1306 PortB.3
#define CS_SSD1306 PortB.4
#define RES_SSD1306 PortB.5

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Options

GLCD_TYPE GLCD_TYPE_SSD1306 Required

GLCD_I2C_Address I2C address of the GLCD. Required

172
The Great Cow BASIC constants for SPI/S4Wire control display characteristics are shown in the table
below.

Constan Controls Options


ts

GLCD_TYP GLCD_TYPE_SSD1306 Required to support 128 * 64 pixels. Mutualy


E exclusive to GLCD_TYPE_SSD1306_32

GLCD_TYP GLCD_TYPE_SSD1306_32 Required to support 128 * 32 pixels. Mutualy


E exclusive to GLCD_TYPE_SSD1306

S4Wire_D 4 wire SPI Mode Required


ata
MOSI_SSD Specifies output pin connected to Must be defined
1306 serial data in D1 pin

SCK_SSD1 Specifies output pin connected to Must be defined


306 serial clock D0 pin

DC_SSD13 Specifies output pin connected to Must be defined


06 data control DC pin

CS_SSD13 Specifies output pin connected to Must be defined


06 chip select CS pin

RES_SSD1 Specifies output pin connected to Must be defined


306 reset RES pin

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Default

GLCD_WIDTH The width parameter of the GLCD 128

GLCD_HEIGHT The height parameter of the GLCD 64 or 32

GLCD_PROTECTOVERRUN Define this constant to restrict pixel operations with the pixel limits Not defined

The Great Cow BASIC variables for control display characteristics are shown in the table below. These
variables control the user definable parameters of a specific GLCD.

Variable Purpose Type

GLCDBackground GLCD background state. A monochrome value.


For mono GLCDs the default is White or 0x0001.

GLCDForeground Color of GLCD A monochrome value.


foreground. For mono GLCDs the default is non-white or 0x0000.

GLCDFontWidth Width of the current Default is 6 pixels.


GLCD font.

173
Variable Purpose Type

GLCDfntDefault Size of the current GLCD Default is 0. This equates to the standard GCB font set.
font.

GLCDfntDefault Size of the current GLCD Default is 1. This equates to the 8 pixel high.
size font.

The Great Cow BASIC commands supported for this GLCD are shown in the table below.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition,


t GCB font set Stringvariable )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific size Box ( Xposition1, Yposition1, Xposition2,
Yposition2, [Optional In LineColour as 0 or 1]
)
FilledBo Draw a box on the GLCD to a specific size FilledBox (Xposition1, Yposition1, Xposition2,
x that is filled with the foreground colour. Yposition2, [Optional In LineColour 0 or 1] )

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or
position that is set with the specific 1)
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte (LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, see bytevariable = GLCDReadByte
Byte the datasheet for usage.

The Great Cow BASIC specific commands for this GLCD are shown in the table below.

Command Purpose

Stopscroll_SSD1306 Stops all scrolling

174
Command Purpose

Startscrollright_SSD1306 ( start , Activate a right handed scroll for rows start through stop Hint,
stop [,scrollspeed] ) the display is 16 rows tall. To scroll the whole display, execute:
startscrollright_SSD1306(0x00, 0x0F)
Parameters are Start row, End row, optionally Scrollspeed

Startscrollleft_SSD1306 ( start , Activate a left handed scroll for rows start through stop Hint,
stop [,scrollspeed] ) the display is 16 rows tall. To scroll the whole display, execute:
startscrollleft_SSD1306(0x00, 0x0F)
Parameters are Start row, End row, optionally Scrollspeed

Startscrolldiagright_SSD1306 ( start Activate a diagright handed scroll for rows start through stop
, stop [,scrollspeed] ) Hint, the display is 16 rows tall. To scroll the whole display,
execute:
startscrolldiagright_SSD1306(0x00, 0x0F)
Parameters are Start row, End row, optionally Scrollspeed

Startscrolldiagleft_SSD1306 ( start Activate a diagleft handed scroll for rows start through stop
, stop [,scrollspeed] ) Hint, the display is 16 rows tall. To scroll the whole display,
execute:
startscrolldiagleft_SSD1306(0x00, 0x0F)
Parameters are Start row,End row, optionally Scrollspeed

SetContrast ( dim_state ) Sets the constrast to select 1 out of 256 contrast steps. Contrast
increases as the value increases.
Parameter is dim value

For a SSD1306 datasheet, please refer here.

This example shows how to drive a SSD1306 based Graphic I2C LCD module with the built in
commands of Great Cow BASIC.

#chip mega328p,16
#include <glcd.h>

; ----- Define Hardware settings


' Define I2C settings
#define HI2C_BAUD_RATE 400
#define HI2C_DATA
HI2CMode Master

; ----- Define GLCD Hardware settings


#define GLCD_TYPE GLCD_TYPE_SSD1306 'for 128 * 64 pixels support
#define GLCD_I2C_Address 0x78

GLCDCLS
GLCDPrint 0, 0, "Great Cow BASIC"
GLCDPrint (0, 16, "Anobium 2015")

175
wait 3 s
GLCDCLS

' Prepare the static components of the screen


GLCDPrint ( 0, 0, "PrintStr") ; Print some text
GLCDPrint ( 64, 0, "@")
; Print some more text
GLCDPrint ( 72, 0, ChipMhz) ; Print chip speed
GLCDPrint ( 86, 0, "Mhz") ; Print some text
GLCDDrawString( 0,8,"DrawStr") ; Draw some text
box 0,0,GLCD_WIDTH-1, GLCD_HEIGHT-1 ; Draw a box
box GLCD_WIDTH-5, GLCD_HEIGHT-5,GLCD_WIDTH-1, GLCD_HEIGHT-1 ; Draw a box
Circle( 44,41,15) ; Draw a circle
line 64,31,0,31 ; Draw a line

DO forever
for CCount = 31 to 127
GLCDPrint ( 64 , 36, hex(longNumber_E ) ) ; Print a HEX string
GLCDPrint ( 76 , 36, hex(longNumber_U ) ) ; Print a HEX string
GLCDPrint ( 88 , 36, hex(longNumber_H ) ) ; Print a HEX string
GLCDPrint ( 100 , 36, hex(longNumber ) ) ; Print a HEX string
GLCDPrint ( 112 , 36, "h" ) ; Print a HEX string

GLCDPrint ( 64 , 44, pad(str(wordNumber), 5 ) ) ; Print a padded string


GLCDPrint ( 64 , 52, pad(str(byteNumber), 3 ) ) ; Print a padded string

box (46,9,56,19) ; Draw a Box


GLCDDrawChar(48, 9, CCount ) ; Draw a character
outString = str( CCount ) ; Prepare a string
GLCDDrawString(64, 9, pad(outString,3) ) ; Draw a string

filledbox 3,43,11,51, wordNumber ; Draw a filled box

FilledCircle( 44,41,9, longNumber xor 1) ; Draw a filled box


line 0,63,64,31 ; Draw a line

; Do some simple maths


longNumber = longNumber + 7 : wordNumber = wordNumber + 3 : byteNumber++
NEXT
LOOP
end

This example shows how to drive a SSD1306 based Graphic SPI LCD module with the built in
commands of Great Cow BASIC.

176
'Chip model
#chip mega328p, 16
#include <glcd.h>

'Defines for a 7 pin SPI module


'RES pin is pulsed low in glcd_SSD1306.h for proper startup
#define MOSI_SSD1306 PortB.1
#define SCK_SSD1306 PortB.2
#define DC_SSD1306 PortB.3
#define CS_SSD1306 PortB.4
#define RES_SSD1306 PortB.5
; ----- Define GLCD Hardware settings
#define GLCD_TYPE GLCD_TYPE_SSD1306 'for 128 * 64 pixels support
#define S4Wire_DATA

dim longnumber as Long


longnumber = 123456
dim wordnumber as word
wordnumber = 62535
dim bytenumber as Byte
bytenumber =255

#define led PortB.0


dir led out

Do
SET led ON
wait 1 s
SET led OFF

GLCDCLS
GLCDPrint (30, 0, "Hello World!")
Circle (18,24,10)
FilledCircle (48,24,10)
Box (70,14,90,34)
FilledBox (106,14,126,34)
GLCDDrawString (32,35,"Draw String")
GLCDPrint (0,46,longnumber)
GLCDPrint (94,46,wordnumber)
GLCDPrint (52,55,bytenumber)
Line (0,40,127,63)
Line (0,63,127,40)
wait 3 s

Loop

177
This example shows how to drive a SSD1306 based Graphic I2C LCD module with 128 * 32 pixel
support.

#chip mega328p,16
#include <glcd.h>

; ----- Define Hardware settings


' Define I2C settings
#define HI2C_BAUD_RATE 400
#define HI2C_DATA
HI2CMode Master

; ----- Define GLCD Hardware settings


#define GLCD_TYPE GLCD_TYPE_SSD1306_32 'for 128 * 32 pixels support
#define GLCD_I2C_Address 0x78

GLCDCLS
GLCDPrint 0, 0, "Great Cow BASIC"
GLCDPrint (0, 16, "Anobium 2017")

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

ST7735 Controllers

This section covers GLCD devices that use the ST7735 graphics controller. The ST7735 is a single-chip
controller/driver for 262K-color, graphic type TFT-LCD.

The Great Cow BASIC constants shown below control the configuration of the ILI9340 controller.
Great Cow BASIC supports an 8 bit bus connectivity. The 8 bit must be a single port of consective bits
- this is shown in the tables below.

To use the ST7735 driver simply include the following in your user code. This will initialise the driver.

#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_ST7735

'Pin mappings for ST7735


#define GLCD_DC porta.0 'example port setting
#define GLCD_CS porta.1 'example port setting
#define GLCD_RESET porta.2 'example port setting
#define GLCD_DI porta.3 'example port setting
#define GLCD_DO porta.4 'example port setting
#define GLCD_SCK porta.5 'example port setting

178
The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Options

GLCD_TYPE GLCD_TYPE_ST7735
GLCD_DATA_PO Not Available for this controller. Not
RT applicable.

GLCD_DC Specifies the output pin that is connected to Data/Command IO pin on Required
the GLCD.

GLCD_CS Specifies the output pin that is connected to Chip Select (CS) on the Required
GLCD.

GLCD_Reset Specifies the output pin that is connected to Reset pin on the GLCD. Required

GLCD_DI Specifies the output pin that is connected to Data In (GLCD out) pin on Required
the GLCD.

GLCD_D0 Specifies the output pin that is connected to Data Out (GLCD in) pin on Required
the GLCD.

GLCD_SLK Specifies the output pin that is connected to Clock (CLK) pin on the Required
GLCD.

The Great Cow BASIC constants for control display characteristics are shown in the table below.

Constants Controls Default

GLCD_WIDTH The width parameter of the GLCD 160


This cannot be changed

GLCD_HEIGHT The height parameter of the GLCD 128


This cannot be changed

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. Always
review the appropiate library for the latest full set of supported commands.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPri Print string of characters on GLCD using GLCDPrint( Xposition, Yposition, Stringvariable
nt GCB font set )

GLCDDra Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
wChar set

179
Comma Purpose Example
nd

GLCDDra Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
wString set Stringvariable )

Box Draw a box on the GLCD to a specific Box ( Xposition1, Yposition1, Xposition2,
size Yposition2, [Optional In LineColour as 0 or 1] )

FilledB Draw a box on the GLCD to a specific FilledBox (Xposition1, Yposition1, Xposition2,
ox size that is filled with the foreground Yposition2, [Optional In LineColour 0 or 1] )
colour.

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or 1)
position that is set with the specific
attribute.

GLCDWri Set a byte value to the controller, see the GLCDWriteByte (LCDByte)
teByte datasheet for usage.

GLCDRea Read a byte value from the controller, bytevariable = GLCDReadByte


dByte see the datasheet for usage.

ST7735_ Specify color as a parameter for many Color constants for this device are shown in the
[color] GLCD commands list below.
Any color can be defined using a valid
hexidecimal word value between 0x0000 to
0xFFFF.

ST7735_BLACK 'hexidecimal value 0x0000


ST7735_BLUE 'hexidecimal value 0xF800
ST7735_RED 'hexidecimal value 0x001F
ST7735_GREEN 'hexidecimal value 0x07E0
ST7735_CYAN 'hexidecimal value 0xFFE0
ST7735_MAGENTA 'hexidecimal value 0xF81F
ST7735_YELLOW 'hexidecimal value 0x07FF
ST7735_WHITE 'hexidecimal value 0xFFFF

For a ST7735 datasheet, please refer here.

Example:

180
;Chip Settings
#chip 16F1937,32
#config Osc = INT, VCAPEN_OFF, MCLRE_ON, PLLEN_ON, CLKOUTEN_OFF

#include <glcd.h>

'Defines for ST7735


#define GLCD_TYPE GLCD_TYPE_ST7735
'Pin mappings for ST7735
#define GLCD_DC porta.0
#define GLCD_CS porta.1
#define GLCD_RESET porta.2
#define GLCD_DI porta.3
#define GLCD_DO porta.4
#define GLCD_SCK porta.5

GLCDPrint(0, 0, "Test of the ST7735 Device")


end

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

ST7920 Controllers

This section covers GLCD devices that use the ST7920 graphics controller.

The Great Cow BASIC constants for control of the connectivity are shown in the table below. The only
connectivity option the 8-bit mode where 8 pins are connected between the microcontroller and the
GLCD to control the data bus.

The ST7920 GLCD is graphica and character mixed mode display.

ST7920 LCD controller/driver IC can display alphabets, numbers, Chinese fonts and self-defined
characters. It supports 3 kinds of bus interface, namely 8-bit, 4-bit and serial. Great Cow BASIC is
currently supports 8-bit only. For LCD only operations (text characters only) you can use the Great Cow
BASIC LCD routines.

All functions, including display RAM, Character Generation ROM, LCD display drivers and control
circuits are all in a one-chip solution. With a minimum system configuration, a Chinese character
display system can be easily achieved.

The ST7920 includes character ROM with 8192 16x16 dots Chinese fonts and 126 16x8 dots half-width
alphanumerical fonts. It supports 64x256 dots graphic display area for graphic display
(GDRAM). Mix-mode display with both character and graphic data is possible. ST7920 has built-in
CGRAM and provide 4 sets software programmable 16x16 fonts.

181
To use the ST7920 driver simply include the following in your user code. This will initialise the driver.

#include <glcd.h>
#DEFINE GLCD_TYPE GLCD_TYPE_ST7920

#define GLCD_Enable PORTA.1 'example port setting


#define GLCD_RS PORTa.0 'example port setting
#define GLCD_RW PORTA.2 'example port setting
#define GLCD_RESET PORTA.3 'example port setting
#define GLCD_DATA_PORT PORTD 'example port setting

The Great Cow BASIC constants for the interface to the controller are shown in the table below.

Constan Controls Options


ts

GLCD_TYP GLCD_TYPE_ST7920 Required


E
GLCD_DAT Specifies the output port that is connected Required
A_PORT between the microcontroller and the GLCD.

GLCD_RS Specifies the output pin that is connected to Required


Register Select on the GLCD.

GLCD_RW Specifies the output pin that is connected to Must be defined unless R/W is disabled), see
Read/Write on the GLCD. The R/W pin can be GLCD_NO_RW
disabled*.

GLCD_RES Specifies the output pin that is connected to Required


ET Reset on the GLCD.

LCD_ENAB Specifies the output pin that is connected to Required


LE Enable on the GLCD.

ST7920Wr Set the time delay between data Required, set to 20 us for 32Mhz support. Can
iteDelay transmissions. be reduced for slower chip speeds.

GLCD_NO_ Disables read/write inspection of the device Optional, but recommend NOT to set. The R/W
RW during read/write operations pin can be disabled by setting the GLCD_NO_RW
constant. If this is done, there is no need for
the R/W to be connected to the chip, and no
need for the LCD_RW constant to be set. Ensure
that the R/W line on the LCD is connected to
ground if not used.

The Great Cow BASIC constants for control display characteristics are shown in the table below.

182
Constants Controls Default

GLCD_WIDTH The width parameter of the GLCD 128


Cannot be changed.

GLCD_HEIGHT The height parameter of the GLCD 64


Cannot be changed.

GLCDFontWidth Specifies the font width of the Great Cow BASIC font set. 6

The Great Cow BASIC commands supported for this GLCD are shown in the table below. For device
specific see the commands with the prefix of ST7920*.

Comma Purpose Example


nd

GLCDCLS Clear screen of GLCD GLCDCLS

GLCDPrin Print string of characters on GLCD using GLCDPrint( Xposition, Yposition,


t GCB font set Stringvariable )

GLCDDraw Print character on GLCD using GCB font GLCDDrawChar( Xposition, Yposition, CharCode )
Char set

GLCDDraw Print characters on GLCD using GCB font GLCDDrawString( Xposition, Yposition,
String set Stringvariable )

Box Draw a box on the GLCD to a specific size Box ( Xposition1, Yposition1, Xposition2,
Yposition2, [Optional In LineColour as 0 or 1]
)
FilledBo Draw a box on the GLCD to a specific size FilledBox (Xposition1, Yposition1, Xposition2,
x that is filled with the foreground colour. Yposition2, [Optional In LineColour 0 or 1] )

Line Draw a line on the GLCD to a specific Line ( Xposition1, Yposition1, Xposition2,
length that is filled with the specific Yposition2, [Optional In LineColour 0 or 1] )
attribute.

PSet Set a pixel on the GLCD at a specific PSet(Xposition, Yposition, Pixel Colour 0 or
position that is set with the specific 1)
attribute.

GLCDWrit Set a byte value to the controller, see the GLCDWriteByte (LCDByte)
eByte datasheet for usage.

GLCDRead Read a byte value from the controller, see bytevariable = GLCDReadByte
Byte the datasheet for usage.

For a TS7920 datasheet, please refer here.

This example shows how to drive a ST7920 based Graphic LCD module with the built in commands of
Great Cow BASIC. See Graphic LCD for details, this is an external web site.

183
Example 1:

;Chip Settings
#chip 16F1937,32
#config Osc = INT, VCAPEN_OFF, MCLRE_ON, PLLEN_ON, CLKOUTEN_OFF

#include <glcd.h>

#define GLCD_TYPE GLCD_TYPE_ST7920


#define GLCD_IO 8
#define GLCD_WIDTH 128
#define GLCD_HEIGHT 160
#define GLCDFontWidth 6

' read delay of 25 is required at 32mhz, this can be reduced to 0 for slower clock
speeds
#define ST7920ReadDelay 25
' write delay of 2 is required at 32mhz. this can be reduced to 1 for slower clock
speeds
#define ST7920WriteDelay 2

#define GLCD_RS PORTa.0


#define GLCD_Enable PORTA.1
#define GLCD_RW PORTA.2
#define GLCD_RESET PORTA.3
#define GLCD_DATA_PORT PORTD

ST7920GLCDEnableGraphics
ST7920GLCDClearGraphics
GLCDPrint 0, 1, "Great Cow BASIC "
wait 1 s

GLCDCLS
ST7920GLCDClearGraphics

rrun = 0
dim msg1 as string * 16

dim xradius, yordinate , radiusErr, incrementalxradius, orginalxradius,


orginalyordinate as Integer

Do forever
GLCDCLS
ST7920GLCDClearGraphics ;clear screen
GLCDDrawString 30,0,"ChipMhz@" ;print string
GLCDDrawString 78,0, str(ChipMhz) ;print string

184
Circle(10,10,10,0) ;upper left
Circle(117,10,10,0) ;upper right
Circle(63,31,10,0) ;center
Circle(63,31,20,0) ;center
Circle(10,53,10,0) ;lower left
Circle(117,53,10,0) ;lower right
GLCDDrawString 30,54,"PIC16F1937" ;print string
wait 1 s ;wait
FilledBox( 0,0,128,63) ;create box
for ypos = 0 to 63 ;draw row by row
ST7920lineh 0,ypos,128, 0 ;draw line
next
wait 1 s ;wait
ST7920GLCDClearGraphics ;clear
loop

Example 2:

;Chip Settings
#chip 16F1937,32
#config Osc = INT, VCAPEN_OFF, MCLRE_ON, PLLEN_ON, CLKOUTEN_OFF

#include <glcd.h>

#define GLCD_TYPE GLCD_TYPE_ST7920


#define GLCD_IO 8
#define GLCD_WIDTH 128
#define GLCD_HEIGHT 160
#define GLCDFontWidth 6

' read delay of 25 is required at 32mhz, this can be reduced to 0 for slower clock
speeds
#define ST7920ReadDelay 25
' write delay of 2 is required at 32mhz. this can be reduced to 1 for slower clock
speeds
#define ST7920WriteDelay 2

#define GLCD_RS PORTa.0


#define GLCD_Enable PORTA.1
#define GLCD_RW PORTA.2
#define GLCD_RESET PORTA.3
#define GLCD_DATA_PORT PORTD

WAIT 1 S
ST7920GLCDEnableGraphics
ST7920GLCDClearGraphics
ST7920Tile "A"

185
GLCDPrint 0, 1, "Great Cow BASIC "

GLCDCLS

rrun = 0
dim msg1 as string * 16

do forever

ST7920GLCDEnableGraphics
ST7920GLCDClearGraphics
ST7920gTile 0x55, 0x55
wait 1 s

ST7920GLCDClearGraphics
ST7920Lineh(0, 0, GLCD_WIDTH)
ST7920Lineh(0, GLCD_HEIGHT - 1, GLCD_WIDTH)
ST7920LineV(0, 0, GLCD_HEIGHT)
ST7920LineV(GLCD_WIDTH - 1, 0, GLCD_HEIGHT)

Box 18,30,28,40

WAIT 2 S

FilledBox 18,30,28,40

ST7920GLCDClearGraphics

Start:

GLCDDrawString 0,10,"Hello" 'Print Hello


wait 1 s
GLCDDrawString 0,10, "ASCII #:" 'Print ASCII #:
Box 18,30,28,40 'Draw Box Around ASCII Character
for char = 0x30 to 0x39 'Print 0 through 9
GLCDDrawString 16, 20 , Str(char)+" "
GLCDdrawCHAR 20, 30, char
wait 250 ms
next
line 0,50,127,50 'Draw Line using line command
for xvar = 0 to 80 'draw line using Pset command
pset xvar,63,on '
next
FilledBox 18,30,28,40 'Draw Box Around ASCII Character
Wait 1 s
ST7920GLCDClearGraphics
GLCDDrawString 0,10,"End "
wait 1 s

186
ST7920GLCDClearGraphics

workingGLCDDrawChar:
ST7920GLCDEnableGraphics
dim gtext as string
gtext = "ST7920 @QC12864B"

for xchar = 1 to gtext(0) 'Print 0 through 9


xxpos = (1+(xchar*6)-6)
GLCDDrawChar xxpos , 0 , gtext(xchar)
next

GLCDDrawString 1, 9, "Great Cow BASIC @2014"


GLCDDrawString 1, 18,"GLCD 128*64"
GLCDDrawString 1, 27,"Using GLCD.H from GCB"
GLCDDrawString 1, 37,"Using GLCD.H GCB@2014"
GLCDDrawString 1, 45,"GLCDDrawChar method"
'GLCDDrawString 1, 54,"ST7920 @QC12864B"
GLCDDrawString 1, 54,"Test Routines"
wait 1 s

ST7920GLCDClearGraphics
ST7920GLCDDisableGraphics
GLCDCLS

msg1 = "Run = " +str(rrun)


rrun++
GLCDPrint 0, 0, "ST7920 @QC12864B"
GLCDPrint 0, 1, "Great Cow BASIC "
GLCDPrint 0, 2, "GLCD 128*64"
GLCDPrint 0, 3, msg1
wait 5 s
GLCDCLS

' show all chars... takes some time!


ST7920CallBuiltinChar

ST7920Tile ( 0xa9 )
wait 1 s
GLCDCLS

' See http://www.khngai.com/chinese/charmap/tblbig.php?page=0


' and see https://sourceforge.net/projects/vietunicode/files/hannom/hannom%20v2005/
for the FONTS!!

dim BIG5code as word

'ST7920 can display half-width HCGROM fonts, user- defined CGRAM fonts and full 16x16

187
CGROM fonts. The
'character codes in 0000H~0006H will use user- defined fonts in CGRAM. The character
codes in 02H~7FH will use
'half-width alpha numeric fonts. The character code larger than A1H will be treated
as 16x16 fonts and will be
'combined with the next byte automatically. The 16x16 BIG5 fonts are stored in
A140H~D75FH while the 16x16 GB
'fonts are stored in A1A0H~F7FFH. In short:
'1. To display HCGROM fonts:
'Write 2 bytes of data into DDRAM to display two 8x16 fonts. Each byte represents 1
character.
'The data is among 02H~7FH.
'2. To display CGRAM fonts:
'Write 2 bytes of data into DDRAM to display one 16x16 font.
'Only 0000H, 0002H, 0004H and 0006H are acceptable.
'3. To display CGROM fonts:
'Write 2 bytes of data into DDRAM to display one 16x16 font.
'A140H~D75FH are BIG5 code, A1A0H~F7FFH are GB code.

for BIG5code = 0xA140 to 0xA1CF


ST7920cTile ( BIG5code )
wait 5 ms
next
GLCDCLS

'To display HCGROM fonts


' Write 2 bytes of data into DDRAM to display two 8x16 fonts. Each byte represents 1
character.
' The data is among 02H~7FH.
' The english characters set...
for HCGROM = 0x2h to 0x7f
ST7920Tile ( HCGROM )
ST7920Tile ( HCGROM )
wait 5 ms
next
GLCDCLS

linetest1:

ST7920GLCDEnableGraphics

ST7920gTile(0x55, 0x55)
wait 1 s
ST7920GLCDClearGraphics

'linehtest:
'
ST7920LineH(0, 0, GLCD_WIDTH)

188
ST7920LineH(0, GLCD_HEIGHT - 1, GLCD_WIDTH)
ST7920LineV(0, 0, GLCD_HEIGHT)
ST7920LineV(GLCD_WIDTH - 1, 0, GLCD_HEIGHT)

box test
ST7920LineH(10 ,0 , 118 )
ST7920LineH(0 ,8 , 128)
ST7920LineH(16 ,16 , 96 )
ST7920LineH(10 ,32 , 108 )
ST7920LineH(0, 16, GLCD_WIDTH)
ST7920LineH(0, 24, GLCD_WIDTH)
ST7920LineH(0, 32, GLCD_WIDTH)
ST7920LineH(0, 40, GLCD_WIDTH)
ST7920LineH(0, 48, GLCD_WIDTH)
ST7920LineH(0, 56, GLCD_WIDTH)
ST7920LineH(0, 63, GLCD_WIDTH)
ST7920LineV(16, 0, GLCD_HEIGHT)
ST7920LineV(17, 0, GLCD_HEIGHT)
ST7920LineV(15, 0, GLCD_HEIGHT)

ST7920LineV(46, 0, GLCD_HEIGHT)
ST7920LineV(47, 0, GLCD_HEIGHT)
ST7920LineV(48, 0, GLCD_HEIGHT)

ST7920LineV(46, 0, GLCD_HEIGHT)
ST7920LineV(47, 0, GLCD_HEIGHT)
ST7920LineV(48, 0, GLCD_HEIGHT)

ST7920LineV(96, 0, GLCD_HEIGHT)
ST7920LineV(97, 0, GLCD_HEIGHT)
ST7920LineV(98, 0, GLCD_HEIGHT

for HCGROM = 0 to GLCD_WIDTH step 8


ST7920LineV(HCGROM, 0, GLCD_HEIGHT)
next

GraphicTestPlace:

ST7920GLCDClearGraphics
ST7920GraphicTest
ST7920GLCDClearGraphics

' Test draw a line


for yrowpos = 0 to 63 step 4
ST7920LineH(0, yrowpos, GLCD_WIDTH)
next

ST7920GLCDClearGraphics

189
ST7920GLCDDisableGraphics
GLCDCLS

ST7920SetIcon( 1, 0x55 )

loop

sub ST7920CallBuiltinChar
' 0xA140 ~ 0xA15F
for ii = 0 to 31

ST7920WriteData( 0xA1)
ST7920WriteData( 0x40 + ii)

next

wait 1 s

GLCDCLS

' 0xA140 ~ 0xA15F


for ii = 0 to 31

ST7920WriteData( 0xA1)
ST7920WriteData( 0xb0 + ii)

next
wait 1 s
GLCDCLS

' 0xA140 ~ 0xA15F


for ii = 0 to 31

ST7920WriteData( 0xA4)
ST7920WriteData( 0x40 + ii)

next
wait 1 s
GLCDCLS
end sub

For more help, see GLCDCLS, GLCDDrawChar, GLCDPrint, GLCDReadByte, GLCDWriteByte or Pset

Supported in <GLCD.H>

190
ST7920GLCDClearGraphics

Syntax:

ST7920GLCDClearGraphics

Explanation:

This command clears the GCLD display.

Example usage:

ST7920GLCDClearGraphics 'clear the screen

ST7920GLCDDisableGraphics

Syntax:

ST7920GLCDDisableGraphics

Explanation:

This command sets the GCLD display controller to text mode.

Example usage:

ST7920GLCDDisableGraphics 'Set to text mode

ST7920GLCDEnableGraphics

Syntax:

ST7920GLCDEnableGraphics

Explanation:

This command sets the GCLD display controller to text mode.

Example usage:

ST7920GLCDEnableGraphics 'Set to text mode

191
ST7920GraphicTest

Syntax:

ST7920GraphicTest

Explanation:

This command tests the graphics functionality of the GLCD display.

Example usage:

ST7920GraphicTest ‘Test the display

ST7920LineHs

Syntax:

ST7920LineHs ( Xpos, Ypos, XLength, Style)

Explanation:

This command draws a line with a specific style. The style is based on the bits value of the byte passed
to the routine.

Example usage:

ST7920LineHs ( 0, 31,128 , 0x55) ‘will draw a dashed line

ST7920Locate

Syntax:

ST7920Locate ( Xpos, Ypos)

Explanation:

This command locates the pixel at the specific X and Y location of the text screen. Subsequent printing
to the GLCD will place a character to the GLCD controller on the specified row and column. Due to the
design of the ST7920 controller (to accomodate Mandarin and Cyrillic), you must place the text on the
column according to the numbers above the diagram below. The addressing is handle by the
command.

192
|--0--|--1--|--2--|... ...|--7--|

+--+--+--+--+--+---------------------+

|H |e |l |l |o | ... | <- row 0 (address 0x80)

+--+--+--+--+--+---------------------+

|T |h |i |s | |i ... | <- row 1 (address 0x90)

+--+--+--+--+--+---------------------+

|' |' |' |' |' |' ... | <- row 2 (address 0x88)

+--+--+--+--+--+---------------------+

|- |- |- |- |- |- ... | <- row 3 (address 0x98)

+--+--+--+--+--+---------------------+

Writing 'a' onto the 1st column, and 1st row:

|--0--|--1--|--2--|... ...|--7--|

+--+--+--+--+--+---------------------+

| | | | | | ... | <- row 0 (address 0x80)

+--+--+--+--+--+---------------------+

| | |a | | | ... | <- row 1 (address 0x90)

+--+--+--+--+--+---------------------+

| | | | | | ... | <- row 2 (address 0x88)

+--+--+--+--+--+---------------------+

| | | | | | ... | <- row 3 (address 0x98)

+--+--+--+--+--+---------------------+

Example usage:

193
ST7920Locate ( 64, 31) ‘the pixel at the mid screen point

ST7920Tile

Syntax:

ST7920Tile ( word variable )

Explanation:

This command tiles the screen with the word value provided.

Example usage:

Dim tileValue as word


tileValue = (0x55 * 256 ) + 0x55
ST7920Tile (tileValue) ‘tile the screen with a nice cross hatch

ST7920cTile

Syntax:

ST7920cTile ( word variable )

Explanation:

Tiles screen with a Chinese Symbol.

This required 2 bytes of data into DDRAM to display one 16x16 font from memory location
A140H~D75FH are BIG5 code, A1A0H~F7FFH are GB code.

Example usage:

Dim CTileValue as word


cTileValue = (0xA140H * 256 ) + 0xA140H
ST7920Tile (CTileValue) ‘tile the screen with a nice cross hatch

ST7920gLocate

Syntax:

194
ST7920gLocate ( Xpos, Ypos)

Explanation:

This command locates the pixel at the specific X and Y location of the graphical screen.

Example usage:

ST7920gLocate ( 64, 31) ‘the pixel at the mid screen point

ST7920gTile

Syntax:

ST7920gTile ( byte variable , byte variable)

Explanation:

Tile LCD screen with two bytes in Graphic Mode.

Example usage:

ST7920gTile (0x55, 0x85) ‘tile the screen with an odd cross hatch

ST7920lineh

Syntax:

ST7920lineh ( Xpos, Ypos, xUnitsStyle, )

Explanation:

This command draws a horizontal line with the specific style. The style can be ON or OFF. Default is
ON.

This is called by the GLCD common routines.

Example usage:

ST7920lineh ( 0, 31,128 , ON) ‘will draw a line

195
ST7920linev

Syntax:

ST7920lineh ( Xpos, Ypos, xUnitsStyle, )

Explanation:

This command draws a vertical line with the specific style. The style can be ON or OFF. Default is ON

This is called by the GLCD common routines.

Example usage:

ST7920lineh ( 0, 31,128 , ON) ‘will draw a line

ST7920GLCDReadByte

Syntax:

byte_variable = ST7920GLCDReadByte

Explanation:

This function return the word value (16 bits) of the GLCD display for the current XY position.

This is called by the GLCD common routines.

See the data sheet for more information.

Example usage:

SET GLCD_RS OFF

ST7920WriteByte( SysCalcPositionY )
ST7920WriteByte( SysCalcPositionX )
' read data
GLCDDataTempWord = ST7920GLCDReadByte
GLCDDataTempWord = ST7920GLCDReadByte
GLCDDataTempWord = (GLCDDataTempWord*256) + ST7920GLCDReadByte

ST7920WriteByte

Syntax:

196
ST7920GLCDWriteByte

Explanation:

This command write to the appropriate location as specified by the current XY position.

This is called by the GLCD common routines.

See the data sheet for more information.

Example usage:

...

SET GLCD_RS OFF

ST7920WriteByte( SysCalcPositionY )
ST7920WriteByte( SysCalcPositionX )
' read data
GLCDDataTempWord = ST7920GLCDReadByte
GLCDDataTempWord = ST7920GLCDReadByte
GLCDDataTempWord = (GLCDDataTempWord*256) + ST7920GLCDReadByte
...

ST7920WriteCommand

Syntax:

ST7920GWriteCommand ( byte_variable)

Explanation:

This command writes a command to the controller.

See the data sheet for more information.

Example usage:

...
ST7920WriteCommand(0x36) ' set the graphics mode on
GLCD_TYPE_ST7920_GRAPHICS_MODE = true
...

197
ST7920WriteData

Syntax:

ST7920GWriteData ( byte_variable)

Explanation:

This command writes data to the controller.

See the data sheet for more information.

Example usage:

...
for yy = 0 to ( GLCD_HEIGHT - 1 )
ST7920gLocate(0, yy)
for xx = 0 to ( GLCD_COLS -1 )
ST7920WriteData( 0x55 )
T7920WriteData( 0x55 )
next
next
...

ST7920gReaddata

Syntax:

byte_variable = ST7920gReaddata

Explanation:

This function return the word value (16 bits) of the GLCD display for the current XY position.

See the data sheet for more information.

Example usage:

...
' Read a word from the display device.
word_variable = ST7920GLCDReadData

198
Box

Syntax:

Box(LineX1,LineY1, LineX2, LineY2 [, LineColour ] )

Explanation:

Draws a box on a graphic LCD from the upper corner of pixel position X1, Y1 location to pixel position
X2,Y2 location.

LineColour can be specified. Typical the value is 0 or 1 for GLCDForeGround and GLCDBackGround
respectively.

See also FilledBox

Circle

Circle:

Circle(XPixelPosition, YPixelPosition, Radius [ [,Optional LineColour] [,Optional


Rounding] ] )

Explanation:

Draws a circle on a GLCD at XPixelPosition, YPixelPosition with a specific Radius.

The constant GLCD_PROTECTOVERRUN can be added to prevent circles from re-drawing at the screen edges.
Ensure the GLCD_Width and GLCD_HEIGHT constants are set correctly when using this additional constant.

Example:

#include <glcd.h>

circle(10,10,10) ;upper left


circle(117,10,10) ;upper right
circle(63,31,10) ;center
circle(63,31,20) ;center
circle(10,53,10) ;lower left
circle(117,53,10) ;lower right

199
FilledBox

Syntax:

FilledBox(LineX1,LineY1, LineX2, LineY2, Optional LineColour = 1)

Explanation:

Draws a filled box on a graphic LCD from the upper corner of pixel X1, Y1 location to pixel X2,Y2
location.

See also Box

FilledCircle

Circle:

FilledCircle(XPixelPosition, YPixelPosition, Radius [,Optional LineColour] )

Explanation:

Draws a circle on a GLCD at XPixelPosition, YPixelPosition with a specific Radius.

Example:

#include <glcd.h>

filledcircle(10,10,10) ;upper left


filledcircle(117,10,10) ;upper right
filledcircle(63,31,10) ;center
filledcircle(63,31,20) ;center
filledcircle(10,53,10) ;lower left
filledcircle(117,53,10) ;lower right

200
GLCDCLS

Syntax:

GLCDCLS

Explanation:

Clears the screen of a Graphic LCD.

This command supports all GLCD displays.

Specific to the ST7920 GLCD devices. This command supports the clearing the GLCD in text mode and
graphics mode.

GLCDDrawChar

Syntax:

GLCDDrawChar(CharLocX, CharLocY, CharCode [, Optional Colour] )

CharLocX is the X coordinate location for the character


CharLocY is the Y coordinate location for the character
CharCode is the ASCII number of the character to display. Can be decimal hex or binary.

Colour can be ON or OFF. For the ST7735 devices this an be any word value that represents the color
palette.

Explanation:

Displays an ASCII character at a specified X and Y location. On a 128x64 Graphic LCD:

X = 1 to 128
Y = 1 to 64

201
GLCDDrawString

Syntax:

GLCDDrawString(CharLocX, CharLocY, String [, Optional Colour] )

CharLocX is the X corrdinate location for the character


CharLocY is the Y coordinate location for the character
String is the string of characters to display
Colour can be ON or OFF. For the ST7735 devices this an be any word value that represents the color
palette

Explanation:

Displays an ASCII character at a specified X and Y location.


On a 128x64 Graphic LCD :
X = 1 to 128
Y = 1 to 64

GLCDPrint

Syntax:

GLCDPrint(PrintLocX, PrintLocY, PrintData)

PrintLocX is the X corrdinate location for the data


PrintLocY is the Y coordinate location for the data
PrintData is a String or String variable of the data to display

Explanation:

Prints string character(s) at a specified location on the GLCD screen.

On a 128x64 GLCD display :


X is typically 0 to 128
Y is typically 0 to 64

GLCDRotate

Syntax:

GLCDROTATE LANDSCOPE | PORTRAIT_REV | LANDSCAPE_REV | PORTRAIT

Explanation:

202
Rotate the GLCD display to a relative position.

GLCD rotation needs to be supported by the GLCD chipset. NOT all GLCD chipset support these
commands.

The options are:

LANDSCAPE
PORTRAIT_REV
LANDSCAPE_REV
PORTRAIT

The command will rotate the screen and set the following variables using the global variables shown
below.

GLCD_WIDTH
GLCD_HEIGHT

The command is supported by the following global constants.

#define LANDSCAPE 1
#define PORTRAIT_REV 2
#define LANDSCAPE_REV 3
#define PORTRAIT 4

GLCDReadByte

Syntax:

byte_variable = GLCDReadByte

Explanation:

Reads a byte of data from the Graphic LCD memory

GLCDTimeDelay

Syntax:

GLCDTime

203
Explanation:

This will call the delay routine that delays data transmissions. By default this is set to 20, which equate
to 20 us. GLCDTimeDelay default of 20us is for 32Mhz support. The can be reduced for slower chip speeds
by change the constant ST7920WriteDelay.

Example usage:

GLCDTime 'call the delay routine


#define ST7920WriteDelay 1 'set the delay to 1 us

GLCDWriteByte

Syntax:

GLCDWriteByte (LCDByte)

Explanation:

Writes a byte of data to the Graphic LCD memory

Line

Syntax:

Line(LineX1,LineY1, LineX2, LineY2, Optional LineColour = 1)

Explanation:

Draws a line on a GLCD from pixel X1, Y1 location to pixel X2,Y2 location.

Example:

#include <glcd.h>

line 0,0,127,63
line 0,63,127,0
line 40,0,87,63
line 40,63,87,0

204
Pset

Syntax:

PSet(XPosition, YPosition, GLCDState)

Explanation:

Sets or Clears a Pixel at the specified XPosition, YPosition. Use GLCDState set to 1 to set the pixel and a
0 clears the pixel.

205
Touch Screen
This is the Touch Screen section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

ADS 7843 Serial Driver

Syntax:

ADS7843_Init

ADS7843_GetXY

ADS7843_SetPrecision

Command Availability:

Available on all microcontrollers. Requires the inclusion of the following:

#include <ADS7843.h>

Explanation:

The ADS7843 device is a 12-bit sampling Analog-to-Digital Converter (ADC) with a synchronous serial
interface and low on resistance switches for driving touch screens.

The Great Cow Basic driver is integrated with the SDD1289 GLCD driver. To use the ADS7843 driver
the following is required to added to the Great Cow BASIC source file.

ADS7843_Init is required to initialise the touch screen. This is mandated.

ADS7843_GetXY this sub-routine returns the X and Y coordinates of touched point.

ADS7843_SetPrecision this sub-routine sets the level of precision of the touch screen.

Required Constants:

Constants Controls/Direction Default Value

ADS7843_DOUT (IN) The chip output pin Mandated

ADS7843_IRQ (IN) The interrupt pin Mandated

ADS7843_CS (OUT) The chip select pin Mandated

ADS7843_CLK (OUT) The clock pin Mandated

206
Constants Controls/Direction Default Value

ADS7843_DIN (OUT) The chip input pin Mandated

The Great Cow Basic commands supported for this chip are:

Command Purpose Example

ADS7843_Init Initialise the device. ADS7843_Init [Optional precision = PREC_EXTREME]

ADS7843_Get Returns the X and Y ADS7843_GetXY (TP_X, TP_Y )


XY coordinates of touched point.

ADS7843_Set Set the precision of the ADS7843_SetPrecision(precision)


Precision conversion result. (with PREC_EXTREME the conversion error is less than
3%)

Precision can be set to four values as shown in the table below. Passing a parameter of
ADS7843_SetPrecision changes the precision controls.

Constants Defined Value Default Value

#define PREC_LOW 1
#define PREC_MEDIUM 2
#define PREC_HI 3
#define PREC_EXTREME 4 Default Value

Example:

For more information see http://www.ti.com/product/ads7843.

This example shows how to drive a SDD1289 based Graphic LCD module with ADS7843 touch
controller.

'Chip Settings
#chip mega2560, 16

'Include
#include <glcd.h>
#include <ADS7843.h>

'GLCD Device Selection


#define GLCD_TYPE GLCD_TYPE_SSD1289
#define GLCD_EXTENDEDFONTSET1
'Define ports for the SSD1289 display

207
#define GLCD_WR PORTG.2
#define GLCD_CS PORTG.1
#define GLCD_RS PORTD.7
#define GLCD_RST PORTG.0
#define GLCD_DB0 PORTC.0
#define GLCD_DB1 PORTC.1
#define GLCD_DB2 PORTC.2
#define GLCD_DB3 PORTC.3
#define GLCD_DB4 PORTC.4
#define GLCD_DB5 PORTC.5
#define GLCD_DB6 PORTC.6
#define GLCD_DB7 PORTC.7
#define GLCD_DB8 PORTA.0
#define GLCD_DB9 PORTA.1
#define GLCD_DB10 PORTA.2
#define GLCD_DB11 PORTA.3
#define GLCD_DB12 PORTA.4
#define GLCD_DB13 PORTA.5
#define GLCD_DB14 PORTA.6
#define GLCD_DB15 PORTA.7

'Define ports for ADS7843


#define ADS7843_DOUT PORTE.5 ' Arduino Mega D3
#define ADS7843_IRQ PORTE.4 ' Arduino Mega D2
#define ADS7843_CS PORTE.3 ' Arduino Mega D5
#define ADS7843_CLK PORTH.3 ' Arduino Mega D6
#define ADS7843_DIN PORTG.5 ' Arduino Mega D4
#define ADS7843_BUSY PORTH.4 ' Arduino Mega D7

Wait 100 ms
num=0
Pset 1, 1, SSD1289_YELLOW
Do Forever

if ADS7843_IRQ=0 then
num++
GLCDPrint 10, 15, str(num),SSD1289_YELLOW, 2
ADS7843_GetXY ( TP_X , TP_Y )
if TP_X>=100 then GLCDPrint 100, 50, Str(TP_X),SSD1289_YELLOW, 2
if TP_X>=10 and TP_X<100 then GLCDPrint 100, 50, Str(TP_X)+" ",SSD1289_YELLOW,
2
if TP_X<10 then GLCDPrint 100, 50, Str(TP_X)+" ",SSD1289_YELLOW, 2
if TP_Y>=100 then GLCDPrint 100, 70, Str(TP_Y),SSD1289_YELLOW, 2
if TP_Y>=10 and TP_Y<100 then GLCDPrint 100, 70, Str(TP_Y)+" ", SSD1289_YELLOW,
2
if TP_Y<10 then GLCDPrint 100, 70, Str(TP_Y)+" ",SSD1289_YELLOW, 2
Pset TP_X, TP_Y, SSD1289_YELLOW
end if

208
Wait 1 ms

Loop

209
Liquid Crystal Display
This is the LCD section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

LCD Overview

Introduction:

The LCD routines in this section allow Great Cow BASIC programs to control an alphanumeric Liquid
Crystal Displays based on the HD44780 IC. This covers most 16 x 1, 16 x 2, 20 x 4 and 40 x 4 LCD
displays.

These methods allow the displays to be connected to the microcontroller in many different ways:

Connection Required Connections


Mode

0 No configuration is required directly by this method. The LCD routines must be


provided with other subroutines which will handle the communication. This is useful
for communicating with LCDs connected through RS232 or I2C.
This is an advanced method of driving an LCD.

1 Uses a combined data and clock line. This mode is used when the LCD is connected
through a shift register 74HC595, as detailed at here.
This method of driving an LCD requires an additional integrated circuit and other
passive components. This is not recommended for the beginner.

2 Uses separated Data and Clock lines. This mode is used when the LCD is connected
through a 74LS174 shift register IC, as detailed at here
This method of driving an LCD requires additional integrated circuits and other
passive components. This is not recommended for the beginner.

4 R/W, RS, Enable and the highest 4 data lines (DB4 through DB7) are connected to the
microcontroller. The use of the R/W line is optional.
This a common method to connect a microcontroller to an LCD. This requires 7(6)
data ports on the microcontroller.

8 R/W, RS, Enable and all 8 data lines. The data lines must all be connected to the same
I/O port, in sequential order. For example, DB0 to PORTB.0, DB1 to PORTB.1 and so on,
with`DB7` going to PORTB.7.
This is a common method to connect a microcontroller to a LCD. This requires 11(10)
data ports on the microcontroller.

10 The LCD is controlled via I2C. A type 10 LCD 12C adapter. Set LCD_10 to 10 for the
YwRobot LCD1602 IIC V1 or the Sainsmart LCD_PIC I2C adapter
This is a common method and requires two data ports on the microcontroller.

210
Connection Required Connections
Mode

12 The LCD is controlled via I2C. A type 12 LCD 12C adapter. Set LCD_10 to `12`for the
Ywmjkdz I2C adapter with a potentiometer (variable resistance) bent over top of
chip.
This is a common method and requires two data ports on the microcontroller.

The support of the types of LCD displays is shown in the following table.

Connection Supported LCD Types:


Mode number of characters x number of lines

0,1,2,4,8,10 and 16 x 1, 16 x 2, 20 x 2, 20 x 4 type LCD displays,


12 also known as 1601, 1602, 2002, 2004 type LCD displays.

4 40 x 4 LCD displays,
also known as 4004 type LCD displays.

See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 1, LCD_IO 2, LCD_IO_2 74xx164, LCD_IO_2 74xx174, LCD_IO 4,
LCD_IO 8, LCD_IO 10 or LCD_IO 12

LCD_IO 0

Using connection mode 0:

To use connection mode 0, a subroutine to write a byte to the LCD must be provided.

Optionally, another subroutine to read a byte from the LCD can also be defined. If the LCD was to be
read, the function LCDReadByte would be set to the name of a function that reads the LCD and returns
the data byte from the LCD. If there is no way (or no requirement) to read from the LCD, then the
LCD_NO_RW constant must be set.

In connection mode 0, the LCD_RS constant will be set automatically to an unused bit variable. The
higher level LCD commands (such as Print and Locate) will set it, and the subroutine is responsible for
writing to the LCD. The subroutine should handle the process and then set the RS pin on the LCD
appropriately.

211
Relevant Constants:

Specific constants are used to control settings for the Liquid Crystal Display routines included with
Great Cow BASIC. To set these constants the main program should specific constants to support the
connection mode using #define.

When using connection mode 0 only one constant must be set - all others are optional or can be
ignored.

Constant Name Controls Value

LCD_IO The I/O mode. 0

For a code example of connection mode 0 program, download here.

See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 1, LCD_IO 2, LCD_IO 2_74xx164, LCD_IO 2_74xx174, LCD_IO 4,LCD_IO 8,
LCD_IO 10 or LCD_IO 12

LCD_IO 1

Using connection mode 1:

This approach uses a single connectivity line that supports a combined data and clock signal between
the microcontroller and the LCD display. This approach is used when the LCD is connected through a
shift register 74HC595, as detailed at here. This connection method is also called a 1-wire connection.

This solution approach recognises the original work provided in the Elektor Magazine.

Relevant Constants:

Specific constants are used to control settings for the Liquid Crystal Display routines included with
Great Cow BASIC. To set these constants the main program should specific constants to support the
connection mode using #define.

When using connection mode 1, only two constants must be set - all others are optional or can be
ignored.

How to connect and control the LCD background led: see LCDBacklight.

Constant Name Controls Default Value

LCD_IO The I/O mode. 1

LCD_CD The clock/data pin used in 1-bit mode. Mandated

LCD.h supports in 1-wire mode the control of pin 4 of the 74HC595 for the background led.

212
For a code example download One Wire LCD Example.

See for further code examples see 0,1 and 2 Wire LCD Solutions.

See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 2 LCD_IO 2_74xx164, LCD_IO 2_74xx174 LCD_IO 4, LCD_IO 8,
LCD_IO 10 or LCD_IO 12

LCD_IO 2_74xx164

Using connection mode 2_74XX164:

Use a Data and a Clock line. This manner is used when the LCD is connected through a shift register IC
either using a 74HC164 or a 74LS164, as detailed at here. This connection method is also called a 2-wire
connection.

This is the preferred two wire method to connect via a shift register to an LCD display.

Relevant Constants:

Specific constants are used to control settings for the Liquid Crystal Display routines included with
Great Cow BASIC. To set these constants the main program should specific constants to support the
connection mode using #define.

When using connection mode 2_74XX164 only three constants must be set - all others are optional or
can be ignored.

Constant Name Controls Default Value

LCD_IO The I/O mode. 2

LCD_DB The data pin used in 2-bit mode. Mandated

LCD_CB The clock pin used in 2- bit mode. Mandated

LCD.h supports in connection mode 2_74XX164 via the control of pin 11 of the 74HC164 / 74LS164 to
the background led/backlight.

How to connect and control the LCD background led: see


http://gcbasic.sourceforge.net/help/_lcdbacklight.html

For a code example download Two Wire LCD Example.

See for further code examples see Two Wire LCD Solutions.

See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 1, LCD_IO 2, LCD_IO 2_74xx74, LCD_IO 4, LCD_IO 8, LCD_IO 10 or
LCD_IO 12

213
LCD_IO 2

Using connection mode 2:

This method uses a Data and a Clock line via a shift register to control the LCD display. This method is
used when the LCD is connected through a shift register IC either using a 74HC164 or a 74LS174, as
detailed at here. This connection method is also called a 2-wire connection.

This is a deprecated method mode to connect an LCD display to a microcontroller via a shift registry
either a 74LS174 (or a 74LS164 with diode connected to pin 11). This method does not support
backlight control and has no additional input/output pin.

If you have used the 2-wire mode prior to August 2015, please choose this method for your existing
code.

See LCD_IO 2 74xx164 for the preferred method to connect an LCD display to a microcomputer via a
shift register.

Relevant Constants:

Specific constants are used to control settings for the Liquid Crystal Display routines included with
Great Cow BASIC. To set these constants the main program should specific constants to support the
connection mode using #define. When using 2-bit mode only three constants must be set - all others
are optional or can be ignored.

Constant Name Controls Default Value

LCD_IO The I/O mode. 2

LCD_DB The data pin used in 2-bit mode. Mandated

LCD_CB The clock pin used in 2- bit mode. Mandated

For a code example download Two Wire LCD Example.

See for further code examples see Two Wire LCD Solutions.

See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 1, LCD_IO 2_74xx164, LCD_IO 2_74xx174, LCD_IO 4, LCD_IO 8,
LCD_IO 10 or LCD_IO 12

LCD_IO 2_74xx174

LCD_IO 2_74xx174 has been deprecated as preferred method mode to connect an LCD display to a
microcontroller via a shift register either a 74LS174 (or a 74LS164 with diode connected to pin 11). This
method does not support backlight control and has no additional input/output pin.

See LCD_IO 2_74xx164 for the preferred method to connect an LCD display to a microcontroller via a

214
shift register.

For more help, see LCD_IO 1, LCD_IO 2, LCD_IO 2_74xx164, LCD_IO 4, LCD_IO 8, LCD_IO 10 or LCD_IO
12

LCD_IO 4

Using connection mode 4:

To use connection mode 4 the R/W, RS, Enable control lines and the highest 4 data lines (DB4 through
DB7) must be connected to the microcontroller.

Relevant Constants:

Specific constants are used to control settings for the Liquid Crystal Display routines included with
Great Cow BASIC. To set these constants the main program should specific constants to support the
connection mode using #define. Constants required for connection mode 4.

Constants are required for 4-bit mode as follows.

Constant Controls Default Value


Name

LCD_SPEED FAST, MEDIUM or SLOW. MEDIUM

LCD_IO Must be 4 4

LCD_RS Specifies the output pin that is connected to Register Select on Must be defined
the LCD.

LCD_RW Specifies the output pin that is connected to Read/Write on the Must be defined (unless
LCD. The R/W pin can be disabled*. R/W is disabled)

LCD_Enable Specifies the output pin that is connected to Read/Write on the Must be defined
LCD.

LCD_DB4 Output pin used to interface with bit 4 of the LCD data bus Must be defined

LCD_DB5 Output pin used to interface with bit 5 of the LCD data bus Must be defined

LCD_DB6 Output pin used to interface with bit 6 of the LCD data bus Must be defined

LCD_DB7 Output pin used to interface with bit 7 of the LCD data bus Must be defined

The R/W pin can be disabled by setting the LCD_NO_RW constant. If this is done, there is no need for the R/W
to be connected to the chip, and no need for the LCD_RW constant to be set. Ensure that the R/W line on
the LCD is connected to ground if not used.

For a code example download Four Wire LCD Example.

Also see for further code examples see Four Wire LCD Solutions.

215
See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 1, LCD_IO 2, LCD_IO 2_74xx164, LCD_IO 2_74xx174, LCD_IO 8,
LCD_IO 10 or LCD_IO 12

LCD_IO 8

Using connection mode 8:

Using connection mode will require R/W, RS, Enable and all 8 data lines.

The data lines must all be connected to the same I/O port, in sequential order. For example, DB0 to
PORTB.0, DB1 to PORTB.1 and so on, with DB7 going to PORTB.7.

Relevant Constants:

These constants are used to control settings for the Liquid Crystal Display routines included with Great
Cow BASIC. To set them, place a line in the main program file that uses #define to assign a value to the
particular constant.

Constants are required for 8-bit mode as follows.

Constant Controls Default Value


Name

LCD_SPEED FAST, MEDIUM or SLOW. MEDIUM

LCD_IO The I/O mode. Can be 2, 4 or 8. 8

LCD_RS Specifies the output pin that is connected to Register Select on Must be defined
the LCD.

LCD_RW Specifies the output pin that is connected to Read/Write on the Must be defined (unless
LCD. The R/W pin can be disabled*. R/W is disabled)

LCD_Enable Specifies the output pin that is connected to Read/Write on the Must be defined
LCD.

LCD_DATA_P Output port used to interface with LCD data bus Must be defined
ORT
LCD_LAT Drives the port with LATx support. Resolves issues with faster Optional
Mhz and the Microchip PIC read/write/modify feature. See
example below.

The R/W pin can be disabled by setting the LCD_NO_RW constant. If this is done, there is no need for the R/W
to be connected to the chip, and no need for the LCD_RW constant to be set. Ensure that the R/W line on
the LCD is connected to ground if not used.

For a code example download Eight Wire LCD example.

For code examples see Eight Wire Examples.

216
See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 1, LCD_IO 2, LCD_IO 2_74xx164, LCD_IO 2_74xx174, LCD_IO 4,
LCD_IO 10 or LCD_IO 12

LCD_IO 10

Using connection mode 10:

The LCD is controlled via I2C of a type 10 LCD 12C adapter. Use LCD_IO 10 for the YwRobot LCD1602 IIC
V1 or the Sainsmart LCD_PIC I2C adapter. To use mode 10 you must define the I2C ports as normal in
your Great Cow BASIC code. Then, define the LCD type, set the I2C_address of the LCD adapter and the
LCD speed, if required. Finally, set the backlight control, if required.

Relevant Constants:

Specific constants are used to control settings for the Liquid Crystal Display routines included with
Great Cow BASIC. To set these constants the main program should specific constants to support the
connection mode using #define.

Constant Name Controls Value

LCD_IO The I/O mode. Must be 10 10

LCD_I2C_Address_1 Address of I2C adapter Default 0x4E

LCD_I2C_Address_2 Address of I2C adapter Not set

LCD_I2C_Address_3 Address of I2C adapter Not set

LCD_I2C_Address_4 Address of I2C adapter Not set

For code examples see I2C LCD Solutions.

See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 1, LCD_IO 2, LCD_IO 2_74xx164, LCD_IO 2_74xx174, LCD_IO 4,
LCD_IO 8, LCD_IO 12

LCD_IO 10 Port Configuration

Using mode 10

When using I2C LCD mode 10 the target I2C device address is setup as shown below. Each bit of the the
variable i2c_lcd_byte is defined to address the correct LCD display port.

217
i2c_lcd_e = i2c_lcd_byte.2
i2c_lcd_rw = i2c_lcd_byte.1
i2c_lcd_rs = i2c_lcd_byte.0
i2c_lcd_bl = i2c_lcd_byte.3
i2c_lcd_d4 = i2c_lcd_byte.4
i2c_lcd_d5 = i2c_lcd_byte.5
i2c_lcd_d6 = i2c_lcd_byte.6
i2c_lcd_d7 = i2c_lcd_byte.7

If you have an I2C LCD display adapter with a different set of connection of the adapter then change
this configuration to suit the specific of the adapter as follows. This should be done in the your main
program code.

#define i2c_lcd_e i2c_lcd_byte.1


#define i2c_lcd_rw i2c_lcd_byte.2
#define i2c_lcd_rs i2c_lcd_byte.0
#define i2c_lcd_bl i2c_lcd_byte.3
#define i2c_lcd_d4 i2c_lcd_byte.7
#define i2c_lcd_d5 i2c_lcd_byte.6
#define i2c_lcd_d6 i2c_lcd_byte.5
#define i2c_lcd_d7 i2c_lcd_byte.4

LCD_IO 12

Using connection mode 12:

The LCD is controlled via I2C. A type 12 is the Ywmjkdz I2C adapter with potentiometer variable
resistor) bent over top of chip. To use mode 12 you must define the I2C ports as normal in your GCB
code. Then, define the LCD type, set the I2C_address of the LCD adapter and the LCD speed, if required.

Relevant Constants:

These constants are used to control settings for the Liquid Crystal Display routines included with Great
Cow BASIC. To set them, place a line in the main program file that uses #define to assign a value to the
particular constant.

When using 2-bit mode only three constants must be set - all others can be ignored.

Constant Name Controls Value

LCD_IO I/O mode 12

LCD_I2C_Address_1 Address of I2C adapter Default 0x4E


could also be 0x27

LCD_I2C_Address_2 Address of I2C adapter Not set

218
Constant Name Controls Value

LCD_I2C_Address_2 Address of I2C adapter Not set

LCD_I2C_Address_2 Address of I2C adapter Not set

To set the correct address see the picture below:

For code examples see I2C LCD Solutions.

See the separate sections of the Help file for the specifics of each Connection Mode.

For more help, see LCD_IO 0, LCD_IO 1, LCD_IO 2 LCD_IO 2_74xx164, LCD_IO 2_74xx174, LCD_IO 4,
LCD_IO 8, LCD_IO 10

LCD_IO 12 Port Configuration

Using mode 12:

When using I2C LCD mode 12 the target I2C device address is setup as shown below. Each bit of the the
variable i2c_lcd_byte is defined to address the correct LCD display port.

219
i2c_lcd_e = i2c_lcd_byte.4
i2c_lcd_rw = i2c_lcd_byte.5
i2c_lcd_rs = i2c_lcd_byte.6
i2c_lcd_bl = i2c_lcd_byte.7
i2c_lcd_d4 = i2c_lcd_byte.0
i2c_lcd_d5 = i2c_lcd_byte.1
i2c_lcd_d6 = i2c_lcd_byte.2
i2c_lcd_d7 = i2c_lcd_byte.3

If you have an I2C LCD display adapter with a different set of connection of the adapter then change
this configuration to suit the specific of the adapter as follows. This should be done in the your main
program code.

#define i2c_lcd_e i2c_lcd_byte.4


#define i2c_lcd_rw i2c_lcd_byte.5
#define i2c_lcd_rs i2c_lcd_byte.6
#define i2c_lcd_bl i2c_lcd_byte.7
#define i2c_lcd_d4 i2c_lcd_byte.3
#define i2c_lcd_d5 i2c_lcd_byte.2
#define i2c_lcd_d6 i2c_lcd_byte.1
#define i2c_lcd_d7 i2c_lcd_byte.0

LCD_SPEED

Using LCD_SPEED:

The communication performance of a LCD display can be controlled via a #DEFINE. This method allows
the timing to be optimised.

Example

#DEFINE LCD_SPEED FAST

Define Required Connections

LCD_SPEE Options are:


D FAST - The speed is approximately 20,000 CPS.
MEDIUM - The speed is approximately 15,000 CPS.
SLOW - The speed is approximately 10,000 CPS.

If LCD_SPEED is not defined, the speed defaults to SLOW

220
CLS

Syntax:

CLS

Command Availability:

Available on all microcontrollers.

Explanation:

The CLS command clears the contents of the LCD, and returns the cursor to the top left corner of the
screen

Example :

'A Flashing Hello World program for Great Cow BASIC

'General hardware configuration


#chip 16F877A, 20

'LCD connection settings


#define LCD_IO 8
#define LCD_DATA_PORT PORTC
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

'Main routine
Do
Print "Hello World"
Wait 1 sec
CLS
Wait 1 sec
Loop

For more help, see LCD Overview

Supported in <LCD.H>

Get

Syntax:

221
var = Get(Line, Column)

Command Availability:

Available on all microcontrollers with the LCD R/W line (pin 5) connected and if the following constant
definition is used; #define LCD_RW. Not available if the LCD is connected using the 0 or 2 bit mode or if
the constant definition #define LCD_NO_RW is used.

Explanation:

The Get function reads the ASCII character code at a given location on the LCD.

For more help, see Put, LCD Overview

Supported in <LCD.H>

LCDBacklight

Syntax:

LCDBacklight ( On | Off )

Command Availability:

Available on all microcontrollers

Explanation:

Sets the LCD backlight on or off

Do not connect the LCD backlight directly to the microcontroller! Always refer to the datasheet for the
correct method to drive the LCD backlight.

The diagram below shows a method to connect the LCD backlight to a microcontroller.

222
The
diagram above was provided by William Roth, January 2015.

Supported in <LCD.H>

LCDCreateChar

Syntax:

LCDCreateChar char, chardata()

Command Availability:

Available on all microcontrollers.

Explanation:

The LCDCreateChar command is used to send a custom character to the LCD.

Each character on the LCD is made up from an 8 row by 5 column (5x8) matrix of pixels. The data to be
sent to the LCD is composed of an 8 element array, where each element corresponds to a row. Inside
each element, the 5 lowest bits make up the data for the corresponding row. When a bit is set a dot will
be drawn at the matching location; when it is cleared, no dot will appear.

An array of more than 8 elements may be used, but only the first 8 will be read.

char is the ASCII value of the character to create. ASCII codes 0 through 7 are usually used to store

223
custom characters.
chardata() is an array containing the data for the character.

Example:

'This program draws a smiling face character

'General hardware configuration


#chip 16F877A, 20

'LCD connection settings


#define LCD_IO 8
#define LCD_DATA_PORT PORTC
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

'Create an array to store the character until it is copied


Dim CharArray(8)

'Set the array to hold the character


'Binary has been used to improve the readability of the code, but is not essential
CharArray(1) = b'00011011'
CharArray(2) = b'00011011'
CharArray(3) = b'00000000'
CharArray(4) = b'00000100'
CharArray(5) = b'00000000'
CharArray(6) = b'00010001'
CharArray(7) = b'00010001'
CharArray(8) = b'00001110'

'Copy the character from the array to the LCD


LCDCreateChar 0, CharArray()

'Draw the custom character


LCDWriteChar 0

For more help, see LCDWriteChar, LCD Overview

Supported in <LCD.H>

LCDCreateGraph

Syntax:

224
LCDCreateGraph value

Command Availability:

Available on all microcontrollers.

Explanation:

The LCDCreateGraph command will create a graph like character which can then be displayed on the
LCD

Example :

;Chip Settings
#chip 16F88,8
#config osc = intrc

;Defines (Constants)
#define LCD_IO 4
#define LCD_RS PORTA.6
#define LCD_NO_RW
#define LCD_Enable PORTA.7
#define LCD_DB4 PORTB.4
#define LCD_DB5 PORTB.5
#define LCD_DB6 PORTB.6
#define LCD_DB7 PORTB.7

Locate 0,0
Print "Reset"
wait 1 s
cls

Graph_Tests:

cls
'Draw the custom character - fill the LCD
repeat 64
LCDWriteChar 0
end Repeat

' Update the characters at high speed without re-printing on LCD


for graphvalue = 0 to 8
LCDCreateGraph ( 0 , graphvalue )
wait 100 ms
next

225
Supported in <LCD.H>

LCDCmd

Syntax:

LCDCMD value

Command Availability:

Available on all microcontrollers.

Explanation:

This command set LCD specific instructions to the LCD display. As shown in the table below.

INSTRUCTION Decimal Hexadecimal

Scroll display one character right (all lines) 28 1E

Scroll display one character left (all lines) 24 18

Home (move cursor to top/left character position) 2 2

Move cursor one character left 16 10

Move cursor one character right 20 14

Turn on visible underline cursor 14 0E

Turn on visible blinking-block cursor 15 0F

Make cursor invisible 12 0C

Blank the display (without clearing) 8 08

Restore the display (with cursor hidden) 12 0C

Clear Screen 1 01

Set cursor position (DDRAM address) 128 + addr 80+ addr

Set pointer in character-generator RAM (CG RAM address) 64 + addr 40+ addr

Example :

;Chip Settings
#chip 16F88,8
#config osc = intrc

226
;Defines (Constants)
#define LCD_IO 4
#define LCD_RS PORTA.6
#define LCD_NO_RW
#define LCD_Enable PORTA.7
#define LCD_DB4 PORTB.4
#define LCD_DB5 PORTB.5
#define LCD_DB6 PORTB.6
#define LCD_DB7 PORTB.7

Locate 0,0
Print "Reset"
wait 1 s
cls

LCD_Command_Tests:

locate 0,8
print "123456"
'Scroll display one character right (all lines) 28
'
lcdcmd 28
wait 1 s
lcdcmd 28
wait 1 s
lcdcmd 28
wait 1 s
lcdcmd 28
wait 1 s

'Scroll display one character left (all lines) 24


'
lcdcmd 24
wait 1 s
lcdcmd 24
wait 1 s
lcdcmd 24
wait 1 s
lcdcmd 24
wait 1 s

'Home (move cursor to top/left character position) 2


'
lcdcursor flash
lcdcmd 2
wait 1 s

227
'Move cursor one character left 16
'
lcdcursor flash
locate 0,8

lcdcmd 16
wait 1 s
lcdcmd 16
wait 1 s
lcdcmd 16
wait 1 s
lcdcmd 16
wait 1 s

'Move cursor one character right 20


'
lcdcmd 20
wait 1 s
lcdcmd 20
wait 1 s
lcdcmd 20
wait 1 s
lcdcmd 20
wait 1 s

Supported in <LCD.H>

LCDCursor

Syntax:

LCDCursor value

Command Availability:

Available on all microcontrollers.

Explanation:

The LCDCursor command will accept the following parameters:

LCDON, LCDOFF, CURSORON, CURSOROFF, FLASHON, FLASHOFF

FLASH, and ON/OFF have been retained for backward compatibility with older releases of GCB.

LCDON will turn on (restore) the LCD display.

228
LCDOFF will turn off (hide) the LCD display.
CURSORON will turn on the cursor.
CURSOROFF will turn off the cursor.
FLASHON will flash the cursor.
FLASHOFF will stop flashing the cursor.

Example :
#config osc = intrc

#chip 16f877a, 8

;Defines (Constants)
#define LCD_IO 4
#define LCD_RS PORTA.6
#define LCD_NO_RW
#define LCD_Enable PORTA.7
#define LCD_DB4 PORTB.4
#define LCD_DB5 PORTB.5
#define LCD_DB6 PORTB.6
#define LCD_DB7 PORTB.7

Start:
CLS
WAIT 3 s
PRINT "START DEMO"
locate 1,0
PRINT "DISPLAY ON"

wait 3 s

CLS
Locate 0,0
Print "Cursor ON"
Locate 1,0
LCDcursor CursorOn
wait 3 S

CLS
LCDcursor CursorOFF
locate 0,0
Print "Cursor OFF"
wait 3 s

CLS
Locate 0,0
Print "FLASH ON"
Locate 1,0

229
LCDcursor FLASHON
wait 3 s

CLS
locate 0,0
Print "FLASH OFF"
LCDCURSOR FLASHOFF
wait 3 sec

Locate 0,0
Print "CURSOR&FLASH ON" 'Both are on at the same time
locate 1,0
LCDCURSOR CURSORON
LCDCURSOR FLASHON
Wait 3 sec

Locate 0,0
Print "CURSOR FLASH OFF"
locate 1,0
LCDCURSOR CursorOFF
LCDCURSOR FLASHOFF
Wait 3 sec

CLS
Locate 0,4
PRINT "Flashing"
Locate 1,4
Print "Display"
wait 500 ms

repeat 5
LCDCURSOR LCDOFF
wait 500 ms
LCDCURSOR LCDON
wait 500 ms
end repeat

CLS
Locate 0,0
Print "DISPLAY OFF"
Locate 1,0
Print "FOR 5 SEC"
Wait 2 SEC
LCDCURSOR LCDOFF
WAIT 5 s

CLS
Locate 0,0

230
LCDCURSOR LCDON
Print "END DEMO"
wait 3 s
goto start

Supported in <LCD.H>

LCDHex

Syntax:

LCDHex value

LCDHex value, LeadingZeroActive

Command Availability:

Available on all microcontrollers.

Explanation:

The LCDHex will display the byte value as a 1 or 2 character HEX string.

value is a byte value from 0 to 255.

LeadingZeroActive is a constant or byte value of 2.

Example :

;Set chip model required:


#chip mega328p, 16
;Setup LCD Parameters
#define LCD_IO 4
#define LCD_NO_RW
#define LCD_Speed MEDIUM 'FAST IS OK ON ARDUINO UNO R3

'Change as necessary
#define LCD_RS PortC.0
#define LCD_Enable PortC.1
#define LCD_DB4 PortC.2
#define LCD_DB5 PortC.3
#define LCD_DB6 PortC.4
#define LCD_DB7 PortC.5

' #chip 16f877a, 8


' ;Setup LCD Parameters

231
' #define LCD_IO 4
' #define LCD_NO_RW
' #define LCD_Speed fast 'FAST IS OK ON 16f877a
'
' ;Change as necessary
' #define LCD_RS PortB.2
' #define LCD_Enable PortB.3
' #define LCD_DB4 PortB.4
' #define LCD_DB5 PortB.5
' #define LCD_DB6 PortB.6
' #define LCD_DB7 PortB.7

'Program Start
DO Forever
CLS
WAIT 2 s
PRINT "Test LCDHex "
wait 3 s
CLS
wait 1 s

for bv = 0 to 255
locate 0,0
Print "DEC " : Print BV
locate 1,0
Print "HEX "
LCDHex BV, LeadingZeroActive ; dislay leading Zero
' LCDHex BV ; do not display leading zero
wait 1 s
next
CLS
wait 1 s
Print "END TEST"
LOOP

Supported in <LCD.H>

LCDHome

Syntax:

LCDHome

Command Availability:

Available on all microcontrollers.

232
Explanation:

The LCDHome command will return the cursor to home position.

The currentcontents of the LCD screen will be retained.

Example:

;Chip Settings
#chip 16F88,8
#config osc = intrc

;Defines (Constants)
#define LCD_IO 4
#define LCD_RS PORTA.6
#define LCD_NO_RW
#define LCD_Enable PORTA.7
#define LCD_DB4 PORTB.4
#define LCD_DB5 PORTB.5
#define LCD_DB6 PORTB.6
#define LCD_DB7 PORTB.7

Locate 0,0
Print "Reset"
wait 1 s
ClS

Cursor_Home_Tests:

cls
lcdcursor flash
print "Test Home Cmd"
LCDHome
wait 3 s

Supported in <LCD.H>

LCDDisplayOn

Syntax:

LCDDisplayOn

Explanation:

Will turn on (restore) the LCD display

233
See also LCDCursor

Supported in <LCD.H>

LCDDisplayOff

Syntax:

LCDDisplayOff

Explanation:

Will turn off (hide) the LCD display.

See also LCDCursor

Supported in <LCD.H>

LCDSpace

Syntax:

LCDSpace value

Command Availability:

Available on all microcontrollers.

Explanation:

The LCDSpace command will print the required number of spaces on the LCD display

value is a byte value from 1 to 255. Where the value is the number of spaces required.

Example :

234
Locate 0,0
Print "Reset"
wait 1 s
cls

LCD_Space_Tests:

lcdcursor flash

lcdspace 12

print "*"

Supported in <LCD.H>

LCDWriteChar

Syntax:

LCDWriteChar char

Command Availability:

Available on all microcontrollers.

Explanation:

The LCDWriteChar command will show the specified character on the LCD, at the current cursor
position.

char is the ASCII value of the character to show. On most LCDs, characters 0 through 7 are user defined,
and can be set using the LCDCreateChar command.

Example :

235
'This program draws a smiling face character

'Create an array to store the character until it is copied


Dim CharArray(8)

'Set the array to hold the character


CharArray(1) = b'00011011'
CharArray(2) = b'00011011'
CharArray(3) = b'00000000'
CharArray(4) = b'00000100'
CharArray(5) = b'00000000'
CharArray(6) = b'00010001'
CharArray(7) = b'00010001'
CharArray(8) = b'00001110'

'Copy the character from the array to the LCD


LCDCreateChar 0, CharArray()

'Draw the custom character


LCDWriteChar 0

For more help, see LCDCreateChar, LCD Overview

Supported in <LCD.H>

Locate

Syntax:

Locate Line, Column

Command Availability:

Available on all microcontrollers.

Explanation:

The Locate command is used to move the cursor on the LCD to the given location.

Line is line number on the LCD display. A byte value from 0 to 255.

Column is column number on the LCD display. A byte value from 0 to 255.

Example :

236
'A Hello World program for Great Cow BASIC.
'Uses Locate to show "World" on the second line

'General hardware configuration


#chip 16F877A, 20

'LCD connection settings


#define LCD_IO 8
#define LCD_DATA_PORT PORTC
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

'Main routine
Print "Hello"
Locate 1, 5
Print "World"

For more help, see LCD Overview

Supported in <LCD.H>

Print

Syntax:

Print string
Print byte
Print word
Print long
Print integer

Command Availability:

Available on all microcontrollers.

Explanation:

The Print command will show the contents of a variable on the LCD. It can display string, word, byte,
long or integer variables.

Example:

237
'A Light Meter program.

'General hardware configuration


#chip 16F877A, 20
#define LightSensor AN0

'LCD connection settings


#define LCD_IO 8
#define LCD_DATA_PORT PORTC
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

CLS
Print "Light Meter"
Locate 1,2
Print "A GCBASIC Demo"
Wait 2 s

Do
CLS
Print "Light Level: "
Print ReadAD(LightSensor)
Wait 250 ms
Loop

For more help, see LCD Overview

Supported in <LCD.H>

Put

Syntax:

Put Line, Column, Character

Command Availability:

Available on all microcontrollers.

Explanation:

The Put command writes the given ASCII character code to the current location on the LCD.

Line is line number on the LCD display. A byte value from 0 to 255.

238
Column is column number on the LCD display. A byte value from 0 to 255.

Character is the requried ASCII code. A byte value from 0 to 255.

Example :

'A scrolling star for Great Cow BASIC

'Misc Settings
#define SCROLL_DELAY 250 ms

'General hardware configuration


#chip 16F877A, 20

'LCD connection settings


#define LCD_IO 8
#define LCD_DATA_PORT PORTC
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

'Main routine
For StarPos = 0 To 16
If StarPos = 0 Then
Put 0, 16, 32
Put 0, 0, 42
Else
Put 0, StarPos - 1, 32
Put 0, StarPos, 42
End If
Wait SCROLL_DELAY
Next

For more help, see LCD Overview

Supported in <LCD.H>

239
Examples

LCD_IO 2 Example

This a connection mode 2 Serial Driver to demonstrate LCD features. This for the 16F877A, but, it can
easily be adapted for other microcontrollers.

A 2 by 16 LCD is assumed.

Based on the works by Thomas Henry and then revised Evan R. Venn

#chip 16F877A,20

#define LCD_IO 2
#define LCD_DB portb.2
#define LCD_CB portb.0
#define LCD_NO_RW
;Here are various LCD commands which can be used.
;These are the LCD commands for the HD44780 controller

#define clrHome = 1 ;clear the display, home the cursor


#define home = 2 ;home the cursor only
#define RtoL = 4 ;print characters right to left
#define insR = 5 ;insert characters to right
#define LtoR = 6 ;print characters left to right
#define insL = 7 ;insert characters to left
#define lcdOff = 8 ;LCD screen off
#define lcdOn = 12 ;LCD screen on, no cursor
#define curOff = 12 ;an alias for the above
#define block = 13 ;LCD screen on, block cursor
#define under = 14 ;LCD screen on, underline cursor
#define undblk = 15 ;LCD screen on, blinking and underline cursor
#define CLeft = 16 ;cursor left
#define CRight = 20 ;cursor right
#define panR = 24 ;pan viewing window right
#define panL = 28 ;pan viewing window left
#define bus4 = 32 ;4-bit data bus mode
#define bus8 = 48 ;8-bit data bus mode
#define mode1 = 32 ;one-line mode (alias)
#define mode2 = 40 ;two-line mode
#define line1 = 128 ;go to start of line 1
#define line2 = 192 ;go to start of line 2
;----- Variables
dim char, msn, lsn, index, ii as byte
;----- Main Program
LoadEeprom ;load the EEprom with strings

240
do forever
printMsg(0) ;print first message
wait 3 S ;pause 3 seconds
printMsg(2) ;print next message
wait 3 S ;pause 3 seconds
repeat 5 ;blink it five times
LCDCmd(lcdOff) ;display off
wait 500 mS ;pause
LCDCmd(lcdOn) ;display on
wait 500 mS ;pause
end repeat
wait 1 S ;pause before next demo
;demonstrate panning
printMsg(4) ;print next message
wait 3 S ;pause 3 seconds
repeat 16
LCDCmd(panL) ;pan left a step at a time
wait 300 mS ;slow down to avoid blur
end repeat
repeat 16
LCDCmd(panR) ;then pan right
wait 300 mS
end repeat
wait 1 S ;pause before next demo
;demonstrate moving the cursor
printMsg(6) ;print next message
wait 3 S ;pause 3 seconds
doHome ;home cursor
LCDCmd(under) ;choose underline cursor
for ii = 0 to 15 ;move cursor across first line
LCDCmd(line1+i)
wait 200 mS
next i
for ii = 0 to 15 ;move cursor across second line
LCDCmd(line2+i)
wait 200 mS
next i
for ii = 15 to 0 step -1 ;move cursor back over second line
LCDCmd(line2+i)
wait 200 mS
next i
for ii = 15 to 0 step -1 ;move cursor back over first line
LCDCmd(line1+i)
wait 200 mS
next i
wait 3 S
;demonstrate blinking block cursor
printMsg(8) ;print next message

241
doHome ;home the cursor
LCDCmd(block) ;choose blinking block cursor
wait 4 S ;pause 4 seconds
LCDCmd(mode1) ;change to one long line mode
doHome ;home the cursor again
LCDCmd(curOff) ;and disable it

;demonstrate scrolling a lengthy one-line marquee


for ii = 0xd0 to 0xff ;print next message - the remaining EEPROM
EPread ii, char ;fetch directly from eeprom
print chr(char)
next i
wait 1 S
doHome ;home cursor once more
repeat 141 ;scroll message twice
LCDCmd(panR)
wait 250 mS
end repeat
wait 2 S
LCDCmd(mode2) ;change back to two line mode
doClr ;clear the screen
;demonstrate all of the characters
printMsg(11) ;print next message
for ii = 33 to 127 ;print first batch of ASCII characters
LCDCmd(line1+12) ;overwrite each character displayed
print chr(ii) ;this is the ASCII code
wait 500 mS
next i
for ii = 161 to 255 ;print next batch of ASCII characters
LCDCmd(line1+12)
print chr(ii)
wait 500 mS
next i
;say good-bye
LCDCmd(line2)
printMsg(11) ;print next message
doHome ;home the cursor
loop

end

;----- Clear the screen


sub doClr
LCDCmd(clrHome)
wait 5 mS ;this command takes extra time
end sub

242
;----- Home the cursor
sub doHome
LCDCmd(home)
wait 5 mS ;and so does this one
end sub

;----- Print a message to the LCD


;The parameter 'row' points to the start of the string.
sub printMsg(in row as byte, in Optional StringLength As Byte = 15)
LCDCmd(line1) ;get set for first line

for ii = 0 to StringLength
index = row*16+ii
EPread index, char ;fetch next character and
print chr(char) ;transmit to the LCD
next
LCDCmd(line2) ;get set for second line
for ii = 0 to StringLength
index = (row+1)*16+ii
EPread index, char ;fetch next character and
print chr(char) ;transmit to the LCD
next
end sub

sub loadEeprom

' Strings for EEPROM, Strings should be limited to 16 characters for the first 13
sstrings, then a long string to fill eeprom
location = 0
WriteEeprom "First we'll show"
WriteEeprom "this message. "
WriteEeprom "Then we'll blink"
WriteEeprom "five times. "
WriteEeprom "Now lets pan "
WriteEeprom "left and right. "
WriteEeprom "Watch the line "
WriteEeprom "cursor move. "
WriteEeprom "A block cursor "
WriteEeprom "is available. "
WriteEeprom "Characters: "
WriteEeprom "Bye! "
WriteEeprom "in one line mode"
WriteEeprom "Next well scroll this long message as a marquee"

end sub

; Write to the device eeprom


sub WriteEeprom ( in Estring() ) as string * 64

243
for ee = 1 to len ( Estring )
HSersend Estring(ee)
epwrite location, Estring(ee)
location++
next

end sub

LCD_IO 4 Example

This is a Serial connection mode 4 Driver to demonstrate LCD features. This for the 16F877A, but, it can
easily be adapted for other microcontrollers.

A 2 by 16 LCD is assumed.

Based on the works by Thomas Henry and then revised Evan R. Venn

#chip 16F877A,20

'Use LCD in 4 pin mode and define LCD pins


#define LCD_IO 4
#define LCD_RW PORTE.1
#define LCD_RS PORTE.0
#define LCD_Enable PORTE.2
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7

;Here are various LCD commands which can be used.


;These are the LCD commands for the HD44780 controller
#define clrHome = 1 ;clear the display, home the cursor
#define home = 2 ;home the cursor only
#define RtoL = 4 ;print characters right to left
#define insR = 5 ;insert characters to right
#define LtoR = 6 ;print characters left to right
#define insL = 7 ;insert characters to left
#define lcdOff = 8 ;LCD screen off
#define lcdOn = 12 ;LCD screen on, no cursor
#define curOff = 12 ;an alias for the above
#define block = 13 ;LCD screen on, block cursor
#define under = 14 ;LCD screen on, underline cursor
#define undblk = 15 ;LCD screen on, blinking and underline cursor
#define CLeft = 16 ;cursor left
#define CRight = 20 ;cursor right
#define panR = 24 ;pan viewing window right

244
#define panL = 28 ;pan viewing window left
#define bus4 = 32 ;4-bit data bus mode
#define bus8 = 48 ;8-bit data bus mode
#define mode1 = 32 ;one-line mode (alias)
#define mode2 = 40 ;two-line mode
#define line1 = 128 ;go to start of line 1
#define line2 = 192 ;go to start of line 2
;----- Variables
dim char, msn, lsn, index, ii as byte
;----- Main Program
LoadEeprom ;load the EEprom with strings

do forever
printMsg(0) ;print first message
wait 3 S ;pause 3 seconds
printMsg(2) ;print next message
wait 3 S ;pause 3 seconds
repeat 5 ;blink it five times
LCDCmd(lcdOff) ;display off
wait 500 mS ;pause
LCDCmd(lcdOn) ;display on
wait 500 mS ;pause
end repeat
wait 1 S ;pause before next demo
;demonstrate panning
printMsg(4) ;print next message
wait 3 S ;pause 3 seconds
repeat 16
LCDCmd(panL) ;pan left a step at a time
wait 300 mS ;slow down to avoid blur
end repeat
repeat 16
LCDCmd(panR) ;then pan right
wait 300 mS
end repeat
wait 1 S ;pause before next demo
;demonstrate moving the cursor
printMsg(6) ;print next message
wait 3 S ;pause 3 seconds
doHome ;home cursor
LCDCmd(under) ;choose underline cursor
for ii = 0 to 15 ;move cursor across first line
LCDCmd(line1+i)
wait 200 mS
next i
for ii = 0 to 15 ;move cursor across second line
LCDCmd(line2+i)
wait 200 mS

245
next i
for ii = 15 to 0 step -1 ;move cursor back over second line
LCDCmd(line2+i)
wait 200 mS
next i
for ii = 15 to 0 step -1 ;move cursor back over first line
LCDCmd(line1+i)
wait 200 mS
next i
wait 3 S
;demonstrate blinking block cursor
printMsg(8) ;print next message
doHome ;home the cursor
LCDCmd(block) ;choose blinking block cursor
wait 4 S ;pause 4 seconds
LCDCmd(mode1) ;change to one long line mode
doHome ;home the cursor again
LCDCmd(curOff) ;and disable it

;demonstrate scrolling a lengthy one-line marquee


for ii = 0xd0 to 0xff ;print next message - the remaining EEPROM
EPread ii, char ;fetch directly from eeprom
print chr(char)
next i
wait 1 S
doHome ;home cursor once more
repeat 141 ;scroll message twice
LCDCmd(panR)
wait 250 mS
end repeat
wait 2 S
LCDCmd(mode2) ;change back to two line mode
doClr ;clear the screen
;demonstrate all of the characters
printMsg(11) ;print next message
for ii = 33 to 127 ;print first batch of ASCII characters
LCDCmd(line1+12) ;overwrite each character displayed
print chr(ii) ;this is the ASCII code
wait 500 mS
next i
for ii = 161 to 255 ;print next batch of ASCII characters
LCDCmd(line1+12)
print chr(ii)
wait 500 mS
next i
;say good-bye
LCDCmd(line2)

246
printMsg(11) ;print next message
doHome ;home the cursor
loop
end

;----- Clear the screen


sub doClr
LCDCmd(clrHome)
wait 5 mS ;this command takes extra time
end sub

;----- Home the cursor


sub doHome
LCDCmd(home)
wait 5 mS ;and so does this one
end sub

;----- Print a message to the LCD


;The parameter 'row' points to the start of the string.
sub printMsg(in row as byte, in Optional StringLength As Byte = 15)
LCDCmd(line1) ;get set for first line

for ii = 0 to StringLength
index = row*16+ii
EPread index, char ;fetch next character and
print chr(char) ;transmit to the LCD
next
LCDCmd(line2) ;get set for second line
for ii = 0 to StringLength
index = (row+1)*16+ii
EPread index, char ;fetch next character and
print chr(char) ;transmit to the LCD
next
end sub

sub loadEeprom
' Strings for EEPROM, Strings should be limited to 16 characters for the first 13
sstrings, then a long string to fill eeprom
location = 0
WriteEeprom "First we'll show"
WriteEeprom "this message. "
WriteEeprom "Then we'll blink"
WriteEeprom "five times. "
WriteEeprom "Now lets pan "
WriteEeprom "left and right. "

247
WriteEeprom "Watch the line "
WriteEeprom "cursor move. "
WriteEeprom "A block cursor "
WriteEeprom "is available. "
WriteEeprom "Characters: "
WriteEeprom "Bye! "
WriteEeprom "in one line mode"
WriteEeprom "Next well scroll this long message as a marquee"
end sub

; Write to the device eeprom


sub WriteEeprom ( in Estring() ) as string * 64
for ee = 1 to len ( Estring )
HSersend Estring(ee)
epwrite location, Estring(ee)
location++
next
end sub

LCD_IO 8 Example

This is an connection mode 8 Driver to demonstrate LCD features. This for the 16F877A, but, it can
easily be adapted for other microcontrollers.

A 2 by 16 LCD is assumed.

Based on the works by Thomas Henry and then revised Evan R. Venn

#chip 16F877A,20

'Use LCD in 8 pin mode and define LCD pins


#define LCD_IO 8
#define LCD_RW PORTE.1
#define LCD_RS PORTE.0
#define LCD_Enable PORTE.2
#define LCD_Data_Port PORTD

;Here are various LCD commands which can be used.


;These are the LCD commands for the HD44780 controller
#define clrHome = 1 ;clear the display, home the cursor
#define home = 2 ;home the cursor only
#define RtoL = 4 ;print characters right to left
#define insR = 5 ;insert characters to right
#define LtoR = 6 ;print characters left to right
#define insL = 7 ;insert characters to left

248
#define lcdOff = 8 ;LCD screen off
#define lcdOn = 12 ;LCD screen on, no cursor
#define curOff = 12 ;an alias for the above
#define block = 13 ;LCD screen on, block cursor
#define under = 14 ;LCD screen on, underline cursor
#define undblk = 15 ;LCD screen on, blinking and underline cursor
#define CLeft = 16 ;cursor left
#define CRight = 20 ;cursor right
#define panR = 24 ;pan viewing window right
#define panL = 28 ;pan viewing window left
#define bus4 = 32 ;4-bit data bus mode
#define bus8 = 48 ;8-bit data bus mode
#define mode1 = 32 ;one-line mode (alias)
#define mode2 = 40 ;two-line mode
#define line1 = 128 ;go to start of line 1
#define line2 = 192 ;go to start of line 2
;----- Variables
dim char, msn, lsn, index, ii as byte
;----- Main Program
LoadEeprom ;load the EEprom with strings

do forever
printMsg(0) ;print first message
wait 3 S ;pause 3 seconds
printMsg(2) ;print next message
wait 3 S ;pause 3 seconds
repeat 5 ;blink it five times
LCDCmd(lcdOff) ;display off
wait 500 mS ;pause
LCDCmd(lcdOn) ;display on
wait 500 mS ;pause
end repeat
wait 1 S ;pause before next demo
;demonstrate panning
printMsg(4) ;print next message
wait 3 S ;pause 3 seconds
repeat 16
LCDCmd(panL) ;pan left a step at a time
wait 300 mS ;slow down to avoid blur
end repeat
repeat 16
LCDCmd(panR) ;then pan right
wait 300 mS
end repeat
wait 1 S ;pause before next demo
;demonstrate moving the cursor
printMsg(6) ;print next message
wait 3 S ;pause 3 seconds

249
doHome ;home cursor
LCDCmd(under) ;choose underline cursor
for ii = 0 to 15 ;move cursor across first line
LCDCmd(line1+i)
wait 200 mS
next i
for ii = 0 to 15 ;move cursor across second line
LCDCmd(line2+i)
wait 200 mS
next i
for ii = 15 to 0 step -1 ;move cursor back over second line
LCDCmd(line2+i)
wait 200 mS
next i
for ii = 15 to 0 step -1 ;move cursor back over first line
LCDCmd(line1+i)
wait 200 mS
next i
wait 3 S
;demonstrate blinking block cursor
printMsg(8) ;print next message
doHome ;home the cursor
LCDCmd(block) ;choose blinking block cursor
wait 4 S ;pause 4 seconds
LCDCmd(mode1) ;change to one long line mode
doHome ;home the cursor again
LCDCmd(curOff) ;and disable it

;demonstrate scrolling a lengthy one-line marquee


for ii = 0xd0 to 0xff ;print next message - the remaining EEPROM
EPread ii, char ;fetch directly from eeprom
print chr(char)
next i
wait 1 S
doHome ;home cursor once more
repeat 141 ;scroll message twice
LCDCmd(panR)
wait 250 mS
end repeat
wait 2 S
LCDCmd(mode2) ;change back to two line mode
doClr ;clear the screen
;demonstrate all of the characters
printMsg(11) ;print next message
for ii = 33 to 127 ;print first batch of ASCII characters
LCDCmd(line1+12) ;overwrite each character displayed
print chr(ii) ;this is the ASCII code

250
wait 500 mS
next i
for ii = 161 to 255 ;print next batch of ASCII characters
LCDCmd(line1+12)
print chr(ii)
wait 500 mS
next i
;say good-bye
LCDCmd(line2)
printMsg(11) ;print next message
doHome ;home the cursor
loop
end

;----- Clear the screen


sub doClr
LCDCmd(clrHome)
wait 5 mS ;this command takes extra time
end sub

;----- Home the cursor


sub doHome
LCDCmd(home)
wait 5 mS ;and so does this one
end sub

;----- Print a message to the LCD


;The parameter 'row' points to the start of the string.
sub printMsg(in row as byte, in Optional StringLength As Byte = 15)
LCDCmd(line1) ;get set for first line

for ii = 0 to StringLength
index = row*16+ii
EPread index, char ;fetch next character and
print chr(char) ;transmit to the LCD
next
LCDCmd(line2) ;get set for second line
for ii = 0 to StringLength
index = (row+1)*16+ii
EPread index, char ;fetch next character and
print chr(char) ;transmit to the LCD
next
end sub

sub loadEeprom

' Strings for EEPROM, Strings should be limited to 16 characters for the first 13
sstrings, then a long string to fill eeprom

251
location = 0
WriteEeprom "First we'll show"
WriteEeprom "this message. "
WriteEeprom "Then we'll blink"
WriteEeprom "five times. "
WriteEeprom "Now lets pan "
WriteEeprom "left and right. "
WriteEeprom "Watch the line "
WriteEeprom "cursor move. "
WriteEeprom "A block cursor "
WriteEeprom "is available. "
WriteEeprom "Characters: "
WriteEeprom "Bye! "
WriteEeprom "in one line mode"
WriteEeprom "Next well scroll this long message as a marquee"
end sub

; Write to the device eeprom


sub WriteEeprom ( in Estring() ) as string * 64
for ee = 1 to len ( Estring )
HSersend Estring(ee)
epwrite location, Estring(ee)
location++
next
end sub

LCD_IO 10 Example

This is an connection mode 10 I2C Driver to demonstrate LCD features. This for the 16F877A, but, it can
easily be adapted for other microcontrollers.

A 2 by 16 LCD is assumed with the LCD being driven using an LCD I2C adapter. Two types are
supported the YwRobot LCD1602 IIC V1 / a Sainsmart LCD_PIC I2C adapter or the Ywmjkdz I2C adapter
with pot bent over top of chip.

The demonstrates reading a DS18B20 and showing the results on the LCD.

Example:

#chip mega328p, 16
#include <DS18B20.h>

; ----- Define Hardware settings


' Define I2C settings - CHANGE PORTS
#define I2C_MODE Master
#define I2C_DATA PORTC.4

252
#define I2C_CLOCK PORTC.5
#define I2C_DISABLE_INTERRUPTS ON

'''Set up LCD
#define LCD_IO 10
#define LCD_I2C_Address_1 0x4E ; LCD 1
#define LCD_I2C_Address_2 0x4C ; LCD 2

; ----- Constants
' DS18B20 port settings - this is required
#define DQ PortC.3

; ----- Quick Command Reference:

'''Set LCD_10 to 10 for the YwRobot LCD1602 IIC V1 or the Sainsmart LCD_PIC I2C
adapter
'''Set LCD_10 to 12 for the Ywmjkdz I2C adapter with pot bent over top of chip

; ----- Variables
dim TempC_100 as word ' a variabler to handle the temperature calculations
dim DSdataRaw as Integer

; ----- Main body of program commences here.

'Change to the correct LCD by setting LCD_I2C_Address_Current to the correct


address then write to LCD.
LCD_I2C_Address_Current = LCD_I2C_Address_1: DisplayInformation ( 1 )
LCD_I2C_Address_Current = LCD_I2C_Address_2: DisplayInformation ( 1 )
wait 4 s
LCD_I2C_Address_Current = LCD_I2C_Address_1: CLS
LCD_I2C_Address_Current = LCD_I2C_Address_2: CLS

ccount = 0
Do forever

' The function readtemp12 returns the raw value of the sensor.
' The sensor is read as a 12 bit value therefore each unit equates to 0.0625 of a
degree
DSdataRaw = readtemp12 ; save to this variable to prevent the delay bewtween
screen up dates
' The function readtemp returns the integer value of the sensor
DSdata = readtemp

LCD_I2C_Address_Current = LCD_I2C_Address_1: DisplayInformation ( 2 ) ; update


LCD1
LCD_I2C_Address_Current = LCD_I2C_Address_2: DisplayInformation ( 2 ) ; update
LCD2

253
DSdata = DSdataRaw ; Set the data
LCD_I2C_Address_Current = LCD_I2C_Address_1: DisplayInformation ( 3 ) ; update
LCD1
DSdata= DSdataRaw ; Set the data
LCD_I2C_Address_Current = LCD_I2C_Address_2: DisplayInformation ( 3 ) ; update
LCD2

ccount++

wait 1 s

loop
End

Sub DisplayInformation ( LCDCommand )

Select case LCDCommand

Case 1
CLS
print "GCBasic 2015"
locate 1,0
print "DS18B20 Demo"

Case 2
' Display the integer value of the sensor on the LCD
locate 0,0
print hex(ccount)
print " Ceil"
locate 0,8
print DSdata
print chr(223)+"C"+" "

Case 3

' Display the integer and decimal value of the sensor on the LCD

SignBit = DSdata / 256 / 128


If SignBit = 0 Then goto Positive
' its negative!
DSdata = ( DSdata # 0xffff ) + 1 ' take twos comp

Positive:

' Convert value * 0.0625. Mulitple value by 6 then add result to


multiplication of the value with 25 then divide result by 100.
TempC_100 = DSdata * 6
DSdata = ( DSdata * 25 ) / 100

254
TempC_100 = TempC_100 + DSdata

Whole = TempC_100 / 100


Fract = TempC_100 % 100
If SignBit = 0 Then goto DisplayTemp
Print "-"

DisplayTemp:
locate 1,0
print hex(ccount)
print " Real"
locate 1,8
print str(Whole)
print "."
' To ensure the decimal part is two digits
Dig = Fract / 10
print Dig
Dig = Fract % 10
print Dig
print chr(223)
print "C"+" "

End Select

end sub

255
Pulse width modulation
This is the Pulse width modulation section of the Help file. Please refer the sub-sections for details
using the contents/folder view.

PWM Overview

Introduction:

The methods described in this section allow the generation of Pulse Width Modulation (PWM) signals.
PWM signals enables the microcontroller to control items like the speed of a motor, or the brightness
of a LED or lamp. The methods can also be used to generate the appropriate frequency signal to drive
an infrared LED for remote control applications.

The PWMOn, PWMOff and HPWM methods use the hardware PWM generation module on the microcontroller.
They will only work on some microcontrollers - see the section on each command for details. PWMOn and
HPWM will cause the hardware PWM module on the microcontroller to start generating a PWM signal,
which will then continue to be generated until the PWMOff instruction is run.

The method PWMOut does not make use of any special hardware within the microcontroller. The PWM
signal is generated only while the PWMOut command is executing - therefore, when the PWMOut is not
executing by moving onto the next command, the PWM signal will stop.

Relevant Constants:

A number of constants are used to control settings for the PWM hardware module of the
microcontroller. To set them, place a line in the main program file that uses #define to assign a value to
the particular constant.

There are two sets of constants: one set for Hardware PWM, and one set for Software PWM.

Hardware PWM

Hardware PWM requires a CCP, CCP1, CCP2, CCP3 or CCP4 module on the microcontroller and Software
PWM has no requirements regarding a supporting hardware modle within the microcontroller.
Hardware PWM is only available through the "CCP" or "CCPx" pin. This is a hardware limitation of
Microchip PIC microcontrollers.

These constants are required for PWMOn.

Constant Name Controls Default Value

PWM_Freq Specifies the output frequency of the PWM module in KHz. 38

PWM_Duty Sets the duty cycle of the PWM module output. Given as percentage. 50

HPWM and PWMOff do not require any constants to operate.

256
Optimisation of the hardware PWM code can be implemented within Great Cow BASIC, see Hardware
PWM Code Optimisation

Software PWM

Constant Controls Default Value


Name

PWM_Delay The PWM Period. The length of any delay used will be multiplied by Not defined -
255. If no value is specified, no delays will be inserted into the PWM no delay
routine.

PWM_Out n The port physical port on the Microchip PIC microcontroller that Not Defined
corresponds to channel n.
n can represent 1, 2, 3 or 4.

PWMOut

Syntax:

PWMOut channel, duty cycle, cycles

Command Availability:

Available on all microcontrollers.

Explanation :

This command uses a software PWM routine included in Great Cow BASIC to produce a PWM signal on
the selected port of the chip. This routine does NOT require a PWM module on the chip.

channel sets the channel that the PWM is to be generated on. This must have been defined previously
by setting the constants PWM_Out1, PWM_Out2, PWM_Out3 or PWM_Out4. The maximum number of channels
available is 4.
duty cycle specifies the PWM duty cycle, and ranges from 0 to 255. 255 corresponds to 100%, 127 to
50%, 63 to 25%, and so on.
cycles is used to set the amount of PWM pulses to supply. This is useful for situations in which a pulse
of a specific length is required. The formula for calculating the time taken for one cycle is:

TCYCLE = (28 + 10C)TOSC+ 255PWM_Delay,

where C is the number of channels used and TOSC is the length of time taken to execute 1 instruction on
the chip (0.2 us on a 20 MHz chip, 1 us on a 4 Mhz chip). PWM_Delay is a length of time specified using
the PWM_Delay constant.

Example 1 :

257
'This program controls the brightness of an LED on PORTB.0
'using the software PWM routine and a potentiometer.
#chip 16f877a, 4

; ----- Constants
'PWM constant. This is a required constant.
#define PWM_Out1 portb.0

; ----- Define Hardware settings


'PWM port out. This is not required but good practice.
dir PWM_Out1 out

'A potentiometer is attached to ANO

; ----- Variables
' No Variables specified in this example.

; ----- Main body of program commences here.


do
'100 cycles is a purely arbitrary value
PWMOut 1, ReadAD(AN0), 100
loop

end

Example 2 :

258
'This program controls the brightness of an LED on gpio.1
'using the software PWM routine and a potentiometer.
#chip 12f675, 4

; ----- Constants
'PWM constant. This is a required constant.
#define PWM_Out1 gpio.1

; ----- Define Hardware settings


'PWM port out. This is not required but good practice.
dir PWM_Out1 out

'A potentiometer is attached to ANO

; ----- Variables
' No Variables specified in this example.

; ----- Main body of program commences here.


do
'100 cycles is a purely arbitrary value
PWMOut 1, ReadAD(AN0), 100
loop
end

PWMOff

Syntax:

PWMOff

Command Availability:

Only available on Microchip PIC microcontrollers with Capture/Compare/PWM module CCP1.

This command does not operate on any other CCP channel except for CCP1.

Explanation:

This command will disable the output of the CCP1/PWM module on the Microchip PIC chip.

Example:

259
'This program will enable a 76 Khz PWM signal, with a duty cycle
'of 80%. It will emit the signal for 10 seconds, then stop.
#define PWM_Freq 76 'Set frequency in KHz
#define PWM_Duty 80 'Set duty cycle to 80 %
PWMOn 'Turn on the PWM
WAIT 10 s 'Wait 10 seconds
PWMOff 'Turn off the PWM

For more help, see PWMOn

PWMOn

Syntax:

PWMOn

Command Availability:

Only available on Microchip PIC microcontrollers with Capture/Compare/PWM module CCP1.

This command does not operate on any other CCP channel except for CCP1.

Explanation:

This command will enable the output of the CCP1/PWM module on the Microchip PIC microcontroller.

Example:

'This program will enable a 76 Khz PWM signal, with a duty cycle
'of 80%. It will emit the signal for 10 seconds, then stop.
#define PWM_Freq 76 'Set frequency in KHz
#define PWM_Duty 80 'Set duty cycle to 80 %
PWMOn 'Turn on the PWM
WAIT 10 s 'Wait 10 seconds
PWMOff 'Turn off the PWM

For more help, see PWMOff

HPWM CCP

Syntax:

HPWM channel, frequency, duty cycle

260
Command Availability:

Only available on Microchip PIC microcontrollers with Capture/Compare/PWM (CCP) module.

This command supports the CCP 8 bit support with Timer 2 only. For PWM 10 Bit support with only
timer see here HPWM 10 Bit

Explanation:

This command sets up the hardware PWM module of the Microchip PIC microcontroller to generate a
PWM waveform of the given frequency and duty cycle. Once this command is called, the PWM will be
emitted until PWMOff is called. If you only need one particular frequency and duty cycle, you should
use PWMOn and the constants PWM_Freq and PWM_Duty instead.

channel is 1, 2, 3, 4 or 5, and corresponds to the pins CCP1, CCP2, CCP3, CCP4 and CCP5 respectively. On
chips with only one CCP port, pin CCP or CCP1 is always used, and channel is ignored. (It should be set
to 1 anyway to allow for future upgrades to more powerful microcontrollers.)

frequency sets the frequency of the PWM output. It is measured in KHz. The maximum value allowed is
255 KHz. The minimum value varies depending on the clock speed. 1 KHz is the minimum on chips 16
MHz or under and 2 Khz is the lowest possible on 20 MHz chips. In situations that do not require a
specific PWM frequency, the PWM frequency should equal approximately 1 five-hundredth the clock
speed of the microcontroller (ie 40 Khz on a 20 MHz chip, 16 KHz on an 8 MHz chip). This gives the best
duty cycle resolution possible.

duty cycle specifies the desired duty cycle of the PWM signal, and ranges from 0 to 255 where 255 is
100% duty cycle.

The optional constant HPWM_FAST can be defined to enable the recalculation of the timer prescaler when
needed. This will provide faster operation, but uses extra byte of RAM and may cause problems if HPWM
and PWMOn are used together in a program. This will not cause any issue when using HPWM and PWMOff in
the same program with HPWM_FAST.

Example:

261
'This program will alter the brightness of an LED using
'hardware PWM.

'Select chip model and speed


#chip 16F877A, 20

'Set the CCP1 pin to output mode


DIR PORTC.2 out

'Main code
do
'Turn up brightness over 2.5 seconds
For Bright = 1 to 255
HPWM 1, 40, Bright
wait 10 ms
next
'Turn down brightness over 2.5 seconds
For Bright = 255 to 1
HPWM 1, 40, Bright
wait 10 ms
next
loop

For more help, see PWMOff

HPWM 10 Bit

Syntax:

HPWM channel, frequency, duty cycle, timer

Command Availability:

Only available on Microchip PIC microcontrollers with the PWM module.

For the Capture/Compare/PWM (CCP) module, see here HPWM CCP

Explanation:

This command sets up the hardware PWM module of the Microchip PIC microcontroller to generate a
PWM waveform of the given frequency and duty cycle. Once this command is called, the PWM will be
emitted until PWMOff is called.

channel is 5, 6 or 7. These corresponds to the HPWM5, HPWM6 or HPWM7 respectively.

262
frequency sets the frequency of the PWM output. It is measured in KHz. The maximum value allowed is
255 KHz. The minimum value varies depending on the clock speed. 1 KHz is the minimum on chips 16
MHz or under and 2 Khz is the lowest possible on 20 MHz chips. In situations that do not require a
specific PWM frequency, the PWM frequency should equal approximately 1 five-hundredth the clock
speed of the microcontroller (ie 40 Khz on a 20 MHz chip, 16 KHz on an 8 MHz chip). This gives the best
duty cycle resolution possible.

duty cycle specifies the desired duty cycle of the PWM signal, and ranges from 0 to 255 where 255 is
100% duty cycle.

timer specifies the desired to be used. These can be timer 2, 4 or 6.

Example:

'This program will alter the brightness of an LED using


'hardware PWM.

'Select chip model and speed


#chip 16F18855, 32

'Set the PWM pin to output mode


DIR PORTA.2 out

'Main code
do
'Turn up brightness over 2.5 seconds
For Bright = 1 to 255
HPWM 6, 40, Bright, 2
wait 10 ms
next
'Turn down brightness over 2.5 seconds
For Bright = 255 to 1
HPWM 6, 40, Bright, 2
wait 10 ms
next
loop

For more help, see PWMOff

Hardware PWM Code Optimisation

About Hardware PWM Code Optimisation

The Hardware PWM module support is implemented by Great Cow BASIC to up to four channels.

For compatibility all channels are supported.

263
To mimise the code, use the following to disable support for a specific Capture/Compare/PWM (CCP)
module.

#define USE_HPWMCCP1 FALSE


#define USE_HPWMCCP2 FALSE
#define USE_HPWMCCP3 FALSE
#define USE_HPWMCCP4 FALSE

To further mimise the code, use the following to disable support for a specific PWM channels. Only
PWM channels 5, 6 and 7 are supported.

#define USE_HPWM5 FALSE


#define USE_HPWM6 FALSE
#define USE_HPWM7 FALSE

To further mimise the code, use the following to disable support for a specific timers.

#define USE_HPWM_TIMER2 TRUE


#define USE_HPWM_TIMER4 TRUE
#define USE_HPWM_TIMER6 TRUE

Example

This will save 335 bytes of program memory by removing support for CCP1, CCP2 and CCP4.

264
#chip 16f18855,32
#Config FEXTOSC_OFF, RSTOSC_HFINT32
#Config WRT_OFF, CPD_ON, MCLRE_ON

UNLOCKPPS
RC2PPS = 0x0A 'RC2->CCP2:CCP2;
LOCKPPS

#define USE_HPWMCCP1 FALSE ' This is not used so optimise


#define USE_HPWMCCP2 TRUE ' This is used so include in the compiled code
#define USE_HPWMCCP3 FALSE ' This is not used so optimise
#define USE_HPWMCCP4 FALSE ' This is not used so optimise

'Setting the port an output is VERY important... LED will not work if you do not set
as an output.
dir portC.2 out ; CCP2

do forever
For Bright = 1 to 255
HPWM 2, 40, Bright
wait 10 ms
next

loop

265
Random Numbers
This is the Random Numbers section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Overview

Introduction:

These routines allow Great Cow BASIC to generate pseudo-random numbers.

The generator uses a 16 bit linear feedback shift register to produce pseudo-random numbers. The
most significant 8 bits of the LFSR are used to provide an 8 bit random number.

When compiling a program, Great Cow BASIC will generate an initial seed for the generator. However,
this seed will be the same every time the program runs, so the sequence of numbers produced by a
given program will always be the same. To work around this, there is a Randomize subroutine. It can
be provided with a new seed for the generator (which will cause the generator to move to a different
point in the sequence). Alternatively, Randomize can be set to obtain a seed from some other source
such as a timer every time it is run.

Relevant Constants:

These constants are used to control settings for the random number generation. To set them, place a
line in the main program file that uses #define to assign a value to the particular constant.

Constant Name Controls Default


Value

RANDOMIZE_SEE Source of the random seed if Randomize is called without a Timer0


D parameter

Example:

#define RANDOMIZE_SEED Timer2

Random

Syntax:

var = Random

Command Availability:

Available on all microcontrollers

266
Explanation:

The Random function will generate a pseudo-random number between 0 and 255 inclusive.

The numbers generated by Random will follow the same sequence every time, until Randomize is used.

Example:

'Set chip model


#chip tiny2313, 1

'Use randomize, with the value on PORTD as the seed


Randomize PORTD

'Generate random numbers, and output on PORTB


Do
PORTB = Random
Wait 1 s
Loop

Randomize

Syntax:

Randomize
Randomize seed

Command Availability:

Available on all microcontrollers

Explanation:

Randomize is used to seed the pseudo random number generator, so that it will produce a different
sequence of numbers each time it is used.

If no seed is specified, then the RANDOMIZE_SEED constant will be used as the seed. If seed is specified,
then it will be used to seed the generator.

It is important that the seed is different every time that Randomize is used. If the seed is always the
same, then the sequence of numbers will always be the same. It is best to use a running timer, an input
port, or the analog to digital converter as the source of the seed, since these will normally provide a
different value each time the program runs.

Example:

267
'Set chip model
#chip tiny2313, 1

'Use randomize, with the value on PORTD as the seed


Randomize PORTD

'Generate random numbers, and output on PORTB


Do
PORTB = Random
Wait 1 s
Loop

268
7-Segment Displays
This is the 7-Segment Displays section of the Help file. Please refer the sub-sections for details using
the contents/folder view.

7 Segment Displays Overview

Introduction

The Great Cow BASIC 7 segment display methods make it easier for Great Cow BASIC programs to
display numbers and letters on 7 segment LED displays.

The Great Cow BASIC methods support up to four digit 7 segment display devices, common
anode/cathode and inversion of the port logic to support driving the device(s) via a transistor.

There are three ways that the 7 segment display routines can be set up.

Metho Description
d

1 Connect the microcontroller to the 7 segment display (via suitable resistors) using any eight
output bits. Use DISP_SEG_x and DISP_SEL_x constants to specify the outpout ports and the
select port(s) to be used.

2 Connect the microcontroller to the 7 segment display (via suitable resistors) using whole port
(8 bits) of the microcontroller. This implies the connections are consectutive in terms of the 8
output bits of the port. Use the DISPLAYPORTn and DISPSELECTn constants to specify the whole
port and the select port(s) to be used. This method will generate the most efficient code.

3 Connect the microcontroller to the 7 segment display (via suitable resistors) using whole port
(8 bits) of the microcontroller. This implies the connections are consectutive in terms of the 8
output bits of the port. Use the DISPLAYPORTn and DISP_SEL_n constants to specify the whole
port and the select port(s) to be used.

The Great Cow BASIC methods assume the 7 segment display(s) is to be connected to a common
parallel bus with a Common Cathode. See the sections Common Cathode and Common Anode for
examples of using Great Cow BASIC code to control these different configurations

Shown below are the differing constants that must be set for the three connectivity options.

Ind Method Descr Constants Default Value


ex iptio
n

1 DISP_SEG_x
&
DISP_SEL_x

269
Ind Method Descr Constants Default Value
ex iptio
n

DISP_S Specifies the output pin (output bit) Must be specified to use this
EG_x used to control a specific segment of connectivity option.
the 7 segment display. There are seven
constants that must be specified.
DISP_SEG_A through DISP_SEG_G. One
must be set for each segment. Typical
commands are: #define DISP_SEG_A
portA.0 #define DISP_SEG_B portA.1
#define DISP_SEG_C portA.2 #define
DISP_SEG_D portA.3 #define DISP_SEG_E
portA.4 #define DISP_SEG_F portA.5
#define DISP_SEG_G portA.6
DISP_S Specifies the output pin (output bit) Optional.
EG_DOT used to control the decimal point on
the 7 segment display. Typical
commands are: #define DISP_SEG_DOT
portA.7
DISP_S Specifies the output pin (output bit) A valid output pin (output bit) must be
EL_x used to control a specific 7 segment specified. Must be specified to use
display. These constants are used to this connectivity option.
control the specific 7 segment display
being addresses. Typical commands
are: #define DISP_SEL_1 portA.0
#define DISP_SEL_2 portA.1

2 DISPLAYPOR
Tn &
DISPSELECT
n
DISPLA Specifies the output port used to Can be DISPLAYPORTA and/or
YPORTn control the 7 segment display. Port.bit DISPLAYPORTB and/or DISPLAYPORTC
>> Segment port.0 >> A port.1 >> and/or DISPLAYPORTD Where
B port.2 >> C port.3 >> D port.4 DISPLAYPORTn can be A, B, C or D which
>> E port.5 >> F port.6 >> G corresponding to displays 1, 2, 3 and
4, respectively. Must be specified to
use this connectivity option.

DISPSE Specifies the output command used to Can be DISPSELECTA and/or DISPSELECTB
LECTn select a specific 7 segment display and/or DISPSELECTC and/or DISPSELECTD
addressed by DISPLAYPORT_n. Used to Must be specified to use this
control output pin (output bit) when connectivity option.
several displays are multiplexed.
Typical commands are: #define
DispSelectA Set portA.0 on #define
DispSelectB Set portA.1 on

270
Ind Method Descr Constants Default Value
ex iptio
n

DISPDE An optional command to specify the Can be DISPDESELECTA and/or


SELECT output command used to deselect a DISPDESELECTB and/or DISPDESELECTC
n
specific 7 segment display addressed and/or DISPDESELECTD
by DISPLAYPORT_n. Used to control
output pin (output bit) when several
displays are multiplexed. Typical
commands are: #define
DispDeSelectA Set portA.0 off
#define DispDeSelectB Set portA.1
off

3 DISPLAYPOR
Tn &
DISP_SEL_n
DISPLA Specifies the output port used to Can be DISPLAYPORTA and/or
YPORTn control the 7 segment display. Port.bit DISPLAYPORTB and/or DISPLAYPORTC
>> Segment port.0 >> A port.1 >> and/or DISPLAYPORTD Where
B port.2 >> C port.3 >> D port.4 DISPLAYPORTn can be A, B, C or D which
>> E port.5 >> F port.6 >> G corresponding to displays 1, 2, 3 and
4, respectively. Must be specified to
use this connectivity option.

DISP_S Specifies the output command used to Must be specified to use this
EL_n select a specific 7 segment display connectivity option. Can be specified
addressed by DISPLAYPORTn. Typical as DISP_SEL_1 and/or DISP_SEL_2
commands are: #define DISP_SEL_1 and/or DISP_SEL_3 and/or DISP_SEL_4
portA.0 #define DISP_SEL_2 portA.1

Example 1:

'A Common Cathode 7 Segment display 2 digit example

#chip 16F886, 8

'support for Common Anode


'#define 7Seg_CommonAnode

'support for pfet or pnp high side drivers


'#define 7Seg_HighSide

' ----- Constants


' You need to specify the port settings
' by one of the following three methods
'The Directions of the ports are automaically set according to the defines
'''METHOD 1 Define individual port pins for segments and selects

271
#define DISP_SEG_A PORTB.0
#define DISP_SEG_B PORTB.1
#define DISP_SEG_C PORTB.2
#define DISP_SEG_D PORTB.3
#define DISP_SEG_E PORTB.4
#define DISP_SEG_F PORTB.5
#define DISP_SEG_G PORTB.6
#define DISP_SEG_DOT PORTB.7 '' available on some displays as dp or colon

#define DISP_SEL_1 PORTC.5


#define DISP_SEL_2 PORTC.4

'''METHOD 2 Define DISPLAYPORTA (B,C,D) for up to 4 digit display segments


''Define DISPSELECTA (B,C,D) for up to 4 digit display selects
'#define DISPLAYPORTA PORTB ' same port name can be assigned
'#define DISPLAYPORTB PORTB

'#define DispSelectA Set portC.5 off


'#define DispSelectB Set portC.4 off
'#define DispDeSelectA Set portC.5 on
'#define DispDeSelectB Set portC.4 on

'''METHOD 3 Define DISPLAYPORTA (B,C,D) for up to 4 digit display segments


''Define port pins for the digit display selects
'#define DISPLAYPORTA PORTB
'#define DISPLAYPORTB PORTB

'#define DISP_SEL_1 PORTC.5


'#define DISP_SEL_2 PORTC.4

Dim Message As String


Message = " HAPPY HOLIDAYS "
Do
For Counter = 1 to len(Message)-1
Repeat 50
Displaychar 1, Message(Counter)
wait 3 ms
DisplayChar 2, Message(Counter+1)
wait 3 ms

end Repeat

Wait 100 ms
Next
Loop

272
Also, see DisplayChar, DisplayValue

273
Common Cathode

This is a Common Cathode 7 Segment display example.

No additional configuration is required when using Common Cathnode.

Constant Controls Comment


Name

7Seg_Common Inverts controls for Common Anode Required for Common Cathode displays
Anode displays

7Seg_HighSi Support PFET or PNP high side Inverts Common Cathode addressing pin logic for
de driving of the display multiplexed displays

This is a Common Cathode 7 Segment display example.

Example:

'Chip model
#chip 16f1783,8

'Output ports for the 7-segment device


#define DISP_SEG_A PORTC.0
#define DISP_SEG_B PORTC.1
#define DISP_SEG_C PORTC.2
#define DISP_SEG_D PORTC.3
#define DISP_SEG_E PORTC.4
#define DISP_SEG_F PORTC.5
#define DISP_SEG_G PORTC.6

' This is the usage of the SEG_DOT for decimal point support
' An optional third parameter of '1' will turn on the decimal point
' of that digit when using DisplayValue command
#define DISP_SEG_DOT PortC.7

'Select ports for the 7-segment device


#define Disp_Sel_1 PortA.1
#define Disp_Sel_2 PortA.2
#define Disp_Sel_3 PortA.3

dim count as word


dim number as word

Do Forever
For count = 0 to 999
number = count
Num2 = 0

274
Num3 = 0
If number >= 100 Then
Num3 = number / 100
'SysCalcTempX is the remainder after a division has been completed
number = SysCalcTempX
End if
If number >= 10 Then
Num2 = number / 10
number = SysCalcTempX
end if
Num1 = number
Repeat 10
DisplayValue 1, Num1,1 'Optional third parameter turns on the dp dot on
that digit
wait 5 ms
DisplayValue 2, Num2
wait 5 ms
DisplayValue 3, Num3
wait 5 ms

end Repeat
Next
Loop

Also, see 7 Degment Display Overview, DisplayChar, DisplayValue

Common Anode

This is a Common Anode 7 Segment display example.

Additional configuration is required when using Common Anode.

When setting up the 7 segment Common Anode display you MUST use the 7Seg_CommonAnode constant.
You can optionally use the 7Seg_HighSide constant to support PFET or PNP high side driving of the
Common Anode displays as follows:

Constant Controls Comment


Name

7Seg_Common Inverts controls for Common Anode Required for Common Cathode displays
Anode displays

7Seg_HighSi Support PFET or PNP high side Inverts Common Cathode addressing pin logic for
de driving of the display multiplexed displays

Example:

'A Common Anode 7 Segment display example using bs250p pfets

275
'Chip model
#chip 16f1783,8

'support for Common Cathode


#define 7Seg_CommonAnode

'support for pfet or pnp high side drivers


#define 7Seg_HighSide

#define DISP_SEG_A PORTC.0


#define DISP_SEG_B PORTC.1
#define DISP_SEG_C PORTC.2
#define DISP_SEG_D PORTC.3
#define DISP_SEG_E PORTC.4
#define DISP_SEG_F PORTC.5
#define DISP_SEG_G PORTC.6
#define DISP_SEG_DOT PORTC.7

#define Disp_Sel_1 PortA.1


#define Disp_Sel_2 PortA.2
#define Disp_Sel_3 PortA.3

dim count as word


dim number as word

Do Forever
For count = 0 to 999
number = count
Num2 = 0
Num3 = 0
If number >= 100 Then
Num3 = number / 100
'SysCalcTempX is the remainder after a division has been completed
number = SysCalcTempX
End if
If number >= 10 Then
Num2 = number / 10
number = SysCalcTempX
end if
Num1 = number
Repeat 10
DisplayValue 1, Num1, 1 'Optional third parameter turns on the dp on that
digit
wait 5 ms
DisplayValue 2, Num2
wait 5 ms
DisplayValue 3, Num3
wait 5 ms

276
end Repeat
Next
Loop

Also, see 7 Degment Display Overview, DisplayChar, DisplayValue

DisplayValue

Syntax:

DisplayValue (display, data, dot)

Command Availability:

Available on all microcontrollers.

Explanation:

This command will display the given value on a seven segment LED display.

display is the number of the display to use. Up to 4 digits.

data is the value between 0 and F to be shown.

dot is an optional parameter. When it is 1 then the decimal point for that digit is turned on.

The command also support HEX characters in the range between 0x00 and 0x0F (0 to 15). See example
two below for usage.

Example 1:

277
'This program will count from 0 to 99 on two LED displays
#chip 16F819, 8
#config osc = int

'See 7 Segment Display Overview for alternate ways of defining Ports


#define DISP_SEG_A PORTB.0
#define DISP_SEG_B PORTB.1
#define DISP_SEG_C PORTB.2
#define DISP_SEG_D PORTB.3
#define DISP_SEG_E PORTB.4
#define DISP_SEG_F PORTB.5
#define DISP_SEG_G PORTB.6
'#define DISP_SEG_DOT PORTB.7 ' Optional DP

#define DISP_SEL_1 PORTA.0


#define DISP_SEL_2 PORTA.1

Do
For Counter = 0 To 99

'Get the 2 digits


Number = Counter
Num1 = 0
If Number >= 10 Then
Num1 = Number / 10
'SysCalcTempX stores remainder after division
Number = SysCalcTempX
End If
Num2 = Number

'Show the digits


'Each DisplayValue will erase the other (multiplexing)
'So they must be called often enough that the flickering
'cannot be seen.
Repeat 500
DisplayValue 1, Num1
Wait 1 ms
DisplayValue 2, Num2
Wait 1 ms
End Repeat
Next
Loop

Example 2:

278
'This program will count from 0 to 0xff on two LED displays
#chip 16F819, 8
#config osc = int

#define DISP_SEG_A PORTB.0


#define DISP_SEG_B PORTB.1
#define DISP_SEG_C PORTB.2
#define DISP_SEG_D PORTB.3
#define DISP_SEG_E PORTB.4
#define DISP_SEG_F PORTB.5
#define DISP_SEG_G PORTB.6

#define DISP_SEL_1 PORTA.0


#define DISP_SEL_2 PORTA.1
#define DISP_SEL_4 PORTA.2
#define DISP_SEL_3 PORTA.3

Do
For Counter = 0 To 0xff

'Get the 2 digits


Number = Counter
Num1 = 0
If Number >= 0x10 Then
Num1 = Number / 0x10
'SysCalcTempX stores remainder after division
Number = SysCalcTempX
End If
Num2 = Number

'Show the digits


'Each DisplayValue will erase the other (multiplexing)
'So they must be called often enough that the flickering
'cannot be seen.
Repeat 500
DisplayValue 1, Num1
Wait 1 ms
DisplayValue 2, Num2
Wait 1 ms
End Repeat
Next
Loop

Also, see 7 Segment Display Overview, DisplayChar, DisplaySegment

279
DisplayChar

Syntax:

DisplayChar (display, character, dot)

Command Availability:

Available on all microcontrollers.

Explanation:

This command will display the given ASCII character on a seven segment LED display.

display is the number of the display to use. Up to 4 digits.

character is the ASCII character to be shown.

dot is an optional parameter. When it is 1 then the decimal point for that digit is turned on.

This example below is a Common Cathode configuration.

Example 1:

'This program will show " Hello " on a LED display


'The display should be connected to PORTB and the Enable on PORTA.0

#chip 16F877A, 20

#define DISPLAYPORTA PORTB


#define DISP_SEL_1 PORTA.0

Dim Message As String


Message = " Hello "
Do
For Counter = 1 to len(Message)
DisplayChar 1, Message(Counter)
Wait 250 ms
Next
Loop

This is a Common Anode example There are three different methods for port specification Note the
ports are specified bit by bit in this case but could be specified like Example 1 See Overview for further
explanation.

280
Example 2:

'This program will show amessage on a LED display


'This is a Dual digit Common anode with driver transistors example
#chip 16F886, 8

'support for Common Anode


#define 7Seg_CommonAnode

'support for pfet or pnp high side drivers


#define 7Seg_HighSide

' Constants
' You need to specify the port settings
#define DISP_SEG_A PORTB.0
#define DISP_SEG_B PORTB.1
#define DISP_SEG_C PORTB.2
#define DISP_SEG_D PORTB.3
#define DISP_SEG_E PORTB.4
#define DISP_SEG_F PORTB.5
#define DISP_SEG_G PORTB.6

#define DISP_SEL_1 PORTC.5


#define DISP_SEL_2 PORTC.4

Dim Message As String


Message = " Happy Holidays "
Do
For Counter = 1 to len(Message)-2
Repeat 50
Displaychar 1, Message(Counter)
wait 3 ms
DisplayChar 2, Message(Counter+1)
wait 3 ms
end Repeat
Wait 100 ms
Next
Loop

Also, see 7 Degment Display Overview, DisplayValue, DisplaySegment

DisplaySegment

Syntax:

281
DisplayValue (display, data)

Command Availability:

Available on all microcontrollers.

Explanation:

This command will display the given value on a seven segment LED display.

display is the number of the display to use. Up to 4 digits.

data is the value between 0 and 255. Where data is the representation of the segments to be set.

Example

'This program will count from 10 to 0 then fire the rocket!


'The method DisplaySegment 1, smallTCharacter. Sets the 7 segment to the value of
120, see the constant, 120 equates to a small t.
; ----- Configuration

#chip 16F690, 4
#config WDT_OFF

; ----- Define Hardware settings


Dir PORTC Out
DIR PORTA.5 out
DIR PORTA.4 out
DIR PORTA.0 out
DIR PORTA.1 out
DIR PORTA.2 in
DIR PORTB.7 out
; ----- Constants
; You need to specify the port settings
#define DISP_SEG_A PORTC.0
#define DISP_SEG_B PORTC.1
#define DISP_SEG_C PORTC.2
#define DISP_SEG_D PORTC.3
#define DISP_SEG_E PORTC.4
#define DISP_SEG_F PORTC.5
#define DISP_SEG_G PORTC.6
#define DECPNT PORTC.7
#define DISP_SEL_1 PORTA.5
#define DISP_SEL_2 PORTA.4
#define DISP_SEL_3 PORTA.1
#define DISP_SEL_4 PORTA.0

282
#define smallTCharacter 120 'raw character for 't' on 7 segment.

#define sw1 PORTA.2

#define firingPort PORTB.7

; ----- Variables
CountDownValue = 10

; ----- Main body of program commences here.


DECPNT = 1 'Decimal Point off

Main:
' Push number to 7 Segment Display
if sw1 = 0 then goto Countdown

num2 = 1
num3 = 0
cnt = 5
gosub display

goto main

Countdown:

num2 = CountDownValue/10
num3 = CountDownValue%10
cnt = 60

gosub display

If sw1 = 0 then goto hld

if CountDownValue = 0 then
firingPort = 1
cnt = 200
gosub dispfire
firingPort = 0
CountDownValue = 10
goto main
end if

CountDownValue = CountDownValue - 1

goto Countdown

283
display:
Repeat cnt
DisplaySegment 1, smallTCharacter
wait 5 ms
Displaychar 2, "-"
DisplayValue 3, Num2
wait 5 ms
DisplayValue 4, Num3
wait 5 ms
end Repeat

return

hld:
if sw1 = 0 then goto hld
cnt = 5
gosub Display
if sw1 = 1 then goto hld
goto countdown

DispFire:
Repeat cnt

Displaychar 1, "F"
wait 5 ms
Displaychar 2, "i"
wait 5 ms
Displaychar 3, "r"
wait 5 ms
Displaychar 4, "E"
wait 5 ms
End Repeat
return

end

Also, see 7 Segment Display Overview, DisplayChar

284
One Wire Devices
This is the One Wire Devices section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

DS18B20

The DS18B20 is a 1-Wire digital temperature sensor from Maxim IC.

The sensor reports degrees C with 9 to 12-bit precision from -55C to 125C (+/- 0.5C).

Each sensor has a unique 64-Bit Serial number etched into it. This allows for a number of sensors to be
used on one data bus. This sensor is used in many data-logging and temperature control projects.

Reading the temperature from a DS18B20 takes up to 750ms.

To use the DS18B20 driver the following is required to added to the Great Cow BASIC source file.

#include <DS18B20.h>

Note the Great Cow BASIC commands do not work with the older DS1820 or DS18S20 as they have a
different internal resolution.

These commands are not designed to be used with parasitically powered DS18B20 sensors.

ReadDigitalTemp

Syntax:

ReadDigitalTemp

Command Availability:

Available on all microcontrollers.

Explanation:

Return the value of the sensor in two global variables. The following two lines must be included in the
Great Cow BASIC source file.

#include <DS18B20.h>
#define DQ PortC.3 ; change port configuration as required

This method returns whole part of the sensor value in the byte variable DSint, the method also returns

285
decimal part of the sensor value in the byte variable DSdec.

Example:

'Chip Settings. Assumes the development board with with a 16F877A


#chip 16F877A,1

*#include <DS18B20.h>*

'Use LCD in 4 pin mode and define LCD pins


#define LCD_IO 4
#define LCD_RW PORTE.1
#define LCD_RS PORTE.0
#define LCD_Enable PORTE.2
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7

' DS18B20 port settings


#define DQ PortC.3

ReadDigitalTemp

' Display the integer value of the sensor on the LCD


locate 0,0
print "Temp"
locate 0,8
print DSInt
print "."
print DSdec
print chr(223)+"C"

ReadTemp

Syntax:

byte_var = ReadTemp

Command Availability:

Available on all microcontrollers.

Explanation:

286
ReadTemp is a function that returns the raw value of the sensor. The following two lines must be
included in the Great Cow BASIC source file.

#include <DS18B20.h>
#define DQ PortC.3 ; change port configuration as required

ReadTemp reads the sensor and stores in output variable. The conversion takes up to 750ms. Readtemp
carries out a full 12 bit conversion and then rounds the result to the nearest full degree Celsius.

To read the full 12 bit value of the sensor use the readtemp12 command.

The temperature is read back in whole degree steps, and the sensor operates from -55 to + 125 degrees
Celsius. Note that bit 7 is 0 for positive temperature values and 1 for negative values (ie negative values
will appear as 128 + numeric value).

Note the Readtemp command does not work with the older DS1820 or DS18S20 as they have a different
internal resolution. This command is not designed to be used with parasitically powered DS18B20
sensors, the 5V pin of the sensor must be connected.

Example:

287
'Chip Settings. Assumes the development board with with a 16F877A
#chip 16F877A,1

#include <DS18B20.h>

'Use LCD in 4 pin mode and define LCD pins


#define LCD_IO 4
#define LCD_RW PORTE.1
#define LCD_RS PORTE.0
#define LCD_Enable PORTE.2
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7

' DS18B20 port settings


#define DQ PortC.3

ccount = 0
CLS

do forever
' The function readtemp returns the integer value of the sensor
DSdata = readtemp

' Display the integer value of the sensor on the LCD


locate 0,0
print hex(ccount)
print " Ceil"
locate 0,8
print DSdata
print chr(223)+"C"

wait 2 s
ccount++

loop

ReadTemp12

Syntax:

byte_var = ReadTemp12

Command Availability:

288
Available on all microcontrollers.

Explanation:

ReadTemp12 is a function that returns the raw value of the sensor. The following two lines must be
included in the Great Cow BASIC source file.

#include <DS18B20.h>
#define DQ PortC.3 ; change port configuration as required

Reads sensor and stores in output variable. The conversion takes up to 750ms. Readtemp12 carries out a
full 12 bit conversion.

This command is for advanced users only. For standard ‘whole degree’ data use the Readtemp command.

The temperature is read back as the raw 12 bit data into a word variable (0.0625 degree resolution).
The user must interpret the data through mathematical manipulation. See the DS18B20 datasheet for
more information on the 12 bit temperature/data information construct.

The function readtemp12 does not work with the older DS1820 or DS18S20 as they have a different
internal resolution. This command is not designed to be used with parasitically powered DS18B20
sensors, the 5V pin of the sensor must be connected.

Example:

'Chip Settings. Assumes the development board with with a 16F877A


#chip 16F877A,1

#include <DS18B20.h>

'Use LCD in 4 pin mode and define LCD pins


#define LCD_IO 4
#define LCD_RW PORTE.1
#define LCD_RS PORTE.0
#define LCD_Enable PORTE.2
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7

' DS18B20 port settings


#define DQ PortC.3
dim TempC_100 as word ' a variable to handle the temperature calculations
ccount = 0
CLS

289
do forever

'Display the integer and decimal value of the sensor on the LCD

' The function readtemp12 returns the raw value of the sensor.
' The sensor is read as a 12 bit value. Each unit equates to 0.0625 of a degree
DSdata = readtemp12
SignBit = DSdata / 256 / 128
If SignBit = 0 Then goto Positive
' its negative!
DSdata = ( DSdata # 0xffff ) + 1 ' take twos comp

Positive:

' Convert value * 0.0625. Mulitple value by 6 then add result to multiplication of
the value with 25 then divide result by 100.
TempC_100 = DSdata * 6
DSdata = ( DSdata * 25 ) / 100
TempC_100 = TempC_100 + DSdata

Whole = TempC_100 / 100


Fract = TempC_100 % 100
If SignBit = 0 Then goto DisplayTemp
Print "-"

DisplayTemp:
locate 1,0
print hex(ccount)
print " Real"
locate 1,8
print str(Whole)
print "."
' To ensure the decimal part is two digits
Dig = Fract / 10
print Dig
Dig = Fract % 10
print Dig
print chr(223)
print "C"
wait 2 s
ccount++

loop

290
Serial Communications
This is the Serial Communications section of the Help file. Please refer the sub-sections for details
using the contents/folder view.

RS232 (software)

This is the Software Serial Communications section of the Help file. Please refer the sub-sections for
details using the contents/folder view.

RS232 Software Overview

Introduction:

These routines allow the microcontroller to send and receive RS232 data.

All functions are implemented using software, so no special hardware is required on the
microcontroller. However, if the microcontroller has a hardware serial module (usually referred to as
UART or USART), and the serial data lines are connected to the appropriate pins, the hardware routines
should be used for smaller code, improved reliability and higher baud rates.

Relevant Constants:

These constants are used to control settings for the RS232 serial communication routines. To set them,
place a line in the main program file that uses #define to assign a value to the particular constant.

Constant Name/s Controls Default Value

SendALow, SendBLow, These are used to define the commands used to send a low No Default
SendCLow (0) bit on serial channels A, B and C respectively. Must be defined

SendAHigh, These are used to define the commands used to send a high No Default
SendBHigh, (1) bit on serial channels A, B and C respectively. Must be defined
SendCHigh

RecALow, RecBLow, The condition that is true when a low bit is being received Sys232Temp.0 OFF
RecCLow Must be defined

RecAHigh, RecBHigh, The condition that is true when a high bit is being received Sys232Temp.0 ON
RecCHigh Must be defined

InitSer

Syntax:

InitSer channel, rate, start, data, stop, parity, invert

Command Availability:

291
Available on all microcontrollers.

Explanation:

This command will set up the serial communications. The parameters are as follows:

channel is 1, 2 or 3, and refers to the I/O ports that are used for communication.

rate is the bit rate, which is given by the letter r and then the desiredrate in bps. Acceptable units are
r300, r600, r1200, r2400, r4800, r9600 and r19200.

start gives the number of start bits, which is usually 1. To make the microcontroller wait for the start
bit before proceeding with the receive, add 128 to start. (Note: it may be desirable to use the
WaitForStart constant here.)

data tells the program how many data bits are to be sent or received. In most situations t his is 8, but it
can range between 1 and 8, inclusive.

stop is the number of stop bits. If start bit 7 is on, then this number will be ignored.

parity refers to a system of error checking used by many devices. It can be odd (in which there must
always be an odd number of high bits), even (where the number of high bits must always be even), or
none (for systems that do not use parity).

invert can be either "normal" or "invert". If it in "invert", then high bits will be changed to low, and low
to high.

Example:

Please refer to SerSend for an example of InitSer

For more help, see RS232 Software Overview

SerSend

Syntax:

SerSend channel, data

Command Availability:

Available on all microcontrollers.

Explanation:

This command will send a byte given by data using the RS232 channel referred to as channel according
to the rules set using InitSer.

292
Example:

'This program will send a byte using PORTB.2, the value of which
'depends on whether a button is pressed. This can be used with the example for
SerReceive.

#chip 16F819, 8
#config Osc = Int

#define RS232Out PORTB.2


#define RS232In PORTB.1

Dir RS232Out Out


Dir RS232In In

'Config Software-UART
#define SendAHigh Set RS232Out ON
#define SendALow Set RS232Out OFF
#define RecAHigh Set RS232In ON
#define RecALow Set RS232In OFF

Dir Button In

InitSer 1, r9600, 1+WaitForStart, 8, 1, none, normal


Do
If Button = On Then Temp = 100
If Button = Off Then Temp = 0
SerSend 1, Temp
Wait 100 ms
Loop

For more help, see RS232 Software Overview, InitSer

SerReceive

Syntax:

SerReceive channel, output

Command Availability:

Available on all microcontrollers.

Explanation:

This command will read a byte from the RS232 channel given by channel according to the rules set

293
using InitSer, and store the received byte in the variable output.

Example:

'This program will read a byte from PORTB.2, and set the LED on if
'the byte is more than 50. This can be used with the SerSend
'example program.

#chip 16F88, 8
#config Osc = Int

#define RecAHigh PORTB.2 ON


#define RecALow PORTB.2 OFF
#define LED PORTB.0

Dir PORTB.0 Out


Dir PORTB.2 In

InitSer 1, r9600, 1 + WaitForStart, 8, 1, none, normal


Do
SerReceive 1, Temp
If Temp <= 50 Then Set LED Off
If Temp > 50 Then Set LED On
Loop

For more help, see RS232 Software Overview, InitSer

SerPrint

Syntax:

SerPrint channel, value

Command Availability:

Available on all microcontrollers.

Explanation:

SerPrint is used to send a value over the serial connection. value can be a string, integer, long, word or
byte.

channel is the serial connection to send data through (1 | 2 |3 ).

SerPrint will not send any new line characters. If the chip is sending to a terminal, these commands
should follow SerPrint.

294
SerSend channel, 13
SerSend channel, 10

Example:

'This program will display any values received over the serial
'connection. If "pot" is received, the value of the analog sensor
'will be sent.

'Chip settings
#chip 18F2525, 8
#config Osc = Int

'LCD settings
#define LCD_IO 4
#define LCD_RS PORTC.7
#define LCD_RW PORTC.6
#define LCD_Enable PORTC.5
#define LCD_DB4 PORTC.4
#define LCD_DB5 PORTC.3
#define LCD_DB6 PORTC.2
#define LCD_DB7 PORTC.1

'Serial settings
#define RS232Out PORTB.0
#define RS232In PORTB.1

'Set pin direction


Dir RS232Out Out
Dir RS232In In

'Config Software-UART
#define SendAHigh Set RS232Out ON
#define SendALow Set RS232Out OFF
#define RecAHigh Set RS232In ON
#define RecALow Set RS232In OFF
set RS232Out On

Do
'Potentiometer
#define POT_PORT PORTA.0
#define POT_AN AN0

'Set pin direction


Dir POT_PORT In

295
'Create buffer variables to store received messages
Dim Buffer As String
Dim OldBuffer As String
BufferSize = 0

'Set up serial connection


InitSer 1, r9600, 1 + WaitForStart, 8, 1, none, invert

'Show test messages


Print "Serial Tester"
Wait 1 s
SerPrint 1, "GCBASIC RS232 Test"
SerSend 1, 13
SerSend 1, 10
Wait 1 s

'Main loop
'Get a byte from the terminal
SerReceive 1, Temp

'If Enter key was pressed, deal with buffer contents


If Temp = 13 Then
Buffer(0) = BufferSize

'Try to execute commands in buffer


If Not ExecCommand (Buffer) Then
'Show message on bottom line, last message on top.
CLS
Print OldBuffer
Locate 1, 0
Print Buffer
'Store the message for next time
OldBuffer = Buffer
End If

BufferSize = 0
End If
'Backspace code, delete last character in buffer
If Temp = 8 Then
If BufferSize > 0 Then BufferSize -= 1
End If
'Received ASCII code between 32 and 127, add to buffer
If Temp >= 32 And Temp <= 127 Then
BufferSize += 1
Buffer(BufferSize) = Temp
End If
Loop

296
'Takes a sensor reading and sends it to terminal
Sub SendSensorReading
SerPrint 1, "Sensor Reading: "
SerPrint 1, ReadAD10(POT_AN)
SerSend 1, 13
SerSend 1, 10
End Sub

'Will check the buffer for a command


'If command found, run it and return true
'If not, return false
Function ExecCommand (CmdIn As String)
ExecCommand = False
'If received command is "pot", show potentiometer value
If CmdIn = "pot" Then
SendSensorReading
ExecCommand = True
End If
End Function

For more help, see RS232 Software Overview

297
RS232 (software optimised)

This is the Software Serial Communications section of the Help file. Please refer the sub-sections for
details using the contents/folder view.

RS232 Software Overview - Optimised

Introduction:

These routines allow the microcontroller to send and receive RS232 data.

SoftSerial is a library for the Creat Cow BASIC compiler and works on AVR and PIC microcontrollers.
These routines allow the microcontroller to send and receive RS232 data. All functions are
implemented using software, so no special hardware is required on the microcontroller. SoftSerial
uses ASM routines for minimal overhead. If the microcontroller has a hardware serial module (usually
referred to as UART or USART) the hardware routines can be used too.

Features

• 3 independent channels Ser1… , Ser2… , Ser3…

• I/O pins user configurable

• polarity can be inverted

• freely adjustable baud rate

• maximum baudrate depends on MCU speed

◦ PIC@ 1Mhz 9600 baud

◦ PIC@ 4Mhz 38400 baud

◦ PIC@ 8Mhz 64000 baud

◦ PIC@16Mhz 128000 baud

◦ AVR@ 1Mhz 28800 baud

◦ AVR@ 8Mhz 115200 baud

◦ AVR@16Mhz 460800 baud

• 5 - 8 data bits

• 1 or 2 stop bits

• parity bit not supported

Relevant Constants:

These constants are used to control settings for the RS232 serial communication routines. To set them,
place a line in the main program file that uses #define to assign a value to the particular constant.

298
Constant Name/s Controls Default value SER1_TXPORT,
Valid SER2_TXPORT,
Values SER3_TXPORT

These are used to define the port for PORTA - No Default Must SER1_TXPIN,
sending on serial channels 1, 2 and 3 PORTx be defined for SER2_TXPIN,
respectively. Note, that we also have to sending SER3_TXPIN
define a PortPin (see next line). It is not
necessary to define this, if we want to
receive only. Sample: #define
SER1_TXPORT PortB

These are used to define the pin (the 0-7 No Default Must SER1_RXPORT,
corresponding bit) for sending on serial be defined for SER2_RXPORT,
channels 1, 2 and 3 respectively. Sample: sending SER3_RXPORT
#define SER1_TXPIN 0

These are used to define the port for PORTA - Must be defined SER1_RXPIN,
receiving on serial channels 1, 2 and 3 PORTx No for receiving SER2_RXPIN,
respectively. Note, that we also have to Default SER3_RXPIN
define a PortPin (see next line). It is not
necessary to define this, if we want to
receive only. Sample: #define
SER1_RXPORT PortA

These are used to define the pin (the 0-7 No Default Must SER1_BAUD,
corresponding bit) for receiving on serial be defined for SER2_BAUD,
channels 1, 2 and 3 respectively. It is not receiving SER3_BAUD
necessary to define this, if we want to send
only. Sample: #define SER1_RXPIN 5

These are used to define the baudrate for 75 - 512000 No Default Must SER1_DATABITS,
sending and receiving on serial channels 1, be defined SER2_DATABITS,
2 and 3 respectively. It is not necessary to SER3_DATABITS
define this, if we want to send only. Sample:
#define SER1_BAUD 19200

These are used to define the databits for 5-8 Optional Default SER1_STOPBITS,
sending and receiving on serial channels 1, =8 SER2_STOPBITS,
2 and 3 respectively. Sample: #define SER3_STOPBITS
SER1_DATABITS 7

These are used to define the stopbits for 1, 2 Optional Default SER1_INVERT,
sending and receiving on serial channels 1, =1 SER2_INVERT,
2 and 3 respectively. Sample: #define SER3_INVERT
SER1_STOPBITS 2

299
Constant Name/s Controls Default value SER1_TXPORT,
Valid SER2_TXPORT,
Values SER3_TXPORT

These are used to define the polarity for On, Off Optional Default SER1_RXNOWAIT,
sending and receiving on serial channels 1, = Off SER2_RXNOWAIT,
2 and 3 respectively. If it is "On", then high SER3_RXNOWAIT
bits will be changed to low, and low to high.
This is useful for connection to a PCs native
serial port or USB-serial converters with
MAX232. Sample: #define SER1_INVERT On

SerNSend

Ser1Send, Ser2Send, Ser3Send

Syntax:

Ser1Send data
Ser2Send data
Ser3Send data

Command Availability:

Available on all microcontrollers.

Explanation:

This command will send a byte given by data using the channel referred to as Ser1.. , Ser2… , Ser3…
according to the rules set by the related defines.

Example:

300
'This program will send one byte using PORTA.5

; ----- Configuration
#chip 12F1501, 1

; ----- Include library


#include <SoftSerial.h>

; ----- Config Serial UART for sending:


#define SER1_BAUD 9600 ; baudrate must be defined
#define SER1_TXPORT PORTA ; I/O port (without .bit) must be defined
#define SER1_TXPIN 5 ; portbit must be defined

; ----- Main body of program commences here.


Ser1Send 88 'send one byte (88 = X)

Exposed in SoftSerial.h authored by Frank Steinberg

SerNPrint

Ser1Print, Ser2Print, Ser3Print

Syntax:

Ser1Print value
Ser2Print value
Ser3Print value

Command Availability:

Available on all microcontrollers.

Explanation:

This command will send a value using the channel referred to as Ser1.. , Ser2… , Ser3… according to the
rules set by the related defines. value can be a string, integer, long, word or byte.

Example:

301
'This program will send text and an icrementing value using PORTB.1

; ----- Configuration
#chip 16F886, 16
#option Explicit

; ----- Include library


#include <SoftSerial.h>

; ----- Config Serial UART :


#define SER1_BAUD 115200 ; baudrate must be defined
; Config I/O ports for transmitting:
#define SER1_TXPORT PORTB ; I/O port (without .bit) must be defined
#define SER1_TXPIN 1 ; portbit must be defined

; ----- Variables
Dim xx As Word
xx = 1000

; ----- Main body of program commences here.


Do Forever
Wait 1 s 'time to enjoy the result
Ser1Send 13 'new line in Terminal
Ser1Send 10
Ser1Print "Software-UART: " 'send a text
Ser1Print xx 'send the value of xx
xx += 1
Loop

Exposed in SoftSerial.h authored by Frank Steinberg

SerNReceive

Ser1Receive, Ser2Receive, Ser3Receive

Syntax:

bytevar = Ser1Receive
bytevar = Ser2Receive
bytevar = Ser3Receive

Command Availability:

Available on all microcontrollers.

Explanation:

302
This function will read a byte using the channel referred to as Ser1.. , Ser2… , Ser3… according to the
rules set by the related defines. The received byte is stored in the variable bytevar. By default the
function waits for the startbit impulse edge before executing the following commands. See the sample
files how to realize timeout-functionality or interrupt-driven receiving.

Example:

'This program will receive bytes on PORTB.0 and send back using PORTB.1

; ----- Configuration
#chip 16F886, 16
#option Explicit

; ----- Include library


#include <SoftSerial.h>

; ----- Config Serial UART :


#define SER1_BAUD 115200 ; baudrate must be defined
#define SER1_DATABITS 7 ; databits optional (default = 8)
#define SER1_STOPBITS 2 ; stopbits optional (default = 1)
#define SER1_INVERT Off ; inverted polarity optional (default = Off)
; Config I/O ports for transmitting:
#define SER1_TXPORT PORTB ; I/O port (without .bit) must be defined
#define SER1_TXPIN 1 ; portbit must be defined
; Config I/O ports for receiving:
#define SER1_RXPORT PORTB ; I/O port (without .bit) must be defined
#define SER1_RXPIN 0 ; portbit must be defined
#define SER1_RXNOWAIT Off ; don't wait for stopbit optional (default = Off)

; ----- Variables
Dim RecByte As Byte

; ----- Main body of program commences here.


Wait 1 Ms 'delay to prevent garbage if sending too quick after init
Ser1Send 10 'new line in Terminal
Ser1Send 13 '
Ser1Print "Please send a byte!"

Do Forever
RecByte = Ser1Receive 'receive one byte - wait until detecting startbit
Ser1Send 13 'new line in Terminal
Ser1Send 10 '
Ser1Print "You sent: " 'send a text
Ser1Send RecByte 'send the sign representing the byte
Loop

303
Exposed in SoftSerial.h authored by Frank Steinberg

304
RS232 (hardware)

This is the RS232 (hardware) section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

RS232 Hardware Overview

Introduction

Great Cow BASIC support programs to communicate easily using RS232.

Great Cow BASIC included microcontroller hardware-based serial routines are intended for use on
microcontrollers with built in serial communications modules - normally referred to in datasheets as
USART or UART modules. Check the microcontroller data sheet for the defined transmit and receive
(TX/Rx) pins. Make sure your program sets the Tx pin direction to Out and the Rx pin direction to In
respectively. If the RS232 lines are connected elsewhere, or the microcontroller has no USART module,
then the Great Cow BASIC software based RS232 routines must be used.

Initialization of the USART module is handled automatically from your program by defining the chip,
speed, and the baudrate. The baudrate generator values are calculated and set, usart is set to
asynchronous, usart is enabled , the receive and transmit are enabled. See the table below.

Example:

#chip mega328p, 16
#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

Command Availability:

Available on all microcontrollers with a USART or UART module.


Microchip PIC supports USART1 and 2.
Atmel AVR supports USART 1,2,3 and 4.

The following table explains the methods that can be implemented when using the Great Cow BASIC
serial routines.

Commands:

Command Parameters Example

Serially print numbers (byte,


word, long) or strings.

305
Command Parameters Example

HSerPrint Number_constant or This subroutine prints a variable


number_variable or string value to usart 1. No additional
[,optional usart address] The parameter for the usart number
optional usart address is is used. HSerprint ( mynum ) To
microcontroller specific buy can print a variable value to usart 2.
be 1, 2, 3 or 4. Note the additional parameter
for the usart address. HSerprint (
mynum, 2 )

Serially receive ascii number


characters and assign to a word
variable

HSerGetNum Number_variable [,optional This subroutine ensures that the


usart address] The optional characters received are
usart address is microcontroller numbers. When a carriage
specific buy can be 1, 2, 3 or 4. return (CR or ASCII code 13) is
received this signifies the end of
the character stream. Defaults to
usart1. To receive number
characters use. HSerGetNum (
mynum ) To receive number
characters via usart2 use.
HSerGetNum ( mynum, 2 )

Serially receive characters as a


string.

HSerGetString User_string_variable [,optional This subroutine ensures that the


usart address] The optional characters treated as a string.
usart address is microcontroller When a carriage return (CR or
specific buy can be 1, 2, 3 or 4. ASCII code 13) is received this
signifies the end of the character
stream. Great Cow BASIC will
determine the default buffering
size for strings. See here for
more help on string sizes.
Defaults to usart1. To receive a
string use.
HserGetString ( mystring ) To a
string via usart2 use.
HserGetString ( mystring, 2 )

Serially receive a character


using a subroutine.

306
Command Parameters Example

HSerReceive byte_variable This subroutine handles the


incoming characters as raw
ASCII values. The subroutine
receives a single byte value in
the range of 0 to 255. The
subroutine can receive a byte
from usart 1, 2, 3 or 4. The public
variable comport can be set
before the use of this method to
select the desired usart address.
If ‘#define USART_BLOCKING’ is
defined then this methods will
wait until it a byte is received. If
‘#define USART_BLOCKING’ is
NOT defined then the method
will returns ASCII value received
or the method will return the
value of 255 to indicate not
ASCII data was received. You
can change the value returned
by setting redefining ‘#define
DefaultUsartReturnValue = [0-
255]’. When ‘#define
USART_BLOCKING’ is NOT
defined this method becomes a
non- blocking method which
allows for the testing and
handling of incoming ASCII data
within the user program. To
receive an ASCII byte value in
blocking mode use. Defaults to
usart1 #define
USART_BLOCKING


HSerReceive (user_byte_variable)
To receive an ASCII byte value
via usart 3 using blocking mode
use #define USART_BLOCKING


Comport = 3
HSerReceive ( user_byte_variable)
To receive an ASCII byte value
use in non-blocking mode use.
Ensure #define
USART_BLOCKING is NOT
defined. This method fefaults to
usart1 HSerReceive
307
Command Parameters Example

Serially receive a character


using a function specifically via
usart1.

HSerReceive1 none This function handles the


incoming characters as raw
ASCII values. The function
receives a single byte value in
the range of 0 to 255. The
function can return only a byte
value from usart 1. The blocking
and non-blocking mode and the
methods are the same as shown
in the previous method. To
receive an ASCII byte value via
usart 1 using blocking mode use
#define USART_BLOCKING


user_number_variable =
HSerReceive1 To receive an ASCII
byte value use in non-blocking
mode use. Ensure #define
USART_BLOCKING is NOT
defined. user_number_variable
= HSerReceive1

Serially receive a character


using a function specifically via
usart2

308
Command Parameters Example

HSerReceive2 none This function handles the


incoming characters as raw
ASCII values. The function
receives a single byte value in
the range of 0 to 255. The
function can receive only a byte
value from usart 2. The blocking
and non-blocking mode and the
methods are the same as shown
in the previous method. To
receive an ASCII byte value via
usart 2 using blocking mode use
#define USART_BLOCKING


user_byte_variable =
HSerReceive2 To receive an ASCII
byte value use in non-blocking
mode use. Ensure #define
USART_BLOCKING is NOT
defined. user_byte_variable =
HSerReceive2

Serially receive a character


using a function from either
usart ports using a parameter to
select the usart.

309
Command Parameters Example

HSerReceiveFrom Usart_number, This function handles the


Default is 1 incoming characters as raw
ASCII values. The function
return a single byte value in the
range of 0 to 255. The function
can receive only a byte value
from usart 1 and usart 2 The
blocking and non-blocking mode
and the methods are the same as
shown in the previous method.
To receive an ASCII byte value
via usart 1 using blocking mode
use #define USART_BLOCKING


user_byte_variable =
HSerReceiveFrom To receive an
ASCII byte value use in non-
blocking mode use. Ensure
#define USART_BLOCKING is
NOT defined. 'Chosen_usart = 2
user_byte_variable =
HSerReceiveFrom (2)

Serially send a byte using any of


the usart ports

HSerSend Byte or byte_variable [,optional This subroutine sends a byte


usart address] + The optional value to usart 1. No additional
usart address is microcontroller parameter for the usart number
specific buy can be 1, 2, 3 or 4. is used. HSerSend( user_byte ) To
print a variable value to usart 2.
Note the additional parameter
for the usart address. HSerSend (
user_byte, 2 )

Serially send a byte and a CR&LF


using any of the usart ports

HSerPrintByteCRLF Byte or byte_variable + This subroutine sends a byte


[,optional usart address] The value to usart 1. HserPrintCRLF
optional usart address is users_byte,2
microcontroller specific buy can
be 1, 2, 3 or 4.

Serially send CR&LF (can be


multiple) using any of the usart
ports

310
Command Parameters Example

HSerPrintCRLF Number of CR&LF to be sent + This subroutine sends a CR&LF


[,optional usart address] The to port 2. HserPrintCRLF 1,2 '
optional usart address is Will send a CR & LF out of
microcontroller specific buy can comport 2 to the terminal
be 1, 2, 3 or 4.

Constants These constants affect the operation of the hardware RS232 routines:

Constant Controls Default Value


Name

USART_BAUD Baud rate (in bps) for the routines to operate at. No default, user must enter a baud.
_RATE Doesn’t have to be a standard baud.

USART_BLOC If defined, this constant will cause the USART No parameter needed. Use
KING routines to wait until data can be sent or received. “#defining” it implement the action.

USART_TX_B If defined, this constant will cause the Transmit No parameter needed. Use
LOCKING USART routines to wait until Transmit register is “#defining” it implement the action.
empty before writing the next byte which prevents
over running the register and losing data.

USART2_BAU Baud rate (in bps) for the routines to operate at. No default, user must enter a baud.
D_RATE Doesn’t have to be a standard baud.

USART2_BLO If defined, this constant will cause the USART No parameter needed. Use
CKING routines to wait until data can be sent or received. “#defining” it implement the action.

USART2_TX_ If defined, this constant will cause the Transmit No parameter needed. Use
BLOCKING USART routines to wait until Transmit register is “#defining” it implement the action.
empty before writing the next byte which prevents
over running the register and losing data.

USART3_BAU Baud rate (in bps) for the routines to operate at. No default, user must enter a baud.
D_RATE Doesn’t have to be a standard baud.

USART3_BLO If defined, this constant will cause the USART No parameter needed. Use
CKING routines to wait until data can be sent or received. “#defining” it implement the action.

USART3_TX_ If defined, this constant will cause the Transmit No parameter needed. Use
BLOCKING USART routines to wait until Transmit register is “#defining” it implement the action.
empty before writing the next byte which prevents
over running the register and losing data.

USART4_BAU Baud rate (in bps) for the routines to operate at. No default, user must enter a baud.
D_RATE Doesn’t have to be a standard baud.

USART4_BLO If defined, this constant will cause the USART No parameter needed. Use
CKING routines to wait until data can be sent or received. “#defining” it implement the action.

311
Constant Controls Default Value
Name

USART4_TX_ If defined, this constant will cause the Transmit No parameter needed. Use
BLOCKING USART routines to wait until Transmit register is “#defining” it implement the action.
empty before writing the next byte which prevents
over running the register and losing data.

USART_DELA This is the delay between characters. 1 ms


Y
SerPrintCR Causes a Carriage return to be sent after every No parameter needed. User
HserPrint automatically. “#defining” it implements the action

SerPrintLF Causes a LineFeed to be sent after every HserPrint. No parameter needed. User
Some communications require both CR and LF “#defining” it implements the action

HSerGetNum

Syntax:

HSerGetNum myNum ‘Gets a multi digit number from USART 1


HSerGetNum myNum,1 ‘Get a multi digit number from USART 1
HSerGetNum myNum,2 ‘Get a multi digit number from USART 2

When the variable type is a word the number range is 0 to 65535


When the variable type is a long the number range is 0 to 99999

Command Availability:

Available on all microcontrollers with a USART or UART module.

Microchip PIC supports USART1 and 2.


Atmel AVR supports USART 1,2,3 and 4.

Explanation:

This command will read a multi digit number received as ascii chars followed by a CR from an external
serial source using a hardware serial module. The command checks that only numbers are input
disregarding other characters while waiting for the ending <CR>. It can be used only as a subroutine.

Example:

312
'This program receives a number and CR from a PC terminal and sends it back on both
usarts
#chip 18f26k22, 16

'Set the pin directions


#define USART_BAUD_RATE 9600
#define USART_BLOCKING
#define USART2_BAUD_RATE 9600
#define USART2_BLOCKING

'Init pins
#define SerInPort PORTc.7 'usart1 in
#define SerOutPort PORTc.6 'usart2 out
'Set pin directions
Dir SerOutPort Out
Dir SerInPort In
Dir PORTB.6 Out 'USART2 out
Dir PORTB.7 In 'USArt2 in
Dir PORTB.0 Out 'leds for testing
Dir PORTB.1 Out 'leds for testing
Wait 100 Ms

'Variables
Dim myNum as Word
'Main body of program commences here.
'Message after reset
HSerPrint "18F26k22"
HSerPrintCRLF

'Main routine
Do forever
'wait for char from UART
'HSerReceive InChar
HSerGetNum myNum,2 'from usart 2
HSerPrint myNum,1 ' send out usart 1
HSerPrint myNum,2 'send out usart 2
HSerPrintCRLF 1,2 'send one CRLF out usart 2
HserPrintCRLF 1,1 ‘send one CRLF out usart 1
loop

Example: This program receives number on serial port 1 and displays. This example shows using a
Long as the input variable.

Therefore, the result is in the range of 0-99999. The example also shows how to detect a buffer
overrun by testing the HSerInByte variable.

313
#chip mega328p, 16

#define USART_BAUD_RATE 9600


#define USART_BLOCKING

Dim myNum as Long ' range 0 to 99999


HSerPrint "Restarted"
HSerPrintCRLF

Do
HSerGetNum myNum
HSerPrint myNum

if HSerInByte <> 13 then


HSerSend 9
HSerPrint "Error buffer overrun" 'You should handle error appropiately
End if
HSerPrintCRLF
loop
End

See also HSerReceive and HSerGetString

HSerGetString

Syntax:

HSerGetString myString ‘Get a multi char string from USART 1


HSerGetString myString,1 ‘Get a multi char string from USART 1
HSerGetString myString,2 ‘Get a multi char string from USART 2

Variable type is string and the routine checks for numbers,letters, and puctuation.

Command Availability:

Available on all microcontrollers with a USART or UART module.

Microchip PIC supports USART1 and 2.


Atmel AVR supports USART 1,2,3 and 4.

Explanation:

This command will read a multi character string received as ascii input to the hardware serial module
followed by a CR from an external serial source. It can be used only as a subroutine. Variable type is

314
string and the routine checks for numbers,letters, and puctuation.

Example:

'This program receives char string and CR from a PC terminal, sends back the string
on the serial port, and turns Led’s on off by command

#chip 18f26k22, 16

'Set the pin directions


#define USART_BAUD_RATE 9600
#define USART_BLOCKING
#define USART2_BAUD_RATE 9600
#define USART2_BLOCKING

'InitUSART
#define SerInPort PORTc.7 'USART 1 Rx Pin
#define SerOutPort PORTc.6 'USART 1 Tx Pin

'Set pin directions


Dir SerOutPort Out
Dir SerInPort In

Dir PORTB.6 Out 'second USART Tx Pin


Dir PORTB.7 In 'second USART Rx Pin

Dir PORTB.0 Out ' LED hooked up for testing


Dir PORTB.1 Out ' LED hooked up for testing

Wait 100 Ms

; ----- Variables
' All byte variables are defined upon use.
Dim myNum as Word
Dim MyString as String

; ----- Main body of program commences here.


'Message after reset
HSerPrint "18F26k22"
HSerPrintCRLF

'Main routine

Do Forever

HSerGetString MyString

315
HSerPrint MyString
HSerSend(13)
If MyString = "LED1 ON" Then
Set PORTB.0 Off
End If
If MyString = "LED1 OFF" Then
Set PORTB.0 On
End If
If MyString = "LED2 ON" Then
Set PORTB.1 Off
End If
If MyString = "LED2 OFF" Then
Set PORTB.1 On
End If

Loop

See also HSerReceive and HSerGetNum

HSerPrint

Syntax:

HSerPrint user_value [,1|2|3|4] 'Choose comport with optional parameter


'Default comport is 11

Command Availability:

Available on all microcontrollers with a USART or UART module.

Microchip PIC supports USART1 and 2.


Atmel AVR supports USART 1,2,3 and 4.

Explanation:

HSerPrint is used to send a value over the serial connection. user_value can be a string, integer, long,
word or byte. HSerPrint is very similar to Print. The data will be sent out the hardware serial module.

HSerPrint will not send any new line characters. If the chip is sending to a terminal, these commands
should follow every HSerPrint :

HSerPrint 13
HSerPrint 10

Example:

316
'This program will display any values received over the serial
'connection. If "pot" is received, the value of the analog sensor
'will be sent.
'Note: This has been adapted from the SerPrint example.

'Chip settings
#chip 18F2525, 8
#config Osc = Int

'LCD settings
#define LCD_IO 4
#define LCD_RS PORTC.7
#define LCD_RW PORTC.6
#define LCD_Enable PORTC.5
#define LCD_DB4 PORTC.4
#define LCD_DB5 PORTC.3
#define LCD_DB6 PORTC.2
#define LCD_DB7 PORTC.1

'USART settings
#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Potentiometer
#define POT_PORT PORTA.0
#define POT_AN AN0

'Set pin directions


Dir POT_PORT In

'Create buffer variables to store received messages


Dim Buffer As String
Dim OldBuffer As String
BufferSize = 0

'Show test messages


Print "Serial Tester"
Wait 1 s
HSerPrint "GCBASIC RS232 Test"
HSerSend 13
HSerSend 10
Wait 1 s

'Main loop
Do
'Get a byte from the terminal
HSerReceive Temp

317
'If Enter key was pressed, deal with buffer contents
If Temp = 13 Then
Buffer(0) = BufferSize

'Try to execute commands in buffer


If Not ExecCommand (Buffer) Then
'Show message on bottom line, last message on top.
CLS
Print OldBuffer
Locate 1, 0
Print Buffer
'Store the message for next time
OldBuffer = Buffer
End If

BufferSize = 0
End If
'Backspace code, delete last character in buffer
If Temp = 8 Then
If BufferSize > 0 Then BufferSize -= 1
End If
'Received ASCII code between 32 and 127, add to buffer
If Temp >= 32 And Temp <= 127 Then
BufferSize += 1
Buffer(BufferSize) = Temp
End If
Loop

'Takes a sensor reading and sends it to terminal


Sub SendSensorReading
HSerPrint "Sensor Reading: "
HSerPrint ReadAD10(POT_AN)
HSerSend 13
HSerSend 10
End Sub

'Will check the buffer for a command


'If command found, run it and return true
'If not, return false
Function ExecCommand (CmdIn As String)
ExecCommand = False
'If received command is "pot", show potentiometer value
If CmdIn = "pot" Then
SendSensorReading
ExecCommand = True
End If
End Function

318
For more help, see also HserPrintByteCRLF and HserPrintCRLF

HSerReceive

Syntax:

Used as subroutine:

HSerReceive (user_byte_variable)

or, if other multiple comports are in use, set the comport before using HSerReceive.

comport = 1 '(1|2|3|4)Not needed unless using multiple comports in use


HSerReceive (_user_byte_variable_)

Used as function:

user_byte_variable = HSerReceive 'Supports only USART1


user_byte_variable = HSerReceive1 'Supports only USART1
user_byte_variable = HSerReceive2 'Supports only USART2

For other comports use Function HSerReceiveFrom

Command Availability:

Available on all microcontrollers with a USART or UART module.

Microchip PIC supports USART1 and 2.


Atmel AVR supports USART 1,2,3 and 4.

Explanation:

This command will read a byte from the hardware RS232 module. It can be used either as a subroutine
or as a function. If used as a subroutine, a variable must be supplied to store the received value in. If
used as a function, it will return the received value.

The subroutine HSerReceive can get a byte from any comport but must set the comport number
immediately before the call. If ”#define USART_BLOCKING” is defined then the HserReceive waits in a
loop until it receives a byte. If” #define USART_BLOCKING” is NOT defined then HserReceive returns
the new byte that was received OR returns 255 because of “DefaultUsartReturnValue = 255” was
defined. This is good because it don’t hold up your program from executing other commands and
your can check it for new data priodically.

Example:

319
'This program will read a value from the USART, and send it to PORTB.

#chip 16F877A, 20

'USART settings
#define USART_BAUD_RATE 9600 'sets up comport 1 for 9600 baud

'Set PORTB to output


Dir PORTB Out
'Set USART receive pin to input
Dir PORTC.7 In

'Main loop
Do
'Get serial data and output value to PortB as 8 bit binary
HSerReceive(InChar) 'Receive data as Subroutine from comport 1
'InChar = HSerReceive 'Could also be written as Function
If InChar <> 255 Then 'If value is 255 then it is old data
PortB = InChar 'If new data then it goes to PortB
End If
Loop

Example 2:

'If you choose no “Blocking” and comment both of them out.


'USART settings
#define USART_BAUD_RATE 9600
'#define USART_BLOCKING ' just none OR one of the blocking
'#define USART_TX_BLOCKING ' statements should be defined

'Main loop
Do
'Get and display value
'If there is no new data, HSerReceive will return default value.
comport = 1
HSerReceive tempvalue
If tempvalue <> 255 Then ‘ don’t change PortB if it is default
PortB = tempvalue
End If

Loop

Example 3:

320
'If you choose no “Blocking” and comment both of them out.
#chip mega328p, 16

#define USART_BAUD_RATE 9600


'#define USART_BLOCKING
'#define USART_TX_BLOCKING

'Don't forget to Set usart pin directions


Dir PortD.1 Out 'com1 USART0
Dir PortD.0 In

Wait 1 s

'Message after reset


HSerPrint "ATmega328P com test"
HSerPrintCRLF

'Main routine hook up FTDI232 usb to serial and use terminal program to check
Start:
comport = 1
HSerReceive(InChar) 'Subroutine needs the comport set
'InChar = HSerReceive ' This function will get from comport 1
If InChar <> 255 Then ' check if for received byte
'return 255 if old data
HSerSend InChar 'send back char to UART
End If
Goto Start

See also RS232 Hardware Overview

HSerReceiveFrom

Syntax:

user_byte = HSerReceiveFrom [,1 | 2 | 3 | 4]


user_byte = HSerReceiveFrom 'Defaults to USART1

'other Receive functions


user_byte = HSerReceive1 'from USART1
user_byte = HSerReceive2 'from USART2

Command Availability:

Available on all microcontrollers with a USART or UART module.

321
Microchip PIC supports USART1 and 2.
Atmel AVR supports USART 1,2,3 and 4.

Explanation:

This command will read a byte from the hardware RS232 module. It can be only be used as a function.
It will return the received value.

Example:

'This program will read a value from the USART, and display it on PORTB.

#chip 16F877A, 20

'USART settings
#define USART_BAUD_RATE 9600
#define USART_BLOCKING
#define USART_TX_BLOCKING

'Set PORTB to input


Dir PORTB Out
'Set USART receive pin to input
Dir PORTC.7 In

'Main loop
Do
'Get byte value
bytein = HSerReceiveFrom (2)
'do something useful
Loop

See also HSerReceive

HSerSend

Syntax:

HSerSend user_byte [,1|2|3|4] 'Choose comport with optional parameter


'Default comport is 1

Command Availability:

Available on all microcontrollers with a USART or UART module.

Microchip PIC supports USART1 and 2.

322
Atmel AVR supports USART 1,2,3 and 4.

Explanation:

This command will send a byte given by user_byte using the hardware RS232 module.

Example:

'This program will send the status of PORTB through the hardware
'serial module.

#chip 16F877A, 20

'USART settings
#define USART_BAUD_RATE 9600 'Initializes USART port with 9600 baud
'#define USART_BLOCKING ' Both of these blocking statements will
#define USART_TX_BLOCKING ' wait for tx register to be empty
' use only one of the two
'Set PORTB to input
Dir PORTB In
'Set USART transmit pin to output
Dir PORTC.6 Out

'Main loop
Do
'Send PORTB value through USART
HSerSend PORTB
HSerSend(13) ' sends a CR
'Short delay for receiver to process message
Wait 10 ms 'probably not necessary with blocking statement
Loop

HserPrintByteCRLF

Syntax:

HserPrintByteCRLF user_data [, 1 | 2 | 3 | 4 ]

Command Availability:

Available on all microcontrollers with a USART or UART module.

Microchip PIC supports USART1 and 2.


Atmel AVR supports USART 1,2,3 and 4.

Explanation:

323
This command will send a byte given by user_data using the hardware USART module and then send
the ASCII codes 13 and 10. ASCII codes 13 and 10 equate to a carriage return and line feed.

Example:

'This program will send the status of PORTB through the hardware serial module.

HserPrintByteCRLF 65 ' Will print a single A on the terminal


HserPrintByteCRL "A" 'Will print a single A on the terminal

See also HserPrintCRLF

HserPrintCRLF

Syntax:

HserPrintCRLF [optional BYTE] [, 1 | 2 | 3 | 4 ]

Command Availability:

Available on all microcontrollers with a USART or UART module.

Microchip PIC supports USART1 and 2.+ Atmel AVR supports USART 1,2,3 and 4.

Explanation:

This command will send ASCII codes 13 and 10 only using the hardware RS232 module. ASCII codes 13
and 10 equate to a carriage return and line feed.

Optionally, you can add a parameter. The number will determine the number of ASCII codes 13 and 10
set to the hardware RS232 module.

Also you can choose the comport with second optional parameter if it is not the default comport 1. If
there is no first optional parameter then you must have atleast acomma before it to indicate this is the
second parameter.

Examples:

324
'This Line will send 1 CR and LF
HserPrintCRLF ' Will send a CR & LF to the terminal

'This Line will send 2 times (CR and LF)


HserPrintCRLF 2 ' Will send 2 times (CR & LF) to the terminal
'out of comport 1

'This Line will send 1 CR and LF


HserPrintCRLF 1,2 ' Will send a CR & LF out of
'comport 2 to the terminal

See also HserPrintByteCRLF

325
PS/2
This is the PS/2 section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

PS/2 Overview

PS2 Overview

These routines make it easier to communicate with a PS/2 device, particularly an external keyboard.

Relevant Constants

These constants affect the operation of the PS/2 routines:

Constant Controls Default


Name Value

PS2Data Pin connected to PS/2 data line Must be


specified

PS2Clock Pin connected to PS/2 clock line. Must be


specified

PS2_DELAY This constant can be set to a delay, such as 10 ms. If set, a delay will be Not set
added at the end of every byte sent or received.

Connections between the Keyboard and the Microcontroller The following diagram show a typical
connection between the keyboard and the microcontroller. The value of R1 and R2 is typically 4.7k for
a 5v system.

InKey

Syntax:

326
output = InKey

Command Availability:

Available on all microcontrollers.

Explanation:

The InKey function will read the last pressed key from a PS/2 keyboard, and return an ASCII value
corresponding to the key. If no key is pressed, then InKey will return 0.

It will also monitor Caps Lock, Num Lock and Scroll Lock keys, and update the status LEDs as
appropriate.

Example:

'A program to accept messages from a standard PS/2 keyboard


'Any keys pressed will be shown on an LCD screen.

'Hardware settings
#chip 18F4620, 20

'LCD connection settings


#define LCD_IO 4
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

'PS/2 connection settings


#define PS2Clock PORTC.1
#define PS2Data PORTC.0
#define PS2_DELAY 10 ms

'Set up key log


Dim KeyLog(32)
DataCount = 0
KeyLog(1) = 32

Main:
'Read the last pressed key
KeyIn = INKEY
'If no key pressed, try reading again

327
If KeyIn = 0 Then Goto Main

'Escape pressed - clear message


If KeyIn = 27 Then
DataCount = 0
For DataPos = 1 to 32
KeyLog(DataPos) = 32
Next
Goto DisplayData
End If

'Backspace pressed - delete last character


If KeyIn = 8 Then
If DataCount = 0 Then Goto Main
KeyLog(DataCount) = 32
DataCount = DataCount - 1
Goto DisplayData
End If

'Otherwise, add the character to the buffer


If KeyIn >= 31 And KeyIn <= 127 Then
DataCount = DataCount + 1
KeyLog(DataCount) = KeyIn
End If

DisplayData:
'Display key buffer
'LCDWriteChar is used instead of Print for greater control
CLS
For DataPos = 1 to DataCount
If DataPos = 17 then Locate 1, 0
LCDWriteChar KeyLog(DataPos)
Next

Goto Main

PS2SetKBLeds

Syntax:

PS2SetKBLeds (LedStatus)

Command Availability:

Available on all microcontrollers.

328
Explanation:

This routine will turn the status LEDs on a keyboard on or off. LedStatus is a variable, of which the
lower 3 bits correspond to the 3 LEDs. Bit 0 is for Scroll Lock, bit 1 controls Num Lock and bit 2 controls
Caps Lock.

Note that this routine does not alter the status variables within the INKEY routine - so even if the Caps
Lock LED is turned on, Caps Lock will stay off.

Example:

'A spinning LED program for a keyboard


'Will flash Num Lock, then Caps Lock, then Scroll Lock.

'Hardware settings
#chip 16F88, 8

#define PS2Clock PORTB.2


#define PS2Data PORTB.3
#define PS2_DELAY 10 ms

'Main Loop
Do

'Turn on only Num Lock (bit 1)


PS2SetKBLeds b'00000010'
Wait 250 ms

'Turn on only Caps Lock (bit 2)


PS2SetKBLeds b'00000100'
Wait 250 ms

'Turn on only Scroll Lock (bit 0)


PS2SetKBLeds b'00000001'
Wait 250 ms

Loop

PS2ReadByte

Syntax:

output = PS2ReadByte

Command Availability:

329
Available on all microcontrollers.

Explanation:

PS2ReadByte will read a byte from the PS/2 bus. It will return the byte, or 0 if no data was returned by
the PS/2 device.

The PS/2 bus will normally be held in the inhibit state. PS2ReadByte will uninhibit the bus for 25 ms. If a
response is received, it will be read. Then, the bus will be placed back in the inhibit state.

Example:

For an example, please refer to the InKey function. PS2 Inkey

PS2WriteByte

Syntax:

PS2WriteByte user_data

Command Availability:

Available on all microcontrollers.

Explanation:

PS2WriteByte will send a byte to a PS/2 device. Once the byte has been written, the PS/2 bus will be
placed in the inhibit state.

Example:

For an example, please refer to the PS2SetKBLeds function.


PS2 Set Keyboard Leds

330
SPI
This is the Serial Peripheral Interface section of the Help file. Please refer the sub-sections for details
using the contents/folder view.

SPI Overview

Syntax:

The SPI interface allows for the transmission and receiption of data simultaneously on two lines (MOSI
and MISO).

The Clock polarity (CPOL) and clock phase (CPHA) are the main parameters that define a clock format
to be used by the SPI bus. Depending on CPOL parameter, SPI clock may be inverted or non-inverted.
CPHA parameter is used to shift the sampling phase. If CPHA=0 the data are sampled on the leading
(first) clock edge. If CPHA=1 the data are sampled on the trailing (second) clock edge, regardless of
whether that clock edge is rising or falling.

CPOL=0, CPHA=0

The data must be available before the first clock signal rising. The clock idle state is zero. The data on
MISO and MOSI lines must be stable while the clock is high and can be changed when the clock is low.
The data is captured on the clock’s low-to-high transition and propagated on high-to-low clock
transition.

CPOL=0, CPHA=1

331
The first clock signal rising can be used to prepare the data. The clock idle state is zero. The data on
MISO and MOSI lines must be stable while the clock is low and can be changed when the clock is high.
The data is captured on the clock’s high-to-low transition and propagated on low-to-high clock
transition.

CPOL=1, CPHA=0

The data must be available before the first clock signal falling. The clock idle state is one. The data on
MISO and MOSI lines must be stable while the clock is low and can be changed when the clock is high.
The data is captured on the clock’s high-to-low transition and propagated on low-to-high clock
transition.

CPOL=1, CPHA=1

The first clock signal falling can be used to prepare the data. The clock idle state is one. The data on
MISO and MOSI lines must be stable while the clock is high and can be changed when the clock is low.
The data is captured on the clock’s low-to-high transition and propagated on high-to-low clock
transition.

Key Commands

332
SPIMode ( _Mode_ [, SPIClockMode])

SPITransfer ( _OutByte_, _InByte_ )

FastHWSPITransfer( _OutByte_ )

The Great Cow BASIC used the microcontrollers hardware module for SPI. The example below shows
an implementation of Hardware and Software SPI. Software SPI allows for a greater choice of ports to
be used to control the SPI operations.

Example

This example demonstrates the SPI capabilities for the mega328p. The process is similar of any
microcontroller..

This example show using the hardware SPI option and a sofware SPI option.

Using hardware SPI mode - make sure the #define SPI_HardwareSPI is not commented out. Using
software SPI mode - comment out #define SPI_HardwareSPI. The example code will then use software
SPI.

Usage

Hardware SPI mode the Data Out, Data In and Clock (DO/DI and SCK) cannot be moved but the
optional Data Command, Chip Select and Reset are all moveable.
Software SPI mode the Data Out, Data In and Clock (DO/DI and SCK), Data Command, Chip
Select and Reset are all moveable.

Code overview

InitSPIMode calls SPIMode if needed, when hardware mode, and set the lines.
The sub SendByteviaSPI is called to handle whether to call the Hardware or use Software
(bit-banging) SPI.

#chip mega328p, 16
#option explicit
#include <UNO_mega328p.h >

#define SPI_HardwareSPI 'comment this out to make into Software SPI but, you may
have to change clock lines

'Pin mappings for SPI - this SPI driver supports Hardware SPI
#define SPI_DC DIGITAL_8 ' Data command line

333
#define SPI_CS DIGITAL_4 ' Chip select line
#define SPI_RESET DIGITAL_9 ' Reset line

#define SPI_DI DIGITAL_12 ' Data in | MISO


#define SPI_DO DIGITAL_11 ' Data out | MOSI
#define SPI_SCK DIGITAL_13 ' Clock Line

dir SPI_DC out


dir SPI_CS out
dir SPI_RESET out
dir SPI_DO Out
dir SPI_DI In
dir SPI_SCK Out

'If DIGITAL_10 is NOT used as the SPI_CS (sometimes called SS) the port must and
output or set as input/pulled high with a 10k resistor.
'As follows:
'If CS is configured as an input, it must be held high to ensure Master SPI
operation.
'If the CS pin is driven low by peripheral circuitry when the SPI is configured
as a Master with the SS pin defined as an input, the
'SPI system interprets this as another master selecting the SPI as a slave and
starting to send data to it!
'If CS is an output SPI communications will commence with no flow control.
dir DIGITAL_10 Out

DIM byte1 As byte


DIM byte2 As byte
DIM byte3 As byte

byte1 = 100 ' temp values (will come from potentiometer later)
byte2 = 150
byte3 = 200

InitSPIMode

do forever
set SPI_CS OFF;
set SPI_DC OFF;
SendByteviaSPI (byte1)
set SPI_CS ON;
set SPI_DC ON

set SPI_CS OFF;


set SPI_DC OFF;
SendByteviaSPI (byte2)
set SPI_CS ON;

334
set SPI_DC ON

set SPI_CS OFF;


set SPI_DC OFF;
SendByteviaSPI (byte3)
set SPI_CS ON;
set SPI_DC ON

wait 10 ms
loop

sub InitSPIMode

#ifdef SPI_HardwareSPI
SPIMode ( MasterFast, SPI_CPOL_0 + SPI_CPHA_0 )
#endif

set SPI_DO OFF;


set SPI_CS ON; therefore CPOL=0
set SPI_DC ON; deselect

End sub

sub SendByteviaSPI( in SPISendByte as byte )

set SPI_CS OFF


set SPI_DC OFF;

#ifdef SPI_HardwareSPI
FastHWSPITransfer SPISendByte
set SPI_CS ON;
exit sub
#endif

#ifndef SPI_HardwareSPI
repeat 8

if SPISendByte.7 = ON then
set SPI_DO ON;
else
set SPI_DO OFF;
end if
SET SPI_SCK On; ; therefore CPOL=0 ==ON, and, where CPOL=1==ON
rotate SPISendByte left
set SPI_SCK Off; ; therefore CPOL=0 =OFF, and, where CPOL=1==OFF

335
end repeat
set SPI_CS ON;
set SPI_DO OFF;
#endif

end Sub

See also SPIMode,SPITransfer,FastHWSPITransfer

SPIMode

Syntax:

SPIMode ( Mode [, SPIClockMode])

Command Availability:

Available on Microchip PIC microcontrollers with Hardware SPI modules.

Explanation:

Mode sets the mode of the SPI module within the microcontroller. These are the possible SPI Modes:

Mode Name Description

MasterSlow Master mode, SPI clock is 1/64 of the frequency of the microcontroller.

Master Master mode, SPI clock is 1/16 of the frequency of the microcontroller.

MasterFast Master mode, SPI clock is 1/4 of the frequency of the microcontroller.

Slave Slave mode

SlaveSS Slave mode, with the Slave Select pin enabled.

SPIClockMode is an optional parameter to set the mode of the SPI clock mode. This optional parameter
sets both the clock polarity and clock edge.

SPIClockMode Description

0 SPI_CPOL = 0 & SPI_CPHA = 0

1 SPI_CPOL = 0 & SPI_CPHA = 1

2 SPI_CPOL = 1 & SPI_CPHA = 0

3 SPI_CPOL = 1 & SPI_CPHA = 1

You can alternatively use constants to set the SPIClockMode as follows:

336
SPIMode ( MasterFast, SPI_CPOL_n + SPI_CPHA_n )

Where the following parameters can be used as a calculation to set the SPIClockMode.

Mode Name Description

SPI_CPOL_0 CPOL = 0

SPI_CPOL_1 CPOL = 1

SPI_CPHA_0 CPHA = 0

SPI_CPHA_1 CPHA = 1

Summary:

When using SPI setting the clock frequency is completed using SPIMode, and the master must also
configure the clock polarity and phase with respect to the data. Using the two options as CPOL and
CPHA.

The timing diagram is shown below. The timing is further described and applies to both the master and
the slave device.

When CPOL=0 the base value of the clock is zero, i.e. the active state is 1 and idle state is 0.

• For CPHA=0, data are captured on the clock’s rising edge (low→high transition) and data is output
on a falling edge (high→low clock transition).

• For CPHA=1, data are captured on the clock’s falling edge and data is output on a rising edge.

When CPOL=1 the base value of the clock is one (inversion of CPOL=0), i.e. the active state is 0 and idle
state is 1.

• For CPHA=0, data are captured on clock’s falling edge and data is output on a rising edge.

• For CPHA=1, data are captured on clock’s rising edge and data is output on a falling edge.

When CPHA=0 means sampling on the first clock edge and , while CPHA=1 means sampling on the
second clock edge, regardless of whether that clock edge is rising or falling. Note that with CPHA=0,
the data must be stable for a half cycle before the first clock cycle.

In other words, CPHA=0 means transmitting data on the active to idle state and CPHA=1 means that
data is transmitted on the idle to active state edge. Note that if transmission happens on a particular
edge, then capturing will happen on the opposite edge(i.e. if transmission happens on falling, then
reception happens on rising and vice versa). The MOSI and MISO signals are usually stable (at their
reception points) for the half cycle until the next clock transition. SPI master and slave devices may
well sample data at different points in that half cycle.

This adds more flexibility to the communication channel between the master and slave.

337
Example

This example demonstrates the SPI capabilities for the mega328p. The process is similar of any
microcontroller..

You must set the data line as inputs and outputs.

#chip mega328p, 16
#option explicit
#include <UNO_mega328p.h >

#define SPI_HardwareSPI 'comment this out to make into Software SPI but, you may
have to change clock lines

'Pin mappings for SPI - this SPI driver supports Hardware SPI
#define SPI_DC DIGITAL_8 ' Data command line
#define SPI_CS DIGITAL_4 ' Chip select line
#define SPI_RESET DIGITAL_9 ' Reset line

#define SPI_DI DIGITAL_12 ' Data in | MISO


#define SPI_DO DIGITAL_11 ' Data out | MOSI
#define SPI_SCK DIGITAL_13 ' Clock Line

dir SPI_DC out


dir SPI_CS out
dir SPI_RESET out
dir SPI_DO Out
dir SPI_DI In
dir SPI_SCK Out

'If DIGITAL_10 is NOT used as the SPI_CS (sometimes called SS) the port must and
output or set as input/pulled high with a 10k resistor.
'As follows:
'If CS is configured as an input, it must be held high to ensure Master SPI
operation.
'If the CS pin is driven low by peripheral circuitry when the SPI is configured
as a Master with the SS pin defined as an input, the

338
'SPI system interprets this as another master selecting the SPI as a slave and
starting to send data to it!
'If CS is an output SPI communications will commence with no flow control.
dir DIGITAL_10 Out

dim outbyte, inbyte as byte

SPIMode ( MasterFast, SPI_CPOL_0 + SPI_CPHA_0 )

do
set SPI_CS OFF; Select line
set SPI_DC OFF; Send Data if off, or, Data if On
SPITransfer ( outbyte, inbyte )
set SPI_CS ON; Deselect Line
set SPI_DC ON
wait 10 ms
loop

See also SPITransfer,FastHWSPITransfer

SPITransfer

Syntax:

SPITransfer tx, rx

Command Availability:

Available on Microchip PIC microcontrollers with Hardware SPI modules.

Explanation:

This command simultaneously sends and receives a byte of data using the SPI protocol. It behaves
differently depending on whether the microcontroller has been set to act as a master or a slave. When
operating as a master, SPITransfer will initiate a transfer. The data in tx will be sent to the slave, whilst
the byte that is buffered in the slave will be read into rx. In slave mode, the SPITransfer command will
pause the program until a transfer is initiated by the master. At this point, it will send the data in tx
whilst reading the transmission from the master into the rx variable.

Example:

There are two example programs for this command - one to run on the slave microcontroller , and one
on the master. A reading is taken from a sensor on the slave, and sent across to the master which
shows the data on its LCD screen.

339
Slave Program:

'Select chip model and configuration


#chip 16F88, 20
#config MCLR_OFF

'Set directions of SPI pins


dir PORTB.2 out
dir PORTB.1 in
dir PORTB.4 in
'Set direction of analogue pin
dir PORTA.0 in

'Set SPI mode to slave


SPIMode Slave

'Allow other microcontroller to initialise LCD


Wait 1 sec

'Main loop - takes a reading, and then waits to send it across.


do
'Note that rx is 0 - this is because no data is to be received.
SPITransfer ReadAD(AN0), 0
loop

Master Program:

340
'General hardware configuration
#chip 16F877A, 20

'LCD connection settings


#define LCD_IO 8
#define LCD_DATA_PORT PORTC
#define LCD_RS PORTD.0
#define LCD_RW PORTD.1
#define LCD_Enable PORTD.2

'Set SPI pin directions


dir PORTC.5 out
dir PORTC.4 in
dir PORTC.3 out

'Set SPI Mode to master, with fast clock


SPIMode MasterFast

'Main Loop
do
'Read a byte from the slave
'No data to send, so tx is 0
SPITransfer 0, Temp

'Display data
if Temp > 0 then
CLS
Print "Light: "
LCDInt Temp
Temp = 0
end if

'Wait to allow time for the LCD to show the given value
wait 100 ms
loop

See also SPIMode,FastHWSPITransfer

FastHWSPITransfer

Syntax:

FastHWSPITransfer tx

Command Availability:

341
Available on Microchip PIC microcontrollers with Hardware SPI modules.

Explanation:

This command only sends a byte of data using the SPI protocol. This command only supports master
mode.

As a master, FastHWSPITransfer will initiate a transfer. The data in tx will be sent to the slave.

Example:

This is an example for this command.

Master Program:

'General hardware configuration


#chip 16F877A, 20

'Set SPI pin directions


dir PORTC.5 out
dir PORTC.4 in
dir PORTC.3 out

'Set SPI Mode to master, with fast clock


SPIMode MasterFast

'Main Loop
do

'Send the value of 0x55


FastHWSPITransfer 0x55

loop

See also SPITransfer,SPIMode

342
I2C Software
This is the I2C Software section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

I2C Overview

Introduction:

These software routines allow Great Cow BASIC programs to send and receive I2C messages. They can
be configured to act as master or slave, and the speed can also be altered.

No hardware I2C module is required for these routines - all communication is handled in software.
However, these routines will not work on 12-bit instruction Microchip PIC microcontrollers (10F,
12F5xx and 16F5xx chips).

Relevant Constants:

These constants control the setup of the software I2C routines:

Constant Controls Default


Value

I2C_MODE Mode of I2C routines (Master or Slave) Master

I2C_DATA Pin on microcontroller connected to I2C data N/A

I2C_CLOCK Pin on microcontroller connected to I2C clock N/A

I2C_BIT_DELAY Time for a bit (used for acknowledge detection) 2 us

I2C_CLOCK_DELAY Time for clock pulse to remain high 1 us

I2C_END_DELAY Time between clock pulses 1 us

I2C_USE_TIMEOUT Set to true if the I2C routines should stop waiting for the I2c bus - the Not Set
routine will exit if a timeout occurs. Should be used when you need to
prevent system lockups on the I2C bus. Supports both software I2C
master and slave mode. Will return the variable I2CAck = FALSE when
a timeout has occurred.

I2C_DISABLE_INTE Disable interrupts during I2C routines. Important when an i2C clock is Not
RRUPTS part of your solution defined.

Example: This example examines the IC2 devices and displays on a terminal. This code will require
adaption but the code shows an approach to discover the IC2 devices.

' I2C Overview - using the ChipIno board, see here for information
#chip 16F886, 8
#config MCLRE_ON

343
' Define I2C settings
#define I2C_MODE Master
#define I2C_DATA PORTC.4
#define I2C_CLOCK PORTC.3
#define I2C_DISABLE_INTERRUPTS ON

'USART/SERIAL PORT via a MAX232 TO PC Terminal


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

Dir PORTc.6 Out


#define USART_DELAY 5 ms

HSerPrintCRLF 2
HSerPrint "I2C Discover using the ChipIno"
HSerPrintCRLF 2

HSerPrint "Started: "


HSerPrint "Searching I2C address space: v0.85"
HSerPrintCRLF

wait 100 ms
dim DeviceID as byte
for DeviceID = 0 to 255
I2CStart
I2CSend ( deviceID )
I2CSend ( 0 )
I2CSend ( 0 )
i2cstop

if I2CSendState = True then

HSerPrint "__"
HSerPrint "ID: 0x"
HSerPrint hex(deviceID)
HSerPrint " (d"
HSerPrint Str(deviceID)
HSerPrint ")"
HSerPrintCRLF
end if
next
HSerPrint "End of Device Search": HSerPrintCRLF 2
End

Supported in <I2C.H>

344
I2CAckPollState

Syntax:

<test condition> I2CAckPollState

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

Should only be used when I2C routines are operating in Master mode, this command will return the
last state of the acknowledge response from a specific I2C device on the I2C bus.

I2CACKPOLL sets the state of variable I2CAckPollState. I2CAckPollState can only read - it cannot be set.

Example:

...
' ACK polling removes the need to for the 24xxxxx device to have a 5ms
write time
I2CACKPOLL( eeprom_device )
' You check the exit state,
' Use I2CAckPollState to check the state of a target device
...

Supported in <I2C.H>

I2CAckpoll

Syntax:

I2CAckpoll ( I2C_device_address )

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

Should only be used when I2C routines are operating in Master mode, this command will look for a

345
specific I2C device on the I2C bus.

This sets a global variable I2CAckPollState that can be inspected in your calling routine.

Example:

...
' ACK polling removes the need to for the 24xxxxx device to have a 5ms write time
I2CACKPOLL( eeprom_device )
' You check the exit state, use I2CAckPollState to check the state of
' the acknowledge from the target device
...

Supported in <I2C.H>

I2CReceive

Syntax:

I2CReceive data
I2CReceive data, ack

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

The I2CReceive command will send data through the I2C connection. If ack is TRUE, or no value is given
for ack, then I2CReceive will send an ack.

If in master mode, I2CReceive will read the data immediately.

If in slave mode, I2CReceive will wait for the master to send the data before reading. When the method
I2CReceive is used in Slave mode the global variable I2CMatch will be set to true when the received
value is equal to the constant I2C_ADDRESS.

Example 1 - Master Mode:

346
' I2C Receive - using the ChipIno board, see here for information. ' This program
reads an I2C register and LED is set to on if the value is over 100.
' This program will read from address 83, register 1.

#chip 16F886, 8
#config MCLRE_ON

'I2C settings
#define I2C_MODE Master
#define I2C_DATA PORTC.4
#define I2C_CLOCK PORTC.3

'Misc settings
#define LED PORTB.5
dir LED Out

'Main loop
Do
'Send start
I2CStart

'Request value
I2CSend 83
I2CSend 1

'Read value
I2CReceive ValueIn

'Send stop
I2CStop

'Turn on LED if received value > 100


Set LED Off
If ValueIn > 100 Then Set LED On

'Delay
Wait 20 ms

Loop

Example 2 - Slave Mode:

See the I2C Overview for the Master mode device to control this Slave mode device.

' I2CReceive_Slave.gcb - using a 16F88.


' This program receives commands from a GCB Master. This Slave has three LEDs

347
attached.

;----- Configuration

#chip 16F88, 8
#config INTRC_IO,MCLR_OFF

#define I2C_MODE Slave ;this is a slave device now


#define I2C_CLOCK portb.4 ;SCL on pin 10
#define I2C_DATA portb.1 ;SDA on pin 7
#define I2C_ADDRESS 0x60 ;address of the slave device

;----- Variables

dim addr, reg, value as byte

;----- Program
#define LED0 porta.2 ;pin 1
#define LED1 porta.3 ;pin 2
#define LED2 porta.4 ;pin 3

dir LED0 out ;0, 1 and 2 are outputs (LEDs)


dir LED1 out ;0, 1 and 2 are outputs (LEDs)
dir LED2 out ;0, 1 and 2 are outputs (LEDs)

do
I2CStart ;wait for Start signal
I2CReceive( addr ) ;then wait for an address

if I2CMatch = true then ;if it matches, proceed

I2CReceive(regval, ACK) ;get the register number


I2CReceive(value, ACK) ;and its value
I2CStop ;release the bus from this end

select case regval ;now turn proper LED on or off


case 0:
if value then
set LED0 on
else
set LED0 off
end if

case 1:
if value then
set LED1 on
else

348
set LED1 off
end if

case 2:
if value then
set LED2 on
else
set LED2 off
end if
case else
;other register numbers are ignored
end select
else
I2CStop ;release bus in any event
end if

loop

Supported in <I2C.H>

I2CReset

Syntax:

I2CReset

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

This will attempt a reset of the I2C by changing the state of the I2C bus.

Example:

...
I2CReset
...

Supported in <I2C.H>

349
I2CRestart

Syntax:

I2CRestart

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

If the I2C routines are operating in Master mode, this command will send a start and restart condition
in a single command.

Example:

...
I2CRESTART
....

Supported in <I2C.H>

I2CSend

Syntax:

I2CSend data
I2CSend data, ack

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

The I2CSend command will send data through the I2C connection. If ack is TRUE, or no value is given
for ack, then I2CSend will wait for an Ack from the receiver before continuing. If in master mode,
I2CSend will send the data immediately. If in slave mode, I2CSend will wait for the master to request the
data before sending.

Example 1:

350
' I2CSend - using the ChipIno board, see here for information.
' This program send commands to a GCB Slave with three LEDs attached.

#chip 16F886, 8
#config MCLRE_ON

'I2C settings
#define I2C_MODE Master
#define I2C_DATA PORTC.4
#define I2C_CLOCK PORTC.3
#define I2C_BIT_DELAY 20 us
#define I2C_CLOCK_DELAY 30 us

#define I2C_ADDRESS 0x60 ;address of the slave device


;----- Variables

dim reg as byte

;----- Program

do

for reg = 0 to 2 ;three LEDs to control


I2CStart ;take control of the bus
I2CSend I2C_ADDRESS ;address the device
if I2CSendState = ACK then
I2CSend reg ;address the particular register
I2CSend ON ;command to turn on LED
end if
I2CStop ;relinquish the bus
wait 100 ms
next reg
wait 1 S ;pause to show results

for reg = 0 to 2 ;similarly, turn them off


I2CStart ;take control of the bus
I2CSend I2C_ADDRESS ;address the device
if I2CSendState = ACK then
I2CSend reg ;address the particular register
I2CSend OFF ;command to turn off LED
end if
I2CStop ;relinquish the bus
wait 100 ms
next reg
wait 1 S ;pause to show results

351
loop

Example 2:

'This program will act as an I2C analog to digital converter


'When data is requested from address 83, registers 0 through
'3, it will return the value of AN0 through AN3.

'Chip model
#chip 16F88, 8

'I2C settings
#define I2C_MODE Slave
#define I2C_CLOCK PORTB.0
#define I2C_DATA PORTB.1

#define I2C_DISABLE_INTERRUPTS ON

'Main loop
Do
'Wait for start condition
I2CStart

'Get address
I2CReceive Address
If Address = 83 Then
'If address was this device's address, respond
I2CReceive Register

OutValue = ReadAD(Register)
I2CSend OutValue
End If

I2CStop

Wait 5 ms
Loop

Supported in <I2C.H>

I2CStart

Syntax:

352
I2CStart

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

If the I2C routines are operating in Master mode, this command will send a start condition. If routines
are in Slave mode, it will pause the program until a start condition is sent by the master. It should be
placed at the start of every I2C transmission.

If interrupt handling is enabled, this command will disable it.

Example:

Please see I2CSend and I2CReceive for an example.

Supported in <I2C.H>

I2CStartoccurred

Syntax:

I2CStartoccurred

Command Availability:

Available on all microcontrollers except 12 bit instruction Microchip PIC microcontrollers (10F,
12F5xx, 16F5xx chips)

Explanation:

If the I2C routine IS operating in Slave mode, this function will check if a start condition has occurred
since the last run of this function. 'Only used in slave mode

Example:

Please see I2CSend and I2CReceive for an example.

Supported in <I2C.H>

I2CStop

Syntax:

353
I2CStop

Command Availability:

Available on all microcontrollers except 12 bit instruction microcontrollers (10F, 12F5xx, 16F5xx chips)

Explanation:

When in Master mode, this command will send an I2C stop condition, and re-enable interrupts if
I2CStart disabled them. In Slave mode, it will re- enable interrupts.

I2CStop should be called at the end of every I2C transmission.

Example:

Please see I2CSend and I2CReceive for an example.

Supported in <I2C.H>

354
I2C/TWI Hardware Module
This is the I2C/TWI section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

HI2C Overview

Introduction:

These methods allow Great Cow BASIC programs to send and receive Inter- Integrated Circuit (I2C™)
messages via:

• Master Synchronous Serial Port (MSSP) module of the microcontroller for the Microchip PIC
architecture, or

• ATMEL 2-wire Serial Interface (TWI) for the Atmel AVR microcontroller architecture.

These methods are serial interfaces that are useful for communicating with other peripheral or
microcontroller devices. These peripheral devices may be serial EEPROMs, shift registers, display
drivers, A/D converters, etc.

The method can operate in one of two operational modes:

• Master Mode, or

• Slave mode (with general address call)

These methods fully implement all the I2C master and slave functions (including general call support)
and supports interrupts on start and stop bits in hardware to determine a free bus (multi-master
function).

These methods implement the standard mode specifications as well as 7-bit and 10-bit addressing. A
“glitch” filter is built into the SCL and SDA pins when the pin is an input. This filter operates in both
the 100 KHz and 400 KHz modes. In the 100 KHz mode, when these pins are an output, there is a slew
rate control of the pin that is independent of device frequency.

A hardware I2C/TWI module within the microcontroller is required for these methods.

The driver supports two hardware I2C ports. The second port is addressed by the suffix HI2C2. All
HI2C commands are applicable to the second HI2C2 port.

The method supports the following frequencies:

Frequency Description Support

Up to 400 kbits/s I2C/TWI fast mode: Defined as transfer rates up to 400 kbit/s Supported

Up to 100 kbit/s. I2C/TWI standard mode: Defined as transfer rates up to 100 kbit/s. Supported

355
Frequency Description Support

Up to 1 Mbit/s. I2C fast-mode plus: Allowing up to 1 Mbit/s. Not Supported

Up to 3.4 Mbit/s. I2C high speed: Allowing up to 3.4 Mbit/s. Not Supported

Relevant Constants:

These constants control the setup of the hardware I2C methods:

Constan Controls Usage


t

Master Operational mode of the HI2CMode ( Master )


microcontroller

Slave Operational mode of the HI2CMode ( Slave )


microcontroller

HI2C_BAU Operational speed of the #define HI2C_BAUD_RATE 400 or


D_RATE microcontroller. Defaults to #define HI2C_BAUD_RATE 100.
100mhz Where #define HI2C_BAUD_RATE 100 is the default value
and therefore does need to be specified.

Port Settings:

The settings of the pin direction is critical to the operation of these methods. Both pins must be set as
inputs and be pulled up with an appropriate resistor (typically 4.k @ 5.0v for 100Mkz transmissions).

Constant Controls Default Value

HI2C_DATA Pin on microcontroller connected to I2C data Must be defined

HI2C_CLOCK Pin on microcontroller connected to I2C clock) Must be defined

Example:

This example examines the IC2 devices and displays on a serial terminal. This code will require
adaption but the code shows an approach to discover the IC2 devices.

' Hardware I2C Overview - using the ChipIno board, see


' http://www.elproducts.com/chipino.html for information

#chip mega328p, 16
#config MCLRE_ON

' Define I2C settings


#define HI2C_BAUD_RATE 400
#define HI2C_DATA PORTC.5

356
#define HI2C_CLOCK PORTC.4
'I2C pins need to be input for SSP module when used on Microchip PIC device
Dir HI2C_DATA in
Dir HI2C_CLOCK in

'MASTER MODE
HI2CMode Master

'USART/SERIAL PORT WORKS WITH max232 THEN TO PC Terminal


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING
Dir PORTc.6 Out
#define USART_DELAY 10 ms

HSerPrintCRLF 2
HSerPrint "Hardware I2C Discover using the "
HSerPrint CHipNameStr
HSerPrintCRLF 2

for deviceID = 0 to 255


HI2CStart
HI2CSend ( deviceID )

if HI2CAckPollState = false then

if (( deviceID & 1 ) = 0 ) then


HSerPrint "W"
else
HSerPrint "R"
end if
HSerSend 9
HSerPrint "ID: 0x"
HSerPrint hex(deviceID)
HSerSend 9
HSerPrint "(d)"+str(deviceID)
HSerPrintCRLF

HI2CSend ( 0 )
HI2CSend ( 0 )
end if

HI2CStop
next
HSerPrintCRLF
HSerPrint "End of Device Search"
HSerPrintCRLF 2

357
Supported in <HI2C.H>

HI2CAckPollState

Syntax:

<test condition[s]> HI2CAckPollState

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

Should only be used when I2C routines are operating in Master mode, this command will return the
last state of the acknowledge response from a specific I2C device on the I2C bus.

HI2CSend sets the state of variable HI2CAckPollState.


HI2CAckPollState can only read - it cannot be set.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

<test condition[s]> HI2C2AckPollState

Example:

This example code would display the devices on the I2C bus.

...
for deviceID = 0 to 255
HI2CStart
HI2CSend ( deviceID )

if HI2CAckPollState = false then


HSerPrint "ID: 0x"
HSerPrint hex(deviceID)
HSerSend 9
end if
next
...

Supported in <HI2C.H>

358
HI2CReceive

Syntax:

HI2CReceive data

HI2CReceive data, ACK


HI2CReceive data, NACK

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

The HI2CReceive command will send data through the I2C connection. If ack is TRUE, or no value is
given for ack, then HI2CReceive will send an ack to the I2C bus.

If in master mode, HI2CReceive will read the data immediately. If in slave mode, HI2CReceive will wait
for the master to send the data before reading.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2Receive _data_

HI2C2Receive _data_, ACK


HI2C2Receive _data_, NACK

Example 1:

'This program reads an I2C register and sets an LED if it is over 100.

'It will read from I2C device with an address of 83, register 1.
' Change the processor
#chip 16F1937, 32
#config Osc = intOSC, MCLRE_ON, PLLEN_ON, VCAPEN_OFF

' Define I2C settings


#define HI2C_BAUD_RATE 400

#define HI2C_DATA PORTC.4


#define HI2C_CLOCK PORTC.3

359
'I2C pins need to be input for SSP module
Dir HI2C_DATA in
Dir HI2C_CLOCK in

'MASTER I2C Device


HI2CMode Master

'Misc settings
#define LED PORTB.0

'Main loop
Do
'Send start
HI2CStart

'Request value
HI2CSend 83
HI2CSend 1

'Read value
HI2CReceive ValueIn

'Send stop
HI2CStop

'Turn on LED if received value > 100


Set LED Off
If ValueIn > 100 Then Set LED On

'Delay
Wait 20 ms

Loop

Example 2:

See the I2C Overview for the Master mode device to control this Slave mode device.

' I2CHardwareReceive_Slave.gcb - using a 16F88.


' This program receives commands from a GCB Master. This Slave has three LEDs
attached.

; This Slave device responds to address 0x60 and may only be written to.
; Within it, there are three registers, 0,1 and 2 corresponding to the three LEDs.
Writing a zero
; turns the respective LED off. Writing anything else turns it on.

360
#chip 16F88, 4
#config INTRC_IO,MCLR_Off

#define I2C_MODE Slave ;this is a slave device now


#define I2C_CLOCK portb.4 ;SCL on pin 10
#define I2C_DATA portb.1 ;SDA on pin 7
#define I2C_ADDRESS 0x60 ;address of the slave device

#define I2C_BIT_DELAY 20 us
#define I2C_CLOCK_DELAY 10 us
#define I2C_END_DELAY 10 us

'Serial settings
#define SerInPort PORTB.6
#define SerOutPort PORTB.7

#define SendAHigh Set SerOutPort OFF


#define SendALow Set SerOutPort On
'Set pin directions
Dir SerOutPort Out
Dir SerInPort In

'Set up serial connection


InitSer 1, r2400, 1 + WaitForStart, 8, 1, none, INVERT
wait 1 s

#define LED0 porta.2 ;pin 1


#define LED1 porta.3 ;pin 2
#define LED2 porta.4 ;pin 3

;----- Variables

dim addr, reg, value,location as byte


addr = 255
reg = 255
value = 255
location = 0
mempointer = 255

;----- Program

dir LED0 out ;0, 1 and 2 are outputs (LEDs)


dir LED1 out ;0, 1 and 2 are outputs (LEDs)
dir LED2 out ;0, 1 and 2 are outputs (LEDs)

361
set LED0 off
set LED1 off
set LED2 off

#define SerialControlPort portb.3


dir SerialControlPort in

'Set up interrupt to process I2C

dir I2C_CLOCK in ; required to input for MSSP module


dir I2C_DATA in ; required to input for MSSP module
SSPADD=I2C_ADDRESS ; Slave address
SSPSTAT=b'00000000' ; configuration
SSPCON=b'00110110' ; configuration
PIE1.SSPIE=1 ; enable interrupt

repeat 3 ;flash LEDs


set LED0 on
set LED1 on
set LED2 on
wait 50 ms
set LED0 off
set LED1 off
set LED2 off
wait 100 ms
end Repeat

oldvalue = 255 ; old value, set up value only


oldreg = 255 ; old value, set up value only

UpdateLEDS ; call method to set LEDs


; set up interrupt
On Interrupt SSP1Ready call I2C_Interrupt

do forever
if reg <> oldreg then ; only process when the reg is a new value
oldreg = reg ; retain old value
show = 1 ; its time to show the LEDS!
if value <> oldvalue then ; logic for tracking old values. You only want to
update terminal once per change
oldvalue = value
show = 1
end if
end if

UpdateLEDS ; Update date LEDs

362
; update serial terminal
if show = 1 and SerialControlPort = 1 then

SerPrint 1, "0x"+hex(addr)
SerSend 1,9

SerPrint 1, STR(reg)
SerSend 1,9

SerPrint 1, STR(value)
SerSend 1,10
SerSend 1,13

show = 0
end if
loop

Sub I2C_Interrupt
' handle interrupt
IF SSPIF=1 THEN ; its a valid interrupt

IF SSPSTAT.D_A=0 THEN ; its an address coming in!


addr=SSPBUF
IF addr=I2C_ADDRESS THEN ; its our address

mempointer = 0 ; set the memory pointer. This code emulates an


EEPROM!

end if
IF addr = ( I2C_ADDRESS | 1 ) THEN ; its our write address
CKP = 0 ; acknowledge command
; If the SDA line was low (ACK), the transmit data must be
loaded into
; the SSPBUF register which also loads the SSPSR
; register. Then, pin RB4/SCK/SCL should be enabled
; by setting bit CKP.

mempointer = 10 ; set a pointer to track incoming write


reqests
if I2C_DATA = 0 then
SSPBUF = 0x22
CKP = 1
readpointer = 0x55
end if
end if

else

363
if SSPSTAT.P = 1 then ' Stop bit has been detected - out of
sequence
' handle event
end if

IF SSPSTAT.S = 1 THEN ' Start bit has been detected - out of


sequence
' handle event
END IF

IF SSPSTAT.R_W = 0 THEN ' Write operations requested

SELECT CASE mempointer


CASE 0
reg = SSPBUF ' incoming value
mempointer++ ' increment our counter
CASE 1
value = SSPBUF ' incoming value
mempointer++ ' increment our counter
CASE ELSE
dummy = SSPBUF ' incoming value
END SELECT

ELSE ' Read operations


SSPBUF = readpointer ' incoming value
readpointer++ ' increment our counter

END IF
END IF
CKP = 1 ' acknowledge command
SSPOV = 0 ' acknowledge command
END IF
SSPIF=0
END SUB

sub UpdateLEDS

select case reg ;now turn proper LED on or off


case 0
if value = 1 then
set LED0 on
else
set LED0 off
end if

364
case 1
if value = 1 then
set LED1 on
else
set LED1 off
end if

case 2
if value = 1 then
set LED2 on
else
set LED2 off
end if

end select

End Sub

Supported in <HI2C.H>

HI2CRestart

Syntax:

HI2CRestart

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

If the HI2C routines are operating in Master mode, this command will send a start and restart
condition in a single command.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2Restart

Example:

365
do
HI2CReStart ;generate a start signal
HI2CSend(eepDev) ;inidcate a write
loop While HI2CAckPollState

HI2CSend(eepAddr_H) ;as two bytes


HI2CSend(eepAddr)
HI2CReStart
HI2CSend(eepDev + 1) ;indicate a read

eep_i = 0 ;loop consecutively


do while (eep_i < eepLen) ;these many bytes
eep_j = eep_i + 1 ;arrays begin at 1 not 0
if (eep_i < (eepLen - 1)) then
HI2CReceive(eepArray(eep_j), ACK) ;more data to get
else
HI2CReceive(eepArray(eep_j), NACK ) ;send NACK on last byte
end if
eep_i++ ;get set for next
loop
HI2CStop

Supported in <HI2C.H>

HI2CSend

Syntax:

HI2CSend data

Command Availability:

Only available for microcontrollers with the MSSP module.

Explanation:

The HI2CSend command will send data through the I2C connection. If in master mode, HI2CSend will
send the data immediately. If in slave mode, HI2CSend will wait for the master to request the data
before sending.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

366
HI2C2Send data

Example:

This example code retrieves multiple bytes from an EEPROM memory device.

do
HI2CReStart ;generate a start signal
HI2CSend(eepDev) ;indicate a write
loop While HI2CAckPollState

HI2CSend(eepAddr_H) ;as two bytes


HI2CSend(eepAddr)
HI2CReStart
HI2CSend(eepDev + 1) ;indicate a read

eep_i = 0 ;loop consecutively


do while (eep_i < eepLen) ;these many bytes
eep_j = eep_i + 1 ;arrays begin at 1 not 0
if (eep_i < (eepLen - 1)) then
HI2CReceive(eepArray(eep_j), ACK) ;more data to get
else
HI2CReceive(eepArray(eep_j), NACK ) ;send NACK on last byte
end if
eep_i++ ;get set for next
loop
HI2CStop

Supported in <HI2C.H>

HI2CStart

Syntax:

HI2CStart

Command Availability:

Only available for microcontrollers with the MSSP module..

Explanation:

If the HI2C routines are operating in Master mode, this command will send a start condition. If
routines are in Slave mode, it will pause the program until a start condition is sent by the master. It

367
should be placed at the start of every I2C transmission.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2Start

Example:

Please see HI2CSend and HI2CReceive for examples.

Supported in <HI2C.H>

HI2CStartOccurred

Syntax:

HI2CStartOccurred

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

Check if a start condition has occurred since the last run of this function

Only used in slave mode.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2StartOccurred

Supported in <HI2C.H>

HI2CMode

Syntax:

HI2CMode Master | Slave

368
Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

Sets the microcontroller to either a Master device or a Slave device.

Only used in slave mode

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2Mode Master | Slave

Supported in <HI2C.H>

HI2CSetAddress

Syntax:

HI2CSetAddress address_number

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

Sets the microcontroller address number in Slave mode.

Only used in slave mode.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2SetAddress address_number

Supported in <HI2C.H>

HI2CStop

Syntax:

369
HI2CStop

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

HI2CStop should be called at the end of every I2C transmission.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2Stop

Example:

Please see HI2CSend and HI2CReceive for an example.

Supported in <HI2C.H>

HI2CStopped

Syntax:

HI2CStopped

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

In Slave mode only. Check if start condition received since last used of HI2CStopped.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2Stopped

Supported in <HI2C.H>

370
HI2CWaitMSSP

Syntax:

HI2CWaitMSSP

Command Availability:

Only available for microcontrollers with the hardware I2C or TWI module.

Explanation:

The methods sets the global byte variable HI2CWaitMSSPTimeout to 255 ( or True ) if the MSSP module
has timeout during operations.

HI2CWaitMSSPTimeout can tested for the status of the I2C bus.

Note:

This command is also available on microcontrollers with a second hardware I2C port.

HI2C2WaitMSSP

Supported in <HI2C.H>

371
Sound
This is the Sound section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Sound Overview

Introduction:

These Great Cow BASIC methods generate tones of a given frequency and duration.

Method Controls

Tone Generate a specified tone for a specified duration in terms of a frequency of a specified
Mhz and units of 10ms

ShortTon Generate a specified tone for a specified duration in terms of a frequency of a 10Mhz and
e units of 1ms

Play Play a tune string. The format of the string is the QBASIC play command.

PlayRTTT Play a tune string. The format of the string is the Nokia cell phone RTTTL format.
L

Relevant Constants:

These constants are used to control settings for the tone generation routines. To set them, place a line
in the main program file that uses #define to assign a value to the particular constant.

Constant Name Controls Default Value

SoundOut The output pin to produce sound on N/A - Must be defined

Note: If an exact frequency is required, or a smaller program is needed, these routines should not be
used. Instead, you should use code like this:

Repeat count
PulseOut SoundOut, period us
Wait period us
End Repeat

Set count and period to the appropriate values as follows:

period to 1000000 / desired frequency / 2


count to desired duration / period.

372
Tone

Syntax:

Tone Frequency, Duration

Command Availability:

Available on all microcontrollers.

Explanation:

This command will produce the specified tone for the specified duration. Frequency is measured in Hz,
and Duration is in 10 ms units.

Please note that this command may not produce the exact frequency specified. While it is accurate
enough for error beeps and small pieces of monophonic music, it should not be used for anything that
requires a highly precise frequency.

Example:

'Sample program to produce a constant A note (440 Hz)


'on PORTB bit 1.
#chip 16F877A, 20
#define SoundOut PORTB.1

Do
Tone 440, 1000
Loop

For more help, see Sound Overview

ShortTone

Syntax:

ShortTone Frequency, Duration

Command Availability:

Available on all microcontrollers.

Explanation:

This command will produce the specified tone for the specified duration. Frequency is measured in

373
units of 10 Hz, and Duration is in 1 ms units. Please note that this command may not produce the exact
frequency specified. While it is accurate enough for error beeps and small pieces of monophonic
music, it should not be used for anything that requires a highly precise frequency.

Example:

'Sample program to produce a tone on PORTB bit 1, based on the


'reading of an LDR on AN0 (usually PORTA bit 0).

#chip 16F88, 20
#define SoundOut PORTB.1

Dir PORTA.0 In

Do
ShortTone ReadAD(AN0), 100
Loop

For more help, see Sound Overview

Play

Syntax:

Play SoundPlayDataString

You must specify the following include and the port of the sound device.

#include <songplay.h>
#define SOUNDOUT PORTN.N

Command Availability:: Available on all microcontrollers.

Explanation: This command will plays a QBASIC sequence of notes. The SoundPlayDataString is a
string representing a musical note or notes to play where Notes are A to G.

Comman Description
d

A-G May be followed by length: 2 = half note, 4 = quarter, also may be followed by # or + (sharp)
or - (flat).

On Sets current octave. n is octave from 0 to 6

Pn Pause playing. n is length of rest

374
Comman Description
d

Ln: Set default note length. n = 1 to 8.

< or > Change down or up an octave

Tn: Sets tempo in L4s/minute. n = 32 to 255, default 120.

Nn Play note n. n = 0 to 84, 0 = rest.

Unsupported QBASIC commands are

Comman Description
d

M Play mode

. Changes note length

For more information on the QBASIC PLAY command set, see


https://en.wikibooks.org/wiki/QBasic/Appendix

Example:

'Sample program to play a string


'on PORTB bit 1.
#chip 16F877A, 20
#include <songplay.h>
#define SoundOut PORTB.1

play "C C# C C#"

For more help, see Sound Overview

Play RTTTL

Syntax:

PlayRTTTL SoundPlayRTTTLDataString

You must specify the following include and the port of the sound device.

#include <songplay.h>
#define SOUNDOUT PORTN.N

375
Command Availability:: Available on all microcontrollers.

Explanation: This command will play a sequence of notes in the Nokia RTTTL string format.

The SoundPlayRTTTLDataString is a string representing a musical note or notes to play where Notes
are A to G. This format and information below is credited to WikiPedia, see here. To be recognized by
ringtone programs, an RTTTL/Nokring format ringtone must contain three specific elements: name,
settings, and notes. For example, here is the RTTTL ringtone for Haunted House:

HauntHouse: d=4,o=5,b=108: 2a4, 2e, 2d#, 2b4, 2a4, 2c, 2d, 2a#4, 2e., e, 1f4, 1a4, 1d#, 2e., d, 2c., b4, 1a4,
1p, 2a4, 2e, 2d#, 2b4, 2a4, 2c, 2d, 2a#4, 2e., e, 1f4, 1a4, 1d#, 2e., d, 2c., b4, 1a4

The three parts are separated by a colon.

• Part 1: name of the ringtone (here: "HauntHouse"), a string of characters represents the name of
the ringtone

• Part 2: settings (here: d=4,o=5,b=108), where "d=" is the default duration of a note. In this case, the
"4" means that each note with no duration specifier (see below) is by default considered a quarter
note. "8" would mean an eighth note, and so on. Accordingly, "o=" is the default octave. There are
four octaves in the Nokring/RTTTL format. And "b=" is the tempo, in "beats per minute".

• Part 3: the notes. Each note is separated by a comma and includes, in sequence: a duration
specifier, a standard music note, either a, b, c, d, e, f or g, and an octave specifier. If no duration or
octave specifier are present, the default applies.

Example 1:

#chip 16f877a
#include <songplay.h>

#define SOUNDOUT PORTA.4


PlayRTTTL "HauntHouse: d=4,o=5,b=108: 2a4, 2e, 2d#, 2b4, 2a4, 2c, 2d, 2a#4, 2e., e,
1f4, 1a4, 1d#, 2e., d, 2c., b4, 1a4, 1p, 2a4, 2e, 2d#, 2b4, 2a4, 2c, 2d, 2a#4, 2e., e,
1f4, 1a4, 1d#, 2e., d, 2c., b4, 1a4"

Example 2:

376
#chip 16f877a
#include <songplay.h>

'Defines
#define SoundOut PORTC.0

Dir SoundOut Out


Dim SoundPlayRTTTLDataString as String

wait 1 s
SoundPlayRTTTLDataString =
"Thegood,:d=4,o=6,b=63:32c,32f,32c,32f,c,8g_5,8a_5,f5,8p,32c,32f,32c,32f,c,8g_5,8a_5,d_"
PlayRTTTL(SoundPlayRTTTLDataString)

wait 1 s
SoundPlayRTTTLDataString
="LedZeppel:d=4,o=6,b=80:8g,16p,8f_,16p,8f,16p,8e,16p,8d,8a5,8c,16p,8b5,16p,a_5,8a5,16f5,
16e5,16d5,8p,16p,16a_5,16a_5,16a_5,8p,16p,16b5,16b5,16b5,8p,16p,16b5,16b5,16b5,8p,16p,16c
,16c,16c,8p,16p,16c,16c,16c"
PlayRTTTL(SoundPlayRTTTLDataString)

Do Forever
Loop
End

For more help, see Sound Overview

377
Timers
This is the Timers section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Timer Overview

Great Cow BASIC supports methods to set, clear, read, start and stop the microcontroller timers.

Great Cow BASIC supports the following timers.

Timer 0
Timer 1
Timer 2
Timer 3
Timer 4
Timer 5
Timer 6
Timer 7
Timer 8
Timer 10
Timer 12

Not all of these timers available on all microcontrollers. For example, if a microcontroller has three
timers, then typically only Timer0, Timer1 and Timer2 will be available.

Please refer to the datasheet for your microcontroller to determine the supported timers and if a
specific timer is 8-bit or 16-bit.

Calculating a Timer Prescaler:

To initialise and change the timers you may have to change the Prescaler.

A Prescaler is an electronic counting circuit used to reduce a high frequency electrical signal to a lower
frequency by integer division. The prescaler takes the basic timer clock frequency and divides it by
some value before being processed by the timer, according to how the Prescaler register(s) are
configured. The prescaler values that may be configured might be limited to a few fixed values, see the
timer specfic page in this Help file or refer to the datasheet.

To use a Prescaler some simple integer maths is required, however, when calculating the Prescaler
there is often be a tradeoff between resolution, where a high resolution requires a high clock
frequency and range where a high clock frequency willl cause the timer to overflow more quickly. For
example, achieving 1 us resolution and a 1 sec maximum period using a 16-bit timer may require some
clever thinking when using 8-bit timers. Please ask for advice via the Great Cow BASIC forum, or,
search for some of the many great resources on the internet to calculate a Prescaler value.

378
Common Langauge:

Using timers has the following terms /common langauge. This following paragraph is intended to
explain the common language.

The Oscillator (OSC) is the system clock, this can be sourced from an internal or external source, OSC is
same the as microcontroller Mhz. This is called the the Frequency of the OSCillator (FOSC) or the
System Clock.

On a Microchip PIC microcontroller, one machine code instruction is executed for every four system
clock pulses.
This means that instructions are executed at a frequency of FOSC/4.
The Microchip PIC datasheets call this FOSC/4 or FOSC4.
All Microchip PIC timer prescales are based on the FOSC/4, not the FOSC or the System Clock.
As Prescale are based upon FOSC/4, you must use FOSC/4 in your timer calculations to get the results
you expect.
All Prescale and Postscale values are integer numbers.

On Atmel AVR microcontroller, most machine code instructions will execute in a single clock pulse.

Timer differences between Microchip PIC and Atmel AVR microcontrollers:

Initialising a timer for a Microchip PIC microcontroller may not operate as expected when using the
same code for an Atmel AVR microcontroller by simply changing the #chip definition. You must
recalculate the Prescaler of a timer when moving timer parameters between Microchip PIC and Atmel
AVR microcontrollers. And, of course, the same when moving timer parameters between Atmel AVR
and Microchip PIC microcontrollers.

Timer Best Practices:

Initialising microcontrollers with very limited RAM using Great Cow BASIC needs carefull
consideration. RAM may be need to be optimised by using ASM to control the timers. You can use Great
Cow BASIC to create the timer related Great Cow BASIC ASM code then manually edit the Great Cow
BASIC ASM to optmise RAM usage. Add your revised and optimised ASM back into your program and
then remove the no longer required calls the the Great Cow BASIC methods. If you need advice on this
subject please ask for advice via the Great Cow BASIC forum.

ClearTimer

Syntax:

379
ClearTimer TimerNo

Command Availability:

Available on all Microchip PIC and Atmel AVR microcontrollers with built in timer modules.

Explanation:

ClearTimer is used to clear the specified timer to a value of 0.

Cleartimer can be used on-the-fly if desired, so there is no requirement to stop the timer first.

Example:

.....
'Clear timer 1
ClearTimer 1
.....

See also, InitTimer1 article for an example.

InitTimer0

Syntax:

InitTimer0 source, prescaler

Command Availability:

Available on all microcontrollers with a Timer 0 module.

See also see: InitTimer0 8bit/16bit for support for microcontrollers with a 8 bit/16 bit Timer 0 module.

Explanation:

InitTimer0 will set up timer 0.

Parameters are required as detailed in the table below:

Paramet Description
er

source The clock source for this specific timer. Can be either Osc or Ext where`Osc` is an internal
oscillator and Ext is an external oscillator.

380
Paramet Description
er

prescaler The value of the prescaler for this specific timer. See the tables below for permitted values
for Microchip PIC or the Atmel AVR microcontrollers.

When the timer overflows from 255 to 0, a Timer0Overflow interrupt will be generated. This can be
used in conjunction with On Interrupt to run a section of code when the overflow occurs.

Microchip PIC microcontrollers:

On Microchip PIC microcontrollers where the prescaler rate select bits are in the range of 2 to 256 you
should use one of the following constants. If the prescaler rate select bits are in the range of 1 to 32768
then see the subsequent table.

Prescaler Value Primary GCB Constant Constant Equates


to value

1:2 PS0_2 0

1:4 PS0_4 1

1:8 PS0_8 2

1:16 PS0_16 3

1:32 PS0_32 4

1:64 PS0_64 5

1:128 PS0_128 6

1:256 PS0_256 7

These correspond to a prescaler of between 1:2 and 1:256 of the oscillator speed where the oscillator
speed is (FOSC/4). The prescaler applies to both the internal oscillator or the external clock.

Atmel AVR microcontrollers:

On Atmel AVR microcontrollers prescaler must be one of the following constants:

The prescaler will only apply when the timer is driven from the Osc the internal oscillator - the
prescaler has no effect when the external clock source is specified.

381
Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:1 PS_1 PS_0_1 1

1:8 PS_8 PS_0_8 2

1:64 PS_64 PS_0_64 3

1:256 PS_256 PS_0_256 4

1:1024 PS_1024 PS_0_1024 5

Example:

This code uses Timer 0 and On Interrupt to generate a Pulse Width Modulation signal, that will allow
the speed of a motor to be easily controlled.

#chip 16F88, 8
#config osc = int

#define MOTOR PORTB.0

'Call the initialisation routine


InitMotorControl

'Main routine
Do
'Increase speed to full over 2.5 seconds
For Speed = 0 to 100
MotorSpeed = Speed
Wait 25 ms
Next
'Hold speed
Wait 1 s
'Decrease speed to zero over 2.5 seconds
For Speed = 100 to 0
MotorSpeed = Speed
Wait 25 ms
Next
'Hold speed
Wait 1 s
Loop

'Setup routine
Sub InitMotorControl

382
'Clear variables
MotorSpeed = 0
PWMCounter = 0

'Add a handler for the interrupt


On Interrupt Timer0Overflow Call PWMHandler

'Set up the timer using the internal oscillator with a prescaler of 1/2 (Equates
to 0)
'Timer 0 starts automatically on a Microchip PIC microcontroller, therefore,
StartTimer is not required.
InitTimer0 Osc, PS0_2

End Sub

'PWM sub
'This will be called when Timer 0 overflows
Sub PWMHandler
If MotorSpeed > PWMCounter Then
Set MOTOR On
Else
Set MOTOR Off
End If
PWMCounter += 1
If PWMCounter = 100 Then PWMCounter = 0
End Sub

Supported in <TIMER.H>

InitTimer0 8bit/16bit

Syntax:

InitTimer0 source, prescaler, postscaler

Command Availability:

Available on microcontrollers with a Timer 0 with an 8 bit/16 bit timer module.

Timer 0 on Microchip PIC 18(L)F, as well as small number of 18C and 16(L)F microcontrollers, can be
configured for either 8-bit or 16-bit operation.

The default operation is as an 8-bit timer.

Refer to the datasheet for your microcontroller to determine if it supports both 8-bit and 16-bit
operation.

383
See also see: InitTimer0 for microcontroller with only an 8 bit Timer 0 module.

Explanation:

InitTimer0 will set up timer 0.

Parameters are required as detailed in the table below:

Paramet Description
er

source The clock source for this specific timer. Can be either Osc or Ext where`Osc` is an internal
oscillator and Ext is an external oscillator.

prescaler The value of the prescaler for this specific timer. See the tables below for permitted values
for Microchip PIC or the Atmel AVR microcontrollers.

When the timer overflows to 0, a Timer0Overflow interrupt will be generated. This can be used in
conjunction with On Interrupt to run a section of code when the overflow occurs.

On Microchip PIC microcontrollers where the prescaler rate select bits are in the range of 2 to 256 you
should use one of the following constants. If the prescaler rate select bits are in the range of 1 to 32768
then see the subsequent table.

Prescaler Value Primary GCB Constant Constant Equates


to value

1:2 PS0_2 0

1:4 PS0_4 1

1:8 PS0_8 2

1:16 PS0_16 3

1:32 PS0_32 4

1:64 PS0_64 5

1:128 PS0_128 6

1:256 PS0_256 7

These correspond to a prescaler of between 1:2 and 1:256 of the oscillator speed where the oscillator
speed is (FOSC/4). The prescaler applies to both the internal oscillator or the external clock.

Timer0 Match (8/16-bit Timer0)

384
On Chips with 8/16-bit Timer0, when in 8-bit mode, Timer0 behaves much like Timers2/4/6. In 8-bit
mode the TMR0H register does not increment. It instead becomes the Period or Match register and is
aliased as "PR0" (Period Register 0).

In 8-bit mode, Timer0 does not technically overflow. Instead when TMR0L increments and matches the
value in the PR0 register, TMR0L is reset to 0. The interrupt flag bit (TMR0IF) bit is then set (based upon
Postscaler).

The default value in the PR0 "match register" is 255. This value can be set/changed in the user program
to set/change the timer period. This can be used to fine tune the timer period.

Microchip PIC microcontrollers 16bit Timer 0 support:

To configure PIC Timer 0 for 16_bit operation add the following line to the source code.

#define TMR0_16bit

As shown above, where Timer 0 supports 16bit you must use the following syntax:

InitTimer0 source, prescaler, postscaler

An example is shown below using the Great Cow BASIC constants. See the tables below for the
constants.

InitTimer0 Osc, PRE0_256 + TMR0_HFINTOSC , POST0_2

In this example specfic values have been passed to the method. Great Cow BASIC supports passing
specfic values to setup Timer 0. These specfic values be obtained from the MicroChip Configurator.

InitTimer0 Osc, 0x91 , 0x48 ' Where these values are specfic to the timer
setup.

Great Cow BASIC constants as detailed in the table below:

385
Paramet Description
er

source The clock source for this specific timer. Can be either Osc or Ext where`Osc` is an internal
oscillator and Ext is an external oscillator.

prescaler The value of the prescaler for this specific timer. See the tables below for permitted values
for Microchip PIC or the Atmel AVR microcontrollers. You may also be required to specify
one of the following clock sources.

TMR0_CLC1
TMR0_SOSC
TMR0_LFINTOSC
TMR0_HFINTOSC
TMR0_FOSC4
TMR0_T0CKIPPS_Inverted
TMR0_T0CKIPPS_True

You should use a simple addition to concatenate the prescaler with a specific clock source.
For example.

PRE0_16 + TMR0_HFINTOSC

postscale See the tables below for permitted values for Microchip.
r Also, refer to the specific datasheet postcaler values.

Microchip PIC microcontrollers where the prescaler rate select bits are in the range of 1 to 32768 you
should use one of the following constants.

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PRE0_1 0

1:2 PRE0_2 1

1:4 PRE0_4 2

1:8 PRE0_8 3

1:16 PRE0_16 4

1:32 PRE0_32 5

1:64 PRE0_64 6

1:128 PRE0_128 7

1:256 PRE0_256 8

386
Prescaler Value Primary GCB Constant Constant Equates
to value

1:512 PRE0_512 9

1:1024 PRE0_1024 10

1:2048 PRE0_2048 11

1:4096 PRE0_4096 12

1:8192 PRE0_8192 13

1:16384 PRE0_16384 14

1:32768 PRE0_32768 15

These correspond to a prescaler of between 1:1 and 1:32768 of the oscillator speed where the oscillator
speed is (FOSC/4). The prescaler applies to both the internal oscillator or the external clock.

On Microchip PIC microcontroller that require postscaler is can be one of the following constants
where the Postscaler Rate Select bits are in the range of 1 to 16.

Postcaler Value Primary GCB Constant Use Numeric Constant

1:1 POST0_1 0

1:2 POST0_2 1

1:3 POST0_3 2

1:4 POST0_4 3

1:5 POST0_5 4

1:6 POST0_6 5

1:7 POST0_7 6

1:8 POST0_8 7

1:9 POST0_9 8

1:10 POST0_10 9

1:11 POST0_11 10

1:12 POST0_12 11

1:13 POST0_13 12

1:14 POST0_14 13

387
Postcaler Value Primary GCB Constant Use Numeric Constant

1:15 POST0_15 14

1:16 POST0_16 15

Example:

This code uses Timer 0 and On Interrupt to generate a Pulse Width Modulation signal, that will allow
the speed of a motor to be easily controlled.

#chip 16F88, 8
#config osc = int

#define MOTOR PORTB.0

'Call the initialisation routine


InitMotorControl

'Main routine
Do
'Increase speed to full over 2.5 seconds
For Speed = 0 to 100
MotorSpeed = Speed
Wait 25 ms
Next
'Hold speed
Wait 1 s
'Decrease speed to zero over 2.5 seconds
For Speed = 100 to 0
MotorSpeed = Speed
Wait 25 ms
Next
'Hold speed
Wait 1 s
Loop

'Setup routine
Sub InitMotorControl
'Clear variables
MotorSpeed = 0
PWMCounter = 0

388
'Add a handler for the interrupt
On Interrupt Timer0Overflow Call PWMHandler

'Set up the timer using the internal oscillator with a prescaler of 1/2 (Equates
to 0)
'Timer 0 starts automatically on a Microchip PIC microcontroller, therefore,
StartTimer is not required.
InitTimer0 Osc, PS0_2

End Sub

'PWM sub
'This will be called when Timer 0 overflows
Sub PWMHandler
If MotorSpeed > PWMCounter Then
Set MOTOR On
Else
Set MOTOR Off
End If
PWMCounter += 1
If PWMCounter = 100 Then PWMCounter = 0
End Sub

Supported in <TIMER.H>

InitTimer1

Syntax:

InitTimer1 source, prescaler

Command Availability:

Available on all microcontrollers with a Timer 1 module.

Explanation:

InitTimer1 will set up timer 1.

Parameters are required as detailed in the table below:

389
Paramet Description
er

source The clock source for this specific timer. Can be either Osc, Ext or ExtOsc where:
Osc is an internal oscillator.
Ext is an external oscillator.
ExtOsc is an external oscillator and only available on a Microchip PIC microcontroller.
Enhanced Microchip PIC microcontrollers with a dedicated TMRxCLK register support
additional clock sources. This includes, but limited to, the following devices: 16F153xx,
16F16xx, 16F188xx and 18FxxK40 Microchip PIC microcontroller series. On these devices
the clock source can be one of the following: Osc is an internal oscillator which is the same
source as FOSC4.
Ext is an external oscillator which is the same source as TxXKIPPS.
ExtOsc is an external oscillator which is the same source as SOSC.
FOSC is an internal oscillator which is the Frequency of the OSCillator.
FOSC4 is an internal oscillator which is the Frequency of the OSCillator divided by 4.
SOSC is an external oscillator which is the same source as SOSC.
MFINTOSC is an internal 500KHz internal clock oscillator.
LFINTOSC is an internal 31Khz internal clock oscillator.
HFINTOSC is an oscillator as specified within the datasheet for each specific microcontroller.
TxCKIPPS is an oscillator input on TxCKIPPS Pin.

prescaler The value of the prescaler for this specific timer. See the tables below for permitted vales
for Microchip PIC or the Atmel AVR microcontrollers.

When the timer overflows an interrupt event will be generated. This interrupt event can be used in
conjunction with On Interrupt to run a section of code when the interrupt event occurs.

Microchip PIC microcontrollers:

On Microchip PIC microcontrollers prescaler must be one of the following constants:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS1_1 0

1:2 PS1_2 16

1:4 PS1_4 32

1:8 PS1_8 48

These correspond to a prescaler of between 1:2 and 1:8 of the oscillator (FOSC/4) speed. The prescaler
will apply to either the oscillator or the external clock input.

390
Atmel AVR microcontrollers:

On the majority of Atmel AVR microcontrollers prescaler must be one of the following constants:

The prescaler will only apply when the timer is driven from the Osc the internal oscillator - the
prescaler has no effect when the external clock source is specified.

Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:0 PS_0 PS_1_0 0

1:1 PS_1 PS_1_1 1

1:8 PS_8 PS_1_8 2

1:64 PS_64 PS_1_64 3

1:256 PS_256 PS1_256 4

1:1024 PS_1024 PS_1_1024 5

On Atmel AVR ATtiny15/25/45/85/216/461/861 microcontrollers prescaler must be one of the following


constants:

The prescaler will only apply when the timer is driven from the Osc the internal oscillator - the
prescaler has no effect when the external clock source is specified.

Prescaler Value Primary GCB Constant Constant Equates


to value

1:0 PS_1_0 0

1:1 PS_1_1 1

1:2 PS_1_2 2

1:4 PS_1_4 3

1:8 PS_1_8 4

1:16 PS_1_16 5

1:32 PS_1_32 6

1:64 PS_1_64 7

1:128 PS_1_128 8

391
Prescaler Value Primary GCB Constant Constant Equates
to value

1:256 PS_1_256 9

1:512 PS_1_512 10

1:1024 PS_1_1024 11

1:2048 PS_1_2048 12

1:4096 PS_1_4096 13

1:8192 PS_1_8192 14

1:16384 PS_1_16384 15

Example 1 (Microchip):

This example will measure that time that a switch is depressed (or on) and will write the results to the
EEPROM.

392
#chip 16F819, 20
#define Switch PORTA.0

Dir Switch In
DataCount = 0

'Initilise Timer 1
InitTimer1 Osc, PS1_8

Dim TimerValue As Word

Do
ClearTimer 1
Wait Until Switch = On
StartTimer 1
Wait Until Switch = Off
StopTimer 1

'Read the timer


TimerValue = Timer1

'Log the timer value


EPWrite(DataCount, TimerValue_H)
EPWrite(DataCount + 1, TimerValue)
DataCount += 2
Loop

Example 2 (Atmel AVR):

This example will flash the yellow LED on an Arduino Uno (R3) once every second.

#Chip mega328p, 16 'Using Arduino Uno R3

#define LED PORTB.5


Dir LED OUT

Inittimer1 OSC, PS_256


Starttimer 1
Settimer 1, 3200 ;Preload Timer

393
On Interrupt Timer1Overflow Call Flash_LED

Do
'Wait for interrupt
loop

Sub Flash_LED
Settimer 1, 3200 'Preload timer
pulseout LED, 100 ms
End Sub

Supported in <TIMER.H>

InitTimer2

Syntax: (MicroChip PIC)

InitTimer2 prescaler, postscaler

Syntax: (Atmel AVR)

InitTimer2 source, prescaler

Command Availability:

Available on all microcontrollers with a Timer 2 module.

InitTimer2 will set up timer 2, according to the settings given.

Explanation:(MicroChip PIC)

Parameters for this timer are detailed in the table below:

Paramete Description
r

prescaler The value of the prescaler for this specific timer. See the tables below for permitted
values.

394
Paramete Description
r

postscaler The value of the postscaler for this specific timer. See the tables below for permitted
values.

Table 1

prescaler can be one of the following settings, if you MicroChip microcontroller has the T2CKPS4 bit
then refer to table 2:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS2_1 0

1:4 PS2_4 1

1:16 PS2_16 2

1:64 PS2_64 3

Table 2

Note that a 1:64 prescale is only avaialable on certain midrange microcontrollers. Please refer to the
datasheet to determine if a 1:64 prescale is supported by a spectific microcontroller.

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS2_1 0

1:2 PS2_2 1

1:4 PS2_4 2

1:8 PS2_8 3

1:16 PS2_16 4

1:32 PS2_32 5

1:64 PS2_64 6

1:128 PS2_128 7

Table 3

postscaler slows the rate of the interrupt generation (or WDT reset) from a counter/timer by dividing it

395
down.

On Microchip PIC microcontroller one of the following constants where the Postscaler Rate Select bits
are in the range of 1 to 16.

Postcaler Value Use Numeric Constant

1:1 Postscaler 0

1:2 Postscaler 1

1:3 Postscaler 2

1:4 Postscaler 3

1:5 Postscaler 4

1:6 Postscaler 5

1:7 Postscaler 6

1:8 Postscaler 7

1:9 Postscaler 8

1:10 Postscaler 9

1:11 Postscaler 10

1:12 Postscaler 11

1:13 Postscaler 12

1:14 Postscaler 13

1:15 Postscaler 14

1:16 Postscaler 15

Explanation:(Atmel AVR)

InitTimer2 will set up timer 2, according to the settings given.

source can be one of the following settings: Parameters for this timer are detailed in the table below:

Paramet Description
er

source The clock source for this specific timer. Can be either Osc or Ext where`Osc` is an internal
oscillator and Ext is an external oscillator.

396
prescaler for Atmel AVR Timer 2 is chip specific and can be selected from one of the two tables shown
below. Please refer to the datasheet determine which table to use and which prescales within that
table are supported by a specific Atmel AVR microcontroller.

Table1: Prescaler Rate Select bits are in the range of 1 to 1024

Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:0 PS_0 PS_2_0 1

1:1 PS_1 PS_2_1 1

1:8 PS_8 PS_2_8 2

1:64 PS_64 PS_2_64 3

1:256 PS_256 PS2_256 4

1:1024 PS_1024 PS_2_1024 5

Table 2: Prescaler Rate Select bits are in the range of 1 to 16384

Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:1 PS_2_1 none 1

1:2 PS_2_2 none 2

1:4 PS_2_4 none 3

1:8 PS_2_8 none 4

1:16 PS_2_16 none 5

1:32 PS_2_32 none 6

1:64 PS_2_64 none 7

1:128 PS_2_128 none 8

1:256 PS_2_256 none 9

1:512 PS_2_512 none 10

1:1024 PS_2_1024 none 11

1:2048 PS_2_2048 none 12

397
Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:4096 PS_2_4096 none 13

1:8192 PS_2_8192 none 14

1:16384 PS_2_16384 none 15

Example:

This code uses Timer 2 and On Interrupt to flash an LED every 200 timer ticks.

#chip 16F1788, 8
#config OSC = INTOSC

#DEFINE LED PORTA.1


DIR LED OUT

#Define Match_Val PR2 'PR2 is the timer 2 match register


Match_Val = 200 'Interrupt afer 200 timer ticks

On interrupt timer2Match call FlashLED 'Interrupt on match


Inittimer2 PS2_64, 15 'Prescale 1:64 /Postscale 1:16 (15)
Starttimer 2

Do
' Wating for interrupt on match val of 100
Loop

'This sub will be called when Timer 2 matches "Match_Val" (PR2)


SUB FlashLED
pulseout LED, 5 ms
END SUB

InitTimer3

Syntax:

InitTimer3 source, prescaler

Command Availability:

Available on all microcontrollers with a Timer 3 module.

398
Explanation:

InitTimer3 will set up timer 3.

Parameters are required as detailed in the table below:

Paramet Description
er

source The clock source for this specific timer. Can be either Osc, Ext or ExtOsc where:
Osc is an internal oscillator.
Ext is an external oscillator.
ExtOsc is an external oscillator and only available on a Microchip PIC microcontroller.
Enhanced Microchip PIC microcontrollers with a dedicated TMRxCLK register support
additional clock sources. This includes, but limited to, the following devices: 16F153xx,
16F16xx, 16F188xx and 18FxxK40 Microchip PIC microcontroller series On these devices
the clock source can be one of the following: Osc is an internal oscillator which is the same
source as FOSC4.
Ext is an external oscillator which is the same source as TxXKIPPS.
ExtOsc is an external oscillator which is the same source as SOSC.
FOSC is an internal oscillator which is the Frequency of the OSCillator.
FOSC4 is an internal oscillator which is the Frequency of the OSCillator divided by 4.
SOSC is an external oscillator which is the same source as SOSC.
MFINTOSC is an internal 500KHz internal clock oscillator.
LFINTOSC is an internal 31Khz internal clock oscillator.
HFINTOSC is an oscillator as specified within the datasheet for each specific microcontroller.
TxCKIPPS is an oscillator input on TxCKIPPS Pin.

prescaler The value of the prescaler for this specific timer. See the tables below for permitted vales
for Microchip PIC or the Atmel AVR microcontrollers.

When the timer overflows an interrupt event will be generated. This interrupt event can be used in
conjunction with On Interrupt to run a section of code when the interrupt event occurs.

Microchip PIC microcontrollers:

On Microchip PIC microcontrollers prescaler must be one of the following constants:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS3_1 0

1:2 PS3_2 16

1:4 PS3_4 32

1:8 PS3_8 48

399
These correspond to a prescaler of between 1:2 and 1:8 of the oscillator (FOSC/4) speed. The prescaler
will apply to either the oscillator or the external clock input.

Atmel AVR microcontrollers:

On the majority of Atmel AVR microcontrollers prescaler must be one of the following constants:

The prescaler will only apply when the timer is driven from the Osc the internal oscillator - the
prescaler has no effect when the external clock source is specified.

Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:0 PS_0 PS_3_0 1

1:1 PS_1 PS_3_1 1

1:8 PS_8 PS_3_8 2

1:64 PS_64 PS_3_64 3

1:256 PS_256 PS_3_256 4

1:1024 PS_1024 PS_3_1024 5

Supported in <TIMER.H>

InitTimer4

Syntax: (MicroChip PIC)

InitTimer4 prescaler, postscaler

Syntax: (Atmel AVR)

InitTimer4 source, prescaler

Command Availability:

Available on all microcontrollers with a Timer 4 module.

InitTimer4 will set up timer 4, according to the settings given.

400
Explanation:(MicroChip PIC)

Parameters for this timer are detailed in the table below:

Paramete Description
r

prescaler The value of the prescaler for this specific timer. See the tables below for permitted
values.

postscaler The value of the postscaler for this specific timer. See the tables below for permitted
values.

Table 1

prescaler can be one of the following settings, if you MicroChip microcontroller has the T4CKPS4 bit
then refer to table 2:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS4_1 0

1:4 PS4_4 1

1:16 PS4_16 2

1:64 PS4_64 3

Table 2

Note that a 1:64 prescale is only avaialable on certain midrange microcontrollers. Please refer to the
datasheet to determine if a 1:64 prescale is supported by a spectific microcontroller.

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS4_1 0

1:2 PS4_2 1

1:4 PS4_4 2

1:8 PS4_8 3

1:16 PS4_16 4

1:32 PS4_32 5

401
Prescaler Value Primary GCB Constant Constant Equates
to value

1:64 PS4_64 6

1:128 PS4_128 7

Table 3

postscaler slows the rate of the interrupt generation (or WDT reset) from a counter/timer by dividing it
down.

On Microchip PIC microcontroller one of the following constants where the Postscaler Rate Select bits
are in the range of 1 to 16.

Postcaler Value Use Numeric Constant

1:1 Postscaler 0

1:2 Postscaler 1

1:3 Postscaler 2

1:4 Postscaler 3

1:5 Postscaler 4

1:6 Postscaler 5

1:7 Postscaler 6

1:8 Postscaler 7

1:9 Postscaler 8

1:10 Postscaler 9

1:11 Postscaler 10

1:12 Postscaler 11

1:13 Postscaler 12

1:14 Postscaler 13

1:15 Postscaler 14

1:16 Postscaler 15

Explanation:(Atmel AVR)

402
InitTimer4 will set up timer 4, according to the settings given.

source can be one of the following settings: Parameters for this timer are detailed in the table below:

Paramet Description
er

source The clock source for this specific timer. Can be either Osc or Ext where`Osc` is an internal
oscillator and Ext is an external oscillator.

prescaler for Atmel AVR Timer 4 can be selected from the table below.

Prescaler Rate Select bits are in the range of 1 to 1024

Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:0 PS_0 PS_4_0 1

1:1 PS_1 PS_4_1 1

1:8 PS_8 PS_4_8 2

1:64 PS_64 PS_4_64 3

1:256 PS_256 PS4_256 4

1:1024 PS_1024 PS_4_1024 5

Example:

This code uses Timer 4 and On Interrupt to generate a 1ms pulse 20 ms.

403
#chip 18F25K80, 8
#config OSC =INTIO2

#DEFINE PIN3 PORTA.1


DIR PIN3 OUT

#Define Match_Val PR4 'PR4 is the timer 2 match register


Match_Val = 154 'Interrupt afer 154 Timer ticks (~20ms)

On interrupt timer4Match call PulsePin3 'Interrupt on match


Inittimer4 PS4_16, 15 'Prescale 1:64 /Postscale 1:16 (15)
Starttimer 4

Do
'Waiting for interrupt on match val of 154
Loop

Sub PulsePin3
pulseout Pin3, 1 ms
End Sub

InitTimer5

Syntax:

InitTimer5 source, prescaler

Command Availability:

Available on all microcontrollers with a Timer 5 module.

Explanation:

InitTimer5 will set up timer 5.

Parameters are required as detailed in the table below:

404
Paramet Description
er

source The clock source for this specific timer. Can be either Osc, Ext or ExtOsc where:
Osc is an internal oscillator.
Ext is an external oscillator.
ExtOsc is an external oscillator and only available on a Microchip PIC microcontroller.
Enhanced Microchip PIC microcontrollers with a dedicated TMRxCLK register support
additional clock sources. This includes, but limited to, the following devices: 16F153xx,
16F16xx, 16F188xx and 18FxxK40 Microchip PIC microcontroller series On these devices
the clock source can be one of the following: Osc is an internal oscillator which is the same
source as FOSC4.
Ext is an external oscillator which is the same source as TxXKIPPS.
ExtOsc is an external oscillator which is the same source as SOSC.
FOSC is an internal oscillator which is the Frequency of the OSCillator.
FOSC4 is an internal oscillator which is the Frequency of the OSCillator divided by 4.
SOSC is an external oscillator which is the same source as SOSC.
MFINTOSC is an internal 500KHz internal clock oscillator.
LFINTOSC is an internal 31Khz internal clock oscillator.
HFINTOSC is an oscillator as specified within the datasheet for each specific microcontroller.
TxCKIPPS is an oscillator input on TxCKIPPS Pin.

prescaler The value of the prescaler for this specific timer. See the tables below for permitted vales
for Microchip PIC or the Atmel AVR microcontrollers.

When the timer overflows an interrupt event will be generated. This interrupt event can be used in
conjunction with On Interrupt to run a section of code when the interrupt event occurs.

Microchip PIC microcontrollers:

On Microchip PIC microcontrollers prescaler must be one of the following constants:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS5_1 0

1:2 PS5_2 16

1:4 PS5_4 32

1:8 PS5_8 48

These correspond to a prescaler of between 1:2 and 1:8 of the oscillator (FOSC/4) speed. The prescaler
will apply to either the oscillator or the external clock input.

405
Atmel AVR microcontrollers:

On the majority of Atmel AVR microcontrollers prescaler must be one of the following constants:

The prescaler will only apply when the timer is driven from the Osc the internal oscillator - the
prescaler has no effect when the external clock source is specified.

Prescaler Value Primary GCB Constant Secondary GCB Constant Constant Equates
to value

1:0 PS_0 PS_5_0 0

1:1 PS_1 PS_5_1 1

1:8 PS_8 PS_5_8 2

1:64 PS_64 PS_5_64 3

1:256 PS_256 PS_5_256 4

1:1024 PS_1024 PS_5_1024 5

Supported in <TIMER.H>

InitTimer6

Syntax:

InitTimer6 prescaler, postscaler

Command Availability:

Available on Microchip microcontrollers with a Timer 6 module.

Explanation:

Parameters for this timer are detailed in the table below:

Paramete Description
r

prescaler The value of the prescaler for this specific timer. See the tables below for permitted
values.

postscaler The value of the postscaler for this specific timer. See the tables below for permitted
values.

406
Table 1

prescaler can be one of the following settings, if you MicroChip microcontroller has the T6CKPS4 bit
then refer to table 3:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS6_1 0

1:4 PS6_4 1

1:16 PS6_16 2

1:64 PS6_64 3

Table 2

Note that a 1:64 prescale is only avaialable on certain midrange microcontrollers. Please refer to the
datasheet to determine if a 1:64 prescale is supported by a spectific microcontroller.

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS6_1 0

1:2 PS6_2 1

1:4 PS6_4 2

1:8 PS6_8 3

1:16 PS6_16 4

1:32 PS6_32 5

1:64 PS6_64 6

1:128 PS6_128 7

Table 3

postscaler slows the rate of the interrupt generation (or WDT reset) from a counter/timer by dividing it
down.

On Microchip PIC microcontroller one of the following constants where the Postscaler Rate Select bits
are in the range of 1 to 16.

407
Postcaler Value Use Numeric Constant

1:1 Postscaler 0

1:2 Postscaler 1

1:3 Postscaler 2

1:4 Postscaler 3

1:5 Postscaler 4

1:6 Postscaler 5

1:7 Postscaler 6

1:8 Postscaler 7

1:9 Postscaler 8

1:10 Postscaler 9

1:11 Postscaler 10

1:12 Postscaler 11

1:13 Postscaler 12

1:14 Postscaler 13

1:15 Postscaler 14

1:16 Postscaler 15

InitTimer7

Syntax:

InitTimer7 source, prescaler

Command Availability:

Available on Microchip microcontrollers with a Timer 7 module.

Explanation:

InitTimer7 will set up timer 7.

Parameters are required as detailed in the table below:

408
Paramet Description
er

source The clock source for this specific timer. Can be either Osc, Ext or ExtOsc where:
Osc is an internal oscillator.
Ext is an external oscillator.
ExtOsc is an external oscillator and only available on a Microchip PIC microcontroller.
Enhanced Microchip PIC microcontrollers with a dedicated TMRxCLK register support
additional clock sources. This includes, but limited to, the following devices: 16F153xx,
16F16xx, 16F188xx and 18FxxK40 Microchip PIC microcontroller series. On these devices
the clock source can be one of the following: Osc is an internal oscillator which is the same
source as FOSC4.
Ext is an external oscillator which is the same source as TxXKIPPS.
ExtOsc is an external oscillator which is the same source as SOSC.
FOSC is an internal oscillator which is the Frequency of the OSCillator.
FOSC4 is an internal oscillator which is the Frequency of the OSCillator divided by 4.
SOSC is an external oscillator which is the same source as SOSC.
MFINTOSC is an internal 500KHz internal clock oscillator.
LFINTOSC is an internal 31Khz internal clock oscillator.
HFINTOSC is an oscillator as specified within the datasheet for each specific microcontroller.
TxCKIPPS is an oscillator input on TxCKIPPS Pin.

prescaler The value of the prescaler for this specific timer. See the tables below for permitted vales
for Microchip PIC or the Atmel AVR microcontrollers.

When the timer overflows an interrupt event will be generated. This interrupt event can be used in
conjunction with On Interrupt to run a section of code when the interrupt event occurs.

Microchip PIC microcontrollers:

On Microchip PIC microcontrollers prescaler must be one of the following constants:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS7_1 0

1:2 PS7_2 16

1:4 PS7_4 32

1:8 PS7_8 48

These correspond to a prescaler of between 1:2 and 1:8 of the oscillator (FOSC/4) speed. The prescaler
will apply to either the oscillator or the external clock input.

409
Supported in <TIMER.H>

InitTimer8

Syntax:

InitTimer8 source, prescaler

Command Availability:

Available on Microchip microcontrollers with a Timer 8 module.

Explanation:

Parameters for this timer are detailed in the table below:

Paramete Description
r

prescaler The value of the prescaler for this specific timer. See the tables below for permitted
values.

postscaler The value of the postscaler for this specific timer. See the tables below for permitted
values.

prescaler can be one of the following settings:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS8_1 0

1:4 PS8_4 1

1:16 PS8_16 2

1:64 PS8_64 3

Note that a 1:64 prescale is only avaialable on certain midrange microcontrollers. Please refer to the
datasheet to determine if a 1:64 prescale is supported by a spectific microcontroller.

410
postscaler slows the rate of the interrupt generation (or WDT reset) from a counter/timer by dividing it
down.

On Microchip PIC microcontroller one of the following constants where the Postscaler Rate Select bits
are in the range of 1 to 16.

Postcaler Value Use Numeric Constant

1:1 Postscaler 0

1:2 Postscaler 1

1:3 Postscaler 2

1:4 Postscaler 3

1:5 Postscaler 4

1:6 Postscaler 5

1:7 Postscaler 6

1:8 Postscaler 7

1:9 Postscaler 8

1:10 Postscaler 9

1:11 Postscaler 10

1:12 Postscaler 11

1:13 Postscaler 12

1:14 Postscaler 13

1:15 Postscaler 14

1:16 Postscaler 15

InitTimer10

Syntax:

InitTimer10 source, prescaler

Command Availability:

Available on Microchip microcontrollers with a Timer 10 module.

411
Explanation:

Parameters for this timer are detailed in the table below:

Paramete Description
r

prescaler The value of the prescaler for this specific timer. See the tables below for permitted
values.

postscaler The value of the postscaler for this specific timer. See the tables below for permitted
values.

prescaler can be one of the following settings:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS10_1 0

1:4 PS10_4 1

1:16 PS10_16 2

1:64 PS10_64 3

Note that a 1:64 prescale is only avaialable on certain midrange microcontrollers. Please refer to the
datasheet to determine if a 1:64 prescale is supported by a spectific microcontroller.

postscaler slows the rate of the interrupt generation (or WDT reset) from a counter/timer by dividing it
down.

On Microchip PIC microcontroller one of the following constants where the Postscaler Rate Select bits
are in the range of 1 to 16.

Postcaler Value Use Numeric Constant

1:1 Postscaler 0

1:2 Postscaler 1

1:3 Postscaler 2

412
Postcaler Value Use Numeric Constant

1:4 Postscaler 3

1:5 Postscaler 4

1:6 Postscaler 5

1:7 Postscaler 6

1:8 Postscaler 7

1:9 Postscaler 8

1:10 Postscaler 9

1:11 Postscaler 10

1:12 Postscaler 11

1:13 Postscaler 12

1:14 Postscaler 13

1:15 Postscaler 14

1:16 Postscaler 15

InitTimer12

Syntax:

InitTimer12 source, prescaler

Command Availability:

Available on Microchip microcontrollers with a Timer 12 module.

Explanation:

Parameters for this timer are detailed in the table below:

Paramete Description
r

prescaler The value of the prescaler for this specific timer. See the tables below for permitted
values.

413
Paramete Description
r

postscaler The value of the postscaler for this specific timer. See the tables below for permitted
values.

prescaler can be one of the following settings:

Prescaler Value Primary GCB Constant Constant Equates


to value

1:1 PS12_1 0

1:4 PS12_4 1

1:16 PS12_16 2

1:64 PS12_64 3

Note that a 1:64 prescale is only avaialable on certain midrange microcontrollers. Please refer to the
datasheet to determine if a 1:64 prescale is supported by a spectific microcontroller.

postscaler slows the rate of the interrupt generation (or WDT reset) from a counter/timer by dividing it
down.

On Microchip PIC microcontroller one of the following constants where the Postscaler Rate Select bits
are in the range of 1 to 16.

Postcaler Value Use Numeric Constant

1:1 Postscaler 0

1:2 Postscaler 1

1:3 Postscaler 2

1:4 Postscaler 3

1:5 Postscaler 4

1:6 Postscaler 5

1:7 Postscaler 6

1:8 Postscaler 7

414
Postcaler Value Use Numeric Constant

1:9 Postscaler 8

1:10 Postscaler 9

1:11 Postscaler 10

1:12 Postscaler 11

1:13 Postscaler 12

1:14 Postscaler 13

1:15 Postscaler 14

1:16 Postscaler 15

Settimer

Syntax:

Settimer timernumber, byte_value

Settimer timernumber, word_value

Command Availability:

Available on all microcontrollers with a Timer modules.

Explanation:

Settimer will set the value of the specified timer with either byte value or a word value. 8-bit timers use
a byte value. 16-bit timers use a word value.

Settimer can be used on-the-fly, so there is no requirement to stop the timer first.

Refer to the datasheet for timer specific information.

Example:

This example shows the operation of setting two timers - is not intended as a meaningful solution.

415
#chip 16f877a, 4
On Interrupt Timer1Overflow call Overflowed
Set PORTB.0 On

InitTimer1 Osc, PS1_8


SetTimer 1, 1
StartTimer 1

InitTimer2 PS2_16, PS2_16


SetTimer 2, 255
StartTimer 2

'Manually set Timer2Overflow to create a second event


'this will event will be handled by the Interrupt sub routine
TMR2IE = 1
end

Sub Interrupt
Set PORTB.2 On
TMR2IF = 0
End Sub

Sub Overflowed
Set PORTB.1 On
TMR1IF = 0
End Sub

Supported in <TIMER.H>

StartTimer

Syntax:

StartTimer TimerNo

Command Availability:

Available on all microcontrollers with a Timer module.

Explanation:

StartTimer is used to start the specified timer.

Timer 0:

Please refer to the datasheet to determine if Timer 0 on specific Microchip PIC microcontroller can be

416
started and stopped with starttimer and stoptimer. If the Microchip PIC microcontroller has a register
named "T0CON" then it supports stoptimer and starttimer.

On Microchip PIC 18(L)Fxxx microcontrollers Timer 0 can be started with starttimer.


On Microchip PIC baseline and midrange microcontrollers starttimer (and stoptimer) has no effect
upon Timer 0.

Example:

This example will measure that time that a switch is depressed (or on) and will write the results to the
EEPROM.

#chip 16F819, 20
#define Switch PORTA.0

Dir Switch In
DataCount = 0

'Initilise Timer 1
InitTimer1 Osc, PS1_8

Dim TimerValue As Word

Do
ClearTimer 1
Wait Until Switch = On
StartTimer 1
Wait Until Switch = Off
StopTimer 1

'Read the timer


TimerValue = Timer1

'Log the timer value


EPWrite(DataCount, TimerValue_H)
EPWrite(DataCount + 1, TimerValue)
DataCount += 2
Loop

Supported in <TIMER.H>

417
StopTimer

Syntax:

StopTimer TimerNo

Command Availability:

Available on all microcontrollers with a Timer modules. Explanation:

On the Microchip PIC 18(L)Fxxx microcontrollers Timer 0 can be stopped with stopttimer.
With respect to Timer 0 on the Microchip PIC baseline and midrage range of microcontrollers
stoptimer (and starttimer) has no effect as Timer 0.

Example:

This example will measure that time that a switch is depressed (or on) and will write the results to the
EEPROM.
The example shows how to stop a timer when not in use.

418
#chip 16F819, 20
#define Switch PORTA.0

Dir Switch In
DataCount = 0

'Initilise Timer 1
InitTimer1 Osc, PS1_8

Dim TimerValue As Word

Do
ClearTimer 1
Wait Until Switch = On
StartTimer 1
Wait Until Switch = Off
StopTimer 1

'Read the timer


TimerValue = Timer1

'Log the timer value


EPWrite(DataCount, TimerValue_H)
EPWrite(DataCount + 1, TimerValue)
DataCount += 2
Loop

Supported in <TIMER.H>

Reading Timers

Great Cow BASIC has the following functions to read the current timer value. They are:

Timer0()
Timer1()
Timer2()
Timer3()
Timer4()
Timer5()
Timer6()
Timer7()
Timer8()
Timer10()
Timer12()

419
Note that these functions should only be used to read the timer value. To write the timer value,
settimer should be used.

Not all of these functions are available on all microcontrollers. For example, if a microcontrollers has
three timers, then typically only Timer0, Timer1 and Timer2 will be available.

Please refer to the datasheet for your microcontroller to determine the supported timer numbers, and
if a specific timer is 8-bit or 16-bit.

420
Variables Operations
This is the Variables Operations section of the Help file. Please refer the sub-sections for details using
the contents/folder view.

Using Variables

Explaination

Using and accessing bytes within word and long numbers etc may be required when you are creating
your solution. This can be done with some ease.

You can access the bytes within word and longs variables using the following as a guide using the
Suffixes _H, _U and _E

Dim workvariable as word


workvariable = 21845
Dim lowb as byte
Dim highb as byte
Dim upperb as byte
Dim lastb as byte

lowb = workvariable
highb = workvariable_H
upperb = workvariable_U
lastb = workvariable_E

To further explain, where

Dim rB as Byte
Dim sW as Word
Dim sW as Word

To extract the bytes from a WORD of 16 bits use the Suffix _H

'To use the bits 7-0 [lower byte] in the Word variable sW
rB = sW

'For bits 15-8 [upper byte] in the Word variable sW, use sw_H
rB = sW_H

To extract the bytes from a LONG of 32 bits use the Suffixes _H, _U and _E, where

421
Dim rB as Byte
Dim sW as Word
Dim tL as Long

‘ For bits 7-0 [lowest byte #0] in Long variable tL


rB = tL

‘ For bits 15-8 [lower middle byte #1] in Long variable tL


rB = tL_H

‘ For bits 23-16 [upper middle byte #2] in Long variable tL


rB = tL_U

‘ For bits 31-24 [highest byte #3] in Long variable tL


rB = tL_E

To extract nibbles from the variable rB

lower_nibble = rB & 0x0F


upper_nibble = (rB & 0xF0) / 16

More on setting Variables and Constants

Explanation

Within Great Cow BASIC you can use regular variable assignments. But, you can also use C like maths
assignments.

The following methods are also supported.

GLCDPrintLoc += 6
CharCode -= 15
CharCode++
CharCode---

Within Great Cow BASIC you can define binary, hexidecimal and decimal constants, see Constants.
Please note what is and what is not support with respect to assigning numbers to constants. An
example program examines what is supported.

422
#chip 16F88, 4
#config Osc = INT, MCLRE_OFF

' All these work


#define Test0 b'11111111'
#define Test1 0b11111111
#define Test2 0B11111111
#define Test3 255
#define Test4 0xFF
#define Test5 0xff
#define Test6 0Xff

# Proof
dir porta Out

porta = test0
porta = test1
porta = test2
porta = test3
porta = test4
porta = test5
porta = test6

You can assigned values/numbers with all the methods shown above (for constants and variables) but
please be aware that you must Use '0' not '00'. One zero equates to zero and two zeros will give you an
unassigned variable.

Constants:

A few critical constants are defined within Great Cow BASIC , you can re-use these constants. They
include:

#define ON 1 ' These are defined in System.h


#define OFF 0
#define TRUE 255
#define FALSE 0

#define OSC = 1 ' These are defined in TIMER.H


#define EXT = 2 ' and, are used by InitTimer0 command
#define EXTOSC = 3

Setting Variables

Syntax:

423
Variable = data

Explanation:

Variable will be set to data.


data can be either a fixed value (such as 157), another variable, or a sum.

All unknown byte variables are assigned Zero. A variable with the name of Forever is not defined by
Great Cow BASIC and therefore defaults to the value of zero.

If data is a fixed value, it must be an integer between 0 and 255 inclusive.

If data is a calculation, then it may have any of the following operands:

+ (add)
- (subtract, or negate if there is no value before it)
* (multiply)
/ (divide)
% (modulo)
& (and)
| (or)
# (xor)
! (not)
= (equal)
<> (not equal)
< (less than)
> (greater than)
<= (less than or equal)
>= (more than or equal)

The final six operands are for checking conditions. They will return FALSE (0) if the condition is false,
or TRUE (255) if the condition is true.

The And, Or, Xor and Not operators function both as bitwise and logical operators.

Great Cow BASIC understands order of operations. If multiple operands are present, they will be
processed in this order:

Brackets
Unary operations (not and negate)
Multiply/Divide/Modulo
Add/Subtract
Conditional operators
And/Or/Xor

424
There are several modes in which variables can be set. Great Cow BASIC will automatically use a
different mode for each calculation, depending on the type of variable being set. If a byte variable is
being set, byte mode will be used; if a word variable is being set, word mode will be used. If a byte is
being set but the calculation involves numbers larger than 255, word mode can be used by adding
[WORD] to the start of one of the values in the calculation. This is known as casting - refer to the
Variables article for more information.

Divide or division: Great Cow BASIC support division. Division can set the global system variable
SysCalcTempX to the remainder of the division. However the following simple rules apply. . If both of
the parameters of the division are constants, the compiler will do the calculation itself and use the
result rather than making the microcontroller work out the same thing every time. So, if there are two
constants used, the microcontroller division routine does not get used, and SysCalcTempX does not get
set. . If either of the parameters of the division are variables, the compiler will ensure the
microcontroller do es the calculation as the result could be different every time. So, in the this case the
microcontroller division routine does get used, and SysCalcTempX is set.

If you prefer, you can add Let to the start of the line. It will not alter the execution of the program, but
is included for those who are used to including it in other BASIC dialects.

Example:

'This program is to illustrate the setting of variables.


Chipmunk = 46 'Sets the variable Chipmunk to 46
Animal = Chipmunk 'Sets the variable Animal to the value of the variable Chipmunk
Bear = 2 + 3 * 5 'Sets the variable Bear to the result of 2 + 3 * 5, 17.
Sheep = (2 + 3) * 5 'Sets the variable Sheep to the result of (2 + 3) * 5, 25.
Animal = 2 * Bear 'Sets the variable Animal to twice the value of Bear.

LargeVar = 321 'LargeVar must be set as a word - see DIM.


Temp = LargeVar / [WORD]5 'Note the use of [WORD] to ensure that the calculation is
performed correctly

Variable Lifecycle

Explanation

Within Great Cow BASIC you can use variables. This section details the Variable Lifecycle when using
variables.

Variable rules - with #Option Explicit

As shown below in the rule without #Option Explicit but ALL variables MUST be defined including
bytes variables.

Variable rules - without #Option Explicit

425
Scope - every variable is global from an addressing/usage point of view.

Once a variable is defined, and then the variable it is used the variable persists.

Aliasing - You can reduce memory usage by Aliasing. Remember all variables are global so you must
be careful.

If there are two variables with the same name, they will be placed in the same memory location. You
can reuse the same variable name in two subs/functions, and you can make the variables different
types, but writing to the variable in one sub will overwrite the value from the other sub, see the
example below.

As a general guide define any shared variables near the start of the program for easier readability.

All variables should be initialised with a desired initialisation value. Do not assume the initialisation
value is Zero.

Variables local to particular subroutines are not implemented.

Specific rules to spefic variable types

All variables are global. Bit variables defined in subs/function are global.

Byte variables do not need to be defined using the DIM statement. See #Option Explicit above. Just to
clarify byte is default type, this means:

Dim MainVar As Byte is unnecessary.


MainVar = 128 automatic defines the MainVar variable

Bit, Word, Longs, Integers and Strings variables must be defined.

All variables are global, but, if they are defined inside a particular subroutine then their type is not, see
the example below:

Example code:

426
Dim MainVar As Byte
Dim OtherVar As Word

MainVar = 128
OtherVar = 514

DemoSub
'At this point:
'MainVar is a byte, value 128
'OtherVar is a word, value 514
'Counter is a byte, value 2
'(Byte is default type, but location shared with that of Counter in DemoSub. High
byte ignored)

Sub DemoSub
Dim Counter As Word
Counter = 2050
'At this point:
'MainVar and OtherVar as byte and word, as in main routine
'Counter is a word, value 2050
End Sub

In DemoSub, Counter is a word. But anywhere else in the program it is a byte unless otherwise
specified. If the variable is used/read in the main routine, it will be treated as a byte, and only the low
8 bits will be returned. In this example the low 8 bits of 2050 are 2.

The main reason for keeping the type inside the subroutine was for the following scenario: A
subroutine uses a temporary variable of type byte, and relies on it overflowing.

Another subroutine uses a temporary variable of the same name, but of word type.

If the first subroutine is already in the program, and then the second one is added, the behaviour of the
first one will not change at all due to the addition of the second one.

The handling of variable types using this method minimises the size of the generated assembly code.

For more help, see Option Explicit

Dim

Syntax:

427
For Variables > 1 byte:
Dim variable[, variable2 [, variable3 ]] [As type ] [Alias othervar [, othervar2 ]]
[At location ]

For Arrays:
Dim array(size) [At location]

Explanation:

Dim has two uses, both of which involve large variables. It can be used to define arrays, bit variables
and all variables larger than 1 byte.

Command Availability:

Available on all microcontrollers.

The Dim variable command is used to inform Great Cow BASIC of variables that are larger than 1 byte,
or to create alternate names for other variables.

The Dim array command also sets up array variables. The maximum array size is determined by the
parameter size is dynamically allocated by the compiler and depends on the specific chip used, as well
as the complexity of the program.

The limit on array size varies dependent on the chip type. The 12F/16F series of chips the array limit is
80 elements. For the Atmel AVR or an 18F there is no limit other than free RAM however Great Cow
BASIC limits the array size to 10,000 elements. If a memory limit is reached, the compiler will give an
error message.

type specifies the type of variable that is to be created. Different variable types can hold values over
different ranges, and use different amounts of RAM. See the Variables article for more information.

When multiple variables are included on the one line, Great Cow BASIC will set them all to the type
that is specified at the end of the line. If there is no type specified, then Great Cow BASIC will make the
variable a byte.

Alias creates a variable using the same memory location as one or more other variables. It is mainly
used internally in Great Cow BASIC to treat system variables as a word. For example, this command is
used to create a word variable, made up from the two memory locations used to store the result of an
A/D conversion:

A variable can be placed at a specific location in the data memory of the chip using the At option.
location will be used whether it is a valid location or not, but a warning will be generated if Great Cow
BASIC has already allocated the memory, or if the memory does not appear to be valid. This can be
used for peripherals that have multi byte buffers in RAM.

428
Dim ADResult As Word Alias ADRESH, ADRESL

Example:

'This program will set up an array, and a word variable

dim DataList(10)
dim Reading as word

Reading = 21978
DataList(1) = 15

dim stringvariable as string

For more help, see:SerPrint articles as these articales show how to use Dim to create string variables
and Variables for more details in creating and managing strings lengths.

BcdToDec_GCB

Syntax:

BcdToDec_GCB ( ByteVariable )

Command Availability:

Available on all microcontrollers.

Support Bytes only.

Explanation:

Converts numbers from Binary Coded Decimal format to decimal.

You can add this function. Just add this to your Great Cow BASIC program and then call it when you
need it.

Example:

Function BcdToDec(va) as byte


BcdToDec=(va/16)*10+va%16
End Function

Also see DecToBcd_GCB

429
DecToBcd_GCB

Syntax:

DectoBcd( ByteVariable )

Command Availability:

Available on all microcontrollers.

Explanation:

Converts numbers from Decimal to Binary Coded Decimal format. Support Bytes only.

You can add this function. Just add this to your Great Cow BASIC program and then call it when you
need it.

Example:

Function DecToBcd(va) as Byte


DecToBcd=(va/10)*16+va%10
End Function

Also see BcdToDec_GCB

Rotate

Syntax:

Rotate variable {Left | Right} [Simple]

Command Availability:

Available on all microcontrollers.

Explanation:

The Rotate command will rotate variable one bit in a specified direction. The bit shifted will be placed
in the Carry bit of the Status register (STATUS.C). STATUS.C acts as a ninth bit of the variable that is being
rotated.

variable supports Bytes, Word and Long variables.

When a variable is rotated right, the bit in the STATUS.C location is placed into the MSB of the variable
being rotated, and the LSB of the variable is placed into STATUS.C location.

430
When rotated left the opposite occurs. The MSB of the variable is shifted to the STATUS.C bit and the
LSB of the variable will contain what was previously in the STATUS.C bit location.

This table shows the operation of the Rotate Left command

Command variable STATUS.C

Values at start: b'01110011' 0

Rotate Left b'11100110' 0

Rotate Left again b'11001100' 1

Rotate Left third time b'10011001' 1

As you may notice the STATUS.C bit added a 0 to the rotation. So this will take 9 shifts left to get back to
the original value.

Simple option

Many times you want to rotate the variable around like the STATUS.C bit wasn’t there so the MSB of the
variable fills the LSB of the variable on Rotate Left or the LSB fills the MSB on Rotate Right. That is
where the SIMPLE option comes in. It adds a hidden step that shifts the STATUS.C bit twice so the bit
moves from one end of the variable to the other.

Command variable STATUS.C

Values at start: b'01110011' 0

Rotate Left b'11100110' 0

Rotate Left again b'11001101' 1

Rotate Left third time b'10011011' 1

Notes: The carry is also called SREG bit C, or simply C flag on AVR.

In some cases the Status.C or C flag may already be set because of prior operations in your program.
Therefore, it may be necessary to clear the C flag before using Rotate. Use Set C Off before using the
Rotate command to clear the flag.

Example:

431
'This program will use Rotate to show a chasing LED.
'8 LEDs should be connected to PORTB, one on each pin.

#chip 16F819, 8
#config osc = int

'Set port direction


Dir PORTB Out

'Set initial state of port (bits 0 and 4 on)


PORTB = b'00010001'

'Chase
C = 0
Do
Rotate PORTB Right Simple
Wait 250 ms
Loop

Set

Syntax:

Set variable.bit {On | Off}

Command Availability:

Available on all microcontrollers.

Explanation:

The purpose of the Set command is to turn individuals bits on and off.

The Set command is most useful for controlling output ports, but can also be used to set variables.

Often when controlling output ports, Set is used in conjunction with constants. This makes it easier to
adapt the program for a new circuit later.

Example:

432
'Blink LED sample program for Great Cow BASIC
'Controls an LED on PORTB bit 0.

'Set chip model and config options


#chip 16F84A, 20

'Set a constant to represent the output port


#define LED PORTB.0

'Set pin direction


Dir LED Out

'Main routine
Do
Set LED On
Wait 1 sec
Set LED OFF
Wait 1 sec
Loop

SWAP4

Syntax:

SWAP4( VariableA)

Command Availability:

Available on all microcontrollers.

Support Bytes only.

Explanation:

A function that swaps (or exchanges) nibbles (or the 8 bits of a byte in nibbles).

Example:

433
dim ByteVariable as Byte

' Set variable to 0x12


ByteVariable = 0x12

ByteVariable = Swap4( ByteVariable )

HSerPrint hex(ByteVariable)

' Would return 0x21

SWAP

Syntax:

SWAP( VariableA, VariableB)

Command Availability:

Available on all microcontrollers.

Support Bytes and Words only.

Explanation:

A function that swaps (or exchanges) one byte or word for another. SWAP support the use of byte and
word variables.

434
String Manipulation
This is the String Manipulation section of the Help file. Please refer the sub-sections for details using
the contents/folder view.

Asc, bytetobin, chr, fill, hex, instr, lcase, left, leftpad, len, mid, pad, right, rtrim, str, trim, ucase, val,
wordtobin or concatenation

Asc

Syntax:

bytevar= ASC(string, [position] )

Command Availability:

Available on all microcontrollers

Explanation:

Returns the character code of the character at the specified position in a string.

ASC returns the character code of a particular character in the string. If the string is an ANSI string, the
returned value will be in the range of 0 to 255. This function DOES NOT support UNICODE.

The optional position parameter determines which character is to be checked. The first character is
one, the second two, etc. If the position parameter is missing, the first character is presumed.

CHR is the natural complement of ASC. CHR produces a one-character string corresponding to its ASCII.

Note:

If the string passed is null (zero-length) or the position is zero or greater than the length of the string
the returned value will be 0.

Example:

charpos = ASC( "ABCD" ) ' Returns 65

charpos = ASC( "ABCD", 2 ) ' Returns 66

For more help, see Chr

435
ByteToBin

Syntax:

stringvar = ByteToBin(bytevar)

Command Availability:

Available on all microcontrollers

Explanation:

The ByteToBin function creates a string of a ANSI (8-byte) characters. The function converts a number
to a string consisting of ones and zeros that represents the binary value.

Note: Supports BYTE variables only. For WORD variables use WordToBin

Example:

string = ByteToBin( 1 ) ' Returns "00000001"

string = ByteToBin( 254 ) ' Returns "11111110"

For more help, see WordToBin

Chr

Syntax:

stringvar = CHR(bytevar)

Command Availability:

Available on all microcontrollers

Explanation:

The CHR function creates a string of a ANSI (1-byte) character.

ASC is the natural complement of CHR.

Example:

436
string = CHR( 65 ) ' Returns "A"

string = CHR( 66 ) ' Returns "B"

For more help, see Asc

Fill

Syntax:

stringvar = Fill ( byte_value_of_the_new_length , pad_character )

Command Availability:

Available on all microcontrollers

Explanation:

The Fill function is used to create string to a specific length that is of a specific character.

The length of the string is specified by the first parameter. The character used to pad the string is
specified by the second parameter, this parameter is optional as the " "(space) character is assumed.

A typical use is to fill a string to be displayed on an LCD or serial terminal.

Example:

'Set chip model


#chip 16F886

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

HserPrint Fill ( 16, "" ) ;will print a string of '*'


HSerPrintCRLF

For more help, see Asc

437
Hex

Syntax:

stringvar = Hex(number)

Command Availability:

Available on all microcontrollers

Explanation:

The Hex function will convert a number into hexadecimal format. The input number should be a byte
variable, or a fixed number between 0 and 255 inclusive. After running the function, the string
variable stringvar will contain a 2 digit hexadecimal number.

Example:

'Set chip model


#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Send EEPROM data over serial connection


'Uses Hex to display as hexadecimal
For CurrentLocation = 0 to 255
'Send location
HSerPrint Hex(CurrentLocation)
HSerPrint ":"
'Read byte and send
EPRead CurrentLocation, CurrByte
HSerPrint Hex(CurrByte)
'Send carriage return/line feed
HSerPrintCRLF
Next

When using the functions Hex() do not leave space between the function call and the left brace. You
will get a compiler error that is meaningless.

438
' use this, note this is no space between the Hex and the left brace!
Hex(number_variable)
' do not use, note the space!
Hex (number_variable)

See Also Str, Val

Instr

Syntax:

location = Instr(source, find)

Command Availability:

Available on all microcontrollers

Explanation:

The Instr function will search one string to find the location of another string within it. source is the
string to search inside, and find is the string to find. The function will return the location of find within
source, or 0 if source does not contain find.

Example:

439
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Fill a string with a message


Dim TestData As String
TestData = "Hello, world!"

'Display the location of "world" within the string


'Will return 8, because "w" in world is the 8th character
'of "Hello, world!"
HSerPrint Instr(TestData, "world")
HSerPrintCRLF

'Display the location of "planet" within the string


'Will display 0, because "planet" does not occur inside
'the string "Hello, world!"
HSerPrint Instr(TestData, "planet")
HSerPrintCRLF

LCase

Syntax:

output = LCase(source)

Command Availability:

Available on all microcontrollers

Explanation:

The LCase function will convert all of the letters in the string source to lower case, and return the result.

Example:

440
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Fill a string with a message


Dim TestData As String
TestData = "Hello, world!"

'Display the string in lower case


'Will display "hello, world!"
HSerPrint LCase(TestData)
HSerPrintCRLF

See Also UCase

Left

Syntax:

output = Left(source, count)

Command Availability:

Available on all microcontrollers

Explanation:

The Left function will extract the leftmost count characters from the input string source, and return
them in a new string.

Example:

441
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Fill a string with a message


Dim TestData As String
TestData = "Hello, world!"

'Display the leftmost 5 characters


'Will display "Hello"
HSerPrint Left(TestData, 5)
HSerPrintCRLF

See Also Mid, Right

LeftPad

Syntax:

LeftPad(string_variable,byte_value_of_the_new_length,pad_character)

Command Availability:

Available on all microcontrollers

Explanation:

The LeftPad function is used to create string to a specific length that is extended with a specific
character to the left hand side of the string.

The length of the string is specified by the second parameter.

The character used to pad the string is specified by the third parameter.

A typical use is to pad a string to be displayed on a serial terminal or LCD.

Example:

'Set chip model


#chip 18F2520, 8

442
DIR PORTA 0x03

' make port C as output


Dir PortC 0x0

'Defines (Constants)
#define LCD_SPEED fast
#define LCD_IO 4
#define LCD_NO_RW
#define LCD_Enable PORTc.0
#define LCD_RS PORTc.1
#define LCD_DB4 PORTa.5
#define LCD_DB5 PORTa.4
#define LCD_DB6 PORTa.3
#define LCD_DB7 PORTa.2
'''--------------------------------------------
'''-------End of board-specific settings-------
'''--------------------------------------------

'''DEMO for padding strings left with


'''1st character of a given string.
'''if no string is given, blanks are used

; ---- variables
DIM inString as string * 5
DIM outString1 as String
DIM outString2 as String

; ---- main body of program begins here

inString = "12345"

outString1 = PADleft(inString, 9, "*#o")


outString2 = PADleft(inString, 9)

'show results on LCD-Display


cls

print instring
print " "
print outstring1
locate 1,0
print instring

443
print " "
print outstring2

end

Len

Syntax:

output= Len( string )

Command Availability:

Available on all microcontrollers

Explanation:

The Len function returns an byte value which is the length of a phrase or a sentence, including the
empty spaces. The format is:

target_byte_variable = Len("Phrase")

or another example. This code will loop through the for-next loop 12 times as determined by the length
of the string:

' create a test string of 12 characters


dim teststring as string * 12

teststring = "0123456789AB"
for loopthrustring = 1 to len(teststring)
hserprint mid(teststring, loopthrustring , 1)
next

Ltrim

Syntax:

stringvar = LTRIM(stringvar)

Command Availability:

Available on all microcontrollers

444
Explanation:

The Ltrim function will trim the 7-bit ASCII space character (value 32) from the LEFT hand side of a
string.

Use Ltrim on text that you have received from another source that may have irregular spacing at the
left hand end of the string.

See Also Trim, Rtrim

Mid

Syntax:

output = Mid(source, start, count)

Command Availability:

Available on all microcontrollers

Explanation:

The Mid function is used to extract characters from the middle of a string variable. source is the
variable to extract from, start is the position of the first character to extract, and count is the number
of characters to extract. If count is not specified, all characters from start to the end of the source
string will be returned.

Example:

445
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Fill a string with a message


Dim TestData As String
TestData = "The cat sat on the mat"

'Extract "cat". The c is at position 5, and 3 letters are needed


HSerPrint "The animal is a "
HSerPrint Mid(TestData, 5, 3)

'Extract the action. "sat" starts at position 9.


HSerPrint "The animal "
HSerPrint Mid(TestData, 9)
HSerPrintCRLF

See Also Left, Right

Pad

Syntax:

out_string = Pad( string_variable, byte_value_of_the_new_length, pad_character)

Command Availability:

Available on all microcontrollers

Explanation:

The Pad function is used to create string to a specific length that is extended with a specific character.

The length of the string is specified by the second parameter. The character used to pad the string is
specified by the third parameter.

A typical use is to pad a string to be displayed on a LCD display.

Example:

446
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Defibe a string
Dim TestData As String * 16
TestData = "Location"

HSerPrint TestData ;will print a string of 8 characters


HSerPrintCRLF
Pad ( TestData, 16, "*" )
HSerPrint TestData ;will print a string of 'Location********'
HSerPrintCRLF

Right

Syntax:

output = Right(source, count)

Command Availability:

Available on all microcontrollers

Explanation:

The Right function will extract the rightmost count characters from the input string source, and return
them in a new string.

Example:

447
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_BLOCKING

'Fill a string with a message


Dim TestData As String
TestData = "Hello, world!"

'Display the rightmost 6 characters


'Will display "world!"
HSerPrint Right(TestData, 6)
HSerPrintCRLF

Rtrim

Syntax:

stringvar = Rtrim(stringvar)

Command Availability:

Available on all microcontrollers

Explanation:

The Rtrim function will trim the 7-bit ASCII space character (value 32) from the RIGHT hand side of a
string.

Use Rtrim on text that you have received from another source that may have irregular spacing at the
right hand end of the string.

See Also Trim, Ltrim

Str

Syntax:

stringvar = Str(number)

Command Availability:

448
Available on all microcontrollers

Explanation:

The Str function will convert a number into a string. number can be any byte or word variable, or a
fixed number between 0 and 65535 inclusive.

The string variable stringvar will contain the same number, represented as a string.

This function is especially useful if a number needs to added to the end of a string, or if a custom data
sending routine has been created but only supports the output of string variables.

Example:

'Set chip model


#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Take an A/D reading


SensorReading = ReadAD(AN0)

'Create a string variable


Dim OutVar As String

'Fill string with sensor reading


OutVar = Str(SensorReading)

'Send
HSerPrint OutVar
HSerPrintCRLF

When using the functions STR() do not leave space between the function
call and the left brace. You will get a compiler error that is
meaningless.

' use this, note this is no space between the STR and the left brace!
STR(number_variable)
' do not use, note the space!
STR (number_variable)

See Also Hex, Val

449
Trim

Syntax:

stringvar = Trim(stringvar)

Command Availability:

Available on all microcontrollers

Explanation:

The Trim function will trim the 7-bit ASCII space character (value 32) from text.

Trim removes all spaces from text except for single spaces between words. Use Trim on text that you
have received from another source that may have irregular spacing at the left or right hand ends of the
string.

See Also Ltrim, Rtrim

UCase

Syntax:

output = UCase(source)

Command Availability:

Available on all microcontrollers

Explanation:

The UCase function will convert all of the letters in the string source to upper case, and return the
result.

Example:

450
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Fill a string with a message


Dim TestData As String
TestData = "Hello, world!"

'Display the string in upper case


'Will display "HELLO, WORLD!"
HSerPrint UCase(TestData)
HSerPrintCRLF

See Also LCase

Val

Syntax:

var = Val(string)

Command Availability:

Available on all microcontrollers

Explanation:

The Val function will extract a number from a string variable, and store it in a word variable. One
potential use is reading numbers that are sent in ASCII format over a serial connection.

Example:

451
'Program for an RS232 controlled dimmer
'Set chip model
#chip 16F1936

'Set up hardware serial connection


#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

'Set pin directions for USART and PWM

'Variable for output level


Dim OutputLevel As Word

'Variables for received bytes


Dim DataIn As String
DataInCount = 0

'Main Loop
Do
'Get serial byte
Wait Until USARTHasData
HSerReceive InByte

'Process latest byte


'Enter key?
If InByte = 13 Then
'Convert output level to numeric variable
OutputLevel = Val(DataIn)

'Output
HPWM 1, 32, OutputLevel

'Clear output buffer for next command


DataIn = ""
DataInCount = 0
End If

'Number?
If InByte >= 48 and InByte <= 57 Then
'Add to end of DataIn string
DataInCount += 1
DataIn(DataInCount) = InByte
DataIn(0) = DataInCount
End If
Loop

452
See Also Hex, Str

WordToBin

Syntax:

stringvar = WordToBin(bytevar)

Command Availability: Available on all microcontrollers

Explanation:

The WordToBin function creates a string of a ANSI (8-byte) characters. The function converts a number
to a string consisting of ones and zeros that represents the binary value.

Example:

string = WordToBin(1) ' Returns "0000000000000001"

string = WordToBin(37654) ' Returns "1001001100010110"

For more help, see ByteToBin

Concatenation

Syntax:

stringvar = variable1 + variable2

Command Availability:

Available on all microcontrollers

Explanation:

The method joins two variables into another variable.

This method does not change the existing strings, but returns a new string containing the text of the
joined variables.

Concatenation joins the elements of a specified values using the specified separator between each
variable.

Example:

453
timevariable = 999
stringvar = "Time = " + timevariable ' Returns Time = 999

454
Miscellaneous Commands
This is the Miscellaneous Commands section of the Help file. Please refer the sub-sections for details
using the contents/folder view.

Dir

Syntax:

Dir port.bit {In | Out} (Individual Form)


Dir port {In | Out | DirectionByte} (Entire Port Form)

Command Availability:

Available on all microcontrollers.

Explanation:

The Dir command is used to set the direction of the ports of the microcontroller chip. The individual
form sets the direction of one pin at a time, whereas the entire port form will set all bits in a port.

In the individual form, specify the port and bit (ie. PORTB.4), then the direction, which is either In or
Out.

The entire port form is similiar to the TRIS instruction offered by some Microchip PIC microcontrollers.
To use it, give the name of the port (i.e. PORTA), and then a byte is to be written into the TRIS variable.
This form of the command is for those who are familiar with the Microchip PIC microcontrollers
internal architecture.

Note: Entire port form will work differently on Atmel AVR microcontrollers when a value other than
IN or OUT is used. Atmel AVR microcontrollers use 0 to indicate in and 1 to indicate out, whereas
Microchip PIC microcontrollers use 0 for out and 1 for in. When IN and OUT are used there are no
compatibility issues.

Example:

455
'This program sets PORTA bits 0 and 1 to in, and the rest to out.
'It also sets all of PORTB to output, except for B1.
'Individual form is used for PORTA:
DIR PORTA.0 IN
DIR PORTA.1 IN
DIR PORTA.2 OUT
DIR PORTA.3 OUT
DIR PORTA.4 OUT
DIR PORTA.5 OUT
DIR PORTA.6 OUT
DIR PORTA.7 OUT
'Entire port form used for B:
DIR PORTB b'00000010'

'Entire port form used for C:


DIR PORTC IN

GetUserID

Syntax:

Command Availability:

Available on all Microchip microcontrollers that support UserIDs.

Explanation:

Reads the memory location and returns the ID for a specific microcontroller.

If the microcontroller does not support GetUSerID then the following message will be issued during
compilation Warning: GetUserID not supported by this microcontroller.

The method reads the memory location 0x8000 + Index and returns it as a Word value, where the
Index 0x00 to 0x0B as follows:

Address Function Rea Writ


d e

8000h-8003h User IDs Yes Yes

8006h/8005h Device ID/Revision ID Yes No

8007h-800Bh Configuration Words 1 through 5 Yes No

Refer to your particular Device Datasheet to confirm the address table

456
Example:

#chip 16F1455
#Config WRT_OFF, MCLRE_ON

#include <GetUserID.h>

#define USART_BAUD_RATE 19200


#define USART_TX_BLOCKING

'Implement ANSI escaope code for serial terminal NOT using a LCD!
#define ESC chr(27)
#define CLS HSerPrint(ESC+"[2J")
#define HOME HSerPrint(ESC+"[H")
#define Print HSerPrint

CLS
HOME

dim UserIDRegister as word

For Index = 0 to 0xF


UserIDRegister = GetUserID(Index)
HserPrint "80" + hex(NVIndex)
HserPrint " : "
HserPrint hex( UserIDRegister_H )
HserPrint hex( UserIDRegister )
Next Index

End

Pot

Syntax:

Pot pin, output

Command Availability:

Available on all microcontrollers.

Explanation:

Pot makes it possible to measure an analog resistance with a digital port, with the addition of a small
capacitor. This is the required circuit:

457
The command works by using the microcontroller pin to discharge the capacitor, then measuring the
time taken for the capacitor to charge again through the resistor.

The value for the capacitor must be adjusted depending on the size of the variable resistor. The
charging time needs to be approximately 2.5 ms when the resistor is at its maximum value. For a
typical 50 k potentiometer or LDR, a 50 nf capacitor is required.

This command should be used carefully. Each time it is inserted, 20 words of program memory are
used on the chip, which as a rough guide is more than 15 times the size of the Set command.

pin is the port connected to the circuit. The direction of the pin will be dealt with by the Pot command.

output is the name of the variable that will receive the value.

Example:

458
'This program will beep whenever a shadow is detected
'A potentiometer is used to adjust the threshold

#chip 16F628A, 4
#config INTOSC_OSC_NOCLKOUT

#define ADJUST PORTB.0


#define LDR PORTB.1
#define SoundOut PORTB.2

Dir SoundOut Out

Do
Pot ADJUST, Threshold
Pot LDR, LightLevel
If LightLevel > Threshold Then
Tone 1000, 100
End If
Loop

See also ladyada.net/library/rccalc.html or cvs1.uklinux.net/cgi-bin/calculators/time_const.cgi for


calculating capacitor value. These sites are not associated with Great Cow BASIC.

PulseOut

Syntax:

PulseOut pin, time units

Command Availability:

Available on all microcontrollers.

Explanation:

The PulseOut command will set the specified pin high, wait for the specified amount of time, and then
set the pin low again. The pin is specified in the same way as it is for the Set command, and the time is
the same as for the Wait command.

Example:

459
'This program flashes an LED on GPIO.0 using PulseOut
#chip 12F629, 4
#config INTRC_OSC_NOCLKOUT

Dir GPIO.0 Out


Do
PulseOut GPIO.0, 1 sec 'Turn LED on for 1 sec
Wait 1 sec 'Wait 1 sec with LED off
Loop

PulseOutInv

Syntax:

PulseOutInv pin, time units

Command Availability:

Available on all microcontrollers.

Explanation:

The PulseOutInv command will set the specified pin low, wait for the specified amount of time, and
then set the pin high. The pin is specified in the same way as it is for the Set command, and the time is
the same as for the Wait command.

Example:

'This program flashes an LED on GPIO.0 using PulseOutInv


#chip 12F629, 4
#config INTRC_OSC_NOCLKOUT

Dir GPIO.0 Out


Do
PulseOutInv GPIO.0, 1 sec 'Turn LED off for 1 sec
Wait 1 sec 'Wait 1 sec with LED on
Loop

PulseIn

Syntax:

460
PulseIn pin, user_variable, time units

Command Availability:

Available on all microcontrollers.

Explanation:

The PulseIn command will monitor the specified pin when the pin is high, and then measure the high
time. It will store the time in the user variable. The user variable must be a WORD if returned units are
expected to be > 255 (Example: Pulse is 500 ms)

PulseIn is not recommended for accurate measurement of microsecond pulses

Example:

#chip 12F629, 4
#config INTRC_OSC_NOCLKOUT

Dir GPIO.0 In
Dim TimeResult as WORD

Do while GPIO.0 = Off 'Wait for next positive edge to start measuring
Loop

Pulsein GPIO.0, TimeResult, ms

PulseInInv

Syntax:

PulseInInv pin, user_variable, time units

Command Availability:

Available on all microcontrollers.

Explanation:

The PulseIn command will monitor the specified pin when the pin is low, and then measure the low
time. It will store the time in the user variable. The user variable must be a WORD if returned units are
expected to be > 255 (Example: Pulse is 500 ms)

PulseInInv is not recommended for accurate measurement of microsecond pulses.

461
Example:

#chip 12F629, 4
#config INTRC_OSC_NOCLKOUT

Dir GPIO.0 In
Dim TimeResult as WORD

Do while GPIO.0 = On 'Wait for next negative edge to start measuring


Loop

PulseinInv GPIO.0, TimeResult, ms

Peek

Syntax:

OutputVariable = Peek (location)

Command Availability:

Available on all microcontrollers.

Explanation:

The Peek function is used to read information from the on-chip RAM of the microcontroller.

location is a word variable that gives the address to read. The exact range of valid values varies from
chip to chip.

This command should not normally be used, as it will make the porting of code to another chip very
difficult.

Example #1 :

'This program will read and check a value from PORTA


'This specific peek will only work on some microcontrollers
Temp = Peek(5)
IF Temp.2 ON THEN SET green ON
IF Temp.2 OFF THEN SET red ON

Example #2

462
' This subroutine will toggle the pin state.
' You must change the parameters for your specific chip.
' Usage as show in examples below.
'
' Toggle @PORTE, 2 ' equates to RE1.
' Wait 100 ms
' Toggle @PORTE, 2
' Wait 100 ms

' Port , Pin address in Binary


' Pin0 = 1
' Pin1 = 2
' Pin2 = 4
' Pin3 = 8
'
' You can toggle any number of pins.
' Toggle @PORTE, 0x55
Sub Toggle ( In DestPort As word, In DestBit )
Poke DestPort, Peek(DestPort) xor DestBit
End sub

See Also Poke

Poke

Syntax:

Poke(location, value)

Command Availability:

Available on all microcontrollers.

Explanation:

The Poke command is used to write information to the on-chip RAM of the microcontroller.

location is a word variable that gives the address to write. The exact range of valid values varies from
chip to chip. value is the data to write to the location.

This command should not normally be used, as it will make the porting of code to another chip very
difficult.

Example 1:

463
'This program will set all of the PORTB pins high
POKE (6, 255)

Example 2:

;Chip Settings
#chip 16F88

Do Forever
FlashPin @PORTB, 8
Wait 1 s
Loop

Sub FlashPin (In DestVar As word, In DestBit)


Poke DestVar, Peek(DestVar) Or DestBit
Wait 1 s
Poke DestVar, Peek(DestVar) And Not DestBit
End Sub

Using @ before the name of a variable (including a special function register) will give you the address
of that variable, which can then be stored in a word variable and used by Peek and Poke to indirectly
access the location.

See Also Peek

Weak Pullups

Weak pullups provide a method to within many microcontrollers such as the Atmel Atmel AVR and
Microchip PIC microcontrollers to support internal/selectable pull-ups for convenience and reduced
parts count.

If you require Weak pullups these internal pull-ups can provide a simple solution.

If you need your weak pull-ups to exactly control current (rare for most microcontroller applications),
then you should consider 10k resistors (5V/10K = 500uA) Why? If you review in the microcontroller
data sheet, there is no resistance given for the weak pull-ups. That is because they are not weak pull-
resistors they are weak pull-up consisting of what appear to be high- resistance channel pFETs. Their
channel resistance will vary with temperature and between parts; not easy to characterize.

The data sheet gives a current range for the internals as 50-400uA (at 5V).

PORTs can have an individually controlled weak internal pull-up. When set, each bit of the appropriate
Microchip PIC register enables the corresponding pin pull-up. There is a master bit within a specific
register bit that enables pull- ups on all pins which also have their corresponding weak pull bit set.
Also when set, there is a weak pull register bit to disable all weak pull-ups.

464
The weak pull-up is automatically turned off when the port pin is configured as an output. The pull-
ups are disabled on a Power-on Reset.

Each specific microcontroller has different registers/bits for this functionality.

You should review the datasheet for the method for a specific microcontroller.

The following code demonstrates how to set the weak pull-ups available on port B of an 18F25K20.

Example:

'A program to show the use of weak pulled-ups on portb.


'Set chip model
#chip 18F25k20,16 'at 16 MHz
'Switch Low-Volt-Programming:
#config LVP = Off
#config MCLR = Off

Set RBPU = 0 'enabling Port B pullups in general.


SET WPUB1 = 1 'portb.1 pulled up
Set WPUB2 = 1 'portb.2
Set WPUB3 = 1 'portb.3
Set WPUB4 = 1 'portb.4

Dir Portb in
Dir Portc out

do
portc.1 = portb.1 'in pin 22, out pin 12
portc.2 = portb.2 'in pin 23, out pin 13
portc.3 = portb.3 'in pin 24, out pin 14
portc.4 = portb.4 'in pin 25, out pin 15

loop 'jump back to the start of the program

'main line ends here


end

Also, see I2C Slave Hardware for an example using a 16F microcontroller.

465
Maths
This is the Maths section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Abs

Syntax:

integer_variable = Abs( integer_variable )

Command Availability:

Available on all microcontrollers.

Explanation:

The Abs function will compute the absolute value of a integer number therefore in the range of -32678
to 32768.

Example:

absolute_value = Abs( -127 ) ' Will return 127


absolute_value = Abs( 127 ) ' Will return 127 also. :-)

Average

Syntax:

integer_variable = Average(byte_variable1 , byte_variable2)

Command Availability:

Available on all microcontrollers.

Explanation:

A function that returns the average of two numbers. This only supports byte variables.

Provides a very fast way to calculate the average of two 8 bit numbers.

Example:

466
average_value = Average(8,4) ' Will return 6

Difference

Syntax:

Difference ( word_variable1 , word_variable2 ) or


Difference ( byte_variable1 , byte_variable2 )

Command Availability:

Available on all microcontrollers.

Explanation:

A function that returns the difference between of two numbers. This only supports byte or word
variables.

Example:

Difference( 8 ,4 ) ' Will return 4


Difference( 0xff01 , 0xfffa ) ' Will return 0xf9 or 249d

Logarithms

Explanation:

Great Cow BASIC support logarithmic functions through the include file <maths.h>.

These functions compute base 2, base e and base 10 logarithms accurate to 2 decimal places, +/- 0.01.

The values returned are fixed-point numbers, with two decimal places assumed on the right. Or if you
prefer, think of the values as being scaled up by 100.

The input arguments are word-sized integers, 1 to 65535. Remember, logarithms are not defined for
non-positive numbers. It is the calling program’s responsibility to avoid these. Output values are also
word-sized.

Local variables consume 9 bytes, while the function parameters consume another 4 bytes, for a grand
total of 13 bytes of RAM used. The lookup table takes 35 words of program memory.

For more help, see Log10, Log2, Loge

Supported in <MATHS.H>

467
Log2

Syntax:

returned_word_variable = Log2 ( word_value )

Command Availability:

Available on all microcontrollers.

Explanation:

The Log2 command will return the base-2 logarithm, to 2 decimal places.

The values returned are fixed-point numbers, with two decimal places assumed on the right. or if you
prefer, think of the values as being scaled up by 100.

Example:

dim log_value as word


log_value = log2 ( 10 ) 'return 3321 equate to 3.321

Supported in <MATHS.H>

Loge

Syntax:

returned_word_variable = Loge ( word_value )

Command Availability:

Available on all microcontrollers.

Explanation:

The Loge command will return the base-e logarithm, to 2 decimal places.

The values returned are fixed-point numbers, with two decimal places assumed on the right. or if you
prefer, think of the values as being scaled up by 100.

Example:

468
dim log_value as word
log_value = loge ( 10 )

Supported in <MATHS.H>

Log10

Syntax:

returned_word_variable = Log10 (word_value)

Command Availability:

Available on all microcontrollers.

Explanation:

The Log10 command will return the base-10 logarithm, to 2 decimal places.

The values returned are fixed-point numbers, with two decimal places assumed on the right. or if you
prefer, think of the values as being scaled up by 100.

Example:

dim log_value as word


log_value = log10 ( 10 ) 'return 230 equate to 2.30

Supported in <MATHS.H>

Power

Syntax:

power( base, exponent )

Explanation:

This function raises a base to an exponent, i.e, power(base,exponent). Calculation powers will become
large, in terms of long numbers, you must ensure the program manage numbers remain within range
of the defined variables.

The base and exponent are Byte sized numbers in this method.
The returned result is a Long.

469
Non-negative numbers are assumed throughout.

Note: 0 raised to 0 is meaningless and should be avoided, but, any other non-zero base raised to 0 is
handled correctly.

Example:

;Thomas Henry -- 5/2/2014

;----- Configuration

#chip 16F88, 8 ;PIC16F88 running at 8 MHz


#config mclr=off ;reset handled internally
#config osc=int ;use internal clock
#include <maths.h> ;required maths.h

;----- Constants

#define LCD_IO 4 ;4-bit mode


#define LCD_RS PortB.2 ;pin 8 is LCD Register Select
#define LCD_Enable PortB.3 ;pin 9 is LCD Enable
#define LCD_DB4 PortB.4 ;DB4 on pin 10
#define LCD_DB5 PortB.5 ;DB5 on pin 11
#define LCD_DB6 PortB.6 ;DB6 on pin 12
#define LCD_DB7 PortB.7 ;DB7 on pin 13
#define LCD_NO_RW 1 ;Ground the RW line on LCD

;----- Variables

dim i, j as byte

;----- Program

dir PortB out ;all outputs to the LCD


for i = 1 to 10 ;do all the way from
for j = 0 to 9 ;1^0 on up to 10^9
cls
print i
print "^"
print j
print "="
locate 1,0
print power(i,j) ;here's the invocation
wait 1 S
next j
next i

470
Supported in <MATHS.H>

Sqrt

Syntax:

word_variable = sqrt ( word )

Explanation:

A square root routine for Great Cow BASIC. The function only involves bit shifting, addition and
subtraction, which makes it fast and efficient.

This method required a word variable as the input and a word variable as the output. The method will
handle arguments of up to 4294.

Command Availability:

Available on all microcontrollers, required MATHS.H include file.

Example:

;Demo: Show the first 100 square roots to 2 decimal places.


;This uses the maths.h include file.

;----- Configuration

#chip 16F88, 8 ;PIC16F88 running at 8 MHz


#config mclr=off ;reset handled internally
#config osc=int ;use internal clock
#include <maths.h> ;required maths.h

;----- Constants

#define LCD_IO 4 ;4-bit mode


#define LCD_RS PortB.2 ;pin 8 is LCD Register Select
#define LCD_Enable PortB.3 ;pin 9 is LCD Enable
#define LCD_DB4 PortB.4 ;DB4 on pin 10
#define LCD_DB5 PortB.5 ;DB5 on pin 11
#define LCD_DB6 PortB.6 ;DB6 on pin 12
#define LCD_DB7 PortB.7 ;DB7 on pin 13
#define LCD_NO_RW 1 ;ground the RW line on LCD

;----- Variables

dim length as byte

471
dim i as word
dim valStr, outStr as string

;----- Program

dir PortB out ;all outputs to the LCD

for i = 0 to 100 ;print first 100 square roots


cls
print "sqrt("
print i
print ")="

valStr = str(sqrt(i)) ;format decimal nicely


length = len(valStr)

select case length


case 1:
outStr = "0.00" ;zero case
case 3:
outStr = left(valStr,1)+ "."+right(valStr,2)
case 4:
outStr = left(valStr,2)+ "."+right(valStr,2)
case 5:
outStr = left(valStr,3)+ "."+right(valStr,2)
end select

print outStr ;display results


wait 2 S
next i

Supported in <MATHS.H>

Trigonometry Sine, Cosine and Tangent

Syntax:

byte_variable = sin( word_variable )

byte_variable = cos( word_variable )

byte_variable = tan( word_variable )

Explanation:

Great Cow BASIC supports Three Primary Trigonometric Functions

472
Great Cow BASIC supports the following functions, sin(x), cos(x), tan(x), where x is a signed integer
representing an angle measured in a whole number of degrees. The output values are also integers,
represented as fixed point decimal fractions.

Details:

The sine, cosine and tangent functions are available for your programs simply by including the header
file offering the precision you need.

#INCLUDE <TRIG2PLACES.H> gives two decimal places


#INCLUDE <TRIG3PLACES.H> gives three decimal places
#INCLUDE <TRIG4PLACES.H> gives four decimal places

In fixed point representation, the decimal point is assumed. For example, with two places of accuracy,
sin(60) returns 87, which you would interpret as 0.87. With three places, 866 is returned, to be
interpreted as 0.866, and so on. Another way of thinking of this is to consider the two-place values as
scaled up by 100, the three-place values scaled up by 1000 and the four-place values scaled up by
10,000.

Sine and cosine are always defined, but remember that tangent fails to exist at 90 degrees, 270 degrees
and all their coterminal angles. It is the responsibility of the calling program to avoid these special
values.

Note that the tangent function is not available to four decimal places, since its value grows so rapidly,
exceeding what the Integer data type can represent.

These routines are completely general. The input argument may be positive, negative or zero, with no
restriction on the size. Further observe that lookup tables are used, so the routines are very fast,
efficient and accurate.

Example:_Show the trigonometric values to three decimal places.

;----- Configuration
#chip 16F88, 8 ;PIC16F88 running at 8 MHz
#config mclr=off ;reset handled internally
#config osc=int ;use internal clock
#include <Trig3Places.h>

;----- Constants

#define LCD_IO 4 ;4-bit mode


#define LCD_RS PortB.2 ;pin 8 is LCD Register Select
#define LCD_Enable PortB.3 ;pin 9 is LCD Enable
#define LCD_DB4 PortB.4 ;DB4 on pin 10
#define LCD_DB5 PortB.5 ;DB5 on pin 11
#define LCD_DB6 PortB.6 ;DB6 on pin 12

473
#define LCD_DB7 PortB.7 ;DB7 on pin 13
#define LCD_NO_RW 1 ;ground the RW line on LCD

;----- Variables

dim i as integer
dim outStr, valStr as string

;----- Program

dir PortB out ;all outputs to the LCD

for i = -720 to 720 ;arguments from -720 to 720


cls
print "sin(" ;print the label
print i ;and the argument
print ")=" ;and closing parenthesis
locate 1,0
printTrig(sin(i)) ;print value of the sine
wait 500 mS ;pause to view

cls ;do likewise for cosine


print "cos("
print i
print ")="
locate 1,0
printTrig(cos(i))
wait 500 mS ;pause to view
cls ;do likewise for tangent
print "tan("
print i
print ")="
locate 1,0
printTrig(tan(i))
wait 500 mS ;pause to view
next i

sub printTrig(in value as integer)


;print decently formatted trig results

outStr = "" ;assume positive (no sign)

if value < 0 then ;handle negatives


outStr = "-" ;prefix a minus sign
value = -1 * value ;but work with positives
end if

valStr = str(value)

474
length = len(valStr)
select case length
case 1:
outStr = outStr + "0.00" + valStr
case 2:
outStr = outStr + "0.0" + valStr
case 3:
outStr = outStr + "0." + valStr
case 4:
outStr = outStr + left(valStr,1) + "." + right(valStr,3)
case 5:
outStr = outStr + left(valStr,2) + "." + right(valStr,3)
end select
print outStr
end sub

Trigonometry ATAN

Syntax:

byte_variable = atan (x_vector,y_vector)

Explanation:

Great Cow BASIC supports Three Primary Trigonometric Functions.

Details:

Great Cow BASIC supports the following functions ATan( x, y) where x and y are the vectors. The
function returns a word representing the angle measured in a whole number of degrees.

The function also returns a global variable NegFlag with returns the quadrant of the angle.

Quadrant 1 = 0 to 89 +
Quadrant 2 = 90 to 179 +
Quadrant 3 = 180 to 269 +
Quadrant 4 = 270 to 359 +

This ATan function is a fast XY vector to integer degree algorithm developed in Jan 2011, see
www.RomanBlack.com and sSee http://www.romanblack.com/integer_degree.htm

The function converts any XY values including 0 to a degree value that should be within +/- 1 degree of
the accurate value without needing large slow trig functions like ArcTan() or ArcCos().

At least one of the X or Y values must be non-zero. This is the full version, for all 4 quadrants and will

475
generate the angle in integer degrees from 0-360. Any values of X and Y are usable including negative
values provided they are between -1456 and 1456 so the 16bit multiply does not overflow.

476
Peripheral Pin Select
This is the Peripheral Pin Select section of the Help file. Please refer the sub-sections for details using
the contents/folder view.

Peripheral Pin Select for Microchip microcontrollers.

Introduction:

Peripheral Pin Select (PPS) enables the digital peripheral I/O pins to be changed to support mapping of
external pins to different pins.

In older 8-bit Microchip devices, a peripheral was hard-wired to a specific pin (example: PWM1 output
on pin RC5).

PPS allows you to choose from a number of output and input pins to connect to the digital peripheral.

This can be extremely useful for routing circuit boards.

There are cases where a change of I/O position can make a circuit board easier to route Sometimes
mistakes are found too late to fix so having the option to change a pinout mapping in software rather
than creating a new printed circuit board can be very helpful.

You must use both commands UnLockPPS and LockPPS to complete any PPS changes. Great Cow BASIC
includes these two macros to ensure this process is handled correctly.

Also, see http://microchip.wikidot.com/8bit:pps for more information.

Example:

477
'Please check configuration before using on an alternative microcontroller.

#chip 16f18855,32
#option explicit
#config RSTOSC_HFINT32

'Set the PPS of the I2C and the RS232 ports.


#startup InitPPS, 85
Sub InitPPS
LOCKPPS
RC0PPS = 0x0010 'RC0->EUSART:TX;
RXPPS = 0x0011 'RC1->EUSART:RX;

SSP1CLKPPS = 0x14 'RC3->MSSP1:SCL1;


SSP1DATPPS = 0x13 'RC4->MSSP1:SDA1;
RC3PPS = 0x15 'RC3->MSSP1:SCL1;
RC4PPS = 0x14 'RC4->MSSP1:SDA1;
UnLockPPS
End Sub

For more help, see: UnlockPPS and LockPPS.

UnLockPPS

Syntax:

UNLOCKPPS

Explanation:

Peripheral Pin Select (PPS) has an operation mode in which all input and output selections can be
prevented to stop inadvertent changes.

PPS selections are unlocked by setting by the use of the UnLockPPS command.

Using this command will ensure the special sequence of Microchip assembler is handled correctly.

Command Availability:

Available on all Microchip microcontrollers only.

478
#chip 16f18855,32
#option explicit
#config RSTOSC_HFINT32

'Set the PPS of the I2C and the RS232 ports.


#startup InitPPS, 85
Sub InitPPS
LOCKPPS
RC0PPS = 0x0010 'RC0->EUSART:TX;
RXPPS = 0x0011 'RC1->EUSART:RX;

SSP1CLKPPS = 0x14 'RC3->MSSP1:SCL1;


SSP1DATPPS = 0x13 'RC4->MSSP1:SDA1;
RC3PPS = 0x15 'RC3->MSSP1:SCL1;
RC4PPS = 0x14 'RC4->MSSP1:SDA1;
UnLockPPS
End Sub

For more help, see: LockPPS.

LockPPS

Syntax:

LOCKPSS

Explanation:

Peripheral Pin Select (PPS) has an operation mode in which all input and output selections can be
prevented to stop inadvertent changes.

PPS selections are locked by setting by the use of the LockPPS command.

Using this command will ensure the special sequence of Microchip assembler is handled correctly.

Command Availability:

Available on all Microchip microcontrollers only.

479
#chip 16f18855,32
#option explicit
#config RSTOSC_HFINT32

'Set the PPS of the I2C and the RS232 ports.


#startup InitPPS, 85
Sub InitPPS
LOCKPPS
RC0PPS = 0x0010 'RC0->EUSART:TX;
RXPPS = 0x0011 'RC1->EUSART:RX;

SSP1CLKPPS = 0x14 'RC3->MSSP1:SCL1;


SSP1DATPPS = 0x13 'RC4->MSSP1:SDA1;
RC3PPS = 0x15 'RC3->MSSP1:SCL1;
RC4PPS = 0x14 'RC4->MSSP1:SDA1;
UnLockPPS
End Sub

For more help, see: UnlockPPS.

480
Compiler Directives
This is the Compiler Directives section of the Help file. Please refer the sub-sections for details using
the contents/folder view.

#chip
Syntax:

#chip model, speed

Explanation:

The #chip directive is used to specify the chip model and speed that Great Cow BASIC must compile for.
model is the model of the microcontroller chip - something along the lines of "16F819". speed is the
speed of the chip in MHz, and is required for the delay and PWM routines.

If speed is not present the compiler will select a frequency default frequency that should work.

1. If the chip has an internal oscillator, the compiler will use that and pick the highest speed it
supports.

2. If the chip does not have an internal oscillator, then Great Cow BASIC will assume that the chip is
being run at its maximum possible clock speed using an external crystal.

3. If you are using an external crystal then you must specify a chip frequency.

When using an AVR, there is not need to specify "AT" before the name.

Examples:

#chip 12F509, 4
#chip 18F4550, 48
#chip 16F88, 0.125
#chip tiny2313, 1
#chip mega8, 16

Setting Other Clock frequencies:

Some alternative compilers allow value of the clock speed to be set with the numerical value in Hertz
(i.e. 24576000). This can be useful when using the clock frequencies other than standard frequencies.

Great Cow BASIC requires clock speeds to be specified in MHz, but will accept decimal points. For
example, if you wanted to run a 16F1827 at 24576000 Hz, you would write the following:

481
#chip 16F1827, 24.576

#config
Syntax:

#config option1, option2, ... , optionN

Explanation:

The #config directive is used to specify configuration options for the chip. There is a detailed
explanation of #config in the Configuration section of help.

See Also Configuration

#define
Syntax:

#define Find Replace

Explanation:

#define will search through the program for Find, and replace it with the value given for Replace.

See Also Defines

#if
Syntax:

#if Condition
...
#endif

Explanation:

The #if directive is used to prevent a section of code from compiling unless Condition is true.

Condition has the same syntax as the condition in a normal Great Cow BASIC if command. The only
difference is that it uses constants instead of variables.

482
Example:

'This program will pulse an adjustable number of pins on PORTB


'The number of pins is controlled by the FlashPins constant
#chip 16F88, 8

'The number of pins to flash


#define FlashPins 2

'Initialise
Dir PORTB Out

'Main loop
Do
#if FlashPins >= 1
PulseOut PORTB.0, 250 ms
#endif
#if FlashPins >= 2
PulseOut PORTB.1, 250 ms
#endif
#if FlashPins >= 3
PulseOut PORTB.2, 250 ms
#endif
#if FlashPins >= 4
PulseOut PORTB.3, 250 ms
#endif
Loop

#ifdef
Syntax:

#ifdef Constant | Constant Value | Var(VariableName)


...
#endif

Explanation:

The #ifdef directive is used to selectively enable sections of code.

There are several ways in which it can be used:

• Checking if a constant is defined

• Checking if a constant is defined and has a particular value

483
• Checking if a system variable exists

• Checking if a system bit has been defined

The advantage of using #ifdef rather than an equivalent series of IF statements is the amount of code
that is downloaded to the chip. #ifdef controls what code is compiled and downloaded, IF controls
what is run once on the chip. #ifdef should be used whenever the value of a constant is to be checked.

Great Cow BASIC also supports the #ifndef directive - this is the opposite of the #ifdef directive - it will
remove code that #ifdef leaves, and vice versa.

Note: The code in the following sections will not compile, as it is missing #chip directives and Dir
commands. It is intended to act as an example only.

Example 1: Enabling code if a constant is defined

#define Blink1

#ifdef Blink1
PulseOut PORTB.0, 1 sec
Wait 1 sec
#endif
#ifdef Blink2
PulseOut PORTB.1, 1 sec
Wait 1 sec
#endif

This code will pulse PORTB.0, but not PORTB.1. This is because Blink1 has been defined, but Blink2 has
not. If the line was added at the start of the program, then both pins would be pulsed.

#define Blink2

The value of the constant defined is not important and can be left off of the #define.

Example 2: Enabling code if a constant is defined and has a given value

484
#define PinsToFlash 2

#ifdef PinsToFlash 1,2,3


PulseOut PORTB.0, 1 sec
#endif
#ifdef PinsToFlash 2,3
PulseOut PORTB.1, 1 sec
#endif
#ifdef PinsToFlash 3
PulseOut PORTB.2, 1 sec
#endif

This program uses a constant called PinsToFlash that controls how many lights are pulsed. PORTB.0 is
pulsed when PinsToFlash is equal to 1, 2 or 3, PORTB.1 is pulsed when PinsToFlash equals 2 or 3, and
PORTB.2 is flashed when PinsToFlash is 3.

Example 3: Enabling code if a system variable is defined

#ifdef NoVar(ANSEL)
SET ADCON1.PCFG3 OFF
SET ADCON1.PCFG2 ON
SET ADCON1.PCFG1 ON
SET ADCON1.PCFG0 OFF
#endif
#ifdef Var(ANSEL)
ANSEL = 0
#endif

The above section of code has been copied directly from a-d.h. It is used to disable the A/D function of
pins, so that they can be used as standard digital I/O ports. If ANSEL is not declared as a system variable
for a particular chip, then the program uses ADCON1 to control the port modes. If ANSEL is defined, then
the chip is newer and its ports can be set to digital by clearing ANSEL.

Example 4: Enabling code if a system bit is defined

Similar to above, except with Bit and NoBit in the place of Var and NoVar respectively.

See Also Defines, #define

#ifndef
Syntax:

485
#ifndef Constant | Constant Value | Var(VariableName)
...
#endif

Explanation:

The #ifndef directive is used to selectively enable sections of code. It is the opposite of the #ifdef
directive - it will delete code in cases where #ifdef would leave it, and will leave code where #ifdef
would delete it.

See the #ifdef article for more information.

#include
Syntax:

#include filename

Explanation:

#include tells Great Cow BASIC to open up another file, read all of the subroutines and constants from
it, and then copy them into the current program.

There are two forms of include; absolute and relative.

Absolute is used to refer to files in the ..\GreatCowBASIC\include directory. The name of the file is
specified in between < and > symbols. For instance, to include the file srf04.h, the directive is:

#include <srf04.h>

Relative is used to read files in the same folder as the currently selected program. Filenames are given
enclosed in quotation marks, such as where mycode.h is the name of the file that is to be read.

#include "mycode.h"

NOTES: It is not essential that the include file name ends in .h - the important thing is that the name
given to Great Cow BASIC is the exact name of the file to be included.

Those who are familiar with #include in assembly or C should bear in mind that #include in Great Cow
BASIC works differently to #include in most other languages - code is not inserted at the location of the
#include, but rather at the end of the current program.

486
#script
Syntax:

#script
[scriptcommand1]
[scriptcommand2]
...
[scriptcommandn]
#endscript

Explanation:

The #script block is used to create small sections of code which Great Cow BASIC runs during
compilation. A detail explanation and example are included in the Scripts article.

See Also Scripts

#startup
Syntax:

#startup SubName [priority]

Explanation:

#startup is used in include files to automatically insert initialization routines. If a define or subroutine
from the file is used in the program, then the specified subroutine will be called.

The priority to #startup support the setting of the priority of the subroutines for all the libraries in a
project.

Subroutines will be called in order from smallest to largest priority number.

InitSys has priority 80, lowlevel communication routines have the priority of 90
All other subroutines defaults to 100.

Notes: Limitations on this directive are:

startup may only occur once within a source file.

No parameters can be passed the the subroutine that is specificed.

487
Example 1:

This example from the hardware I2C library set the subroutine with the priority of 90.

#startup HIC2Init, 90

Example 2:

This example from would be included in user code to ensure the PPS setting are set prior to use of the
MSSP or USART.

#chip 16f18855,32
#option explicit
#config RSTOSC_HFINT32

'Set the PPS of the I2C and the RS232 ports.


#startup InitPPS, 85
Sub InitPPS
RC0PPS = 0x0010 'RC0->EUSART:TX;
RXPPS = 0x0011 'RC1->EUSART:RX;

SSP1CLKPPS = 0x14 'RC3->MSSP1:SCL1;


SSP1DATPPS = 0x13 'RC4->MSSP1:SDA1;
RC3PPS = 0x15 'RC3->MSSP1:SCL1;
RC4PPS = 0x14 'RC4->MSSP1:SDA1;
End Sub

#mem
This directive is obsolete.

Great Cow BASIC determines the amount of memory on a chip automatically, and will ignore the #mem
directive.

It is recommended that this directive is removed from all programs.

Other directives
The built-in #defines are used to support the #IFDEF command set are as follows. The table also shows
which #defines are supported as string in HSerPrint, SerPrint and other string related commands.

488
Directi Descrip Output Usage Returns
ve tion

ChipADC String #IFDEF & Output The number of A/D inputs on the current chip
commands

ChipEEp Number #IFDEF & Output The number of Bytes in EEPROM memmory
rom commands

ChipIO String #IFDEF & Output The number of general purpose IO pins
commands

ChipMHz String #IFDEF & Output The microcontroller clock speed


commands

ChipNam Number #IFDEF Only The microcontroller type


e
ChipNam String #IFDEF & Output The microcontroller name
eStr commands

ChipPin Number #IFDEF & Output The number of microcontroller pins.


s commands

ChipRam Number #IFDEF & Output The RAM size


commands

ChipFam Number #IFDEF & Output See the table below


ily commands

ChipWor Number #IFDEF & Output The number of WORDS in Flash memmory
ds commands

Var() Functio Not applicable True if a register is declared (or false if not declared) in the
n currently specficied microcontroller’s .dat file.
Var(register_name)

NoVar() Functio Not applicable True if a register is NOT declared (or false if declared) in the
n currently specficied microcontroller’s .dat file.
NoVar(register_name)

Bit() Functio Not applicable True if a bit is declared (or false if not declared) in the currently
n specficied microcontroller’s .dat file. Bit(bit_name)

NoBit() Functio Not applicable True if a bit is NOT declared (or false if declared) in the
n currently specficied microcontroller’s .dat file. NoBit(bit_name)

Allof() Functio Not applicable True if all defines are declared: AllOf(define1, define2, …)
n

OneOf() Functio Not applicable True if one of the defines is declared: OneOf(define1, define2,
n …)

489
This table shows the ChipFamily constants mapped to the microcontroller architecture.

ChipFamily Value Microcontroller Characteristics

100 AVR core version V0E class microcontrollers

110 AVR core version V1E class microcontrollers

120 AVR core version V2E class microcontrollers

130 AVR core version V3E class microcontrollers but essentially the mega32u6 only

12 Baseline devices. 12 Bit instruction set

15 Mid-range core devices. 14 Bit instruction set with enhanced instruction set class

15 plus Mid-range core devices. 14 Bit instruction set with enhanced instruction set and
familyVariant=1 with large memory capability class

16 High end core devices. 16 Bit instruction set, memory addressing architecture
and an extended instruction set.

490
Compiler Options
This is the Compiler Options section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

#Option Explicit
Syntax:

#option explicit

This option ensures that all variables are dimensioned in the user program. The scope is the user code
only and no other code space like .h or include files.

#option explicit requires all variables,including bytes, in the user program to be defined.

Variables can be defined and not used within your user program. Unused variables will not allocate
memory.

Introduction:

Example:

'Set chip model


#chip 16f877a

'Example command
#option explicit

dim myuserflag as byte

myuserflag = true

For more help, see Variable Lifecycle

#Option NoConfig
Syntax:

#option NoConfig

This option will prevent the generated assembler from generating _Config items.

491
#option NoConfig is used when using a bootloader.

Introduction:

Example:

'Set chip model


#chip 16f877a

'Example command
#option NoConfig

'User Code......

#Option Bootloader
Syntax:

#option bootloader address

Explanation:

#option bootloader prevents the overwriting of any pre-loaded bootloader code, vectors, etc. below the
address and have all Great Cow BASIC code start at address.

A bootloader is a program that stays in the microcontroller and communicates with the PC, typically
through the serial interface. The bootloader receives a user program from the PC and writes it in the
flash memory, then launches this program in execution. Bootloaders can only be used with those
microcontrollers that can write their flash memory through software.

The bootloader itself must be written into the flash memory with an external programmer.

In order for the bootloader to be launched after each reset, a goto bootloader instruction must exist
somewhere in the first 4 instructions; There are two types of bootloaders, some that require that the
user reallocate the code and others that by themselves reallocate the first 4 instructions of the user
program to another location and execute them when the bootloader exits.

The diagram below shows the architecture of a bootloader. The left hand is the operation of the
instructions without a bootloader. The right hand shows the initial instruction of goto the bootoader,
then, when the bootloader has initialised the execution of the start code.

492
See example bootload software.

Example:

#option bootloader 0x800

#Option NoContextSave
Syntax:

#option NoContextSave

Explanation:

Interrupts can occur at almost any time, and may interrupt another command as it runs. To ensure
that the interrupted command can continue properly after the interrupt, some temporary variables
(the context) must be saved. Normally Great Cow BASIC will do this automatically, but in some cases it
may be necessary to prevent this. If porting some existing assembly code to Great Cow BASIC, or
creating a bootloader using Great Cow BASIC that will call another program,

NoContextSave can be used to prevent the context saving code from being added automatically.

Be very careful using this option - it is very easy to cause random corruption of variables. If creating
your own context saving code, you may need to save several variables. These are:

1. For Microchip PIC microcontrollers 12F/16F: W, STATUS, PCLATH

2. For Microchip PIC microcontrollers 12F1/16F1/18F: W, STATUS, PCLATH, PCLATU, BSR

493
For Atmel AVR microcontrollers: All 32 registers

Other variables may also need to be saved, depending on what commands are used inside the
interrupt handler. Everything that is saved will also need to be restored manually when the interrupt
handler finishes.

Example:

' This shows an example that could be used by a bootloader to call some application
code.

' The application code must deal with context save and restore
' Suppose that application code starts at location 0x100, with interrupt vector at
0x108

'Chip model
#chip 18F2620

'Do not save context automatically


#option NoContextSave

'Main bootloader routine


Set PORTB.0 On
'Do other stuff to make this an actual bootloader and not a trivial example
'Transfer control to application code
goto 0x100

'Interrupt routine - this will be placed at the interrupt vector


Sub Interrupt
'If any interrupt occurs, jump straight to application interrupt vector
goto 0x108
End Sub

#Option NoLatch
Syntax:

#option nolatch

This option disables PORTx to LATx redirection.

Introduction:

The Great Cow BASIC compiler will redirect all I/O pin writes from PORTx to LATx registers on
16F1/18F
3. Microchip PIC microcontrollers.

494
The Microchip PIC mid-range microcontrollers use a sequence known as Read-Modify-Write (RMW)
when changing an output state (1 or 0) on a pin. This can cause unexpected behavior under certain
circumstances.

When your program changes the state on a specific pin, for example RB0 in PORTB, the
microcontroller first READs all 8 bits of the PORTB register which represents the states of all 8 pins in
PORTB (RB7-RB0).

The microcontroller then stores this data in the MCU. The bit associated with RB that you’ve
commanded to MODIFY is changed, and then the microcontrollers WRITEs all 8 bits (RB7- RB0) back
to the PORTB register.

During the first reading of the PORT register, you will be reading the actual state of the physical pin.
The problem arises when an output pin is loaded in such a way that its logic state is affected by the
load. Instances of such loads are LEDs without current-limiting resistors or loads with high capacitance
or inductance.

For example, if a capacitor is attached between pin and ground, it will take a short while to charge
when the pin is set to 1. On the other hand, if the capacitor is discharged, it acts like a short circuit,
forcing the pin to '0' state, and, therefore, a read of the PORT register will return 0, even though we
wrote a 1 to it.

Great Cow BASIC resolves this issue using the LATx register when writing to ports, rather than using
PORTx registers. Writing to a LATx register is equivalent to writing to a PORTx register, but readings
from LATx registers return the data value held in the port latch, regardless of the state of the actual
pin. So, for reading use PORTx.

Note:

You can use the #option nolatch if problems occur with compiler redirection.

#Option Volatile
Syntax:

#option volatile `bit`

This option ensure port setting are glitch-free.

Introduction:

#option volatile bit where bit is an IO bit, like PORTB.0 appended.

This will cause the compiler to set the bit without any glitches when copying a value from another
variable, but will increase code size slightly.

495
Example:

'Set chip model


#chip 16f877a

'Example command
#option volatile portb.0

dir portb.0 out

do forever

portb.0 = !portb.0

loop

496
Using Assembler
This is the Using Assembler section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Assembler Overview
Introduction:

You can use microcontroller assembler code within your Great Cow BASIC code.

You can put the assembler code inline in with your source code. The assembler code will be passed
through to the assembly file associated with your project.

Great Cow BASIC should recognise all of the commands in the microcontroller datasheet.

The commands should be in lower case, this is good practice, and have a space or tab in front of the
command.

Even if the mnemonics are not being formatted properly, gputils/MPASM should still be capable of
assembling the source code.

Format commands as follows:

Example:

btfsc STATUS,Z
bsf PORTB,1

497
Macros
This is the Macros section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Macros Overview
Introduction:

You can use macros within your Great Cow BASIC code.

Macros are similar to subroutines. But during compilation, everything is inserted inline. This may
increase the code size slightly, but it also reduces stack usage.

Parameters are handled in a similar way to how constants are handled, so there is a lot more freedom
when passing things in to a macro. (Unlike subs or functions, where everything must be stored in a
variable.)

For example, for PulseOut one parameter is a pin, and the other is a time length like "500 ms". Neither
of those parameters could be stored in a variable, but passing them in as macro parameters is possible.

Demonstration Program:

'PulseOut Macro
macro Pulseout (Pin, Time)
Set Pin On
Wait Time
Set Pin Off
end macro

498
Example Macros
This is the Example Macros section of the Help file. Please refer the sub-sections for details using the
contents/folder view.

Measuring a Pulse Width

Introduction

The demomstration shows how a macro can be used to optimised code by compiling code inline.

When the measurement of a pulse width to sub-microsecond resolution is required for instance
measuring the high or low pulse width of an incoming analog signal a comparator can be combined
with a timer to provide the pulse width.

Microchip PIC has published a "Compiled Tips 'N Tricks Guide" that explains how to do certain tasks
with Microchip PIC 8-bit microcontrollers.

This guide provides the steps that need to be taken to perform the task of measuring a pulse width.
The guide provides guidance on measuring a pulse width using Timer 1 and the CCP module. This
guidance was used as the basis for the Great Cow BASIC port the shown below. The guidance was
generic and in this example polling the CCP flag bit was more convenient than using an interrupt.

In this demonstration shown below, a 16F1829 microcontroller operating at 32 Mhz uses the internal
oscillator. The demomstration code is based on a macro that uses Timer1 and CCP4. However, any of
the four CCP modules could be used, the 16F1829 microcontroller has four CCP module.

The timer resolution of this method uses a timer Prescaler of 1:8 and a microcontroller frequency of 32
MHz giving a pulse width resolution is 1ms. With the timer Prescaler of 1:2 and the microcontroller
frequency of 32MHz the resolution is 250 ns.

The accuracy is dependent upon the accuracy of the system clock, but oscilliscope measurements have
show an accuracy of +- 1us from 3us to 1000us.

In this demonstration the following was implemented

• Using Great Cow BASIC a macro to ensure the generated assembler is inline to ensure the timing is
consistent and no sub routines are called.

• Another microcontroller was used to generate the pulses to be measured

• A TEK THS730A oscilliscope was used to measure/verify pulse widths

• A 4x20 LDC module with an I2C Backpack was used to display the results. However, as an
alternative, a serial output
to a terminal program to view the data could be used

This demonstration could be improved by adding code to poll the TIMER1 overflow flag. IF the timer

499
overflows, then either no pulse was detected or the pulse was longer than allowed by the
prescaler/OSC settings. In this case, return a value of zero for pulse width.

Usage:

To get positive pulse width use:

PULSE_IN

PULSE_IN returns a global word variable Pulse_Width

Demonstration Program:

#Chip 16F1829, 32
#CONFIG MCLRE = OFF

'Setup Software I2C


#define I2C_MODE Master
#define I2C_DATA PORTA.2
#define I2C_CLOCK PORTC.0
#define I2C_DISABLE_INTERRUPTS ON

'Set up LCD
#define LCD_IO 10
#define LCD_SPEED FAST
#define LCD_Backlight_On_State 1
#define LCD_Backlight_Off_State 0

'Note: This example can be improved by adding code to poll the 'TIMER1 overflow flag.
IF the timer overflows, then either no 'pulse was detected or the pulse was longer than
allowed by the 'prescaler/OSC settings. In this case, return a value of zero 'for pulse
width.

CLS
PRINT "Pulse Width Test"
DIM PULSE_WIDTH AS WORD
DIR PORTC.6 IN

'Setup timer
'Set timer1 using PS1_2 gives 250ns resolution
InitTimer1 OSC, PS1_8
wait 1 s
CLS

'MAIN PROGRAM LOOP


DO

500
PULSE_IN 'Call the Macro to get positive pulse width.
Locate 0,0
PRINT Pulse_Width
PRINT " "
wait 1 s
Loop

MACRO PULSE_IN 'Measure Pulse Width


'Configure CCP4 to Capture rising edge
CCP4CON = 5 'Set to 00000101
StartTimer 1
CCP4IF = 0

do while CCP4IF = 0 'Wait for rising edge


loop

TMR1H = 0: TMR1L = 0 'Clear timer to zero


CCP4IF = 0 'Clear flag

'Configure CCP4 to Capture Falling Edge


CCP4CON = 4 '00000100'

do while CCP4IF = 0 'Wait for falling edge


loop

StopTimer 1 'Stop the time


Pulse_Width = TIMER1 'Save the timer value
CCP4IF = 0 'Clear the CCP4 flag
End MACRO

Also see Macros Overview

Implementing a method with a Pin name as a parameter

Introduction

A constant such as a Pin name cannot be passed to a sub routine or a function. This is a constraint of
Great Cow BASIC.

A macro can be used to implement a method of passing a constant to reusable code section.

The example shown below implements a button press routine and takes an input port constant and
prints the result on an LCD display.

Note: A macro will use more program memory as the macro will be compiled as inline code.
Therefore, for every use of the macro will use additional program memory - the same amount of

501
program memory for each call to the macro.

Demonstration Program:

#chip 16F877a, 16
#define Button PORTC.1 ' Switch on PIN 14 via 10K pullup resistor
DIR Button In
wait 1 sec

'USART settings
#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING

;======== MAIN PROGRAM LOOP ================


HSerPrint "Button Test"
HSerPrintCRLF 2
Do
Test_button ( button )
Loop
;==========================================

Macro Test_button (Button)


if Button = ON then
wait 10 ms 'debounce
ButtonCount = 0

Do While Button = On
Wait 10 ms
ButtonCount += 1
Loop

if ButtonCount > 5 then


if ButtonCount > 50 then 'Long push
hserprint "Long push"
else 'Short push
hserprint "Short push"
end if
HSerPrintCRLF
end if
wait 1 s
end if
End Macro

Also see Macros Overview

502
Example Programs
Flashing LEDs and an Interrupt
Explanation:

This code implements four flashing LEDs. This is based on the Microchip PIC Low Pin Count Demo
Board.

The example program will blink the four red lights in succession. Press the Push Button Switch, labeled
SW1, and the sequence of the lights will reverse. Rotate the potentiometer, labeled RP1, and the light
sequence will blink at a different rate.

This implements an interrupt for the switch press, reads the analog port and set the LEDs.

Demonstration program:

#chip 18F14K22, 32
#config OSC = IRC, MCLRE_OFF

'Works with the low count demo board

'Set the input pin direction


#define SwitchIn1 PORTa.3
Dir SwitchIn1 In

#define LedPort PORTc


DIR PORTC OUT

'Setup the ADC pin direction


Dir PORTA.0 In
dim ADCreading as word

'Setup the input pin direction


#define IntPortA PORTA.1
Dir IntPortA In

'Variable and constants


#define intstate as byte
intstate = 0
#define minwait 1

dim ccount as byte


dim leddir as byte

503
ccount = 8
leddir = 0

SET PORTC = 15
WAIT 1 S

SET PORTC = 0

'Setup the Interrupt


Set IOCA.3 on
Dir porta.3 in
On Interrupt PORTABCHANGE Call Setir

'Set initial LED direction


setLedDirection

DO FOREVER

INTON
ADCreading = ReadAD10(AN0)
if ADCreading < minwait then ADCreading = minwait

'Set LEDs
Set PortC = ccount
wait ADCreading ms

if leddir = 0 then
rotate ccount left simple
'Restart LED position
if ccount = 16 then
ccount = 128
end if

end if

if leddir = 1 then
rotate ccount Right simple
'Restart LED position
if ccount = 128 then
ccount = 8
end if

end if
'Reset interrupt - this may be been reset so set to zero so interrupt can
operate.
intstate = 0

504
Loop

'Interrupt routine.
sub Setir

if IntPortA = 0 and intstate = 0 then


intstate = 1
wait while SwitchIn1 = 0
setLedDirection
end if

end sub

sub setLedDirection

'Set LED values


select case leddir

case 0
leddir = 1
ccount = 8

case 1
leddir = 0
ccount = 1

end select

End Sub

See Also Interrupts, ReadAD10

Flashing LED with timing parameters


Explanation:

This is an example of how to define a subroutine.

When called, this subroutine will blink an LED for the number of times and duration as determined by
the input parameters.

The syntax of the subroutine is:

505
' Flash_LED (numtimes, OnTime, (optional) OffTime)
' Where numtimes is from 1 - 255 and OnTime/OffTime is
' from 0 - 65535 ms. If OffTime is not entered, then
' OffTime = OnTime.

Sub Flash_LED (in numtimes, in OnTime as WORD, Optional OffTime as WORD = OnTime)
repeat numtimes
set LED on
wait OnTime ms
set LED OFF
wait OffTime ms
end repeat
End Sub

Shown below is a working example program using a Microchip PIC 18F25K22.

Change Settings/PORTS as needed for other Chips.

Connect an LED to the LED pin via a 1K series resistor.

Demonstration program:

506
#chip 18F25K22, 16
#config OSC = INTIO67, MCLRE = OFF, XINST = OFF
#define LED PORTC.1 'Led on PIN 14 via 1K resistor
DIR LED OUT
wait 1 sec

;======== MAIN PROGRAM LOOP ================


Do
Flash_LED ( 3,250 ) '3 Flashes 250 ms equal on/off time
Wait 2 Sec
Flash_LED ( 5,250,500 ) '5 flashes On 250 ms / off 500 ms
Wait 2 Sec
Flash_LED ( 10,100 ) '10 rapid flashes
Wait 2 Sec
Loop
;==========================================

Sub Flash_LED (in numtimes, in OnTime as WORD, optional OffTime as word = OnTime)
repeat numtimes
set LED on
wait OnTime ms
set LED OFF
wait OffTime ms
end repeat
End Sub

Generate Accurate Pulses


Explanation:

The PulseOut Command is a reliable method for generating pulses if accuracy is not critical, the
PulseOut command uses a calculation of the clock to speed for the timing .

If you need better accuracy and resolution then an alternative approach is required.

To generate pulses in the 100 us to 2500 us range with an accuracy of +- 1us over this range is practical
using the approach shown in this example.

This example code works on a midrange PIC16F690 operating at 8Mhz. However, it should work on
any Microchip PIC microcontroller, but may need some minor modifications.

Usage:

Pulse_Out_us ( word_value )

507
How It Works:

Timer1 is loaded with a preset value based upon the variable passed to the sub routine. The timer
(Timer1) is started and the pulse pin (the output pin) is set high. When Timer1 overflows the Timer1
interrupt flag bit (TMR1IF) is set. This causes the program to exit a polling loop and set the pulse Pin off.
Then, Timer1 is stopped and TMRIF flag is cleared and the sub routine exits.

This method supports delays between 5 us and 65535 us and uses Timer1.

Test Results:

These tests were completed using a Saleae Logic Analyzer.

Pulse setting Time Results

Pulse_Out_us (2500) 2501.375 us


Pulse_Out_us (1000) 1000.750 us
Pulse_Out_us (100) 100. 125 us
Pulse_Out_us (10) 10.125 us
Pulse_Out_us with less then 4 Unreliable results

Demonstration program:

;**************************************
; Code: Output an accurate pulse
; Author: William Roth 03/13/2015
;**************************************

#chip 16F690,8

; ---- Define Hardware settings


; ---- Define I2C settings - CHANGE PORTS AS REQUIRED
#define I2C_MODE Master
#define I2C_DATA PORTB.4
#define I2C_CLOCK PORTB.6
#define I2C_DISABLE_INTERRUPTS ON

; ---- Set up LCD - Using I2C LCD Backpack


#define LCD_IO 10
#define LCD_I2C_Address_1 0x4e ; default to 0x4E
; ---- May need to use SLOW or MEDIUM if your LCD is a slower device.
#define LCD_SPEED Medium
#define LCD_Backlight_On_State 1
#define LCD_Backlight_Off_State 0

CLS

508
; ---- USART settings
#define USART_BAUD_RATE 38400
#define USART_TX_BLOCKING
DIR PORTB.7 OUT

; ---- Setup Pulse parameters


#define PulsePin PORTC.4
Dim Time_us As WORD
Dir PulsePin Out 'Pulsout pin
Set PulsePin off

; ---- Setup Timer


InitTimer1 Osc, PS1_2 'For 8Mhz Chip
'InitTimer1 Osc, PS1_4, 'For 16 Mhz Chip
TMR1H = 0: TMR1L = 0 'Clear timer1
TMR1IF = 0 'Clear timer1 int flag
TMR1IE = on 'Enable timer1 Interrupt (Flag only)

' **** This is the MAIN loop *****


Do
PULSE_OUT_US (2500) 'Measured as 2501.375 us
wait 19 ms
Pulse_Out_US (1000) 'Measured as 1000.750 us
wait 19 ms
Pulse_Out_US (100) 'Measured as 100.125 us
wait 19 ms
Pulse_Out_US (10) 'Measured as 10.125 us
Wait 19 ms
loop

SUB PULSE_OUT_US (IN Variable as WORD)


TMR1H = 65535 - Variable_H 'Timer 1 Preset High
TMR1L = (65535 - Variable) + 4 'Timer 1 Preset Low
Set TMR1ON ON 'Start timer1
Set PulsePin ON 'Set Pin high
Do While TMR1IF = 0 'Wait for Timer1 overflow
Loop
Set PulsePin off ' Pin Low
Set TMR1ON OFF ' Stop timer 1
TMR1IF = 0 'Clear the Int flag
END SUB

Also see PulseOut

Graphical LCD Demonstration

509
Explanation:

This demonstration code shows the set of commands supported by Great Cow BASIC.

Demonstration program:

;Chip Settings
#chip 16F877a,16

#include <glcd.h>

'Setup the GLCD


#Define glcd_rw PORTD.3 'RW pin on LCD
#Define glcd_reset PORTD.4 'Reset pin on LCD
#Define glcd_cs1 PORTD.1 'CS1, CS2 can be reversed
#Define glcd_cs2 PORTD.2 'CS1, CS2 are be reversed
#Define glcd_rs PORTD.5 'D/I pin on LCD
#Define glcd_enable PORTD.4 'E pin on LCD
#Define glcd_db0 PORTB.0 'D0
#Define glcd_db1 PORTB.1 'D1
#Define glcd_db2 PORTB.2 'D2
#Define glcd_db3 PORTB.3 'D3
#Define glcd_db4 PORTB.4 'D4
#Define glcd_db5 PORTB.5 'D5
#Define glcd_db6 PORTB.6 'D6
#Define glcd_db7 PORTB.7 'D7 on LCD

'Specify the type of GLCD


#define GLCD_TYPE GLCD_TYPE_KS0108
#define GLCD_WIDTH 128
#define GLCD_HEIGHT 64
#define GLCD_PROTECTOVERRUN

wait 1 s
GLCDCLS
GLCDPrint 0, 1, "Great Cow BASIC "
wait 1 s
GLCDCLS

rrun = 0
dim msg1 as string * 16

do forever

GLCDCLS
Box 18,30,28,40
Line 0,0,127,63

510
Line 0,63,127,0
wait 1 s

FilledBox 18,30,28,40
wait 1 s

GLCDCLS

GLCDDrawString 30,0,"ChipMhz@"
GLCDDrawString 78,0, str(ChipMhz)
Circle(10,10,10,1) 'upper left
Circle(117,10,10,1) 'upper right
Circle(63,31,10,1) 'center
Circle(63,31,20,1) 'center
Circle(10,53,10,1) 'lower left
Circle(117,53,10,1) 'lower right
wait 1 s

GLCDDrawString 30,0,"ChipMhz@"
GLCDDrawString 78,0, str(ChipMhz)
FilledCircle(10,10,10,1) 'upper left
FilledCircle(117,10,10,1) 'upper right
FilledCircle(63,31,10,1) 'center
FilledCircle(63,31,20,1) 'center
FilledCircle(10,53,10,1) 'lower left
FilledCircle(117,53,10,1) 'lower right
wait 1 s

GLCDCLS
GLCDDrawString 30,0,"ChipMhz@"
GLCDDrawString 78,0, str(ChipMhz)
Circle(10,0,10,1) 'upper left
Circle(117,0,10,1) 'upper right
Circle(63,31,10,1) 'center
Circle(63,31,20,1) 'center
Circle(10,63,10,1) 'lower left
Circle(117,63,10,1) 'lower right
wait 1 s

GLCDCLS
GLCDDrawString 0,10,"Hello" 'Print Hello
wait 1 s
GLCDDrawString 0,10, "ASCII #:" 'Print ASCII #:
Box 18,30,28,40 'Draw Box Around ASCII Character
for char = 0x30 to 0x39 'Print 0 through 9
GLCDDrawString 16, 20 , Str(char)+" "
GLCDdrawCHAR 20, 30, char
wait 250 ms

511
next
line 0,50,127,50 'Draw Line using line command
for xvar = 0 to 80 'Draw line using Pset command
pset xvar,63,on
next
FilledBox 18,30,28,40 'Draw Box Around ASCII Character '
wait 1 s
GLCDCLS
GLCDDrawString 0,10,"End "
wait 1 s
GLCDCLS

workingGLCDDrawChar:
dim gtext as string
gtext = "KS0108"

for xchar = 1 to gtext(0) 'Print 0 through 9


xxpos = (1+(xchar*6)-6)
GLCDDrawChar xxpos , 0 , gtext(xchar)
next

GLCDDrawString 1, 9, "Great Cow BASIC @2014"


GLCDDrawString 1, 18,"GLCD 128*64"
GLCDDrawString 1, 27,"Using GLCD.H from GCB"
GLCDDrawString 1, 37,"Using GLCD.H GCB@2014"
GLCDDrawString 1, 45,"GLCDDrawChar method"
GLCDDrawString 1, 54,"Test Routines"

wait 1 s
GLCDCLS

msg1 = "Run = " +str(rrun)


rrun++
GLCDPrint 0, 3, msg1
wait 1 s
GLCDCLS

loop

For more help, see Graphical LCD Demonstration, GLCDCLS, GLCDDrawChar, GLCDPrint,
GLCDReadByte, GLCDWriteByte, Pset

InfraRed Remote
Explanation:

Great Cow BASIC support interfacing with IR remote controls. The header file contains explanations,

512
for both hardware and software.

This has been tested on many different IR sensors, and different remote controls.

Demonstration program:

The example is expected to work with most any IR sensor running at a 38 kHz carrier frequency.

513
;This demo prints the device number and key number sent by
;a Sony compatible IR remote control unit to an LCD

;Thomas Henry --- 4/23/2014

#chip 16F88, 8 ;PIC16F88 running at 8 MHz


#config mclr=off ;reset handled internally
#config osc=int ;use internal clock
#include <SonyRemote.h> ;include the header file

;----- Constants

#define LCD_IO 4 ;4-bit mode


#define LCD_RS PortB.2 ;pin 8 is Register Select
#define LCD_Enable PortB.3 ;pin 9 is Enable
#define LCD_DB4 PortB.4 ;DB4 on pin 10
#define LCD_DB5 PortB.5 ;DB5 on pin 11
#define LCD_DB6 PortB.6 ;DB6 on pin 12
#define LCD_DB7 PortB.7 ;DB7 on pin 13
#define LCD_NO_RW 1 ;ground RW line on LCD

#define IR_DATA_PIN PortA.0 ;sensor on pin 17

;----- Variables

dim device, button as byte

;----- Program

dir PortA in ;A.0 is IR input


dir PortB out ;B.2 - B.6 for LCD

do
readIR_Remote(device, button) ;wait for button press

cls ;show device code


print "Device: "
print device

locate 1,0
print "Button: " ;show button code
print button

wait 10 mS ;ignore any repeats


loop ;repeat forever

514
See also SonyRemote.h.

SonyRemote.h

Explanation: Sony IR Remote Control Library for Great Cow BASIC

This include file will let you easily read and use the infrared signals from a Sony compatible television
remote control. In particular, the remote control transmits a pulse modulated signal, the sensor detects
this, and the subroutine in this header file decodes the signal, returning two numbers: one
representing the device (television, VCR, DVD, tuner, etc.), while the the other returns the key which
has been depressed (VOL+, MUTE, channel numbers 0 through 9, etc.).

This has been tested and confirmed with a fixed remote control purchased surplus for $2.00 from All
Electronics, as well as an universal remote control, set to Sony mode.

Moreover it has also been tested with a Panasonic IR sensor and a Vishay sensor, both purchased
surplus for about fifty cents.

Every combination performed well, and it is probably the; case that most any garden variety 38 kHz IR
sensor will work. The only tricky bit is making sure you get the pinout for your sensor correct; search
out the datasheet for whichever device you use.

There are only three pins: Ground Vcc Data

It is essential to filter the power applied to the Vcc pin. Do this by connecting a 100 ohm resistor from
the +5V power supply to the Vcc pin, and bridge the pin to ground with a 4.7uF electrolytic capacitor.

The Data pin requires a 4.7k pullup resistor.

There is only one constant required of the calling program. It indicates which port line the IR sensor is
connected to. For example,

#DEFINE IR_DATA_PIN PORTA.0

There is one subroutine:

readIR_Remote(IR_rem_dev, IR_rem_key)

The values returned are, respectively, the device number mentioned earlier and the key that is
currently pressed. Both are byte values.

Seventeen local bytes are consumed, and two bytes are used for the output parameters. That’s a grand
total of nineteen bytes required when invoking this subroutine.

Header File

515
sub readIR_Remote(out IR_rem_dev as byte, out IR_rem_key as byte)
dim IR_rem_count, IR_rem_i as byte
dim IR_rem_width(12) as byte ;pulse width array

do
IR_rem_count = 0 ;wait for start bit
do while IR_DATA_PIN = 0 ;measure width (active low)
wait 100 uS ;24 X 100 uS = 2.4 mS
IR_rem_count++
loop
loop while IR_rem_count < 20 ;less than this so wait

for IR_rem_i = 1 to 12 ;read/store the 12 pulses


do
IR_rem_count = 0
do while IR_DATA_PIN = 0 ;zero = 6 units = 0.6 mS
wait 100 uS ;one = 12 units = 1.2 mS
IR_rem_count++
loop
loop while IR_rem_count < 4 ;too small to be legit

IR_rem_width(IR_rem_i) = IR_rem_count ;else store pulse width


next IR_rem_i

IR_rem_key = 0 ;command built up here


for IR_rem_i = 1 to 7 ;1st 7 bits are the key
IR_rem_key = IR_rem_key / 2 ;shift into place
if IR_rem_width(IR_rem_i) > 10 then ;longer than 10 mS
IR_rem_key = IR_rem_key + 64 ;so call it a one
end if
next

IR_rem_dev = 0 ;device number built up here


for IR_rem_i = 8 to 12 ;next 5 bits are device number
IR_rem_dev = IR_rem_dev / 2
if IR_rem_width( IR_rem_i ) > 10 then
IR_rem_dev = IR_rem_dev + 16
end if
next
end sub

Midpoint Circle Algorithm


Explanation:

Great Cow BASIC can draw circles using the midpoint circle algorithm. The midpoint circle algorithm

516
determines the points needed for drawing a circle. The algorithm is a variant of Bresenham’s line
algorithm, and is thus sometimes known as Bresenham’s circle algorithm, although not actually
invented by Jack E. Bresenham.

The example program below show the midpoint circle algorithm within Great Cow BASIC.

Example Output on GLCD Device:

'Midpoint Circle algorithm


'Chip model
#chip 16F886, 8 ;PIC16F88 running at 8 MHz
#config mclr=off ;reset handled internally
#config osc=int ;use internal clock

#include <glcd.h>

;----- Constants

;Pinout is shown for the LCM12864H-FSB-FBW


;graphical LCD available from Amazon.

; +5V ;LCD pin 1


; ground ;LCD pin 2
; Vo = wiper of pot ;LCD pin 3
#define GLCD_DB0 PORTB.0 ;LCD pin 4
#define GLCD_DB1 PORTB.1 ;LCD pin 5
#define GLCD_DB2 PORTB.2 ;LCD pin 6
#define GLCD_DB3 PORTB.3 ;LCD pin 7
#define GLCD_DB4 PORTB.4 ;LCD pin 8
#define GLCD_DB5 PORTB.5 ;LCD pin 9
#define GLCD_DB6 PORTB.6 ;LCD pin 10
#define GLCD_DB7 PORTB.7 ;LCD pin 11
#define GLCD_CS2 PORTA.0 ;LCD pin 12

517
#define GLCD_CS1 PORTA.1 ;LCD pin 13
#define GLCD_RESET PORTA.2 ;LCD pin 14
#define GLCD_RW PORTA.3 ;LCD pin 15
#define GLCD_RS PORTA.4 ;LCD pin 16
#define GLCD_ENABLE PORTA.6 ;LCD pin 17
; Vee = pot low side ;LCD pin 18
; backlight anode ;LCD pin 19
; backlight cathode ;LCD pin 20

#define GLCD_TYPE GLCD_TYPE_KS0108


#define GLCD_WIDTH 128
#define GLCD_HEIGHT 64

;----- Program

Do forever

GLCDDrawString 30,0,"ChipMhz@"
GLCDDrawString 78,0, str(ChipMhz)
Circle(10,10,10,0) ;upper left
Circle(117,10,10,0) ;upper right
Circle(63,31,10,0) ;center
Circle(63,31,20,0) ;center
Circle(10,53,10,0) ;lower left
Circle(117,53,10,0) ;lower right
GLCDDrawString 30,54,"PIC16F886"

loop

I2C Master Hardware


Explanation:

This program demonstrates how to read and write data from an EEPROM device using the serial
protocal called I2C.

This program uses the hardware I2C module within the microcontroller. If your microcontroller does
not have a hardware I2C module then please use the software I2C Great Cow BASIC ibrary.

This program has three sections.

1. Read a single byte from the EEPROM

2. Write and read a page of 64 bytes to and from the EEPROM, and

3. Finally display the contents of the EEPROM.

This program has an interrupt driven serial handler to capture and manage input from a serial

518
terminal.

Demonstration program:

'Change the microcontroller, frequency and config to suit your needs.


#chip 16F1937, 32
#config Osc = intOSC, MCLRE_ON, PLLEN_ON, VCAPEN_OFF

'Required Library to read and write to an EEPROM


#include <I2CEEPROM.h>

' Define I2C settings - CHANGE PORTS


#define HI2C_BAUD_RATE 400
#define HI2C_DATA PORTC.4
#define HI2C_CLOCK PORTC.3
'I2C pins need to be input for SSP module for Microchip PIC devices.
Dir HI2C_DATA in
Dir HI2C_CLOCK in
'I2C MASTER MODE
HI2CMode Master

' THIS CONFIG OF THE SERIAL PORT WORKS WITH max232 THEN TO PC
' USART settings
#define USART_BAUD_RATE 9600
Dir PORTc.6 Out
Dir PORTc.7 In
#define USART_DELAY 5 ms
#define USART_TX_BLOCKING
wait 500 ms

'Create a Serial Interrupt Handler


On Interrupt UsartRX1Ready Call readUSART

' Constants etc required for the serial Buffer Ring


#define BUFFER_SIZE 32
#define bkbhit (next_in <> next_out)
' Required Variables for the serial Buffer Ring
Dim buffer(BUFFER_SIZE)
Dim next_in as byte: next_in = 1
Dim next_out as byte: next_out = 1

Dim syncbyte as Byte


wait 125 ms

' Read ONE byte from the EEPROM


dim DeviceID as byte

519
dim EepromAddress, syscounter as word
#define EEpromDevice 0xA0

'Master Main Loop


location = 0
'Define our array
dim outarray(64), inarray(64)

do
HSerPrintCRLF 2
HSerPrint "Commence Array Write and Read"
'Populate the array
for tt = 1 to 64
outarray(tt) = tt
next

'Library write call is: eeprom_wr_array(device_number, page_size, address,


array_name, number_of_bytes)
eeprom_wr_array(EEpromDevice, 64, location, outarray, 64)

'Library read call is: eeprom_rd_array(device_number, address, array_name,


number_of_bytes)
eeprom_rd_array(EEpromDevice, location, inarray, 64)

'Show results of the read of the I2C EEPROM


HSerPrintCRLF 2
for tt = 1 to 64

if outarray(tt) <> inarray(tt) then


Hserprint "!"
HSerPrint inarray(tt)
else
HSerPrint inarray(tt)
end if
HSerPrint ","
next

HSerPrintCRLF 2
HSerPrint "Commence Write and Read a single byte":HSerPrintCRLF
HSerPrint "Read value should be "
HSerPrint str(location):HSerPrintCRLF
HSerPrint "Read = "
'Use library to write and read from the I2C EEPROM
eeprom_wr_byte (EEpromDevice, location, location)
eeprom_rd_byte (EEpromDevice, location, bbyte )

HSerPrint bbyte

520
location++
HSerPrintCRLF 2

'Show the connnected I2C devices on the Serial terminal.


HI2CDeviceSearch
HSerPrint "Commence Dump of the EEPROM"
validateEEPROM
Loop
End

'Show the attached I2C devices


sub HI2CDeviceSearch
'Assumes serial is operational
HSerPrintCRLF
HSerPrint "I2C Device Search"
HSerPrintCRLF 2
for deviceID = 0 to 255
HI2CStart
HI2CSend ( deviceID )
if HI2CAckPollState = false then
HSerPrint "ID: 0x"
HSerPrint hex(deviceID)
HSerSend 9
testid = deviceID | 1
select case testid
case 49
Hserprint "DS2482_1Channel_1Wire Master"
case 65
Hserprint "Serial_Expander_Device"
Case 73
Hserprint "Serial_Expander_Device"
case 161
Hserprint "EEProm_Device_Device"
case 163
Hserprint "EEProm_Device_Device"
case 165
Hserprint "EEProm_Device_Device"
case 167
Hserprint "EEProm_Device_Device"
case 169
Hserprint "EEProm_Device_Device"
case 171
Hserprint "EEProm_Device_Device"
case 173
Hserprint "EEProm_Device_Device"
case 175
Hserprint "EEProm_Device_Device"

521
case 209
Hserprint "DS1307_RTC_Device"
case 249
Hserprint "FRAM_Device"
case else
Hserprint "Unknown_Device"
end select
HI2CSend ( 0 )
HI2CSend ( 0 )
HSerPrintCRLF
end if
HI2CStop
next
HSerPrint "End of Device Search"
HSerPrintCRLF 2
end sub

'Validation EEPROOM code


sub validateEEPROM
EepromAddress = 0
HSerPrintCRLF 2
HSerPrint "Hx"
HSerPrint hex(EepromAddress_h)
HSerPrint hex(EepromAddress)
HSerPrint " "

for EepromAddress = 0 to 0xffff


'Read from EEPROM using a library function
eeprom_rd_byte EEPromDevice, EepromAddress, objType

HSerPrint hex(objType)+" "


if ((EepromAddress+1) % 8 ) = 0 then
HSerPrintCRLF
HSerPrint "Hx"
syscounter = EepromAddress + 1
HSerPrint hex(syscounter_h)
HSerPrint hex(syscounter)
HSerPrint " "
end if
'Has serial data been received
if bkbhit then
syschar = bgetc
select case syschar
case 32
do while bgetc = 32
loop
case else
HSerPrintCRLF

522
HSerPrint "Done"
exit sub
end select
end if
next
HSerPrintCRLF
HSerPrint "Done"
end Sub

' Start of Serial Support functions


' Required to read the serial port
' Assumes serial port has been initialised
Sub readUSART
buffer(next_in) = HSerReceive
temppnt = next_in
next_in = ( next_in + 1 ) % BUFFER_SIZE
if ( next_in = next_out ) then ' buffer is full!!
next_in = temppnt
end if
End Sub

' Serial Support functions


' Get characters from the serial port
function bgetc
wait while !(bkbhit)
bgetc = buffer(next_out)
next_out=(next_out+1) % BUFFER_SIZE
end Function

I2C Slave Hardware


Explanation:

This program demonstrates how to control and display using a LCD the code for the keypad.

This program can be adaptedThis program uses the hardware I2C module within the microcontroller.
If your microcontroller does not have a hardware I2C module then please use the software I2C Great
Cow BASIC ibrary. for most microcontrollers.

This program also has an interrupt driven I2C handler to manage the I2C from the Start event.

Demonstration program:

'Code for the keypad and LCD Microchip PIC microcontroller on the Microlab board v2
'microcontroller is responsible for:

523
' - Reading keypad
' - Displaying data on LCD
' - communication with main Microchip PIC microcontroller via I2C
' - providing 5 keypad lines to main Microchip PIC microcontroller (for
compatibility)
' - receiving remote control signals for button and keypad

'This code has support for two keypad layouts. This is one possible layout:
'0123
'4567
'89AB
'CDEF
'And this is the other possible layout:
'123A
'456E
'789D
'A0BC
'Select the keypad layout by uncommenting one of these lines:
'#define KEYPAD_KEYMAP KeypadMap0123
#define KEYPAD_KEYMAP KeypadMap123F

'Chip and config


#chip 16F882, 8
#config osc = INTOSCIO

'Ports connected to keypad


'Column ports need pullups, hence columns are on PORTB for built in weak pullups
#define KEYPAD_COL_1 PORTB.4
#define KEYPAD_COL_2 PORTB.5
#define KEYPAD_COL_3 PORTB.6
#define KEYPAD_COL_4 PORTB.7
#define KEYPAD_ROW_1 PORTA.4
#define KEYPAD_ROW_2 PORTA.3
#define KEYPAD_ROW_3 PORTA.2
#define KEYPAD_ROW_4 PORTA.1

'Ports connected to LCD


#define LCD_IO 4
#define LCD_RW PORTA.7
#define LCD_RS PORTA.6
#define LCD_Enable PORTA.5
#define LCD_DB4 PORTA.4
#define LCD_DB5 PORTA.3
#define LCD_DB6 PORTA.2
#define LCD_DB7 PORTA.1
#define BACKLIGHT PORTA.0

'Button port (for remote control)

524
#define BUTTON PORTB.0

'Keypad ports connected to main Microchip PIC microcontroller


'These are disabled when KeyoutDisabled = true
#define KEYOUT_A PORTC.5
#define KEYOUT_B PORTC.2
#define KEYOUT_C PORTC.1
#define KEYOUT_D PORTC.0
#define KEYOUT_DA PORTB.1

'I2C ports
#define I2C_DATA PORTC.4
#define I2C_CLOCK PORTC.3

'RS232/USART settings
'To do if/when remote support needed

'Initialise
Dir KEYOUT_A Out
Dir KEYOUT_B Out
Dir KEYOUT_C Out
Dir KEYOUT_D Out
Dir KEYOUT_DA Out

Dir BACKLIGHT Out


Dir BUTTON In 'Is an output, turn off by switching pin to Hi-Z

'Initialise I2C Slave


'I2C pins need to be input for SSP module
Dir I2C_DATA In
Dir I2C_CLOCK In
HI2CMode Slave
HI2CSetAddress 128

'Buffer for incoming I2C messages


'Each message takes 4 bytes
Dim I2CBuffer(10)
BufferSize = 0
OldBufferSize = 0

'Set up interrupt to process I2C


On Interrupt SSP1Ready Call I2CHandler

'Enable weak pullups on B4-7 (keypad col pins)


NOT_RBPU = 0
WPUB = b'11110000'

'Key buffers

525
'255 indicates no key, other value gives currently pressed key
RemoteKey = 255
OutKey = 255
KeyoutDisabled = False 'False if KEYOUT lines used to send key

'Main loop
Do

'Read keypad, send value


CheckPressedKeys
SendKeys

'Check for I2C messages


ProcessI2C

Loop

'This keymap table is for this arrangement:


'0123
'4567
'89AB
'CDEF
Table KeypadMap0123
3
7
11
15
2
6
10
14
1
5
9
13
0
4
8
12
End Table

'This keymap table is for this arrangement:


'123F
'456E
'789D
'A0BC
Table KeypadMap123F
15

526
14
13
12
3
6
9
11
2
5
8
0
1
4
7
10
End Table

Sub CheckPressedKeys
'Subroutine to:
' - Read keypad
' - Check remote keypress
' - Decide which key to output

'Read keypad
If RemoteKey <> 255 Then
OutKey = RemoteKey
Else
EnableKeypad
OutKey = KeypadData

End If

End Sub

Sub EnableKeypad
'Disable LCD so that keypad can be activated
Set LCD_RW Off 'Write mode, don't let LCD write

'Re-init keypad
InitKeypad

End Sub

Sub I2CHandler
'Handle I2C interrupt
'SSPIF doesn't trigger for stop condition, only start!

'If buffer full flag set, read

527
Do While HI2CHasData
HI2CReceive DataIn

'Sending code
If BufferSize = 0 Then
LastI2CWasRead = False
'Detect read address
If DataIn = 129 Then
LastI2CWasRead = True

HI2CSend OutKey

KeyoutDisabled = True
Dir KEYOUT_A In
Dir KEYOUT_B In
Dir KEYOUT_C In
Dir KEYOUT_D In
Dir KEYOUT_DA In

Exit Sub
End If
End If

If BufferSize < 10 Then I2CBuffer(BufferSize) = DataIn


BufferSize += 1
Loop

End Sub

Sub SendKeys

'Don't run if not using KEYOUT lines


If KeyoutDisabled Then Exit Sub

'Send pressed keys


If OutKey <> 255 Then
'If there is a key pressed, set output lines
If OutKey.0 Then
KEYOUT_A = 1
Else
KEYOUT_A = 0
End If
If OutKey.1 Then
KEYOUT_B = 1
Else
KEYOUT_B = 0
End If

528
If OutKey.2 Then
KEYOUT_C = 1
Else
KEYOUT_C = 0
End If
If OutKey.3 Then
KEYOUT_D = 1
Else
KEYOUT_D = 0
End If

KEYOUT_DA = 1
Else
'If no key pressed, clear data available line to main Microchip PIC
microcontroller
KEYOUT_DA = 0
End If

End Sub

Sub ProcessI2C

If HI2CStopped Then
IntOff

If LastI2CWasRead Then BufferSize = 0

If BufferSize <> 0 Then


OldBufferSize = BufferSize
BufferSize = 0
End If
IntOn
End If

If OldBufferSize <> 0 Then

CmdControl = I2CBuffer(1)

'Set backlight
If CmdControl.6 = On Then
Set BACKLIGHT On
Else
Set BACKLIGHT Off
End If

'Set R/S bit


LCD_RS = CmdControl.4

529
'Send bytes to LCD
LCDDataBytes = CmdControl And 0x0F
If LCDDataBytes > 0 Then
For CurrSendByte = 1 To LCDDataBytes
LCDWriteByte I2CBuffer(LCDDataBytes + 1)
Next
End If
'LCDWriteByte I2CBuffer(2)

OldBufferSize = 0
End If

End Sub

RGB LED Control


Explanation:

This program demonstrates how to drive an RGB LED to create 4096 different colors. Each of the three
;elements (red, green and blue) responds to 16 different levels. A value of 0 means the element never
turns on, while a value of 15 means the element never shuts off. Values in between these two extremes
vary the pulse width.

This program is an interrupt driven three channel PWM implementation.

The basic carrier frequency depends upon the microcontroller clock speed. For example, with an 8
MHz clock, the LED elements are modulated at about 260 Hz. The interrupts are generated by Timer 0.
With an 8 MHz clock they occur about every 256 uS. The interrupt routine consumes about 20 uS.

Do not forget the current limiting resistors to the LED elements. A value of around 470 ohms is typical,
but you may want to adjust the individual values, to balance the color response.

In this demonstration, three potentiometers are used to set the color levels using the slalom technique.

Demonstration program:

530
;----- Configuration
#chip 16F88, 8 ;PIC16F88 running at 8 MHz
#config mclr=off ;reset handled internally
#config osc=int ;use internal clock
;----- Constants
#define LED_R PortB.0 ;pin to red element
#define LED_G PortB.1 ;pin to green element
#define LED_B PortB.2 ;pin to blue element
;----- Variables
dim redValue, greenValue, blueValue, ticks as byte
;----- Program
dir PortA in ;three pots for inputs
dir PortB out ;the LED outputs
on interrupt Timer0Overflow call update
initTimer0 Osc, PS0_1/2
do
redValue = readAD(AN0)/16 ;red -- 0 to 15
greenValue = readAD(AN1)/16 ;green -- 0 to 15
blueValue = readAD(AN2)/16 ;blue -- 0 to 15
loop

Sub update ;interrupt routine


ticks++ ;increment master timekeeper
if ticks = 15 then ;start of the count
ticks = 0
if redValue <> 0 then ;only turn on if nonzero
set LED_R on
end if
if greenValue <> 0 then
set LED_G on
end if
if blueValue <> 0 then
set LED_B on
end if
end if
if ticks = redValue then ;time to turn off red?
set LED_R off
end if
if ticks = greenValue then ;time to turn off green?
set LED_G off
end if
if ticks = blueValue then ;time to turn off blue?
set LED_B off
end if
end sub

531
Serial/RS232 Buffer Ring
Explanation:

This program demonstrates how to create a serial input buffer ring.

This program program uses an interrupt event to capture the incoming byte value and place in the
buffer ring. When a byte is received the buffer ring is incremented to ensuer the next byte is handled
correctly.

Testing bkbhit will set to True when a byte has been received. Reading the function bgetc will return
the last byte received.

Demonstration program:

;Chip Settings
#chip 16F1937,32
#config LVP=OFF, BODEN=OFF, WDT=OFF, OSC=XT

' [change to your config] This is the config for a serial terminal
' turn on the RS232 and terminal port.
' Define the USART port
#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING
#define USART_BLOCKING
' [change to your config] Ensure these port addresses are correct
#define SerInPort PORTc.7
#define SerOutPort PORTc.6
'Set pin directions
Dir SerOutPort Out
Dir SerInPort In

'This assumes you are using an ANSI compatible terminal. Use PUTTY.EXE it is very
easy to use.

HSerPrint "Started: Serial between two devices"


HSerSend 10
HSerSend 13

' Pot port


DIR PORTA.0 IN

'Interrupt Handlers
On Interrupt UsartRX1Ready Call readUSART

' Constants etc required for Buffer Ring


#define BUFFER_SIZE 8

532
#define bkbhit (next_in <> next_out)
;Variables
Dim buffer( BUFFER_SIZE - 1 ) 'we will use element 0 in the array as part of out
buffer
Dim next_in as byte: next_in = 0
Dim next_out as byte: next_out = 0
Dim syncbyte as Byte

syncbyte = 0x55 ' you can use 255 - your choice

Do
' Send some info to another device
Repeat 3
HSerSend syncbyte
end Repeat
HSerprint readad(an0)

do while bkbhit
' get three sync chars then display the next char in buffer
if bgetc = syncbyte and bgetc = syncbyte and bgetc = syncbyte then
HSerPrint "sync'ed '"
HSerPrint chr(bgetc)
HSerSend 10
HSerSend 13
end if
Loop
Loop

Sub readUSART
buffer(next_in) = HSerReceive
temppnt = next_in
next_in = ( next_in + 1 ) % BUFFER_SIZE
if ( next_in = next_out ) then ' buffer is full!!
next_in = temppnt
end if
End Sub

function bgetc
wait while !(bkbhit)
bgetc = buffer(next_out)
next_out=(next_out+1) % BUFFER_SIZE
end Function

Trigonometry Circle
Explanation:

533
Great Cow BASIC can draw circles on a Graphical LCD devcie using Great Cow BASIC library functions.

Demonstration program:

;Circle and filled circle commands on a graphic LCD.


;This uses the 2-place trigonometric routines found in the include file.

;Thomas Henry -- 4/17/2014

;----- Configuration

#chip 16F88, 8 ;PIC16F88 running at 8 MHz


#config mclr=off ;reset handled internally
#config osc=int ;use internal clock

#include <GLCD.h>
#include <Trig2Places.h>

;----- Constants

;Pinout is shown for the LCM12864H-FSB-FBW


;graphical LCD available from Amazon.

; +5V ;LCD pin 1


; ground ;LCD pin 2
; Vo = wiper of pot ;LCD pin 3
#define GLCD_DB0 PORTB.0 ;LCD pin 4
#define GLCD_DB1 PORTB.1 ;LCD pin 5
#define GLCD_DB2 PORTB.2 ;LCD pin 6
#define GLCD_DB3 PORTB.3 ;LCD pin 7
#define GLCD_DB4 PORTB.4 ;LCD pin 8
#define GLCD_DB5 PORTB.5 ;LCD pin 9
#define GLCD_DB6 PORTB.6 ;LCD pin 10
#define GLCD_DB7 PORTB.7 ;LCD pin 11
#define GLCD_CS2 PORTA.0 ;LCD pin 12
#define GLCD_CS1 PORTA.1 ;LCD pin 13

534
#define GLCD_RESET PORTA.2 ;LCD pin 14
#define GLCD_RW PORTA.3 ;LCD pin 15
#define GLCD_RS PORTA.4 ;LCD pin 16
#define GLCD_ENABLE PORTA.6 ;LCD pin 17
; Vee = pot low side ;LCD pin 18
; backlight anode ;LCD pin 19
; backlight cathode ;LCD pin 20

#define GLCD_TYPE GLCD_TYPE_KS0108


#define GLCD_WIDTH 128
#define GLCD_HEIGHT 64

;----- Variables

'None required.

;----- Program

GLCDCLS

circle(10,10,10) ;upper left


circle(117,10,10) ;upper right
filledcircle(63,31,10) ;center
circle(63,31,20) ;center
filledcircle(10,53,10) ;lower left
filledcircle(117,53,10) ;lower right

See also Trigonometry, Circle, FilledCircle,

535
Great Cow Graphical BASIC
This is the Great Cow Graphical BASIC section of the Help file. Please refer the sub-sections for details
using the contents/folder view.

Code Documentation
Documenting Great Cow BASIC is key for ease of use. This section is intended for developers only.

Documenting is the ability to read some extra information from comments in libraries.

Some comments that start with ''' have a special meaning, and will be displayed as tooltips or as
information to the user. These tooltips helps inexperienced users to use extra libraries.

1. Great Cow BASIC uses ; (a semicolon) to show comments that it has placed automatically, and ' to
indicate ones that the user has placed. When loading a program, it will not load any that start with
a ; (semi-colon). The use of comments do not impact the users but it worthy of note.

2. As for code documentation comments, Great Cow BASIC will load information about
subroutines/functions and any hardware settings that need to be set.

3. For subroutines, a line before the Sub or Function line that starts with ''' will be used as a tooltip
when the user hovers over the icon. A line that starts with '''@ will be interpreted differently,
depending on what comes after the @. '''@param ParamName Parameter Description will add a
description for the parameter. For a subroutine, this will show in the Icon Settings panel under the
parameter when the user has selected that icon.

4. For functions, it will show at the appropriate time in the Parameter Editor wizard. '''@return
Returned value applies to functions only. It will be displayed in the Parameter Editor wizard when
the user is asked to choose a function. An example of all this is given in srf04.h:

'''Read the distance to the nearest object


'''@param US_Sensor Sensor to read (1 to 4)
'''@return Distance in cm
Function USDistance(US_Sensor) As Word

5. If a subroutine or command is used internally in the library, but Great Cow BASIC users should not
see it, it can be hidden by placing '''@hide before the Sub or Function line. Another example from
srf04.h:

'''@hide
Sub InitUSSensor

These should hopefully be pretty easy to add. It is also possible to add Hardware Settings. A particular

536
setting can be defined anywhere in the file, using this syntax:

'''@hardware condition, display name, constant, value type

These comments informs Great Cow BASIC when to show the setting. Normally, this is All, but
sometimes it can include a constant, a space and then a comma separated list of values. display name
is a friendly name for the setting to display. constant is the constant that must be set, and valuetype is
the type that will be accepted for that constant’s value. To allow for multiple value types, enter a list of
types with a | between them.

6. Allowed types are:

free - Allows anything


label - Allows any label
condition - Allows a condition
table - Allows a data table
bit - Allows any bit from variable, or bit variable
io_pin - Allows an IO pin
io_port - Allows an entire IO port
number - Allows any fixed number or variable
rangex:y - Allows any number between x and y
var - Allows any variable
var_byte - Allows any byte variable
var_word - Allows any word variable
var_integer - Allows any integer variable
var_string - Allows any string variable
const - Allows any fixed number
const_byte - Allows any byte sized fixed number
const_word - Allows any word sized fixed number
const_integer - Allows any integer sized fixed number
const_string - Allows any fixed string
byte - Allows any byte (fixed number or variable)
word - Allows any word
integer - Allows any integer
string - Allows any string
array - Allows any array

7. When the library is added the program, Great Cow BASIC will show a new device with the name of
the library file on the Hardware Settings window. The user can then set the relevant constants
without necessarily needing to see any code. Adding a Great Cow BASIC library to Great Cow BASIC
will not result in any changes to the library. Great Cow BASIC uses the information it reads to help
edit the user’s program, but then the user’s program is passed to the compiler along with the
unchanged library.

8. Hardware Settings are a bit more involved to add, but hopefully the bit of extra documentation for

537
subroutines will be straight forward.

Windows .NET Support


From Great Cow Graphical BASIC version 0.941 supports use on newer Windows versions without
having the pre-requisite of .NET 3.5.

538
Great Cow BASIC for Linux
This is the Great Cow BASIC for Linux section of the Help file. Please refer the sub-sections for details
using the contents/folder view.

Overview
Introduction: Great Cow BASIC can be used when using the Linux Operating System.

This instructions are not distribution specific, but are for Linux only (not Windows).

Instructions: Complete the following steps to compile and install Great Cow BASIC for Linux:

1. Install FreeBasic from your distributions repository or


http://www.freebasic.net/wiki/CompilerInstalling

2. Download the "Great Cow BASIC - Linux Distribution" from SourceForge at


https://sourceforge.net/projects/gcbasic/files/

3. Unrar/unpack GCB@Syn.rar to a location of your choice within your home directory (eg. within
Downloads) with either a file manager or from a console.

4. From a console, change to the Great Cow BASIC Sources in the unpacked directory:

eg. cd ~/Downloads/GCB@Syn/GreatCowBasic/Sources/GCBASIC

5. Make sure that install.sh is set as executable (ie. chmod +x install.sh), and then execute:
./install.sh build

6. You will need root privileges for this step. You can switch user (su) to root, or optionally use sudo.

Execute: [sudo] ./install.sh install

7. If you su’d to root, use exit to drop back to your normal user. Then, be sure to follow the
instructions given by the script for updating your path.

8. Confirm proper execution, and the version, of Great Cow BASIC by executing: gcbasic /version

Now you can create and compile GCB source files.

Programming microcontrollers:

To program your microcontroller with your Great Cow BASIC-created hex file, you will need additional
software.

For Microchip PIC microcontroller programming, you might find what you need at:

539
http://www.microchip.com/DevelopmentTools/ProductDetails.aspx?PartNO=pg164120

For Atmel AVR microcontroller programming, you will need avrdude. It should be available in your
distributions repository. If not, check here: http://www.nongnu.org/avrdude/

Great Cow BASIC Maintenance


This is the Great Cow BASIC maintenance section of the Help file. Please refer the sub-sections for
details using the contents/folder view.

Great Cow BASIC Maintenance


Introduction: Great Cow BASIC maintenance covers the key processess that the developers use to
maintain and build the solution.

This insights are not distribution specific

Solution Architecture: Complete the components are key for a complete solution:

1. Great Cow BASIC installer

2. Great Cow BASIC chip specific .DAT files

3. Great Cow BASIC Help

4. Great Cow BASIC IDE

Great Cow BASIC installer:

To be completed.

Great Cow BASIC chip specific .DAT files:

The process to create the .DAT file for chips is as follows:

The MPASM *.INC or the AVR *<XML files are used to source the full scope of regisers and bits),

If present a .DEV file is used to source the default settings. A .DEV is also used for pinout data and and
config settings if possible, but not all chips have a .dev file so the process will works using #3 or #4. We
also try to get pinout data from the xml files if the dev file was not found. If present the .INFO is used to
source the default settings.

If a .DEV file or .INFO file is not present a routine called GuessDefaultConfig witin getchipdata.exe is
used. This option sets the bit(s). For 18f chips: 18FDefaultASMConfig.TXT. This simply overwrites all
options stated in 18FDefaultASMConfig.TXT and clearly states this in the output .dat file.

540
In all cases the default mask is sometimes specified for a particular config option and that is used for
ASMConfig

An example the processing of a .DEV. This is the 18F25K20 example. For this, Disabled is default:

field (key=FCMEN mask=0x40 desc="Fail-Safe Clock Monitor Enable" init=0)


setting (req=0x40 value=0x0 desc="Disabled")
setting (req=0x40 value=0x40 desc="Enabled")

For this, RC1 is default (no init=, so the setting with a value matching the mask is used)

This is what the bit of 8bit_device.info looks like for WRTD on the 18F45K22:

To get the default WRTD value, it gets the default value of that word (0xe0) from the
CONFIGREG_INFO_TYPE line, then ands it with the mask for the WRTD option (0x80) to get the device
value of that option (0x80). Which matches the value for WRTD=OFF

An example the processing of a 8bit_device.info

Where the default is selected from the Info_Type.

An example of the processing of 18FDefaultASMConfig.TXT

DEBUG= OFF
XINST = OFF

541
Great Cow BASIC Help:

To be completed.

Great Cow BASIC IDE:

To be completed.

542

You might also like