'********************************************************************
'* SMS Message Relay controller
'* uP: AT89S2313
'* Language: BASCOM-AVR 1.11.8.7
'* Originally posted: 2005.Feb.27
'* Last updated: 2007.Nov.19
'* Version: V1.10
'********************************************************************
$regfile = "2313def.dat"
$crystal = 8000000
$baud = 19200
Const Dlcd = 0
Dim Rs232_exit As Byte
Dim Read_ok As Bit
Dim Data_ok As Bit
Dim Sync_ok As Bit
Dim Read_num As Byte
Dim Read_select As Byte
Dim S2 As String * 40
Dim Gsm_signal As String * 3
Dim Time1_count As Byte
Dim Time1_ok As Bit
Dim Ch As Byte
Dim S2addr As Integer
Read_noop Alias 0
Read_gsm_sta1 Alias 1
Read_gsm_m1 Alias 2
Dim Relay(4) As Byte
Control_char Alias 0
Status_action Alias 1
Single_action Alias 2
Multiple_action Alias 3
Invalid_action Alias 4
On_action Alias 5
Off_action Alias 6
Toggle_action Alias 7
#if Dlcd
Declare Sub Lcdlocation(byval Row As Byte , Byval Col As Byte)
#endif
Config Portb = Output
' Set all Relays OFF
Relay(1) = 2 : Relay(2) = 3 : Relay(3) = 4 : Relay(4) = 7
For Ch = 1 To 4
Set Portb.relay(ch)
Next Ch
#if Dlcd
'Serial connection to LCD is via Port B.6
'LCD runs at 9600 baud
Open "comb.6:9600,8,n,1" For Output As #2
'LCD Reset pin is driven from PortB.5
Reset Portb.5 'Drive pin low
Waitms 400
Set Portb.5 'Then high
Waitms 400
#endif
' Once enabled, the timer counts each clock period (or you can select a
' divided down input clock if you prefer). When the timer overflows (65536
' counts) you get an interrupt. With a 8MHz clock, this doesn't work out to
' anything very useful. At 8MHz, each clock pulse is 125nS and 65536 of them
' is 8.192 milliseconds.
' I want a timer that resolves to 1000mS, so the first step is to divide down
' the input clock . Input clock to divide by 256, so now each clock pulse is
' worth (8.192/256)=32uS.
' The trick is to preload the counter with a value that will cause it to count
' for 1000mS. Each time the counter expires, you can force the new number back
' into the timer register. We need 1/.000032 or 31250 counts. However, the
' counter expires at 65536, so the correct number to preload is 65536-31250 or
' 34285 This way, the timer will count up 31250 counts (1 second) and
' expire.
Const 1000ms = 34285
Config Timer1 = Timer , Prescale = 256
On Timer1 Timer1_int
On Urxc Rec_rs232 'define serial receive ISR
' Initialize the GSM Modem
Print "AT&FE0V0+CMGF=1;+CNMI=2,1,0,0,0"
Time1_count = 0 : Timer1 = 1000ms : Time1_ok = 0
Enable Timer1
Enable Interrupts
Start Timer1
Do
If Time1_ok = 1 Then ' Timer fires every 1 sec and wraps at 10sec
Read_ok = 0 : Read_num = 0 : Data_ok = 0 : Rs232_exit = 0 : Sync_ok = 0
Stop Timer1
If Time1_count = 5 Then ' t+5
Read_select = Read_gsm_m1
Print "AT+CMGR=1" ' Read Message
Gosub Rs232_r
If Data_ok = 1 Then
Print "AT+CMGD=1" ' Delete Message
#if Dlcd
Call Lcdlocation(3 , 0)
Print #2 , "Msg: " ; S2
#endif
Gosub Read_message
Time1_count = Time1_count + 5
End If
Elseif Time1_count = 3 Then ' t+3
Read_select = Read_gsm_sta1 : Gsm_signal = ""
Print "AT+CSQ" ' Signal Quality
Gosub Rs232_r
If Read_ok = 0 Then Gsm_signal = "--" 'If Timeout waiting for Response
#if Dlcd
Call Lcdlocation(1 , 14)
Print #2 , "Signal: " ; Gsm_signal ;
#endif
End If
Reset Time1_ok
Start Timer1
End If
Loop
Timer1_int:
Timer1 = 1000ms
Set Time1_ok
Incr Time1_count
Incr Rs232_exit
If Time1_count > 9 Then Time1_count = 0 ' 10 * 1sec = 10sec
Return
Rec_rs232:
Incr Read_num
If Read_select = Read_gsm_m1 Then
'+CMGR: "REC READ","+447762722186",,"05/02/26,11:07:47+00" chr(13)chr(10)
'Hello chr(13)chr(10)
If Udr = 43 And Sync_ok = 0 Then '"+"-->43
Read_num = 1
Sync_ok = 1
S2 = ""
Elseif Sync_ok = 1 Then
Select Case Read_num
Case 5:
If Udr <> 82 Then Read_ok = 1 '"R"-->82
Case Else
If Data_ok = 1 Then
If Udr = 13 Then ' Until 1st chr(13)
Read_ok = 1
Else ' Accumulate data
S2 = S2 + Chr(udr)
End If
End If
' Read to end of first line before we are ready
If Udr = 10 Then Data_ok = 1
End Select
End If
' Signal quality check
Elseif Read_select = Read_gsm_sta1 Then
'+CSQ: 31,99
If Udr = 43 Then Read_num = 1
Select Case Read_num
Case 4:
If Udr <> 81 Then Read_ok = 1 '"Q"-->81
Case 7 To 8:
'"0..9"-->48..57
If Udr > 47 And Udr < 58 Then Gsm_signal = Gsm_signal + Chr(udr)
Case 9:
Read_ok = 1
End Select
End If
Rs232_exit = 0 'Reset RS232 timeout
Return
Rs232_r:
Udr = 0
Reset Usr.7
Reset Ucr.7
Enable Urxc 'enable receive isr
Start Timer1
Do
If Rs232_exit > 3 Then Exit Do
Loop Until Read_ok = 1
Disable Urxc
Stop Timer1
Return
'Inbound String From The Gsm Modem Will Have The Following Syntax:
' a. R - Single Relay action followed by [SRT]
' - Set / Reset / Toggle action and a number of the relay [1-4]
'
' RS2 - Set relay number 2 (ON).
' RR4 - Reset relay number 4 (OFF)
Read_message:
' Use address pointer its more efficent than this--> mid(s2,read_num,1)
S2addr = Varptr(s2)
Read_select = Control_char
For Read_num = 1 To Len(s2)
Ch = Inp(s2addr)
Incr S2addr
Select Case Read_select
Case Control_char:
Select Case Ch
' Case 83 : Read_select = Status_action '"S"-->83
Case 82 : Read_select = Single_action '"R"-->82
Case Else Read_select = Invalid_action
End Select
Case Single_action:
Select Case Ch
Case 82 : Read_select = Off_action '"RR"
Case 83 : Read_select = On_action '"RS"
Case Else Read_select = Invalid_action
End Select
Case On_action:
If Ch > 47 And Ch < 53 Then ' 1..4
Ch = Ch - 48
Reset Portb.relay(ch)
End If
Case Off_action:
If Ch > 47 And Ch < 53 Then ' 1..4
Ch = Ch - 48
Set Portb.relay(ch)
End If
End Select
Next
Return
#if Dlcd
Sub Lcdlocation(byval Row As Byte , Byval Col As Byte)
Col = Col + 32
Row = Row + 32
Print #2 , "\B" ; Chr(col) ; Chr(row);
End Sub
#endif