UBW Tester Liberty Basic Program
Back to main UBW page

Screenshot of UBW Tester Basic Program
General
I wrote this little program in Liberty Basic to illustrate how easy it is to do a simple GUI in LB that talks to a UBW. This program is for Firmware C only, and all it does is allow you to turn each bit of Port B on and off with the buttons on the screen. However, it does illustrate a simple way to have LB query Windows to find all available COM ports, then list them in a pull down box. When you select one of the available ports, it opens it and starts writing the current data byte to the port. If you connect up LEDs to each of your Port B pins, then your UBW board can look the same as the green LEDs on the UBW Tester window!

How It Works
When the app runs, it creates the window, asks Windows about the available COM ports and puts them in the pull down box, then waits for you to do something. Each time you click on a ON or OFF button, it updates the 'current byte' of data. When you select one of the com ports (use the one that your UBW is on) it opens the port and every 50ms sends the byte to the port. As you change the byte with the ON and OFF buttons, it sends the new value. It also prints out the byte in hex and decimal in the output box.

Update (7/17/06)
A new version of Firmware C is now out (v1.0) which sends back a byte (the current input bits of Port A) every time you send a byte to the UBW. So you can now use Firmware C for both input and output. Also a small bug was fixed in the tester application presented here that would prevent com ports over 10 from appearing in the drop down box. The tester application has been updated to show the value of the byte going out to the UBW and the byte coming back (showing the current state of Port A bits).

Files
A Zip file of all necessary files (basic source, LED bitmaps, and FreeForm GUI editor file)

Questions? E-mail me at my e-mail address
Back to main UBW page

The Code

