'Control firmware for simple 70cm FM transceiver with DRA818U.
'Uses Atmega48, LCD 2x16, and 6 buttons.
'Uses internal clock of 8MHz.
'Configuration bits: see http://599.cz/view.php?cisloclanku=2015052801
$regfile = "m48def.dat"                                     'Compilation for Atmega48
$crystal = 8000000                                          'Clock frequency 8MHz
$hwstack = 32                                               'Memory usage
$swstack = 0
$framesize = 64
$baud = 9600                                                'Serial (UART) speed 9600bps
'Default parameters for UART are:  Parity none, Data bits 8, Stop bits 1, Handshake none

'********* config LCD **************************************
Config Lcd = 16x2
Config Lcdpin = Pin , Db4 = Portd., Db5 = Portb., Db6 = Portb., Db7 = Portb., E = Portd., Rs = Portd.5
Cursor Off
'************ Deffinition of special character *************
Deflcdchar 1 , 32 , 31 , 17 , 27 , 27 , 31 , 32 , 32        'Special character to show (LCD) RX or TX under CTCSS
Cls

'********* Config Interrupt Ovf1 Timer1 ********************
Enable Interrupts
Config Timer1 = Timer , Prescale = 1024
On Ovf1 Turn_light_off                                      'Turn off the Led after some time

'***************************************************************************
'Aliases for Buttons * Config as Inputs *** Set Pull-Ups *******************
'***************************************************************************
Butt1 Alias Pinc.: Config Butt1 = Input : Set Butt1
Butt2 Alias Pind.: Config Butt2 = Input : Set Butt2
Butt3 Alias Pinc.: Config Butt3 = Input : Set Butt3
Butt4 Alias Pind.: Config Butt4 = Input : Set Butt4
Butt5 Alias Pinc.: Config Butt5 = Input : Set Butt5
Butt6 Alias Pind.: Config Butt6 = Input : Set Butt6

'* Alias for LED **** Config as Output ** Set On Led **
Led Alias Portc.: Config Led = Output : Set Led
'* Alias for PWR *** Config as output *** Set to 1W ***
Pwr Alias Portb.: Config Pwr = Output : Reset Pwr

'***************************************************************************
'*** Variables declarations ************************************************
'***************************************************************************
Dim Setgroup$ As String * 46                                'String to send completed data through UART to the DRA818V
Setgroup$ = "AT+DMOSETGROUP=0,"                             'Inicial value of the string

Dim E_freq As Eram Dword                                    'Variable of Frequency saved in EEprom
Dim E_rptr As Eram Byte                                     'Variable of Repeater-operating status saved in EEprom
Dim E_ctcss As Eram Byte                                    'Number of CTCSS tone saved in EEprom
Dim E_subtone_status As Eram Byte                           'Variable of subtones state (Tx, Rx, Both) saved in EEprom

Dim Freq As Dword                                           'Variable of actual "working" frequency
Dim Rptr As Byte                                            'Variable of actual Repeater-operating status
Dim Ctcss As Byte                                           'Number of actualy set CTCSS tone
'Dim Ctcss$ As String * 3                                   'not in use
Dim Subtone_status As Byte                                  'Variable of actual subtones status (Tx, Rx, Both)
Dim Sub_tx As Byte                                          'The number of actually set CTCSS tone for Tx
Dim Sub_rx As Byte                                          'The number of actually set CTCSS tone for Rx
Dim Sub_tx$ As String * 4                                   'The number of CTCSS as string to send via UART (Rx)
Dim Sub_rx$ As String * 4                                   'The number of CTCSS as string to send via UART (Tx)
Dim Sub_status_tx$ As String * 1                            'One char string to show whether CTCSS is active on Tx
Dim Sub_status_rx$ As String * 1                            'One char string to show whether CTCSS is active on Rx

Dim Rx_frq As Dword                                         'Working Rx frequency
Dim Rx_frq$ As String * 8                                   'String of Rx frequency to send through UART to DRA818
Dim Tx_frq As Dword                                         'Working Tx frequency
Dim Tx_frq$ As String * 8                                   'String of Tx frequency to send through UART to DRA818

Dim Tone As Byte                                            'Number represents a frequency of CTCSS tone (to show on LCD)
Dim Tone$ As String * 3                                     'String to show the frequency of CTCSS tone on LCD

Dim Pwr_out As String * 3                                   'A string to show the set power (High, Low)
Pwr_out = " 1W"                                             'At start the High power (1 Watt) is set up

'***************************************************************************
'**** Constants ************************************************************
'***************************************************************************
Const Rptr_shift = 76000                                    'Shift frequency for repeater (7600kHz)
Const Step_1 = 250                                          'Smaller frequency step   (25kHz)
Const Step_2 = 10000                                        'Larger frequency step    (1MHz)

