' ********************************************************************** ' * File: uk_BASAVR_023.BAS * ' * Version: 1.1 * ' * Date: 23.08.10 * ' * Development Tools: Bascom-AVR Demo Ver. 1.11.9.1 + * ' * + AVR bootloader grifo(r) Ver. 1.2 * ' * Cards: GMM AM08 + GMM TST3 * ' * Developed by: GRIFO(r) Italian Technology * ' * via Dell'Artigiano 8/6 * ' * 40016 S. Giorgio di Piano (BO) * ' * Tel. +39 051 892052 Fax. +39 051 893661 * ' * http://www.grifo.com http://www.grifo.it * ' * Author: Gianluca Angelini * ' ********************************************************************** ' Example program 23 of BASCOM AVR course. ' It manages a calculator able to perform the 4 foundamental operations, through ' an alphanumeric display with 2 x 20 characters and a matrix keyboard with ' 4 x 4 keys. ' The program requires a formula composed by a first operand, one operator and ' a second operand on the same row and then it shows the result obtained from ' the formula on the second row. The operands can have sign and decimal point, ' up to 8 maximum significant digits. ' The formula is inserted and the result is displayed through the matrix ' keyboard and LCD display, available on GMM TST3. ' Moreover the program present itself and show the user instructions on a serial ' console provided of monitor and keyboard and it must communicate with a fixed ' physical protocol at 19200 Baud, 8 Bit x chr, 1 Stop bit, No parity. ' This console can be another system capable to support a serial RS 232 ' communication. In order to simplify the use it can be used a PC provided of ' one COMx line, that execute a terminal emulation program as HYPERTERMINAL or ' the homonym modality provided by BASCOM AVR (see IDE Configuration). ' The program works only when the GMM AM08 is mounted on Z1 socket of GMM TST3!! ' ' Added instructions: None. ' ' 23/08/10: uk_BASAVR_023.BAS - Ver 1.1 - By G.A. ' First version. ' ' '**************************** IDE Configurations ******************************* ' NOTE: in order to coorectly use this demo program, please execute the following ' steps: ' 1) Check the availability of M8DEF.DAT file into the directory where the ' BASCOM AVR is installed and copy it if not present. ' 2) Into the window "Options | Compiler | Chip" set: ' Chip: m8def.dat ' XRAM: None ' HW Stack: 64 ' Soft Stack: 32 ' Framesize: 64 ' XRAM waitstate: disabled ' External Access Enable: disabled ' 3) Into the window "Options | Compiler | LCD" set: ' LCD type = 20 * 2 ' BUS mode = 4 bit ' Data mode = pin ' Enable = PORTD.2 ' RS = PORTD.3 ' DB7 = PORTC.3 ' DB6 = PORTC.2 ' DB5 = PORTD.5 ' DB4 = PORTD.4 ' LCD-address = don't care ' RS-address = don't care ' Make upper 3 bits 1 in LCD designer = not selected ' 4) Into the window "Options | Communication" set: ' COM port = the PC line connected to GMM AM08, through GMM TST3 ' Baudrate = 19200 ' Parity = None ' Databits = 8 ' Stopbit = 1 ' Handshake = None ' Emulation = TTY ' Font = Terminal, Normal, 12 points, white colour ' Backcolor = Navy ' 5) At the end of compilation, after the code is programmed on GMM AM08, open ' the terminal emulation window of BASCOM AVR with the option: Tools | ' Terminal emulator (Ctrl+T) and then reset or powen on the Mini Module. '************************* Compiler directives ********************************* $regfile "M8DEF.DAT" ' Definitions file for used microcontroller $romstart = &H0 ' Code start address on FLASH $crystal = 7372800 ' Microcontroller crystal frequency $hwstack = 64 ' Hardware stack space $swstack = 32 ' Software stack space $framesize = 64 ' Frame space $map ' Generate debug information $baud = 19200 ' Serial communication speed: 19200 Baud ' Other parameters fixed to: 8 bit x chr ' 1 Stop bit ' No parity '******************************* Definitions *********************************** ' The resources used by program are connected as described in following table. ' !!! Note: On GMM TST3 the jumpers must be set in following positions: ' J1 in 2-3 ; J3 in 1-2 ; J10 in 1-2 ; J11 in 1-2 !!! ' ' hardware pin Z1 pin Signal Used uP ' resource GMM TST3 GMM AM08 GMM AM08 signal ' TST1.Row0 33 27 ADC7 ADC7 ' TST1.Row1 32 26 PC0 ADC0 PC0 ' TST1.Row2 31 25 PC1 ADC1 PC1 ' TST1.Row3 30 24 PB1 OC1A PB1 ' TST1.Col0 29 23 PB0 ICP PB0 ' TST1.Col1 28 22 PB2 OC1B /SS PB2 ' TST1.Col2 27 21 PD6 AIN0 PD6 ' TST1.Col3 26 20 PD7 AIN1 PD7 ' LCD.DB4 23 17 PD4 T0 XCK PD4 ' LCD.DB5 22 16 PD5 T1 PD5 ' LCD.DB6 21 15 PC2 ADC2 PC2 ' LCD.DB7 19 13 PC3 ADC3 PC3 ' LCD.E 25 19 PD2 INT0 PD2 ' LCD.RS 24 18 PD3 INT1 PD3 ' ' Signal pin COMx pin CN5 pin Z1 pin Signal Signal ' PC DB9 GMM TST3 GMM TST3 GMM AM08 GMM AM08 uP ' TX 3 3 9 3 RxD RS232 PD0 ' RX 2 2 10 4 TxD RS232 PD1 ' GND 5 5 20 14 GND - ' This table shows that the connection cable between PC COM line and CN5 of ' GMM TST3 is a normal pin to pin cable or direct. Grifo(r) can supply it by ' requesting the CCR 9+9E code. Pinrow0 Alias 7 ' A/D input connected to row 0 of GMM TST3 keyboard TST1 Pinrow1 Alias Pinc.0 ' Bit with input signal connected to row 1 of GMM TST3 keyboard TST1 Pinrow2 Alias Pinc.1 ' Bit with input signal connected to row 2 of GMM TST3 keyboard TST1 Pinrow3 Alias Pinb.1 ' Bit with input signal connected to row 3 of GMM TST3 keyboard TST1 Pincol0 Alias Portb.0 ' Bit with output signal connected to column 0 of GMM TST3 keyboard TST1 Pincol1 Alias Portb.2 ' Bit with output signal connected to column 1 of GMM TST3 keyboard TST1 Pincol2 Alias Portd.6 ' Bit with output signal connected to column 2 of GMM TST3 keyboard TST1 Pincol3 Alias Portd.7 ' Bit with output signal connected to column 3 of GMM TST3 keyboard TST1 Pinrx Alias Ddrd.0 ' Bit with direction signal connected to GMM AM08 RxD Pintx Alias Ddrd.1 ' Bit with direction signal connected to GMM AM08 TxD '************************* Constants declaration ******************************* Const Nokey = &HFF ' Value that indicate no key pressed Const Debdt = 5 ' Debouncing execution time in milliseconds Const Debtime = 20 ' Debouncing time for real key in milliseconds Const Debcycle = Debtime / Debdt ' Debouncing number obtained by defined times Const Rep1sttime = 500 ' First autorepeat time for key in milliseconds Const Rep1stcycle = Rep1sttime / Debdt ' Cycles number for first autorepeat Const Repnexttime = 100 ' Next autorepeat time for key in milliseconds Const Repnextcycle = Repnexttime / Debdt ' Cycles number for next autorepeat Const Nextrep = Rep1sttime - Repnexttime ' Next autorepeat start time for key in milliseconds Const Nextcycle = Nextrep / Debdt ' Cycles number for next autorepeat start Const Maxcol = 20 ' Maximum number of display column Const Maxrow = 2 ' Maximum number of display rows '************************* Variables declaration ******************************* Dim Keypos As Byte ' Position of key pressed on matrix keyboard Dim Key As Byte ' Code of key pressed on matrix keyboard Dim Krow As Byte ' Rows states of matrix keyborad Dim Kcol As Byte ' Column states of matrix keyboard Dim Kcode(16) As Byte ' Array with keys codes of matrix keyboard Dim Debpos As Byte ' Position of key pressed under debouncing Dim Debcnt As Byte ' Debouncing counter Dim Reppos As Byte ' Positione of key pressed under autorepeat Dim Repcnt As Byte ' Autorepeat counter Dim Disrow As Byte ' Row of current cursor display position Dim Discol As Byte ' Column of current cursor display position Dim Newform As Boolean ' Flag for new formula Dim Operand1 As Single ' First operand Dim Operand2 As Single ' Second operand Dim Result As Single ' Operation result Dim Formula As String * 22 ' String for formula Dim Operstr As String * 11 ' String for operands Dim Operat As String * 1 ' Searche operator Dim Posop As Byte ' Operator position in the formula Dim Lenstr As Byte ' Strings length '************************ Subroutines declaration ****************************** Declare Sub Ini_key() ' Initialize lines of matrix keyboard Declare Sub Set_col() ' Set column state of matrix keyboard Declare Sub Get_row() ' Acquire rows states of matrix keyboard Declare Sub Scan_keypos() ' Acquire state of matrix keyboard Declare Sub Deb_key() ' Acquire state of matrix keyboard with debouncing Declare Sub Rep_key() ' Acquire state of matrix keyboard with autorepeat and debouncing Declare Sub Inp_formula() ' Acquire formula from keyboard and show it on display Declare Sub Conv_operand() ' Converts operands from string to number '****************************** Main program *********************************** Main: Pinrx = 0 ' Initialize signals for serial communication Pintx = 0 ' as digital inputs Call Ini_key() ' Initialize line of matrix keyboard ' Lines connection of LCD (see on line help, GMM TST3 electric diagram and ' previous table for further informations) Config Lcdmode = Port ' Drive display through microcontroller's port lines Config Lcdbus = 4 ' Drive display with 4 bits Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portd.2 , Rs = Portd.3 Config Lcd = 20 * 2 ' LCD display with 20 columns and 2 rows Cls ' Clear LCD display and set position on first character Print "Calculator for 4 foundamental operations with keyboard and display of GMM TST3" Print "The keys on the 4x4 keyboard, have following meanings:" Print "# -> +" Print "C -> -" Print "* -> *" Print "D -> /" Print "B -> ." Print "A -> =" Print "Insert formula with first operand operator second operand, with no spaces," Print "and terminate with =. The maximum formula length is equal to 20 chrs" Print "available on display rows." Do ' Begin endless loop Call Inp_formula() ' Acquire formula through GMM TST3 Locate 2 , 1 ' Set cursor position on second row of GMM TST3 display Operat = "+" ' Search Sum operator Posop = Instr(formula , Operat) If Posop = 0 Then ' If Sum operator is not available Operat = "*" ' Search Multiply operator Posop = Instr(formula , Operat) If Posop = 0 Then ' If Multiply operator is not available Operat = "/" ' Search Divisor operator Posop = Instr(formula , Operat) If Posop = 0 Then ' If Divisor operator is not available Operat = "-" ' Search minus sign or Subtract operator Posop = Instr(formula , Operat) If Posop = 1 Then ' If there is minus sign on first operand Operat = "-" ' Re-search Subtract operator Posop = Instr(2 , Formula , Operat) End If End If End If End If If Posop <> 0 Then ' Formula with valid operator Call Conv_operand() ' Converts operands into numbers Select Case Operat ' Check operator found in formula Case "+": ' If Sum operator Result = Operand1 + Operand2 ' Perform addition of two operands Case "-": ' If Subtract operator Result = Operand1 - Operand2 ' Perform subtraction of two operands Case "*": ' If Multiply operator Result = Operand1 * Operand2 ' Perform multiplication of two operands Case "/": ' If Divide operator Result = Operand1 / Operand2 ' Perform division of two operands End Select Lcd Result ' Show result on display Else ' Formula with no valid operator Lcd "Err" ' Show error message on display End If Loop ' End endless loop End '*************************** End of main program ******************************* '*********************** Subroutines used by program *************************** '*********************** Subroutines used by program *************************** ' Initialize resources, variables and peripheral devices used for matrix ' keyboard management. ' Input: None ' Output: Kcode() = array with initialized keys codes ' Debpos, Debcnt = variables for debouncing initialized ' Reppos, Repcnt = variables for autorepeat inizialized Sub Ini_key() ' One of the 8 lines required to manage the 4x4 matrix keyboard, is connected ' to a microcontroller analog signal and thus it is managed through the ' relative A/D converter section Config Adc = Single , Prescaler = Auto , Reference = Avcc ' Initialize A/D section with conversion on request, Start Adc ' best prescaler, Vref=5 V and enable it ' Initialize remaining 7 lines of matrix keyboard connected to digital signals ' of microcontroller Ddrc.0 = 0 ' Initialize signals connected to rows of matrix keyboard Ddrc.1 = 0 ' as digital inputs Ddrb.1 = 0 Pincol0 = 1 ' Initialize signals connected to column of matrix keyboard Ddrb.0 = 1 ' as digital outputs at high level Pincol1 = 1 Ddrb.2 = 1 Pincol2 = 1 Ddrd.6 = 1 Pincol3 = 1 Ddrd.7 = 1 Kcode(1) = "/" ' Set keys codes of matrix keyboard in Kcode(2) = "+" ' in proper array. Key D equals to / Kcode(3) = "0" ' Key # equal to + Kcode(4) = "*" Kcode(5) = "-" ' Key C equal to - Kcode(6) = "9" Kcode(7) = "8" Kcode(8) = "7" Kcode(9) = "." ' Key B equal to . (decimal point) Kcode(10) = "6" Kcode(11) = "5" Kcode(12) = "4" Kcode(13) = "=" ' Key A equal to = Kcode(14) = "3" Kcode(15) = "2" Kcode(16) = "1" Debpos = Nokey ' No key pressed under debouncing Debcnt = 0 ' Initialize debouncing counter Reppos = Nokey ' No key pressed under Autorepeat Repcnt = 0 ' Initialize autorepeat counter End Sub ' Set a low level on a single column of the 4 available in the matrix keyboard ' of GMM TST3. ' Input: Kcol = Column number to set low (0..3) ' Output: None Sub Set_col() If Kcol = 0 Then ' Set column 0 state Pincol0 = 0 Else Pincol0 = 1 End If If Kcol = 1 Then ' Set column 1 state Pincol1 = 0 Else Pincol1 = 1 End If If Kcol = 2 Then ' Set column 2 state Pincol2 = 0 Else Pincol2 = 1 End If If Kcol = 3 Then ' Set column 3 state Pincol3 = 0 Else Pincol3 = 1 End If End Sub ' Acquire and check the states of the 4 rows of GMM TST3 matrix keyboard ' Input: None ' Output: Krow = Number of the row at low level (0..3, Nokey if none is low) Sub Get_row() Local Adres As Word ' Local variable for A/D conversion result Krow = Nokey ' Set rows state for no key pressed ' One of the 4 lines connected to rows of 4x4 matrix keyboard, is connected ' to a microcontroller analog signal and thus it is acquired through the ' relative channel of A/D converter section Adres = Getadc(pinrow0) ' Acquire state of A/D input connected to row 0 If Adres < 100 Then ' Check and set row 0 state Krow = 0 End If ' Acquire remaining 3 rows of matrix keyboard connected to digital signals ' of microcontroller If Pinrow1 = 0 Then ' Check and set row 1 state Krow = 1 End If If Pinrow2 = 0 Then ' Check and set row 2 state Krow = 2 End If If Pinrow3 = 0 Then ' Check and set row 3 state Krow = 3 End If End Sub ' Verify state of matrix keyboard on GMM TST3, by setting low the 4 columns and ' checking the states of the 4 rows that compose the same keyboard. When more ' keys are contemporaneously pressed, it is returned the position of those ' connected to higher column. The position is calculated with locical operations ' in place of arithmetic ones, in order to optimize execution times. ' Input: None ' Output: Keypos = Position of key pressed (Nokey if none is pressed) Sub Scan_keypos() Keypos = Nokey ' Initialize code of no key pressed Kcol = 0 ' Set current column=the first Do Call Set_col() ' Set low current column Call Get_row() ' Get rows state If Krow <> Nokey Then ' Check if there is a key pressed Keypos = Kcol ' Obtain key pressed position from column Shift Keypos , Left , 2 ' and row starting from 0: multiply column by 2 Keypos = Keypos Or Krow ' and add row Incr Keypos ' Obtain key position starting from 1 End If Incr Kcol ' Increase current column Loop Until Kcol > 3 ' Repeat up to last column End Sub ' Verify state of matrix keyboard on GMM TST3, by performing the scanning and ' managing debouncing. This debounce avoids to recognize the typical rebounds ' of each electric button as pressures and releases of the same button, by ' obtaining a real state of pressed keys. ' Input: Debpos = Position of key pressed under debouncing ' Debcnt = Debouncing counter ' Output: Keypos = Position of real key pressed (Nokey if none is pressed) ' Debpos = Updated position of key pressed under debouncing ' Debcnt = Updated debouncing counter Sub Deb_key() Call Scan_keypos() ' Perform matrix keyboard scanning ' Debouncing management: verifies if the possible pressed key has been pushed continuosly for all ' the debouncing time and if this condition is satisfied returns its position. This verify is performed ' with two variables: the Debpos memorizes the position of the previously pressed key and the ' Debcnt counts the number of consecutive scans with key pressed. In order to obtain a Debouncing ' time equal to value defined in Debtime, the Deb_key() subroutines must be called at regular ' time interval long Debdt milliseconds. If Keypos <> Nokey Then ' If there is a pressed key If Keypos = Debpos Then ' If a key was already pressed, that is under debouncing Incr Debcnt ' Increase debouncing counter Else ' Key was not already pressed Debpos = Keypos ' Saves position of new key under debouncing Debcnt = 0 ' Reset debouncing counter End If If Debcnt >= Debcycle Then ' If debouncing time is elapsed Debcnt = 0 ' Reset counter to restart with next debouncing Key = Kcode(keypos) ' Get pressed key code from dedicated array End If Else ' Nessun tasto premuto Debpos = Nokey ' Set no key under debouncing Debcnt = 0 ' Reset debouncing counter End If End Sub ' Verify state of matrix keyboard on GMM TST3, by performing the scanning, ' managing debouncing and autorepeat. This autorepeat defines the timings for ' key pressed recognition to Rep1sttime for the first key pressed and to ' Repnexttime for the next ones. ' Input: Reppos = Position of key pressed under autorepeat ' Repcnt = Autorepeat counter ' Output: Key = ASCII code of key pressed with autorepeat (Nokey if none is pressed) ' Reppos = Updated position of key pressed under autorepeat ' Repcnt = Updated autorepeat counter Sub Rep_key() Call Deb_key() ' Acquire state of matrix keyboard with debouncing ' Autorepeat management: check if the possible key pressed is just pressed or it has been ' pressed for all the autorepeat time, in the last condition it returns its code. ' This check is performed through two variables: the Reppos memorizes the position of the ' key previously pressed and the Repcnt counts the number of consecutive scans with key ' pressed. ' The check on the end of autorepeat time is always performed on the higher time Rep1sttime, ' but the counter is initialized with a different value if it is the first autorepeat or ' a following ones. In order to obtain the right autorepeat times, defined in Rep1sttime ' and Repnexttime constants, the Rep_key() subroutine must be called at regular time ' interval long Debdt milliseconds. Key = Nokey ' No real key pressed If Keypos <> Nokey Then ' If there is a key pressed If Keypos = Reppos Then ' If key was already pressed, that is under Autorepeat Incr Repcnt ' Increase autorepeat counter Else ' Key was not pressed Reppos = Keypos ' Save position new key under autorepeat Repcnt = 0 ' Reset counter for first autorepeat Key = Kcode(keypos) ' Get code of just pressed key from dedicated array End If If Repcnt >= Rep1stcycle Then ' If time of first autorepeat is elapsed Repcnt = Nextcycle ' Set autorepeat counter for next Autorepeat Key = Kcode(keypos) ' Get code of real key pressed under autorepeat, from dedicated array End If Else ' Nessun tasto premuto Reppos = Nokey ' Set no key under Autorepeat Repcnt = 0 ' Reset counter for first autorepeat End If End Sub ' Manage formula input from GMM TST3 keyboard and shows it on display of the ' same GMM TST3. ' When first key is pressed it also clears the display in order to erase the ' previous formula and arrange for new one. It accepts all the 16 keys with the ' previously described correspondence: 10 digits (0..9), 4 operators (+,-,*,/), ' decimal point and equal. ' The input is completed when the equal key is pressed or the display line is ' full. ' Input: None ' Output: Formula = string with inserted formula Sub Inp_formula() Newform = 1 ' Denote start management of new formula Formula = "" ' Initialize string with formula Operstr = " " ' Avoid immediate exit from following loop Lenstr = 0 ' Initialize length of formula string Do ' Loop that acquire, show, and save formula Waitms Debdt ' Delay equal to Debouncing time Call Rep_key() ' Acquire state of matrix keyboard with autorepeat and debouncing If Key <> Nokey Then ' Check if there is a key pressed If Newform = 1 Then ' If it is the first key of new formula Newform = 0 ' Denote formula not new Cls ' Clear LCD display and set position on first character End If Operstr = Chr(key) ' Obtain character with key pressed Lcd Operstr ' Show key pressed on LCD display If Operstr <> "=" Then ' If pressed key is not the = Formula = Formula + Operstr ' Save pressed key into the string with formula End If Incr Lenstr ' Increase length of string with formula End If Loop Until Operstr = "=" Or Lenstr >= Maxcol ' Repeat until key = is pressed or pressed 20 keys End Sub ' Converts the two operands available inside the string with formula into the ' two equivalent numbers. ' Input: Formula = string variable with formula ' Posop = position of operator in the formula ' Output: Operand1 = first operand ' Operand2 = second operand Sub Conv_operand() Lenstr = Posop - 1 ' Obtain characters number of first operand Operstr = Left(formula , Lenstr) ' Extract string with first operand from formula Operand1 = Val(operstr) ' Convert first operand string in number Lenstr = Len(formula) ' Obtain characters number of second operand Lenstr = Lenstr - Posop Operstr = Right(formula , Lenstr) ' Extract string with second operand from formula Operand2 = Val(operstr) ' Convert second operand string in number End Sub '******************* End of subroutines used by program ************************