'''''''''''''''''''''''''''''''''''''''''''''''''''''
' UBW Tester.bas
'
' Written by Brian Schmalz
' as part of the UBW Project
' http://www.schmalzhaus.com/UBW
' Free for all to use and improve
' 2/20/06
'
' DESCRIPTION:
' This Liberty Basic program will allow you to do a simple
' test with your UBW board (any version) if you have
' Firmware C on it. Firmware C just takes each byte
' of data it receives over the USB and outputs it to
' port B of the PIC.
'
' This application gives you eight on and eight off
' buttons to turn each Port B pin on or off, and allows
' you to select a com port.
'
' NOTE: You must have your UBW pluged in BEFORE you
' run this application. This application, when it is
' first run, will go out and get a list of all available
' COM ports on your PC, and will list them in the drop
' down menu. When you pick one, it opens the port and
' begins to write a byte of data down every 50ms.
' It also prints the byte in hexidecimal and decimal
'

    Global  kMaxCOMPorts            ' How many com ports do we look at?
    kMaxCOMPorts = 40

' Dim all of the arrays
    DIM CombComPort$(kMaxCOMPorts)  ' Holds strings for COM port numbers (COM1, COM2, etc.)
' Call out global variables
    GLOBAL bSerialPortOpen          ' 1 if serial port has been successfully opened
    bSerialPortOpen = 0             ' Default it to unopened
    GLOBAL PortB                    ' This is the value we send to the UBW every tick
    PortB = 0                       ' Holds the current byte to output to Port B.

' We don't want the cosole window
    nomainwin

'Form created with the help of Freeform 3 v03-27-03
'Generated on Feb 23, 2006 at 14:15:39


[setup.main.Window]

    '-----Begin code for #main

    WindowWidth = 205
    WindowHeight = 430
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)


    '-----Begin GUI objects code

    button #main.button1,"B0 ON",[B0ONClick], UL,   5,  17,  70,  25
    button #main.button2,"B1 ON",[B1ONClick], UL,   5,  47,  70,  25
    button #main.button3,"B2 ON",[B2ONClick], UL,   5,  77,  70,  25
    button #main.button4,"B3 ON",[B3ONClick], UL,   5, 107,  70,  25
    button #main.button5,"B4 ON",[B4ONClick], UL,   5, 137,  70,  25
    button #main.button6,"B5 ON",[B5ONClick], UL,   5, 167,  70,  25
    button #main.button7,"B6 ON",[B6ONClick], UL,   5, 197,  70,  25
    button #main.button8,"B7 ON",[B7ONClick], UL,   5, 227,  70,  25
    button #main.button9,"B0 OFF",[B0OFFClick], UL,  80,  17,  70,  25
    button #main.button10,"B1 OFF",[B1OFFClick], UL,  80,  47,  70,  25
    button #main.button11,"B2 OFF",[B2OFFClick], UL,  80,  77,  70,  25
    button #main.button12,"B3 OFF",[B3OFFClick], UL,  80, 107,  70,  25
    button #main.button13,"B4 OFF",[B4OFFClick], UL,  80, 137,  70,  25
    button #main.button14,"B5 OFF",[B5OFFClick], UL,  80, 167,  70,  25
    button #main.button15,"B6 OFF",[B6OFFClick], UL,  80, 197,  70,  25
    button #main.button16,"B7 OFF",[B7OFFClick], UL,  80, 227,  70,  25
    bmpbutton #main.bmpbutton18, ".\LightOff.bmp", [bmpbutton18Click], UL, 165, 22
    bmpbutton #main.bmpbutton19, ".\LightOff.bmp", [bmpbutton19Click], UL, 165, 52
    bmpbutton #main.bmpbutton20, ".\LightOff.bmp", [bmpbutton20Click], UL, 165, 82
    bmpbutton #main.bmpbutton21, ".\LightOff.bmp", [bmpbutton21Click], UL, 165, 112
    bmpbutton #main.bmpbutton22, ".\LightOff.bmp", [bmpbutton22Click], UL, 165, 142
    bmpbutton #main.bmpbutton23, ".\LightOff.bmp", [bmpbutton23Click], UL, 165, 172
    bmpbutton #main.bmpbutton24, ".\LightOff.bmp", [bmpbutton24Click], UL, 165, 202
    bmpbutton #main.bmpbutton25, ".\LightOff.bmp", [bmpbutton25Click], UL, 165, 232
    TextboxColor$ = "white"
    textbox #main.TextboxOutputByte,   5, 282, 175,  25
    statictext #main.statictext27, "Output Byte (Hex : Decimal)",   5, 257, 162,  20
    textbox #main.TextboxInputByte,   5, 337, 175,  25
    statictext #main.statictext27, "Input Byte (Hex : Decimal)",   5, 312, 162,  20
    statictext #main.statictext28, "COM Port",   5, 372,  57,  20
    ComboboxColor$ = "white"
    combobox #main.CombComPort, CombComPort$(), [CombComPortDoubleClick],   75, 372, 100, 100

    '-----End GUI objects code

    open "UBW FW C Tester v1.0" for window as #main
    print #main, "font ms_sans_serif 10"

    '----------------END FREEFORM CODE--------------
    '________________DO NOT INCLUDE IN PASTE________
    loadbmp "ON", "LightOn.bmp"
    loadbmp "OFF", "LightOff.bmp"
    print #main, "trapclose [quit.main]"
    ' Go do TimerTick every 50ms
    timer 50, [TimerTick]
    ' Populate the drop down list of available COM ports
    gosub [GetCOMPorts]

[main.inputLoop]   'wait here for input event
    wait

[B0ONClick]   'Perform action for the button named 'button1'
    print #main.bmpbutton18, "bitmap ON"
    PortB = PortB OR 1
    wait

[B1ONClick]   'Perform action for the button named 'button2'
    print #main.bmpbutton19, "bitmap ON"
    PortB = PortB OR 2
    wait

[B2ONClick]   'Perform action for the button named 'button3'
    print #main.bmpbutton20, "bitmap ON"
    PortB = PortB OR 4
    wait

[B3ONClick]   'Perform action for the button named 'button4'
    print #main.bmpbutton21, "bitmap ON"
    PortB = PortB OR 8
    wait

[B4ONClick]   'Perform action for the button named 'button5'
    print #main.bmpbutton22, "bitmap ON"
    PortB = PortB OR 16
    wait

[B5ONClick]   'Perform action for the button named 'button6'
    print #main.bmpbutton23, "bitmap ON"
    PortB = PortB OR 32
    wait

[B6ONClick]   'Perform action for the button named 'button7'
    print #main.bmpbutton24, "bitmap ON"
    PortB = PortB OR 64
    wait

[B7ONClick]   'Perform action for the button named 'button8'
    print #main.bmpbutton25, "bitmap ON"
    PortB = PortB OR 128
    wait

[B0OFFClick]   'Perform action for the button named 'button9'
    print #main.bmpbutton18, "bitmap OFF"
    PortB = PortB AND 254   '11111110
    wait

[B1OFFClick]   'Perform action for the button named 'button10'
    print #main.bmpbutton19, "bitmap OFF"
    PortB = PortB AND 253   '11111101
    wait

[B2OFFClick]   'Perform action for the button named 'button10'
    print #main.bmpbutton20, "bitmap OFF"
    PortB = PortB AND 251   '11111011
    wait

[B3OFFClick]   'Perform action for the button named 'button10'
    print #main.bmpbutton21, "bitmap OFF"
    PortB = PortB AND 247   '11110111
    wait

[B4OFFClick]   'Perform action for the button named 'button13'
    print #main.bmpbutton22, "bitmap OFF"
    PortB = PortB AND 239   '11101111
    wait

[B5OFFClick]   'Perform action for the button named 'button14'
    print #main.bmpbutton23, "bitmap OFF"
    PortB = PortB AND 223   '11011111
    wait

[B6OFFClick]   'Perform action for the button named 'button15'
    print #main.bmpbutton24, "bitmap OFF"
    PortB = PortB AND 191   '10111111
    wait

[B7OFFClick]   'Perform action for the button named 'button16'
    print #main.bmpbutton25, "bitmap OFF"
    PortB = PortB AND 127   '01111111
    wait

[bmpbutton18Click]   'Perform action for the bmpbutton named 'bmpbutton18'
[bmpbutton19Click]   'Perform action for the bmpbutton named 'bmpbutton19'
[bmpbutton20Click]   'Perform action for the bmpbutton named 'bmpbutton20'
[bmpbutton21Click]   'Perform action for the bmpbutton named 'bmpbutton21'
[bmpbutton22Click]   'Perform action for the bmpbutton named 'bmpbutton22'
[bmpbutton23Click]   'Perform action for the bmpbutton named 'bmpbutton23'
[bmpbutton24Click]   'Perform action for the bmpbutton named 'bmpbutton24'
    wait

[CombComPortDoubleClick]   'Perform action for the combobox named 'CombComPort'
    gosub [OpenSerialPort]
    wait

' Come here every tick of the timer.
' Send out our byte, and update the edit field
[TimerTick]
    if gSerialPortOpen = 1 then
        ' This is what does all of the work - output the byte to port B of
        ' the UBW board.
        print #commHandle, chr$(PortB);
        print #main.TextboxOutputByte, "0x";dechex$(PortB);" : ";PortB

        In$ = input$(#commHandle, lof(#commHandle))
        print #main.TextboxInputByte, "0x";dechex$(asc(left$(In$, 1)));" : ";asc(left$(In$, 1))
    end if
    wait

[quit.main] 'End the program
    gosub [CloseSerialPort]
    close #main
    end

''''''''''''''''''''''
' UTILITY ROUTINES   '
''''''''''''''''''''''

'
' GetCOMPorts
'
' This subroutine will populate the drop-down list called #main.CombComPort
' with all of the currently available COM ports. You can change #main.CombComPort
' to whatever you use in your program.
'
[GetCOMPorts]
    ' First clear out #main.CombComPort
    for Port = 0 to kMaxCOMPorts
        CombComPort$(Port) = ""
    next Port

    CurrentComboIndex = 0
    ' We're going to loop from 1 to 254 and see if each port is available
    for TestPort = 1 to kMaxCOMPorts
        if IsCOMPortAvailable(TestPort) = 1 then
            ' Add this port into #main.CombComPort
            CombComPort$(CurrentComboIndex) = "COM" + str$(TestPort)
            print "Adding COM" + str$(TestPort)
            CurrentComboIndex = CurrentComboIndex + 1
        end if
    next TestPort

    ' Now reload the combbox to get the new array values
    print #main.CombComPort, "reload"

    return

' Helper function for [GetCOMPorts]
' Returns 0 if the Port is not available on this system (either already opened or doesn't
' exist) and 1 if the port is available.
function IsCOMPortAvailable(Port)
    struct lpSecurityAttributes, _
        nLength as long, _
        lpSecurityDescriptor as long, _
        bInheritHandle as long

    lpFileName$ = "\\.\COM" + str$(Port)

    dwDesiredAccess = 0
    dwShareMode = 1 + 2
    dwCreationDisposition = 3
    dwFlagsAndAttributes = 128
    hTemplateFile = 0

    calldll #kernel32, "CreateFileA", _
        lpFileName$ as ptr, _
        dwDesiredAccess as long, _
        dwShareMode as long, _
        lpSecurityAttributes as struct, _
        dwCreationDisposition as long, _
        dwFlagsAndAttributes as long, _
        hTemplateFile as long, _
        retcode as long
    hObject = retcode

    ' Test the return code to see if the port is available and free
    if retcode = -1 then
        IsCOMPortAvailable = 0
    else
        ' If we were able to open it, then close it and return TRUE
        calldll #kernel32, "CloseHandle", _
            hObject as long, _
            retcode as long

        IsCOMPortAvailable = 1
    end if

end function


' Handle opening the serial port
[OpenSerialPort]

    oncomerror [ComErrorHandler]

    if gSerialPortOpen = 1 then
        gosub [CloseSerialPort]
    end if

    print #main.CombComPort, "contents? ComPort$"

    open ComPort$;":9600,8,N,1,RS,DS0,CS0" for random as #commHandle
    gSerialPortOpen = 1

    return

' Handle closing the serial port
[CloseSerialPort]

    if gSerialPortOpen = 1 then
        close #commHandle
    end if

    gSerialPortOpen = 0

    return

' We get here if there is a com error at some point.
[ComErrorHandler]
    ' Display the com error box
    notice "Com Error"; chr$(13); "Some type of com port error has occured. Your computer may not have a valid com port at COM"; str$(ComPortNumber); " or there might be another error. "; chr$(13); "Error: "; ComError$; " Port: "; str$(ComPortNumber); " ErrorNo: "; str$(ComErrorNumber)

    gosub [CloseSerialPort]

    wait