Const Direct = 1                                            'Normal direct (Rx=Tx)
Const Repeater = 2                                          'Normal repater (Tx=Rx-7600kHz)
Const Rptr_inp = 3                                          'Listening at the input frequency of a repeater

Const No_sub = 1                                            'CTCSS not used
Const Tx_sub = 2                                            'CTCSS on Tx side
Const Both_sub = 3                                          'CTCSS on both Tx and Rx

Const Band_limit_upper = 4400000                            'Upper limit of Freq which loads from EEprom
Const Band_limit_lower = 4300000                            'Lower limit of Freq which loads from EEprom
Const Band_limit_default = 4335000                          'Default freq when data in EEprom out of limits

Const Repeater_limit_upper = 4394250                        'Upper limit for automatic switch to repeater mode
Const Repeater_limit_lower = 4386500                        'Lower limit for automatic switch to repeater mode

Const Cw_limit = 4320000                                    'Edges of the CW and ...
Const Ssb_limit = 4330000                                   '... the SSB portions of 70cm band.

'***************************************************************************
'***** Read and set frequency from EEprom **********************************
'***************************************************************************
Freq = E_freq
If Freq > Band_limit_upper Then                             'When frequency is above the HAM band...
   Freq = Band_limit_default                                '...then sets the default frequency
End If
If Freq < Band_limit_lower Then                             'When the frequency is below the HAM band (FM)...
   Freq = Band_limit_default                                '...then sets the default frequency
End If

'****************************************************************************
'**** Read and set a repeater state from EEprom *****************************
'****************************************************************************
Rptr = E_rptr
If Rptr > Rptr_inp Then                                     'When the status is "unknown"...
   Rptr = Direct                                            '...then sets the direct mode
End If

'****************************************************************************
'**** Read and set the CTCSS number from EEprom *****************************
'****************************************************************************
Ctcss = E_ctcss
If Ctcss > 38 Then                                          'The 38 is the highest number of the CTCSS tone (see a datasheet of DRA818V)
   Ctcss = 0
End If

'***************************************************************************
'**** Read and set CTCSS status (None, Tx, Tx+Rx) **************************
'***************************************************************************
Subtone_status = E_subtone_status
If Subtone_status > Both_sub Then                           'When the CTCSS status is in "unknown" state...
   Subtone_status = Tx_sub                                  '...then set CTCSS to Tx
End If


Gosub Sub_status_set                                        'Set all params from EEprom and send it via UART to DRA818V

'***************************************************************************
'**** Some advertisement to the display  ;-) *******************************
'**** Here the TRX works, even if display shows this advertisement *********
'***************************************************************************
Locate 1 , 1 : Lcd "UHF FM ver: 1.00"
Locate 2 , 1 : Lcd "DRA818U+Atmega48"
Wait 4 : Cls
Locate 1 , 1 : Lcd " Author: OK1HDU "
Locate 2 , 1 : Lcd " May 24th 2015 "
Wait 4 : Cls
'***************************************************************************

Gosub Setgroup                                              'After advertisement set and show params from EEprom

'***************************************************************************
'**** Main loop, waiting for the buttons ***********************************
'***************************************************************************
Do
If Butt6 = 1 Then                                           'Button 6 released
   Debounce Butt1 , 0 , Freq_up , Sub                       'Button 1 - frequency Up (small step)
   Debounce Butt2 , 0 , Freq_dwn , Sub                      'Button 2 - frequency Down (small step)
   Debounce Butt3 , 0 , Ctcss_up , Sub                      'Button 3 - CTCSS Up
   Debounce Butt4 , 0 , Ctcss_dwn , Sub                     'Button 4 - CTCSS Dwn
   Debounce Butt5 , 0 , Rptr_switch , Sub                   'Button 5 - Direct x Repeater mode
Elseif Butt6 = 0 Then                                       'Button 6 hold
   Debounce Butt1 , 0 , Freq_up , Sub                       'Button 1 - frequency UP (large step)
   Debounce Butt2 , 0 , Freq_dwn , Sub                      'Button 2 - frequency Down (large step)
   Debounce Butt3 , 0 , Sub_state , Sub                     'Button 3 - CTCSS mode (None, Tx, Both)
   Debounce Butt4 , 0 , Light , Sub                         'Button 4 - LED (background light)
   Debounce Butt5 , 0 , Power_set , Sub                     'Button 5 - Set the power (1W x Low)

End If
Loop





'+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
'+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
'+ + +  S U B R U T I N E S  + + + + + + + + + + + + + + + + + + + + + + + +
'+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
'+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +


