;TI83+VFD.gcb ;This program takes a result from the TI83+ and sends it to an external LCD, ;and set of 11 VFD tubes for display. ;It is a combination of an interface between a TI83+ calculator developed by ;Thomas Henry ("A Mathematics Engine For Microcontrollers" Nuts & Volts Aug 2013), ;and my coding for the VFD display. ;10:40 29.01.2021 ;Hardware connections, generally: ;TI83+ interfaced with a 16F88, which outputs data to an LCD ;and shift register/VFD driver (A6812SA) for the VFD tubes (11 tubes). ;A PIC12F683 controls a boost regulator for VFD power: ;see PWM_for_VFD2.gcb ;******************************************************** ;----- Settings #chip 16F88, 8 ;PIC16F88 running at 8 MHz #config mclr=on ;external reset #config osc=int ;use internal oscillator #option Explicit ;insures all variables dimensioned #include "TI-Library.gcb" ;library routines used for interface with TI83+ ;Make sure library in same directory as this code #define button PortA.4 ;Pushbutton for Start Loop (Requests new input) #define data PortB.7 ;data to shift register in (SDI) #define clock PortB.6 ;clock to shift register CLK #define latch PortB.5 ;latch to shift register STROBE (latch) ;Next 2 pins are the TI interface: #define Data0 PortB.0 ;Data0 wire (red) to pin 6 #define Data1 PortB.1 ;Data1 wire (white) to pin 7 #define signLED PortB.2 ;LED indicating negative result on pin 8 ;----- Hardware settings #define LCD_IO 4 ;4-bit mode #define LCD_RS PortA.0 ;RS on pin 17 #define LCD_Enable PortA.1 ;E on pin 18 #define LCD_DB4 PortA.2 ;DB4 on pin 1 #define LCD_DB5 PortA.3 ;DB5 on pin 2 #define LCD_DB6 PortA.6 ;DB6 on pin 15 #define LCD_DB7 PortA.7 ;DB7 on pin 16 #define LCD_NO_RW 1 ;ground the RW line on LCD ;----- Variables for TI83+/PIC interface dim value as string ;(in/out) floating point number dim name as byte ;(in) name of TI83+ variable (A-Z) ;----- Variables dim length as Byte ;length of the string "value" dim character as byte ;for ASCII characters of the string "value" dim count as byte ;main loop counter dim sign as bit ;value sign: 0b1 for -, 0b0 for + dim digit as word ;indicates which tube is energized; needs 11 bits dim numeral as byte ;determines which segments are lit; needs 8 bits dim clocks as Byte ;sub loop counters ;------Constants Table 11digits as word ;items are code for which digit is energized b'10000000000' ;table item 1 ;digit 1 b'01000000000' ;had to use this notation as 0b notation b'00100000000' ;returns only zeros with this version b'00010000000' ;of the compiler (v0.98.06). Fixed in .07 b'00001000000' b'00000100000' b'00000010000' b'00000001000' b'00000000100' b'00000000010' b'00000000001' ;table item 11 ;digit11 End Table wait 100 mS ;wait for things to settle ;----- I/O (dir) dir PortA.4 in ;RA4 in (button); PortA otherwise defined by LCD_IO 4 dir PortB 0b00000011 ;RB0, RB1, data 0 and data 1 in (TI83+ interface) ;RB2 out (signLED), rest out ;prepare the A6812SA: clearRegister ;fill register with 0's so no display garbage on power up ;----- Main Program---------------------------------------------------------------- ;On the TI83+, STO number or answer to S, then press button to display on LCD(and VFDs). ;This retrieves the value stored in "S", which you can change ;at any time by storing a new value. You can use any of the TI83's ;variables (A to Z), I arbitrarily chose S. ;More ideal would be that whenver you press Enter, ;the answer would be stored and sent to the PIC. Still working on that..... Start: ;User instructions for entering new input Do cls : locate 0,0 : print "<=10 char, STO" : LCDWriteChar 126 : print "S" ;<=10 because TI-Library adds . or 0; store to S locate 1,0 : print "No EE," : LCDWriteChar 126 : print "Press btn" ;No exponents; press button to exit loop & initiate ;retrieval of number stored in calculator wait 250 mS If button = 0b0 then exit do ;On button press, exit loop Loop Begin: ;Retrieves TI83+ input and processes it for displays ;Next 2 lines use the TI-library by Thomas Henry name = "S" ;Identify variable to retrieve getNum ;Retrieves value of "S" to PIC, stored in string "value" length = len(value) ;determine how many characters in the string named value ;this includes numerals, minus sign, and decimal, including ;0 or decimal which may be added by TI-Library If length > 11 then ;11 or less characters will fit on the 11 tubes cls : locate 0,0 : print "<=10,try again.." locate 1,0 : print "No EE," : LCDWriteChar 126 : print "Press btn" wait 250 mS goto Begin: ;try again with less than 10 characters this time... End if cls : locate 0,0 print value ;Sends value of "S" to LCD. May have a . or 0 added. locate 1,0 print "length = " : print length ;(used this for debugging, can be removed) character = ASC(value,1) ;converts 1st character of the string to ASCII If character = 45 then ;if the character is the negative sign (-) sign = 0b1 ;then the sign LED will be turned on else ;if not (i.e. a number or decimal point) sign = 0b0 ;then the sign LED will not be turned on below end if signLED = sign ;make it so (turn led on or off) If length > 11 then length = 11 ;maximum times for main loop to run; circuit uses 11 tubes If (length < 11) and (sign = 0b1) then length = length -1 ;If a negative number length < 11, only want loop to run as ;many times as there are characters,including a decimal (if present). ;-1 exludes the minus sign character from being counted in the length. ;If length<11 and positive, then no such adjustment is needed. ;------------MULTIPLEXING LOOP do For count = 1 to length ;for each digit/character, in succession ReadTable 11digits, count, digit ;Table name, item number in table, variable to store it in ;note "count" refers to item number in the table If sign = 0b1 then ;if a negative character = ASC(value,count + 1) ;convert character of the string to ASCII starting with 2nd char. ;here, "count" is the character position in the string value. else ;if sign is not 0b1 character = ASC(value,count) ;convert character of the string to ASCII starting with 1st char. end if If character = 52 then numeral = 0b10110010 ;4 This section essentially converts each ASCII If character = 56 then numeral = 0b11111110 ;8 character into a binary number that codes for If character = 46 then numeral = 0b00000001 ;. which segments are illuminated. If character = 48 then numeral = 0b11011110 ;0 Each time through the loop, If character = 53 then numeral = 0b01110110 ;5 a digit, and If character = 50 then numeral = 0b11101100 ;2 corresponding numeral If character = 57 then numeral = 0b11110110 ;9 are chosen. The binary number for each If character = 54 then numeral = 0b01111110 ;6 will later be sent to PortB.7 If character = 51 then numeral = 0b11100110 ;3 If character = 49 then numeral = 0b10000010 ;1 If character = 55 then numeral = 0b11000010 ;7 Latch = 0 ;don't latch ("strobe") data yet sendall ;send digit, numeral, and extra bit to shift register Latch = 1 ;move register contents into latch, presented at outputs wait 2 mS ;short enough to avoid appearence of flicker next length wait (24 - (length * 2)) mS ;this is 2 mS per energized tube. Extra time needed when ;less than 11 tubes energized to create uniform brightness If button = 0 then goto begin ;exit loop, retrieve and process new input loop ;fetch and send next digit and character end sub sendall ;sends digit and numeral to shift register For clocks = 1 to 11 ;11 bits to read Clock = 0 ;condition for register to accept data data = digit.0 ;puts LSB of digit on GPIO.0 Clock = 1 ;condition for register to latch data digit = FNLSR(digit,1) ;shift bits to right by 1 next For clocks = 1 to 8 ;8 bits to read Clock = 0 data = numeral.0 ;puts LSB of numeral on GPIO.0 Clock = 1 numeral = FNLSR(numeral,1) ;shift bits to right by 1 next end sub sub clearRegister ;fills register with zeros For clocks = 1 to 20 clock = 0 data = 0 clock = 1 Next end sub