;**************************************************************************** ; ; MCPOCSAG v0.2.2 - Firmware for Motorola mc micro trunking radio ; for use as an Amateur-Radio transceiver ; ; Copyright (C) 2004 - 2006 Felix Erckenbrecht, DG1YFE ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ; ; ;**************************************************************************** ;***************************** ; M E N U ;***************************** ;***************************** ; I N I T _ M E N U ;***************************** menu_init pshb psha ldaa #IDLE staa m_state ; begin in IDLE state clr m_timer_en ; disable menu timer pula pulb rts ;***************************** ; M E N U ;***************************** ; ; "Menü" Subroutine ; ; Parameter : none ; ; Ergebnis : none ; ; changed Regs : none ; ; menu pshb psha pshx jsr sci_rx tsta bne m_keypressed jmp m_end m_keypressed jsr sci_tx_w ; Zeichen bestätigen LCDTIME(LCDDELAY) ; Timeout Timer reset clra addd #key_convert ; index key convert table xgdx ldab 0,x ; Key übersetzen ldaa m_state ; Status holen cmpa #IDLE ; nothing to do? beq m_idle cmpa #F_IN ; Frequenzeingabe im Gange? beq m_f_in cmpa #D_FULL ; Display voll ? beq m_d_full jmp m_end ;******************************* ; ;m_j_set_ofs ; jmp m_set_ofs ;******************************* ; M I D L E ; ; m_idle cmpb #10 ; Zahl? bcc m_idle_men1 jmp m_start_input ; Start der Eingabe m_idle_men1 cmpb #KC_D1 bne m_idle_men2 jmp m_frq_up ; Kanal+ m_idle_men2 cmpb #KC_D2 bne m_idle_men3 jmp m_frq_down ; Kanal- m_idle_men3 cmpb #KC_D3 bne m_idle_men4 jmp m_prnt_rc ; Rundenzähler ausgeben m_idle_men4 cmpb #KC_RAUTE bne m_idle_men5 jmp m_frq_store ; Frequenz im EEPROM speichern m_idle_men5 cmpb #KC_STERN bne m_idle_men6 jmp m_frq_del m_idle_men6 cmpb #KC_D7 bne m_idle_end jmp m_chg_offset m_idle_end jmp m_end ; keine Ziffer, dann nix machen ;******************************* ; M S T A R T I N P U T ; m_start_input ldx #dbuf2 jsr save_dbuf ; Displayinhalt in dbuf2 sichern jsr lcd_clr ; Display löschen m_print jsr m_reset_timer ; Menü-Timer Reset (Timeout für Eingabe setzen) ldaa #F_IN ; Frequenzeingabe beginnt staa m_state addb #$30 ; aus Taste/Nummer ASCII Char erzeugen xgdx clra ldab cpos addd #f_in_buf xgdx stab 0,x ; Zeichen in Frequenzeingabe Puffer sichern PUTCHAR jmp m_end ; Zurück ; ;********************************** ; M B A C K S P A C E ; ; eingegebenes Zeichen löschen ; m_backspace jsr m_reset_timer jsr lcd_backspace clra ldab cpos addd #f_in_buf xgdx clr 0,x ; String im Frequenzeingabe-Puffer terminieren jmp m_end ; Zurück ;********************************** ; M D F U L L ; ; Display voll, Zifferneingabe ignorieren ; m_d_full ; Display voll, Zifferneingabe ignorieren jsr m_reset_timer cmpb #10 ; keine Zahl? bcc m_non_numeric ; dann irgendwas machen jmp m_end ; ansonsten ignorieren ;********************************** ; M F I N ; ; Frequenzeingabe, Eingabe entgegennehmen ; m_f_in cmpb #10 ; Zahl? bcc m_non_numeric ; dann irgendwas machen ldaa cpos ; sonst nachsehen cmpa #08 ; ob noch Platz im Display bne m_print ; ldaa #D_FULL ; Display voll, state anpassen staa m_state jmp m_end ;********************************** ; M C L R D I S P L ; ; Display und Eingabe löschen ; m_clr_displ jsr m_reset_timer jsr lcd_clr clr f_in_buf ; Erstes Zeichen im Eingabebuffer auf 0 (Buffer "leer") jmp m_end ;********************************** ; ; M N O N N U M E R I C ; ; Nicht numerische Eingabe entgegennehmen ; m_non_numeric cmpb #KC_CLEAR ; 'C' beq m_clr_displ cmpb #KC_STERN ; '*' beq m_backspace cmpb #KC_RAUTE ; '#' beq m_set_freq jmp m_end ;******************************* ; ; M S E T F R E Q ; ; eingegebene Frequenz setzen ; m_set_freq clra ldab cpos addd #f_in_buf xgdx clr 0,x ; Eingabe mit 0 terminieren pshx ; 32 Bit Platz schaffen auf Stack pshx ; für Ergebnis der Frequenzberechnung tsx ; Zeiger auf Zwischenspeicher (Stack) nach X ldd #f_in_buf ; Zeiger auf Eingabestring holen jsr frq_calc_freq ; Frequenz berechnen tsx ; Zeiger auf Frequenz DWord nach X xgdx ; Zeiger von X nach D ldx frequency+2 ; aktuell gesetzte Frequenz holen pshx ldx frequency pshx ; und sichern xgdx ; Frequenzzeiger wieder nach X jsr set_freq ; Frequenz setzen jsr lcd_clr ; LCD löschen ldab #IDLE stab m_state ; nächster State ist wieder IDLE ldab #200 ; Universaltimer auf 200ms setzen stab gp_timer ; solange hat die PLL maximal Zeit um eizurasten m_wait_lock ldab pll_locked_flag ; Ist die PLL eingerastet? andb #$7F ; 'changed' Bit ausblenden. No Lock -> B=0 bne m_lock ; PLL ist eingerastet -> loop beenden ldab gp_timer ; gp_timer!=0 ? bne m_wait_lock ; dann loop m_no_lock PRINTF(m_no_lock_str) ; Fehlermeldung ausgeben WAIT(500) ; 500ms warten tsx ; jsr set_freq pulx pulx jsr lcd_clr bra m_frq_prnt ldx #0 stx m_timer ; Menü Timer auf 0 setzen ; Displayinhalt am Routinenende wiederherstellen bra msf_end ; zum Ende springen m_lock pulx pulx ; alte Frequenz vom Stack löschen PRINTF(m_ok) ; "OK" ausgeben - PLL ist eingerastet WAIT(200) ; 200ms warten m_frq_prnt WCPOS(0) ; Cursor auf 0 setzen ldx frequency+2 ; Frequenz Lo Word holen ldd frequency ; Frequenz Hi Word holen pshx ; Lo Word auf Stack xgdx pshx ; Hi Word auf Stack ldaa #'l' ; unsigned Longint ausgeben ldab #3 ; die letzten 3 Stellen abscheiden jsr putchar pulx pulx clr m_timer_en ; Menü Timer disabled - Aktuelles Display = neues Display pshb psha ; WLCDR($36) ; grüne LED an clr pll_timer ; PLL Timer auf 0 pula pulb msf_end pulx pulx ; eingegebene Frequenz vom Stack löschen ;*********** ; M E N D ;*********** m_end ldab m_timer_en ; timer disabled ? beq m_return ; Dann nichts tun... ldx m_timer ; menu timer holen bne m_return ; timer nicht abgelaufen, dann return clr m_timer_en ; timer disable ldx #dbuf2 jsr restore_dbuf ; Displayinhalt wiederherstellen ldab #IDLE ; Zurück zum Idle State stab m_state ; State speichern m_return pulx pula pulb rts ;******************************* ; M S H O W M E N U ; ; Konfigurationsmenü anzeigen ; m_show_menu ldx #dbuf2 jsr save_dbuf ; Displayinhalt in dbuf2 sichern jsr lcd_clr ; Display löschen jsr m_reset_timer ; Menü-Timer Reset (Timeout für Eingabe setzen) ldaa #SHOW ; Frequenzeingabe beginnt staa m_state jmp m_end ;******************************* ; M F R Q U P ; ; Frequenz einen Kanal nach oben ; m_frq_up ldab rxtx_state bne mfu_end ldx frequency+2 pshx ldx frequency pshx ldx #0 ldd #FSTEP jsr add32 tsx jsr set_freq jmp m_frq_prnt mfu_end jmp m_end ;******************************* ; M F R Q D O W N ; ; Frequenz einen Kanal nach unten ; m_frq_down ldab rxtx_state bne mfd_end ldx #FSTEP pshx ldx #0 pshx ldd frequency+2 ldx frequency jsr sub32 tsx jsr set_freq jmp m_frq_prnt mfd_end jmp m_end ;************************************** ; m_prnt_rc ldab m_timer_en bne mpr_nosave ldx #dbuf2 jsr save_dbuf ; Displayinhalt in dbuf2 sichern mpr_nosave jsr lcd_clr ; Display löschen jsr m_reset_timer ; Menü-Timer Reset (Timeout für Eingabe setzen) ldx rc_last_sec clrb pshx pshb pshb ldaa #'l' jsr putchar pulx pulx jmp m_end ;************************************** ; m_frq_store ldab m_timer_en bne mfs_nosave ldx #dbuf2 jsr save_dbuf ; Displayinhalt in dbuf2 sichern mfs_nosave jsr lcd_clr ; Display löschen PRINTF(m_writing) WAIT(200) ldx offset+2 pshx ldx offset pshx ldx frequency+2 pshx ldx frequency pshx clra clrb jsr eep_write tsta ins beq mfs_w1 jmp mfs_fail1 mfs_w1 clra ldab #1 jsr eep_write tsta ins beq mfs_w2 jmp mfs_fail2 mfs_w2 clra ldab #2 jsr eep_write tsta ins bne mfs_fail3 clra ldab #3 jsr eep_write tsta ins bne mfs_fail4 clra ldab #4 jsr eep_write tsta ins bne mfs_fail5 clra ldab #5 jsr eep_write tsta ins bne mfs_fail6 clra ldab #6 jsr eep_write tsta ins bne mfs_fail7 clra ldab #7 jsr eep_write tsta ins bne mfs_fail8 ldx crc_init pshx ldx #frequency ldd #8 jsr crc16 clra ldab #8 jsr eep_write tsta ins bne mfs_fail9 clra ldab #9 jsr eep_write tsta ins bne mfs_fail10 jsr lcd_clr ; Display löschen PRINTF(m_stored) WAIT(1000) ldx #dbuf2 jsr restore_dbuf ; Displayinhalt wiederherstellen jmp m_end ; Frequenz im EEPROM speichern mfs_fail1 ins mfs_fail2 ins mfs_fail3 ins mfs_fail4 ins mfs_fail5 ins mfs_fail6 ins mfs_fail7 ins mfs_fail8 ins mfs_fail9 ins mfs_fail10 jsr lcd_clr PRINTF(m_failed) WAIT(1000) ldx #dbuf2 jsr restore_dbuf ; Displayinhalt wiederherstellen jmp m_end ;************************************** ; m_frq_del ldx #dbuf2 jsr save_dbuf ; Displayinhalt in dbuf2 sichern jsr lcd_clr ; Display löschen PRINTF(m_delete) WAIT(200) clra clrb jsr eep_rand_read tsta bne mfd_fail ; Byte 0 lesen comb ; invertieren pshb clra clrb jsr eep_write ; und schreiben tsta ins bne mfd_fail ; jetzt passt die CRC nicht mehr, Frequenz wird aus RoM initialisiert jsr lcd_clr ; Display löschen PRINTF(m_ok) WAIT(1000) ldx #dbuf2 jsr restore_dbuf ; Displayinhalt wiederherstellen jmp m_end ; Frequenz im EEPROM speichern mfd_fail jsr lcd_clr PRINTF(m_failed) WAIT(1000) ldx #dbuf2 jsr restore_dbuf ; Displayinhalt wiederherstellen jmp m_end ;************************************** ; m_chg_offset ldx #dbuf2 jsr save_dbuf ; Displayinhalt in dbuf2 sichern jsr lcd_clr ; Display löschen PRINTF(m_offset) WAIT(500) ldd offset xgdx cpx #FOFF2>>16 beq mco_to_zero cpx #FOFF>>16 beq mco_to_ofs2 ldx #FOFF%65536 stx offset+2 pshx ldx #FOFF>>16 stx offset pshx jsr lcd_clr ; Display löschen ldaa #'l' clrb jsr putchar ; Offset ausgeben pulx pulx WLCDR($66) WLCDR($6E) ; Pfeil als Zeichen für "Ablage aktiviert" bra mco_end mco_to_zero ldx #0 stx offset+2 pshx stx offset pshx jsr lcd_clr ; Display löschen ldaa #'l' clrb jsr putchar ; Offset ausgeben pulx pulx WLCDR($66) WLCDR($6D) ; Pfeil löschen ; Cursor muss nicht zurückgesetzt weden, da Display eh gleich gelöscht wird bra mco_end mco_to_ofs2 ldx #FOFF2%65536 stx offset+2 pshx ldx #FOFF2>>16 stx offset pshx jsr lcd_clr ; Display löschen ldaa #'l' clrb jsr putchar ; Offset ausgeben pulx pulx WLCDR($66) WLCDR($6F) ; Pfeil/blinken als Zeichen für "Ablage aktiviert" mco_end WAIT(1000) ldx #dbuf2 jsr restore_dbuf jmp m_end ;************************************** ; m_reset_timer ; Eingabe Timeout zurücksetzen pshx pshb ldx #MENUTIMEOUT ; Eingabe Timeout im 100ms stx m_timer ldab #1 stab m_timer_en ; timer aktivieren pulb pulx rts ; ;************************************** ; m_ok .db "OK",0 m_no_lock_str .db "NO LOCK ",0 m_out_str .db "out of",0 m_range_str .db "Range ",0 m_writing .db "writing",0 m_stored .db "stored",0 m_failed .db "failed",0 m_delete .db "deleting",0 m_offset .db "ABLAGE",0