'**************************************************************************
'**** Show Frequencies, CTCSS, etc.... on LCD 2x16 ************************
'**************************************************************************
Show_lcd:
Tone = Lookup(ctcss , Subtones_table)                       'Take CTCSS tone from table
Tone$ = Str(tone) : Tone$ = Format(tone$ , "000")           'change tone to string

Locate 1 , 1 : Lcd "Rx: " ; Rx_frq$                         'Display everything on the LCD
Locate 2 , 1 : Lcd "Tx: " ; Tx_frq$
Locate 2 , 14 : Lcd Pwr_out
Locate 1 , 14 : Lcd Tone$
Locate 1 , 13 : Lcd Sub_status_rx$
Locate 2 , 13 : Lcd Sub_status_tx$
Return

'*************************************************************************
'*** Collect data and send it through UART *******************************
'*************************************************************************
Setgroup:
Enable Timer1                                               'Start light timer
Timer1 = 0
Set Led                                                     'and turn light ON
Enable Ovf1                                                 'Enable overflow interrupt

If Rptr = 1 Then                                            'set frequencies, depending on repeater status
   Tx_frq = Freq
   Rx_frq = Freq
Elseif Rptr = 2 Then
   Tx_frq = Freq - Rptr_shift
   Rx_frq = Freq
Elseif Rptr = 3 Then
   Tx_frq = Freq - rptr_shift
   Rx_frq = Freq - rptr_shift
End If

Tx_frq$ = Str(tx_frq) : Tx_frq$ = Format(tx_frq$ , "   .    ")       'turn frequencies to strings
Rx_frq$ = Str(rx_frq) : Rx_frq$ = Format(rx_frq$ , "   .    ")
Sub_tx$ = Str(sub_tx) : Sub_tx$ = Format(sub_tx$ , "0000")  'turn CTCSS numbers to strings
Sub_rx$ = Str(sub_rx) : Sub_rx$ = Format(sub_rx$ , "0000")

Setgroup$ = Setgroup$ + Tx_frq$ : Setgroup$ = Setgroup$ + ","       'Make the long string to send data...
Setgroup$ = Setgroup$ + Rx_frq$ : Setgroup$ = Setgroup$ + ","       '...via UART to DRA818V (46 characters)
Setgroup$ = Setgroup$ + Sub_tx$ : Setgroup$ = Setgroup$ + ","
Setgroup$ = Setgroup$ + "1" : Setgroup$ = Setgroup$ + ","
Setgroup$ = Setgroup$ + Sub_rx$

Print Setgroup$                                             'Sending string to DRA818V
Setgroup$ = "AT+DMOSETGROUP=0,"                             'Again set the inicial value of the string
Gosub Show_lcd                                              'Show values on a display
Return


'**************************************************************************
'**** Setting a Power *****************************************************
'**************************************************************************
Power_set:
Toggle Pwr                                                  'Swap the output to switching transistor(PORTb.5)
If Pwr = 0 Then
Pwr_out = " 1W"
Elseif Pwr = 1 Then
Pwr_out = "Low"
End If
Gosub Setgroup
Return

'**************************************************************************
'**** Toggle (swap) background light (LED) ********************************
'**************************************************************************
Light:
Toggle Led
Return

'**************************************************************************
'**** Save Values to EEprom and turn the light Off (LED) ******************
'**************************************************************************
Turn_light_off:
E_freq = Freq                                               'Save actual frequency to EEprom
E_rptr = Rptr                                               'Save actual Repeater status to EEprom
E_ctcss = Ctcss                                             'Save actual CTCSS number
E_subtone_status = Subtone_status                           'Save actual CTCSS status

Disable Timer1
Disable Ovf1
Reset Led                                                   'Turn off the LED (background light)
Return

'**************************************************************************
'**** Frequency step UP ***************************************************
'**************************************************************************
Freq_up:
If Butt6 = 0 Then
   Freq = Freq + Step_2                                     'large step (1MHz)
Else
   Freq = Freq + Step_1                                     'Small step (25kHz)
End If
If Freq >= Repeater_limit_lower Then                        'Limits for automatic repeater shift
   If Freq <= Repeater_limit_upper Then                     '   -//-
      Rptr = Repeater                                       'Set to repeater operation
   Else
      Rptr = Direct                                         'Set to simplex operation
   End If
End If
If Freq >= Cw_limit Then                                    'Jump over the CW ...
   If Freq < Ssb_limit Then                                 '... and SSB portion of the band.
      Freq = Ssb_limit
   End If
