''''''''''''''''''''''''''''''''''''''''''''''''''''' ' UBW_RC_Tester.bas ' ' Written by Brian Schmalz ' as part of the UBW Project ' http://www.greta.dhs.org/UBW ' Free for all to use and improve ' 01/26/2007 ' ' DESCRIPTION: ' This application will only work with UBW FW D 1.4.0 and above. ' When the user opens a COM port, it will set all of PortB to ' outputs and start sending out RC servo commands to those pins. ' ' ' Take care of some constants so that our code is more readable Global TRUE TRUE = 1 Global FALSE FALSE = 0 Global MAXCOMPORTS ' How many com ports can we hold in our drop down list? MAXCOMPORTS = 10 Global HIGHESTCOMPORT ' Highest numerical com port to check for HIGHESTCOMPORT = 20 Global TICKRATE ' In ms how often do we do call the tick timer routine TICKRATE = 50 Global GETCOMPORTRATE ' How many ticks between checking for new COM ports GETCOMPORTRATE = 10000 Global MAXRCVALUE ' Corresponds to 2.0ms of pulse time MAXRCVALUE = 11900 ' Call out global variables DIM RCValues(8) ' Holds current values for all 8 bits of PortB RC servo outputs Global OpenedCOMPort$ ' Holds the name of the com port we currently have opened, if any OpenedCOMPort$ = "" ' Dim all of the arrays DIM COMPort$(MAXCOMPORTS) ' Holds strings for COM port numbers (COM1, COM2, etc.) DIM NewCOMPort$(MAXCOMPORTS) ' Holds strings for COM port numbers (COM1, COM2, etc.) inside GetCOMPort routine [setup.main.Window] WindowWidth = 400 WindowHeight = 400 UpperLeftX=int((DisplayWidth-WindowWidth)/2) UpperLeftY=int((DisplayHeight-WindowHeight)/2) textbox #main.RCValue1, 20, 80, 100, 20 textbox #main.RCValue2, 20, 110, 100, 20 textbox #main.RCValue3, 20, 130, 100, 20 textbox #main.RCValue4, 20, 160, 100, 20 textbox #main.RCValue5, 20, 190, 100, 20 textbox #main.RCValue6, 20, 220, 100, 20 textbox #main.RCValue7, 20, 250, 100, 20 textbox #main.RCValue8, 20, 280, 100, 20 ComboboxColor$ = "white" combobox #main.COMPort, COMPort$(), [comboboxCOMPortDoubleClick], 10, 40, 100, 100 statictext #main.statictext88, "COM Port", 10, 10, 57, 20 menu #main, "File",_ "Quit", [quit.main] open "UBW RC Tester v1.0 (For UBW FW D v1.4.0)" for window as #main print #main, "font ms_sans_serif 10" print #main, "trapclose [quit.main]" ' Populate the drop down list of available COM ports gosub [GetCOMPorts] ' Set up inital RC output values for pin = 1 to 8 RCValues(pin) = int((MAXRCVALUE / 8) * pin) next pin ' Go do TimerTick every 50ms timer TICKRATE, [TimerTick] [main.inputLoop] 'wait here for input event wait ' Each time the user selects a new COM port, close the old one (if any) and open the new one [comboboxCOMPortDoubleClick] gosub [CloseSerialPort] gosub [OpenSerialPort] wait ' Application wide tick routine - called every TICKRATE ms. [TimerTick] ' Always shut off the timer in case things take longer than we anticipate timer 0 ' Check to see if it's time to check for new com ports if GetCOMPortCount = 0 then gosub [GetCOMPorts] ' If we go do it, then reload the counter GetCOMPortCount = GETCOMPORTRATE else ' Otherwise just decriment it every tick GetCOMPortCount = GetCOMPortCount - 1 end if ' Go check to see if there's any new data for us on our COM port gosub [CheckForNewData] gosub [SetNewRCValues] gosub [SendNewRCValues] ' Now re-arm our timer timer TICKRATE, [TimerTick] wait ' Set the new values for each of the 8 RC Servos [SetNewRCValues] for pin = 1 to 8 RCValues(pin) = RCValues(pin) + 200 if (RCValues(pin) > MAXRCVALUE) then RCValues(pin) = 1 end if next pin print #main.RCValue1, str$(RCValues(1)) print #main.RCValue2, str$(RCValues(2)) print #main.RCValue3, str$(RCValues(3)) print #main.RCValue4, str$(RCValues(4)) print #main.RCValue5, str$(RCValues(5)) print #main.RCValue6, str$(RCValues(6)) print #main.RCValue7, str$(RCValues(7)) print #main.RCValue8, str$(RCValues(8)) return ' Here we look at if there's any data that's come from the COM port ' since the last time we checked. We look for the result of ' I commands, and errors. [CheckForNewData] if OpenedCOMPort$ <> "" then NumBytes = lof(#commHandle) DataIn$ = input$(#commHandle, NumBytes) if DataIn$ <> "" then 'Now see if we got the response to an "I" command print DataIn$ end if end if return [quit.main] 'End the program gosub [CloseSerialPort] close #main end ''''''''''''''''''''''''''''''''''''' ' UBW SEND/RECEIVE UTILITY ROUTINES ' ''''''''''''''''''''''''''''''''''''' ' Create a set of commands to send the new values to the UBW [SendNewRCValues] if OpenedCOMPort$ <> "" then OutStr$ = "" for pin = 1 to 8 OutStr$ = OutStr$ + "RC,B," + str$(pin-1) + "," + str$(RCValues(pin)) + chr$(13) next pin print #commHandle, OutStr$; end if return ' This subroutine sets the direction of the bits on the UBW board ' Normally you'll call this once at the beginning of your application ' to set the direction of the bits, and then just use the O and I ' commands to read and write the bits. sub SendCCommand DirAOut, DirBOut, DirCOut, AnalogOut if OpenedCOMPort$ <> "" then OutStr$ = "C," + str$(DirAOut) + "," + str$(DirBOut) + "," + str$(DirCOut) + "," + str$(AnalogOut) + chr$(13) print #commHandle, OutStr$; end if end sub ''''''''''''''''''''''''''''''' ' BIT/BYTE UTILITY ROUTINES ' ''''''''''''''''''''''''''''''' ' Flip the bit 'Bit' in byte 'Byte' and return the new byte. function BitFlip(Byte, Bit) if TstBit(Byte, Bit) = 1 then BitFlip = (Byte AND (255 XOR (2^Bit))) else BitFlip = (Byte OR (2^Bit)) end if end function ' Test bit "Bit" in variable "Byte" and return it's value (1 or 0) function TstBit(Byte, Bit) TestBit = 0 if ((Byte AND (2^Bit)) > 0) then TstBit = 1 end if end function ''''''''''''''''''''''''''''''' ' COM PORT 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.COMPort ' to whatever you use in your program. ' [GetCOMPorts] ' First clear out our 'new' COM Ports array for Port = 0 to MAXCOMPORTS NewCOMPort$(Port) = "" next Port ' We start with index 1, since that's where the combo box starts CurrentComboIndex = 1 ' We're going to loop from 1 to 254 and see if any of those COM ports are available for TestPort = 1 to HIGHESTCOMPORT ' If we hit upon our currently opened COM port, we add that to our list too to keep things simple if IsCOMPortAvailable(TestPort) = 1 OR "COM" + str$(TestPort) = OpenedCOMPort$ then ' Add this port into 'new' COM port array NewCOMPort$(CurrentComboIndex) = "COM" + str$(TestPort) CurrentComboIndex = CurrentComboIndex + 1 end if next TestPort ' Now compare to see if there are any differences between the two lists ' of COM ports (old vs new) bAreTheSame = TRUE for Port = 1 to MAXCOMPORTS ' Now, if the COM port strings at this index are not the same, then something's changed ' and we need to remember that fact and exit the loop if NewCOMPort$(Port) <> COMPort$(Port) then bAreTheSame = FALSE exit for end if next Port ' If they are not the same, then copy over new to old and update combobox if (bAreTheSame = FALSE) then for Port = 1 to MAXCOMPORTS COMPort$(Port) = NewCOMPort$(Port) next Port ' Now reload the combbox to get the new array values print #main.COMPort, "reload" end if ' If the currently selected COM port is empty, and we have some COM port in our list, then ' set our currently selected COM port to the first one. print #main.COMPort, "contents? CurComPort$" if CurComPort$ = "" and CurrentComboIndex > 1 then print #main.COMPort, "selectindex 1" gosub [CloseSerialPort] gosub [OpenSerialPort] end if 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 ' The other reason we could have an available com end function ' Handle opening the serial port [OpenSerialPort] oncomerror [ComErrorHandler] print #main.COMPort, "contents? ComPort$" if ComPort$ <> "" and OpenedCOMPort$ <> ComPort$ then print #main.COMPort, "contents? ComPort$" OpenedCOMPort$ = ComPort$ open ComPort$;":9600,8,N,1,RS,DS0,CS0" for random as #commHandle ' Send the inital data direction command call SendCCommand 255,0,255,0 end if return ' Handle closing the serial port [CloseSerialPort] if OpenedCOMPort$ <> "" then close #commHandle OpenedCOMPort$ = "" end if 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