End If
Gosub Setgroup                                              'Jump to send data through UART and to LCD
Waitms 100
If Butt1 = 0 Then                                           'Button Auto repeat function (after 100ms)
    Goto Freq_up
End If
Return

'***************************************************************************
'**** Frequency step DOWN **************************************************
'***************************************************************************
Freq_dwn:
If Butt6 = 0 Then
   Freq = Freq - Step_2                                     'Large step (1MHz)
Else
   Freq = Freq - Step_1                                     'Small step (25kHz)
End If
If Freq <= Repeater_limit_upper Then                        'limits for automatic repeater shift
   If Freq >= Repeater_limit_lower Then                     '   -//-
      Rptr = Repeater                                       'Set to repeater operation
   Else
      Rptr = Direct                                         'Set to simplex operation
   End If
End If
If Freq < Ssb_limit Then                                    'Jump over the CW ...
   If Freq >= Cw_limit Then                                 '... and SSB portion of the band.
      Freq = Cw_limit - Step_1
   End If
End If
Gosub Setgroup                                              'Jump to send data through UART and to LCD
Waitms 100
If Butt2 = 0 Then
   Goto Freq_dwn                                            'Button Auto repeat function
End If
Return

'***************************************************************************
'*** Switch Repeater operation (Simplex, Repeater, Listening of input) *****
'***************************************************************************
Rptr_switch:
Rptr = Rptr + 1                                             ' 1 ~ simplex
If Rptr > Rptr_inp Then                                     ' 2 ~ repeater
Rptr = Direct                                               ' 3 ~ listening input
End If
Gosub Setgroup                                              'Jump to send data through UART and to LCD
Return

'***************************************************************************
'**** CTCSS subtone Up *****************************************************
'***************************************************************************
Ctcss_up:
Ctcss = Ctcss + 1                                           'See a table of subtones in a Data table at the end
If Ctcss > 38 Then                                          'of the program
Ctcss = 0                                                   ' 0 ~ no subtone  (just carrier squelch)
End If
Gosub Sub_status_set
Waitms 100
If Butt3 = 0 Then                                           'Button auto repeat function
   Goto Ctcss_up
End If
Return

'***************************************************************************
'**** CTCSS subtone Down ***************************************************
'***************************************************************************
Ctcss_dwn:
Ctcss = Ctcss - 1                                           'See a table of subtones in a Data table at the end
If Ctcss > 38 Then                                          'of the program
Ctcss = 38                                                  ' 0 ~ no subtone  (just carrier squelch)
End If
Gosub Sub_status_set
Waitms 100
If Butt4 = 0 Then                                           'Button auto repeat function
   Goto Ctcss_dwn
End If
Return

'***************************************************************************
'**** CTCSS subtone status (None, Tx, Tx+Rx) *******************************
'***************************************************************************
Sub_state:
Subtone_status = Subtone_status + 1                         ' 1 ~ CTCSS neither Tx nor Rx
If Subtone_status > Both_sub Then                           ' 2 ~ Tx CTCSS , Rx clear
   Subtone_status = No_sub                                  ' 3 ~ Both Tx and Rx use CTCSS
End If
Gosub Sub_status_set
Return

'***************************************************************************
'**** CTCSS subtone status (None, Tx, Tx+Rx). Second part ******************
'*** Sets strings of CTCSS for sending via UART and a notice on LCD ********
'***************************************************************************
Sub_status_set:
If Subtone_status = No_sub Then                             'CTCSS is not used
   Sub_tx = 0 : Sub_status_tx$ = " "
   Sub_rx = 0 : Sub_status_rx$ = " "
Elseif Subtone_status = Tx_sub Then                         'CTCSS is used on the Tx side
   Sub_tx = Ctcss : Sub_status_tx$ = Chr(1)
   Sub_rx = 0 : Sub_status_rx$ = " "
Elseif Subtone_status = Both_sub Then                       'CTCSS is used on both Tx and Rx side
   Sub_tx = Ctcss : Sub_status_tx$ = Chr(1)
   Sub_rx = Ctcss : Sub_status_rx$ = Chr(1)
End If
Gosub Setgroup                                              'Jump to send data via UART and to LCD
Return

End                                                         'Kanets filma

'***************************************************************************
'**** Table of subtones. Frequencies displayed without decimal point.) *****
'***************************************************************************
Subtones_table:
Data 0 , 67 , 71 , 74 , 77 , 79 , 82 , 85 , 88 , 91 , 94 , 97 , 100 , 103 , 107 , 110 , 114 , 118 , 123 , 127 , 131 , 136 , 141 , 146 , 151 , 156 , 162 , 167 , 173 , 179 , 186 , 192 , 203 , 210 , 218 , 225 , 233 , 241 , 250