;---------------------------------------- ; ATS 3B Firmware ; ; version m8 ;---------------------------------------- ; ; Radio hardware design and initial software design by Steven Weber KD1JV ; Changes and modifications to software by Michael Harnage W1MT ; ; Copyright (c) 2005,2006,2007,2008 Steven Weber KD1JV and Michael Harnage W1MT ; ; Permission is hereby granted, free of charge, to any person obtaining ; a copy of this software and associated documentation files (the ; "Software"), to deal in the Software without restriction, including ; without limitation the rights to use, copy, modify, merge, publish, ; distribute, sublicense, and/or sell copies of the Software, and to ; permit persons to whom the Software is furnished to do so, subject to ; the following conditions: ; ; The above copyright notice and this permission notice shall be included ; in all copies or substantial portions of the Software. ; ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; ; ;---------------------------------------- #include "msp430x12x2.h" ; ; This code supports the ATS3B only ; ; Change the SIDETONE_DELAY will affect the sidetone ; ; 27 -> 606Hz default ATS3B ; 28 -> 585Hz default ATS2,3,3A ; 33 -> 496Hz close enuf to 500Hz ; 37 -> 442Hz for the musician's ; 41 -> 400Hz lowest we dare go ; ; Probably don't want to modify this unless you have modified ; the hardware audio chain to handle non 600Hz sidetones. #define SIDETONE_DELAY 27 ; Other misc defines ; Code compile switches #define MULTI_MUTE 1 ; Constants #define MILLISEC_DELAY 33 #define INTERMENU_DELAY 480 #define SCAN_DELAY 120 #define NUM_KEYER_BYTES 126 #define DIT_WAIT 4 ; ; The following are options that may or may not work ; They are left for others who may want their functionality ; ;#define ANYBUTTON ;#define PAUSE ORG 00200h flags: DS 4 ; general flag bits fbin: DS 4 ; Tx DDS phase word, low ; Tx DDS phase word, high fbin_other: DS 4 ; other phase words, for split mode / 2 words fbcd: DS 4 ; BCD freq lsw ; BCD freq msw 7.040.000 would be "0704 0000" fbcd_other: DS 4 ; the other vfo, double word fbc: DS 4 ; Tx freq in binary, low byte, output of bcd2bin routine ; Tx freq in binary, high byte, output of bcd2bin routine bandstep_ptr: ; pointer to current bandstep lut entry DS 2 bandstep_up: DS 4 ; and step can be 10,50, [or 1000000] Hz / 2 words ; initialized to 50Hz bandstep_dn: DS 4 ; band step can be 10,50, [or 1000000] Hz / 2 words ; initialized to -50Hz scan_a: DS 4 ; start of scanning, lsb ; msb scan_b: DS 4 ; end of scanning, lsb ; msb ; ; The following need to stay in the same order :) ; Especially important that fref be first, as these ; get stored to flash in this exact order! ; fref: DS 4 ; DDS reference freq in binary ; DDS reference freq in binary ofst: DS 4 ; IF offset freq, DDS phase word, low ; IF offset freq, DDS phase word, high bflag: DS 2 ; second flag bit register command_speed: DS 2 ; command output speed word keyer_speed: DS 2 ; keyer speed word ENDOFVARRAM: ORG 00240h rammem: ORG rammem + NUM_KEYER_BYTES ramend: ; keyer memory stop, will allow NUM_KEYER_BYTES chars (including ; markers and end of strings) ; Don't want to get too close to 0300h as that is where ; the stack starts. Since one block of flash it 128 and I want ; keep the last two bytes 0ffffh this works out nicely. #define PI_DAH 01h,&P2IN #define PI_DIT 02h,&P2IN #define PI_TUNEUP 04h,&P2IN ; 08h,&P2IN ; check the input voltage #define PI_SPLIT 01h,&P1IN #define PO_SIDETONE 020h,&P2OUT #define PI_MENU 02h,&P1IN #define PI_TUNEDN 04h,&P1IN #define PO_TRANSMIT 08h,&P1OUT #define PO_SDATA 010h,&P1OUT #define PO_SCLK 020h,&P1OUT #define PO_FSYNC 040h,&P1OUT #define PO_MUTE 080h,&P1OUT ;led SEGMENTS ; ;P3.0 = b 1 ;P3.1 = a 6 0 ;P3.2 = c 7 ;P3.3 = DP 4 2 ;P3.4 = e 5 3 ;P3.5 = d ;P3.6 = f ;P3.7 = g #define LED_e (BIT1+BIT0+BIT6+BIT7+BIT4+BIT5) #define LED_L (BIT6+BIT4+BIT5) #define LED_h (BIT6+BIT4+BIT7+BIT2) #define LED_I (BIT0+BIT2) #define LED_EQUAL (BIT7+BIT5) #define LED_r (BIT4+BIT7) #define LED_T (BIT6+BIT4+BIT7) #define LED_Y (BIT6+BIT7+BIT0+BIT2+BIT5) #define LED_M (BIT4+BIT2+BIT7) #define LED_o (BIT4+BIT5+BIT2+BIT7) #define LED_V (BIT4+BIT5+BIT2) #define LED_d (BIT0+BIT2+BIT7+BIT4+BIT5) #define LED_S (BIT1+BIT6+BIT7+BIT2+BIT5) #define LED_n (BIT4+BIT7+BIT2) #define LED_O (BIT1+BIT6+BIT4+BIT5+BIT2+BIT0) #define LED_P (BIT4+BIT6+BIT1+BIT0+BIT7) #define LED_F (BIT1+BIT6+BIT7+BIT4) #define LED_t (BIT6+BIT7+BIT4) #define LED_E (BIT1+BIT7+BIT5+BIT6+BIT4) #define LED_C (BIT1+BIT6+BIT4+BIT5) #define LED_a (BIT1+BIT0+BIT7+BIT2+BIT4+BIT5) #define LED_A (BIT4+BIT6+BIT1+BIT0+BIT2+BIT7) #define LED_b (BIT6+BIT7+BIT4+BIT2+BIT5) #define LED_QUESTION (BIT1+BIT0+BIT7+BIT4) #define LED_BLANK 0xf7 #define LED_ALLBLANK 0xff #define LED_DP (BIT3) #define LED_0 (BIT1+BIT6+BIT4+BIT5+BIT2+BIT0) #define LED_1 (BIT0+BIT2) #define LED_2 (BIT1+BIT0+BIT7+BIT4+BIT5) #define LED_3 (BIT1+BIT0+BIT7+BIT2+BIT5) #define LED_4 (BIT6+BIT7+BIT0+BIT2) #define LED_5 (BIT1+BIT6+BIT7+BIT2+BIT5) #define LED_6 (BIT1+BIT6+BIT4+BIT5+BIT2+BIT7) #define LED_7 (BIT1+BIT0+BIT2) #define LED_8 (BIT1+BIT6+BIT4+BIT5+BIT2+BIT7+BIT0) #define LED_9 (BIT1+BIT6+BIT7+BIT0+BIT2) ; ; Setup the flags symbols ; ; flags+0 #define F0_SIDETONE BIT0 #define F0_DAH_LATCH BIT1 #define F0_DIT_LATCH BIT2 #define F0_SCANMODE BIT3 ; flags+1 #define F1_STRAIGHTKEY BIT0 #define F1_VFO BIT1 #define F1_SPLIT BIT2 ;;;#define F1_ADCINT BIT3 ; flags+2 #ifdef MULTI_MUTE #define F2_AFA BIT0 #endif #define F2_ENTERFREQ BIT1 #define F2_MEMSTORE BIT2 #define F2_LAST_DIT BIT3 ; flags+3 #define F3_MEMPLAY BIT0 #define F3_BEACON BIT1 #define F3_SCANLED BIT2 #define F3_80M BIT3 ; bflags #define BF_IAM_MODE_B BIT0 #define BF_MHZ BIT1 #define BF_STEALTH BIT2 #define BF_NOLED BIT3 ; ; Set up interrupt vectors ; ORG 0FFFEh DW reset ; 0xFFF0 Timer A CC1-2, TA ORG 0fff0h DW timer ; 0xFFF2 Timer A CC0 ORG 0fff2h DW millisecond_isr ORG 0FFEAh DW ADC10 ORG 0FFE4h DW PORT1 ORG 0FFE6h DW PORT2 ;---------------------------------------- ; ; ; The clock ticks 32768 times a second. ; ;---------------------------------------- ORG 0E000h ; 8k boundary millisecond_isr: ; Start of handler Interrupt for TACCR0 CCIFG add #MILLISEC_DELAY,&TACCR0 inc r6 reti timer: add &TAIV,PC ; add offset to Jump table reti ; Vector 0: no interrupt jmp ccifg_1_hnd ; Vector 2: TACCR1 jmp ccifg_2_hnd ; Vector 4: TACCR2 reti ; Vector 6: reserved reti ; Vector 8: reserved taifg: reti ; Vector 10: TAIFG ;---------------------------------------- ; sidetone timer isr ;---------------------------------------- ccifg_1_hnd: add #SIDETONE_DELAY,&TACCR1 ; SIDETONE_DELAY clock cycles for timer bit.b #F0_SIDETONE,&flags ; sidetone jnc nost xor.b #PO_SIDETONE ; sidetone reti nost: bic.b #PO_SIDETONE ; sidetone reti ;---------------------------------------- ; keyer timer isr ;---------------------------------------- ccifg_2_hnd: add @r4,&TACCR2 inc r5 reti ;---------------------------------------- ; ADC isr ;---------------------------------------- ADC10: bic.w #LPM3,0(SP) reti ;---------------------------------------- ; Port 1 isr ;---------------------------------------- PORT1: bic.w #LPM3,0(SP) ; mov.b &P1IN,&P1IES ; edge select bic.b #007h,&P1IFG reti ;---------------------------------------- ; PORT 2 isr ;---------------------------------------- PORT2: bic.w #LPM3,0(SP) ; mov.b &P2IN,&P2IES ; edge select bic.b #007h,&P2IFG reti ;---------------------------------------- ; main entry point - configure mpu ;---------------------------------------- reset: mov #0300h,SP ; initialize stack pointer mov #WDTPW+WDTHOLD,&WDTCTL ; stop watchdog timer mov.b #0f8h,&P1DIR ; mov.b &P1IN,&P1IES ; edge select bis.b #007h,&P1IES ; edge select bic.b #007h,&P1IFG bis.b #007h,&P1IE ;;; mov.b #0e0h,&P1OUT mov.b #PO_FSYNC ; set PO_FSYNC mov.b #020h,&P2DIR ; mov.b &P2IN,&P2IES ; edge select bis.b #007h,&P2IES ; edge select bic.b #007h,&P2IFG bis.b #007h,&P2IE ;;; clr.b &P2OUT mov.b #0ffh,&P3DIR mov.b #LED_ALLBLANK,&P3OUT bis.b #DCO0+DCO1+DCO2,&DCOCTL ; DCO0+DCO1+DCO2 bis.b #RSEL0+RSEL1+RSEL2,&BCSCTL1 ; RSEL0+RSEL1+RSEL2 , set max DCO freq mov #TASSEL_1+MC_2,&TACTL ; TASSEL_1+MC_2 [aclk and continous up] mov #OUTMOD_4+CCIE,&TACCTL0 ; OUTMOD_4+CCIE [toggle and compare/capture int enable] mov #OUTMOD_4+CCIE,&TACCTL1 ; OUTMOD_4+CCIE mov #OUTMOD_4+CCIE,&TACCTL2 ; OUTMOD_4+CCIE mov #MILLISEC_DELAY,&TACCR0 ; just to start it mov #SIDETONE_DELAY,&TACCR1 ; just to start it mov #default_speed,r4 mov &default_speed,&TACCR2 ; just to start it bic.b #PO_SIDETONE ; clr PO_SIDETONE mov.b #(BIT4+BIT3),&ADC10AE ; enable A3 and A4 mov #(SREF0+ADC10SHT1+ADC10SHT0+ADC10SR+REF2_5V+REFON+ADC10ON+ADC10IE),&ADC10CTL0 ; init adc eint cmp &flash_fref,&fref jne continue_boot cmp #014fh,&ofst+2 jne continue_boot ; ; Reset has occurred, presume to be caused by over current during transmit ; bis.b #LED_BLANK,&P3OUT bic.b #LED_E,&P3OUT ovload: bit.b #PI_MENU ;;; make this a sleep vice poll jc ovload ; bis.w #LPM3,SR bis.b #LED_BLANK,&P3OUT ov_1: bit.b #PI_MENU jnc ov_1 mov #02100h,r15 call #out16 ; open dds serial line call #bcd2bin ; calc bin for phase accumulator of dds call #offset ; send lo freq to dds, lo= f(rx,if) mov #02000h,r15 call #out16 jmp wait continue_boot: mov #band_step_lut_5,r15 mov #band_step_lut_5,&bandstep_ptr mov @r15+,&bandstep_up mov @r15+,&bandstep_dn mov @r15+,&bandstep_up+2 mov @r15+,&bandstep_dn+2 rstent: mov #02100h,r15 call #out16 ; open dds serial line clr.b &flags ; clear byte 0 of flags bic.b #(~F1_STRAIGHTKEY),&flags+1 clr &flags+2 ; clr bytes 2 and 3 of flags call #clr_r6 rstdly: cmp #500,r6 jlo rstdly ; wait a little ;---------------------------------------- ; get user options ;---------------------------------------- rst6: mov #flash_fref, r13 mov #fref,r14 get_loop: mov @r13+,0(r14) incd r14 cmp #ENDOFVARRAM,r14 jne get_loop bic.b #-1-BF_IAM_MODE_B,&bflag ; ignore all but the iambic bit #ifdef MULTI_MUTE bis.b #F2_AFA,&flags+2 ; enable sidetone for morse bic.b #PO_MUTE ; P1.7 Mute on #endif ;---------------------------------------- ; test for calibrate mode ;---------------------------------------- call #clr_r6 rst0: cmp #300,r6 jlo rst0 bit.b #005h,&P1IN ; ck for Split and Tune Dn jnz rst2 br #calref ;---------------------------------------- ; test for straight key mode ;---------------------------------------- rst2: bic.b #F1_STRAIGHTKEY,&flags+1 bit.b #PI_DAH ; check for Dah jc rst3 bis.b #F1_STRAIGHTKEY,&flags+1 ; set straight key flag rst3: bit.b #PI_MENU ; check for Menu jc rst4 mov #0x1100+LED_V,r14 ; 'v' call #mrsout mov #0x0700+LED_M,r14 ; 'm' call #mrsout mov #0x3c00+LED_7,r14 ; '8' call #mrsout rst4: mov #(INCH2+ADC10DIV0+ADC10SSEL0),&ADC10CTL1 ; int adc bis #(ENC+ADC10SC),&ADC10CTL0 ; start adc bis.w #LPM3, SR ; sleep till adc done bic #(ENC+ADC10ON),&ADC10CTL0 ; turn off enable conv and adc core mov &ADC10MEM,r10 cmp #0300h,r10 ; compare ADC result to find band jge bint80 cmp #0200h,r10 jge bint40 cmp #0100h,r10 jge bint30 cmp #0060h,r10 jge bint20 cmp #015h,r10 jge bint17 ; jmp bint15 ; fall thru bint15: mov #BAND_15,r13 jmp bntst4 bint17: mov #BAND_17,r13 jmp bntst4 bint20: mov #BAND_20,r13 jmp bntst4 bint30: mov #BAND_30,r13 jmp bntst4 bint40: mov #BAND_40,r13 jmp bntst4 bint80: mov #BAND_80,r13 bis.b #F3_80M,&flags+3 ; 80m flag bntst4: mov @r13+,&fbcd+2 ; load from BAND_ lut mov @r13+,&fbcd mov @r13+,r14 call #mrsout ; send '4'|'3'|'2'|'8'|'7'|'5' depending on band mov @r13+,&scan_a+2 mov #00000h,&scan_a mov @r13+,&scan_b+2 mov #00000h,&scan_b bic.b #F1_VFO,&flags+1 ; vfo flag, set to A mov &fbcd,&fbcd_other ; save freq in other vfo mov &fbcd+2,&fbcd_other+2 ; high word call #calc_new_freq mov &fbin,&fbin_other ; init the other fbin mov &fbin+2,&fbin_other+2 ; high word mov #02000h,r15 call #out16 ; close dds serial line #ifdef MULTI_MUTE bic.b #F2_AFA,&flags+2 bis.b #PO_MUTE ; P1.7 Mute off #endif jmp wait ; ; band data ; BAND_160: ;;; DW 00181h ;;; DW 00000h ;;; DW 02f30h ;;; DW 00180h ;;; DW 00182h BAND_80: DW 00356h DW 00000h DW 03c00h+LED_8 DW 00355h DW 00357h BAND_40: DW 00704h DW 00000h DW 02100h+LED_4 DW 00703h DW 00705h BAND_30: DW 01011h DW 00000h DW 02300h+LED_3 DW 01010h DW 01012h BAND_20: DW 01406h DW 00000h DW 02700h+LED_2 DW 01405h DW 01407h BAND_17: DW 01807h DW 00000h DW 03800h+LED_7 DW 01807h DW 01816h BAND_15: DW 02106h DW 00000h DW 02000h+LED_5 DW 02105h DW 02107h BAND_12: ;;; DW 02490h ;;; DW 00000h ;;; DW 02f00h+LED_xx ;;; DW 02489h ;;; DW 02491h BAND_10: ;;; DW 02806h ;;; DW 00000h ;;; DW 02f00h+LED_xx ;;; DW 02805h ;;; DW 02807h ;---------------------------------------- ; main loop - input polling ;---------------------------------------- waitr: mov #0x0a00+LED_r,r14 ; 'r' call #mrsout waitmenu_loop: bit.b #PI_MENU jnc waitmenu_loop waitsplit_loop: bit.b #PI_SPLIT jnc waitsplit_loop wait: bis.w #LPM3, SR ; sleep bic.b #F0_SCANMODE,&flags ; clr scan mode bit.b #F1_STRAIGHTKEY,&flags+1 ; straight key flag jnc wait3 call #isDit jc wait4 br #strkey wait3: call #isDit jc wait3a br #padin_dit wait3a: call #isDah jc wait4 br #padin_dah wait4: bit.b #PI_SPLIT ; P2.3 Split/Rit jnc split bit.b #PI_MENU ; P1.1 Menu jnc fun bit.b #BF_STEALTH,&bflag jc wait bit.b #PI_TUNEUP ; P2.2 Tune Up jnc tnup bit.b #PI_TUNEDN ; P1.2 Tune Down jnc tndn jmp wait ;---------------------------------------- ; Synchronize the beginning of timer(s) ;---------------------------------------- clr_r5: mov #TASSEL_1+MC_0+ID_0,&TACTL ; ACLK+MODE0 (stopped) mov &TAR,&TACCR2 mov #TASSEL_1+MC_2+ID_0,&TACTL ; ACLK+MODE2 (start continous up) add @r4,&TACCR2 clr r5 ret clr_r6: mov #TASSEL_1+MC_0+ID_0,&TACTL ; ACLK+MODE0 (stopped) mov &TAR,&TACCR0 mov #TASSEL_1+MC_2+ID_0,&TACTL ; ACLK+MODE2 (start continous up) add #MILLISEC_DELAY,&TACCR0 clr r6 ret ;---------------------------------------- ; Calculate new frequency routine(s) ;---------------------------------------- calc_new_freq_spl: push r15 ; if not scan mode the skip the flashies bit.b #F0_SCANMODE,&flags jnc calc_new_freq_spl_c calc_new_freq_spl_a: ; if noled mode then skip the flashies bit.b #BF_NOLED,&bflag jc calc_new_freq_spl_c bis.b #LED_BLANK,&P3OUT bit.b #F3_SCANLED,&flags+3 jc calc_new_freq_spl_b bis.b #F3_SCANLED,&flags+3 bic.b #(BIT6+BIT2),&P3OUT jmp calc_new_freq_spl_d calc_new_freq_spl_b: bic.b #F3_SCANLED,&flags+3 bic.b #(BIT4+BIT0),&P3OUT jmp calc_new_freq_spl_d ; skip the beep, since scanmode calc_new_freq_spl_c: call #kilo_beep calc_new_freq_spl_d: call #calc_new_freq pop r15 ret calc_new_freq: call #bcd2bin ; calc bin for phase accumulator of dds call #offset ; send lo freq to dds, lo= f(rx,if) ret ;---------------------------------------- ; scan mode start ;---------------------------------------- scan_mode_start_scanning: bis.b #F0_SCANMODE,&flags mov #0800h+LED_S,r14 ; 's' call #mrsout jmp tnup ;---------------------------------------- ; tune up ;---------------------------------------- tnup: ; short wait call #clr_r6 tnup_short_wait: cmp #100,r6 jlo tnup_short_wait ; if tndn ; enter scan mode bit.b #PI_TUNEDN ; P1.2 Tune Down jnc scan_mode_start_scanning ; fi mov #SCAN_DELAY*4,r15 tnok: clrc dadd &bandstep_up,&fbcd ; add bandstep dadd &bandstep_up+2,&fbcd+2 tu1: call #calc_new_freq_spl call #clr_r6 tu_lp2: bit.b #F0_SCANMODE,&flags ; scan flag jnc tnup_noscan_continue tnup_scan: bit.b #PI_MENU ; P1.1 Menu jnc waitr ; check for upper scan limit cmp &fbcd+2,&scan_b+2 ; ck highest bytes jlo reset_scan jnz tnup_scan_continue cmp &fbcd,&scan_b ; ck lower bytes jlo reset_scan jmp tnup_scan_continue reset_scan: mov &scan_a,&fbcd mov &scan_a+2,&fbcd+2 mov #00800h+LED_S,r14 ; 's' call #mrsout call #calc_new_freq_spl jmp tnup_scan_continue tnup_noscan_continue: bit.b #PI_TUNEUP ; P2.2 Tune Up jc wait tnup_scan_continue: cmp r15,r6 jlo tu_lp2 mov #SCAN_DELAY,r15 jmp tnok ;---------------------------------------- ; tune down ;---------------------------------------- tndn: ; short wait call #clr_r6 tndn_short_wait: cmp #100,r6 jlo tndn_short_wait ; if tnup ; enter scan mode bit.b #PI_TUNEUP ; P2.2 Tune Up jnc scan_mode_start_scanning ; fi mov #SCAN_DELAY*4,r15 tdok: setc dadd &bandstep_dn,&fbcd ; subtract bandstep dadd &bandstep_dn+2,&fbcd+2 td1: call #calc_new_freq_spl call #clr_r6 td_lp2: bit.b #PI_TUNEDN ; P1.2 Tune Down jc wait cmp r15,r6 jlo td_lp2 mov #SCAN_DELAY,r15 jmp tdok ;---------------------------------------- ; Kilohertz boundary beep routine ; add a beep if 1000Hz boundary hit ;---------------------------------------- kilo_beep: mov &fbcd,r14 and #00fffh,r14 jnz kilo_beep_ex mov #00200h+LED_e,r14 ; 'e' call #mrsout kilo_beep_ex: ret ;---------------------------------------- ; Split/rit menu options ;---------------------------------------- split: call #clr_r6 split_4: bit.b #PI_SPLIT ; Split button jc keyer_memory cmp #INTERMENU_DELAY,r6 jlo split_4 split_rtn: mov #vfo_options, r8 jmp fun_parser ;---------------------------------------- ; switch vfo routine ;---------------------------------------- switch_vfo_mode: xor.b #F1_SPLIT,&flags+1 ; switch mov #00600h+LED_n,r14 ; load "n" bis.b #LED_DP,&P3OUT bit.b #F1_SPLIT,&flags+1 ; what are we really? jnc split_vfo_mode_announce mov #00800h+LED_S,r14 ; load "s" bic.b #LED_DP,&P3OUT split_vfo_mode_announce: call #mrsout call #offset jmp wait keyer_memory: br #kmemout ; goto memory play function ;---------------------------------------- ; switch vfo's ;---------------------------------------- switch_vfo: ; switch VFO's here mov &fbin,&fbin_other ; save current fbin to fbin_other mov &fbin+2,&fbin_other+2 mov &fbcd,r14 ; switch them mov &fbcd_other,&fbcd mov r14,&fbcd_other mov &fbcd+2,r14 mov &fbcd_other+2,&fbcd+2 mov r14,&fbcd_other+2 xor.b #F1_VFO,&flags+1 ; switch mov #00500h+LED_a,r14 ; load "a" bit.b #F1_VFO,&flags+1 ; test vfo flag a=0 b=1 jnc switch_vfo_a mov #01800h+LED_b,r14 ; load "b" switch_vfo_a: call #mrsout call #calc_new_freq jmp wait ;---------------------------------------- ; Synchronize vfo's - make the other vfo ; the same as the current vfo ;---------------------------------------- synchronize_vfos: mov &fbin,&fbin_other ; save current fbin to fbin_other mov &fbin+2,&fbin_other+2 mov &fbcd,&fbcd_other mov &fbcd+2,&fbcd_other+2 jmp waitr ; could be waitr vice wait if want confirmation ;---------------------------------------- ; menu options ;---------------------------------------- menu_options: ; menu button options DW 00000h ; letter to announce (this one silent) DW mfrqout ; jmp DW 00800h+LED_S ; 's' DW spd_keyer ;;; DW 00201h+LED_e ; 'e' not for SK ;;; DW enfreq ;;; DW 00301h+LED_T ; 't' not for SK ;;; DW tune DW 08700h+LED_M ; 'm' not for SK DW kmemint ;;; DW 01a00h+LED_C ; 'c' ;;; DW spd_command DW 01600h+LED_P ; 'p' DW setup DW 0ffffh ; no more vfo_options: ; vfo button options DW 00000h ; letter to announce, this one silent DW switch_vfo ; jmp ; DW 01b00h ; 'y' DW 03100h+LED_EQUAL ; '=' DW synchronize_vfos DW 00f00h+LED_o ; 'o' for vfo mode DW switch_vfo_mode ;;; DW 08a00h+LED_C ; 'sc' for scan ;;; DW 01400h+LED_F ; 'f' for scan ;;; DW scan_mode ;;; DW 04000h+LED_S ; 'ss' ;;; DW band_step DW 0ffffh ; no more menu_options_end: ;---------------------------------------- ; menu or split button option parser ;---------------------------------------- fun: call #clr_r6 fun_loopA: bit.b #PI_SPLIT jnc enfreq ; dfe bit.b #PI_TUNEDN jnc tune ; tune bit.b #PI_TUNEUP jnc batV ; battery voltage fun_quick: cmp #333,r6 jne fun_loopA mov #menu_options, r8 fun_parser: cmp.b #0ffh,0(r8) ; at end of menu marker? jeq mdexit ; yes, exit cmp #0,0(r8) ; no, silent announce? jeq fun_skip ; yes, skip announcing bit #BITF,0(r8) ; no, skip if in straight key mode? jnc fun_continue ; no bit.b #F1_STRAIGHTKEY,&flags+1 ; yes, check for straight key flag jnc fun_continue ; if no sk flag continue add #4,r8 ; otherwise sk flag is true so skip this option jmp fun_parser fun_continue: mov @r8,r14 ; announce the option bic #BITF,r14 call #mrsout fun_skip: incd r8 ; get to the jump label part of this option call #clr_r6 fun_loop: bit.b #PI_MENU ; Yes, I know....both menu and split buttons are jnc fun_skip1 ; here so that this works for either button bit.b #PI_SPLIT ; It can make for some interesting button pressing.... jnc fun_skip1 br @r8 ; do this menu option fun_skip1: cmp #INTERMENU_DELAY,r6 ; wait a little (2/3 second) jlo fun_loop incd r8 jmp fun_parser ; continue to next option mdexit: mov #01900h+(0),r14 ; no led call #mrsout jmp waitmenu_loop ;---------------------------------------- ; setup ;---------------------------------------- setup: setup1: #ifdef MULTI_MUTE bic.b #PO_MUTE ; P1.7 Mute on #endif bit.b #PI_TUNEUP ; P2.2 Tune Up jnc imode ; iambic mode setup bit.b #PI_TUNEDN jnc annunciate_speed bit.b #PI_SPLIT jnc led_mode bit.b #PI_MENU ; P1.1 Menu jnc setup2a ; jmp setup1 setup2a: mov #02700h+LED_2,r14 ; load "2" call #mrsout setup2: #ifdef MULTI_MUTE bic.b #PO_MUTE ; P1.7 Mute on #endif bit.b #PI_TUNEUP ; P2.2 Tune Up jnc scan_get ; bit.b #PI_TUNEDN jnc scan_set bit.b #PI_SPLIT jnc band_step_mode bit.b #PI_MENU ; P1.1 Menu jc setup2 str_su: call #wrsup ; save prefs in flash jmp waitr scan_get: ; scan -> vfo mov &scan_a,&fbcd mov &scan_a+2,&fbcd+2 mov &scan_b,&fbcd_other mov &scan_b+2,&fbcd_other+2 mov #00a00h+LED_r,r14 ; load "r" call #mrsout jmp setup2 scan_set: ; vfo -> scan mov &fbcd,&scan_a mov &fbcd+2,&scan_a+2 mov &fbcd_other,&scan_b mov &fbcd_other+2,&scan_b+2 mov #00800h+LED_S,r14 ; load "S" call #mrsout jmp setup2 band_step_mode: mov &bandstep_ptr,r15 cmp #band_step_lut_M,r15 jlo band_step_mode_A mov #(band_step_lut_1+band_step_lut_1-band_step_lut_5),r15 band_step_mode_A: add #(band_step_lut_5-band_step_lut_1),r15 mov r15,&bandstep_ptr mov @r15+,&bandstep_up mov @r15+,&bandstep_dn mov @r15+,&bandstep_up+2 mov @r15+,&bandstep_dn+2 mov @r15,r14 call #mrsout jmp setup2 annunciate_speed: mov &keyer_speed,&command_speed mov #01a00h+LED_C,r14 ; load "C" call #mrsout jmp setup1 led_mode: xor.b #BF_NOLED,&bflag ; switch NOLED flag mode mov #00700h+LED_M,r14 ; load "M" bit.b #BF_NOLED,&bflag ; test NOLED flag mode jc led_mode_ex mov #01400h+LED_L,r14 ; load "L" led_mode_ex: call #mrsout jmp setup imode: xor.b #BF_IAM_MODE_B,&bflag ; switch iambic mode mov #00500h+LED_a,r14 ; load "a" bit.b #BF_IAM_MODE_B,&bflag ; test iambic mode jnc imode_ex mov #01800h+LED_b,r14 ; load "b" imode_ex: call #mrsout jmp setup ;---------------------------------------- ; Band Step lookup table ;---------------------------------------- band_step_lut_1: ; 10Hz DW 00010h DW 09989h DW 00000h DW 09999h DW 02f00h+LED_1 band_step_lut_5: ; 50Hz DW 00050h DW 09949h DW 00000h DW 09999h DW 02000h+LED_5 band_step_lut_h: ; 100Hz DW 00100h DW 09899h DW 00000h DW 09999h DW 01000h+LED_h band_step_lut_M: ; 1MHz DW 00000h DW 09999h DW 00100h DW 09899h DW 00700h+LED_M ;---------------------------------------- ; Enter frequency mode ;---------------------------------------- enfreq: mov #01200h+LED_F,r14 ; load "F" call #mrsout #ifdef MULTI_MUTE bic.b #PO_MUTE ; P1.7 Mute on bis.b #F2_AFA,&flags+2 ; enable sidetone for morse #endif bis.b #F2_ENTERFREQ,&flags+2 ; enter freq flag clr r8 br #few1 ;---------------------------------------- ; Enter keyer memory ;---------------------------------------- kmemint: #ifdef MULTI_MUTE bic.b #PO_MUTE ; P1.7 Mute on bis.b #F2_AFA,&flags+2 ; enable sidetone for morse #endif mov #rammem,r8 bis.b #F2_MEMSTORE+F2_ENTERFREQ,&flags+2 ; memory and enter freq flag jmp kmlp2 ;********************************* ;measure battery voltage ;********************************* batV: bic.b #PO_MUTE ;mute receiver bis #(ADC10ON),&ADC10CTL0 bic #INCH2,&ADC10CTL1 ; !A4 or P2.4 bis #(INCH0+INCH1),&ADC10CTL1 ; A3 or P2.3 mov #01800h+LED_b,r14 ; send "B" call #mrsout bis #(ENC+ADC10SC),&ADC10CTL0 bis.w #LPM3, SR mov &ADC10MEM,r10 bic #(ENC+ADC10ON),&ADC10CTL0 ;turn off enable conv and adc core mov #00036h,r9 ; compensate for diode drop ; mov #340,r10 ; for testing should read out 6.89V + 0.36V or 7.25 batV_144: cmp #71,r10 jl batV_X clrc dadd #0144h,r9 sub #71,r10 jmp batV_144 batV_X: mov #4,r15 rla r10 rla r10 rla r10 rla r10 mov r10,r11 rla r10 rla r10 rla r10 add r11,r10 ; x144 batV_10: cmp #710,r10 jl batV_1 clrc dadd #00010h,r9 sub #710,r10 jmp batV_10 batV_1: cmp #71,r10 jl batV_out clrc dadd #00001h,r9 sub #71,r10 jmp batV_1 batV_out: call #mconv call #mconv mov #0a00h+LED_r,r14 ; send 'r' call #mrsout call #mconv call #mconv bis.b #PO_MUTE ;unmute receiver br #wait ;---------------------------------------- ; calc LO offset (LO=f(tx,offset) ; send LO to dds ;---------------------------------------- offset: mov &ofst,r12 mov &ofst+2,r13 mov &fbin,r15 mov &fbin+2,r14 bit.b #F3_80M,&flags+3 ; 80m flag jc offj_1 sub r12,r15 ; 80m condition subc r13,r14 jmp offj_2 offj_1: add r12,r15 ; 40m,30m,20m,17m,15m condition addc r13,r14 offj_2: call #ddsout ret ;---------------------------------------- ; talk to the dds chip routine ;---------------------------------------- talk_2_dds: rla r15 rlc r14 rla r15 rlc r14 ; r14 x4 rrc r15 rrc r15 ; r15 essentially unchanged bis r12,r15 call #out32 ; this could be out16 with no effect mov r14,r15 bis r12,r15 call #out16 ret ;---------------------------------------- ; send LO to dds and ; send tx freq to dds ;---------------------------------------- ddsout: mov #04000h,r12 call #talk_2_dds txdds: ; load current fbin mov &fbin,r15 ; assume split off and load fbin mov &fbin+2,r14 ; if split/rit then bit.b #F1_SPLIT,&flags+1 ; Split/Rit flag jnc txdds_a ; load fbin_other mov &fbin_other,r15 ; split on, so load fbin_other mov &fbin_other+2,r14 ; endif txdds_a: mov #08000h,r12 call #talk_2_dds ret ;---------------------------------------- ; Serial out to dds ;---------------------------------------- out32: out16: out: mov #16,r13 bic.b #PO_FSYNC ; P1.6 FSYNC dds, tell dds data is coming, frame sync mbits: rlc r15 jc one bic.b #PO_SDATA ; 0, P1.4 SDATA dds, send 0 dclok: nop bic.b #PO_SCLK ; P1.5 SCLK dds, trigger dds clock in nop bis.b #PO_SCLK ; P1.5 SCLK dds, reset dec r13 jne mbits bis.b #PO_FSYNC ; P1.6 FSYNC dds, no more data outout: ret one: bis.b #PO_SDATA ; 1, P1.4 SDATA dds, send 1 jmp dclok ;---------------------------------------- ; Any button clicked routine ;---------------------------------------- #ifdef ANYBUTTON anyButton: bit.b #PI_MENU ; exit on any button jnc anyButton_set bit.b #PI_SPLIT jnc anyButton_set bit.b #PI_TUNEDN jnc anyButton_set bit.b #PI_TUNEUP jnc anyButton_set clrc ret anyButton_set: setc ret #endif ;---------------------------------------- ; Tune mode ;---------------------------------------- tune: mov #00300h+LED_T,r14 ; load "T" call #mrsout tune_loop: bic.b #PO_MUTE ; P1.7 Mute on bit.b #PI_DAH ; P2.0 Dah jnc en_tx bit.b #PI_TUNEUP jnc en_tx #ifdef ANYBUTTON call #anyButton jnc tune_loop #else bit.b #PI_MENU ; P1.1 Menu jc tune_loop #endif tu_w5: #ifdef ANYBUTTON call #clr_r5 tu_wdly: cmp #DIT_WAIT*7,r5 ; word space jlo tu_wdly #else tu_w5a: bit.b #PI_MENU ; P1.1 Menu jc tu_w5a #endif br #waitr en_tx: bis.b #F0_SIDETONE,&flags ; enable sidetone ;;; bic.b #PO_MUTE ; P1.7 Mute on mov #0838h,r15 ; txfreq call #out16 bis.b #PO_TRANSMIT ; P1.3 Transmit enable tu_w2: bit.b #PI_DIT ; Dit jnc de_tx bit.b #PI_TUNEDN jnc de_tx #ifdef ANYBUTTON call #anyButton jc de_tx #endif jmp tu_w2 de_tx: bic.b #PO_TRANSMIT ; P1.3 Transmit disable bic.b #F0_SIDETONE,&flags ;stop sidetone call #clr_r6 tu_w3: cmp #5,r6 jlo tu_w3 mov #02000h,r15 call #out16 ; close dds serial line tu_w4: cmp #15,r6 jlo tu_w4 bis.b #PO_MUTE ; P1.7 Mute off jmp tune_loop ;---------------------------------------- ; straight key mode ;---------------------------------------- strkey: bis.b #F0_SIDETONE,&flags ; enable sidetone bic.b #PO_MUTE ; P1.7 Mute on mov #0838h,r15 ; txfreq call #out16 bis.b #PO_TRANSMIT ; P1.3 Transmit enable sk_lp: call #isDit jnc sk_lp sk_lp2: bic.b #PO_TRANSMIT ; P1.3 Transmit disable bic.b #F0_SIDETONE,&flags ;stop sidetone call #clr_r6 sk_lp3: cmp #5,r6 jlo sk_lp3 mov #02000h,r15 call #out16 ; close dds serial line sk_lp4: cmp #15,r6 jlo sk_lp4 bis.b #PO_MUTE ; P1.7 Mute off br #wait ;---------------------------------------- ; paddle mode ;---------------------------------------- padinb_dit: bis.b #F0_DIT_LATCH,&flags; jmp padinb padinb_dah: bis.b #F0_DAH_LATCH,&flags; jmp padinb padin_dit: bis.b #F0_DIT_LATCH,&flags; jmp padin padin_dah: bis.b #F0_DAH_LATCH,&flags; ; jmp padin ; fall thru padin: mov #0001h,r7 ; start marker bit padinb: call #clr_r5 bis.b #F0_SIDETONE,&flags ; enable sidetone bic.b #PO_MUTE ; P1.7 Mute on bit.b #F2_ENTERFREQ,&flags+2 ; Enter freq flag jc padntx mov #0838h,r15 ; dds call #out16 bis.b #PO_TRANSMIT ; P1.3 Transmit enable padntx: mov &keyer_speed,r4 bit.b #F0_DIT_LATCH,&flags ; dit jc dot bit.b #F0_DAH_LATCH,&flags ; dah jc dash jmp space ;just in case! ;---------------------------------------- dot: clrc rlc r7 bic.b #F0_DIT_LATCH,&flags bis.b #F2_LAST_DIT,&flags+2 dota: cmp #DIT_WAIT/2,r5 jlo dota dot2: call #isDah jc dot1 bis.b #F0_DAH_LATCH,&flags dot1: cmp #DIT_WAIT,r5 jlo dot2 jmp space ;---------------------------------------- dash: setc rlc r7 bic.b #F0_DAH_LATCH,&flags bic.b #F2_LAST_DIT,&flags+2 dasha: cmp #(DIT_WAIT*3)/2,r5 jlo dasha dash2: call #isDit jc dash1 bis.b #F0_DIT_LATCH,&flags dash1: cmp #DIT_WAIT*3,r5 jlo dash2 ;jmp space ; fall through ;---------------------------------------- space: call #clr_r5 call #clr_r6 bic.b #PO_TRANSMIT ; P1.3 Transmit disable bic.b #F0_SIDETONE,&flags ; disable sidetone sp_lp3: cmp #5,r6 jlo sp_lp3 mov #02000h,r15 call #out16 ; close dds serial line splp: cmp #DIT_WAIT,r5 jlo splp bit.b #BF_IAM_MODE_B,&bflag ; test iambic mode jnc sp_lp_not_mode_b bit.b #F0_DIT_LATCH,&flags ; latch check jc padinb bit.b #F0_DAH_LATCH,&flags ; latch check jc padinb sp_lp_not_mode_b: bic.b #F0_DIT_LATCH+F0_DAH_LATCH,&flags ; latch clear call #isDit jc sp_lp_not_isDit ;isDit call #isDah ;isDit and not isDah jc padinb_dit ;isDit and isDah sp_lp_isDit_isDah: bit.b #F2_LAST_DIT,&flags+2 jc padinb_dah jmp padinb_dit sp_lp_not_isDit: call #isDah ;not isDit and isDah jnc padinb_dah ;not isDit and not isDat ;fall through bit.b #F2_ENTERFREQ,&flags+2 ; enter freq flag jc ltrsp bis.b #PO_MUTE ; P1.7 Mute off br #wait3 ; should this be wait vice wait3? ;---------------------------------------- ; test for letter space ;---------------------------------------- ltrsp: call #clr_r5 ltrsp1: call #isDit ; bit.b #PI_DIT ; P2.1 Dit jc ltrsp1a jmp padinb_dit ltrsp1a: call #isDah ; bit.b #PI_DAH ; P2.0 Dah jc ltrsp1b jmp padinb_dah ltrsp1b: cmp #DIT_WAIT,r5 ; make this smaller to help with entering code , vice orig of #9 or #DIT_WAIT*3 jlo ltrsp1 bit.b #F2_MEMSTORE,&flags+2 jc kmem br #decode ; jnc decode ;---------------------------------------- ; keyer mem temp store ;---------------------------------------- kmem: mov.b r7,0(r8) inc r8 cmp #ramend,r8 ; mem limit test jeq strkmem_out kmlp1clr: call #clr_r5 kmlp1: call #isDah ; bit.b #PI_DAH ; P2.0 Dah jc kmlp1a jmp padin_dah kmlp1a: call #isDit ; bit.b #PI_DIT ; P2.1 Dit jc kmlp1b jmp padin_dit kmlp1b: cmp #DIT_WAIT*7,r5 jlo kmlp2 cmp #rammem,r8 ; test for beginning of memory jeq kmlp2 cmp.b #000h,-1(r8) ; test for word space, so we don't store duplicate word space's jeq kmlp2 ;;; cmp.b #0ffh,-1(r8) ; test for slot marker ;;; jeq kmlp2 mov #00200h+LED_e,r14 ; 'e' but only if prev byte not a space or marker call #mrsout ; put out a 'e' here to let user know a word space was added clr r7 jmp kmem ;;; mov.b r7,0(r8) ;;; inc r8 ;;; cmp #ramend,r8 ; mem limit test ;;; jeq strkmem_out kmlp2: ;;; bit.b #PI_DIT ; P2.1 Dit ;;; jc kmlp2a ;;; jmp padin_dit kmlp2a: ;;; bit.b #PI_DAH ; P2.0 Dah ;;; jc kmlp2b ;;; jmp padin_dah kmlp2b: bit.b #PI_MENU ; P1.1 Menu jc kmlp2c jmp strkmem kmlp2c: bit.b #PI_TUNEDN ; P1.2 Tune Down jc kmlp1 ; fall thru to redoslot: ;---------------------------------------- ; redoslot - back up 1 memory slot during memory entry ; effectively erase the last slot ;---------------------------------------- redoslot: dec r8 cmp #rammem,r8 ; test for beginning jeq km_l2 cmp.b #0ffh,0(r8) ; test for marker jne redoslot mov #00400h+LED_I,r14 ; 'i' call #mrsout inc r8 jmp kmlp2 ;---------------------------------------- ; store keyer message ;---------------------------------------- strkmem: bit.b #001h,r8 ; odd memory? jne strkmem_out ; even mov.b #0ffh,0(r8) ; odd inc r8 strkmem_out: mov #0ffffh,0(r8) ; even and end of mem out mov #rammem,r8 jmp kmelp1 ;---------------------------------------- ; send keyer message ;---------------------------------------- kmemout: bis.b #F3_MEMPLAY,&flags+3 ; memory flag mov #flash_rammem,r8 ; ; this is where the logic for multiple memory goes ; call #clr_r6 mem_choice: bit.b #PI_SPLIT jc mem_choice_4 ; toggle button keyer mode xor.b #BF_STEALTH,&bflag ; toggle flag bic.b #F3_MEMPLAY,&flags+3 ; memory flag bit.b #BF_STEALTH,&bflag ; test stealth mode jc stealth_beep br #waitr ; send 'r' to indicate normal stealth_beep: mov #00200h+LED_e,r14 ; send 'e' to indicate stealth call #mrsout br #wait mem_choice_4: bit.b #PI_MENU jnc kmelp1 bit.b #PI_TUNEDN jc mem_choice_tuneup mem_choice_1: inc r8 cmp.b #0ffh,-1(r8) ; skip to byte after next ff jne mem_choice_1 jmp kmelp1 mem_choice_tuneup: bit.b #PI_TUNEUP jc mem_choice_loop mem_choice_2: inc r8 cmp.b #0ffh,-1(r8) ; skip to byte after next ff jne mem_choice_2 mem_choice_3: inc r8 cmp.b #0ffh,-1(r8) ; skip to byte after next ff jne mem_choice_3 jmp kmelp1 mem_choice_loop: cmp #333,r6 ; 1/3 second delay jlo mem_choice bic.b #F3_MEMPLAY,&flags+3 ; memory flag br #split_rtn kmemout1: bis.b #F3_MEMPLAY,&flags+3 ; memory flag mov #flash_rammem,r8 kmelp1: mov.b @r8+,r14 cmp.b #000h,r14 ; is a word space? jeq kwds cmp.b #0ffh,r14 ; is at end? jne kmelp2 bit.b #F3_MEMPLAY,&flags+3 ; sending memory? jc eostrg cmp.b #0ffh,0(r8) jeq eostrg ; only exit if 2 ff in a row kmelp2: swpb r14 call #mrst ; transmit character! #ifdef PAUSE bit.b #F1_STRAIGHTKEY,&flags+1 ; straight key flag jc kmelp3 call #isDah jnc kpause #endif kmelp3: bit.b #PI_MENU ; P1.1 Menu jnc intbmod call #isDit jnc exkm jmp kmelp1 ;---------------------------------------- ; message word space delay ;---------------------------------------- kwds: call #clr_r5 kwdslp: cmp #DIT_WAIT*7,r5 ; word space jlo kwdslp jmp kmelp1 #ifdef PAUSE ;---------------------------------------- ; message pause ;---------------------------------------- kpause: call #isDit jnc intbmod call #isDah jnc kpause jmp kmelp1 #endif eostrg: bit.b #F3_BEACON,&flags+3 ; beacon flag jc beacm bit.b #F2_MEMSTORE+F2_ENTERFREQ,&flags+2 ; memory and enter freq flags jc kmemfs bic.b #F3_MEMPLAY,&flags+3 ; memory flag br #wait exkm: call #isDit jnc exkm bic.b #F3_MEMPLAY+F3_BEACON,&flags+3 ; beacon and memory flags br #waitr ;---------------------------------------- ; beacon mode ;---------------------------------------- intbmod: bit.b #F3_BEACON,&flags+3 ; test beacon flag jnc intbmod_1 jmp exbcnm intbmod_1: bis.b #F3_BEACON,&flags+3 ; beacon flag call #clr_r6 bis.b #F0_SIDETONE,&flags ; enable sidetone ibmd_j2: cmp #250,r6 ; short beep for feedback jlo ibmd_j2 bic.b #F0_SIDETONE,&flags ; disable sidetone ibmd_j: call #isDit jnc ibmd_j jmp kmelp1 beacm: call #clr_r6 bealp1: ; test for SK mode bit.b #F1_STRAIGHTKEY,&flags+1 ; straight key jc beac_sk call #isDah jnc exbcnm beac_sk: call #isDit jnc exbcnm cmp #3500,r6 ; delay between beacons 3.5 seconds jlo bealp1 jmp kmemout1 exbcnm: bic.b #F3_MEMPLAY+F3_BEACON,&flags+3 ; beacon and memory flags br #waitr ;---------------------------------------- ; write keyer memory ;---------------------------------------- kmemfs: bit.b #PI_MENU ; P1.1 Menu jnc km_l1 bit.b #PI_SPLIT ; P2.3 Rit jc kmemfs km_l2: mov #00200h+LED_e,r14 ; 'e' call #mrsout mov #00700h+LED_M,r14 ; 'm' call #mrsout br #kmemint km_l1: bic.b #F2_MEMSTORE+F2_ENTERFREQ,&flags+2 ; memory and enter freq flags ; move menu tables to ram ..... from menu_options-2 to ramend till menu_options_end.... ; mov #ramend,r8 ; mov #menu_options-2,r13 ; to get the buffer, forces the FF's at end of keyer memory ; ; sub 2 is not needed but does not hurt either ;km_preloop: ; mov @r13+,0(r8) ; incd r8 ; cmp #menu_options_end,r13 ; jne km_preloop mov #rammem,r12 mov #flash_rammem,r13 call #cl_flash call #wr_flsh ; write flash mwrdone: mov #00200h+LED_e,r14 ; 'e' call #mrsout #ifdef MULTI_MUTE bic.b #F2_AFA,&flags+2 ; disable sidetone for morse bis.b #PO_MUTE ; P1.7 Mute off #endif br #wait ;---------------------------------------- ;output morse character ;---------------------------------------- mrst: mov &keyer_speed,r4 jmp mrs_lp4 mrsout: mov &command_speed,r4 cmp.b #0,r14 jeq mrs_lp4 bit.b #BF_NOLED,&bflag jc mrs_lp4 bis.b #LED_BLANK,&P3OUT bic.b r14,&P3OUT mrs_lp4: mov #9,r12 ; limit bits to look at bic.b #PO_MUTE ; P1.7 Mute on mrs_lp1: dec r12 jz mrs_ext rlc r14 ; find marker bit (1) jnc mrs_lp1 mrs_lp3: dec r12 jz mrs_ext ; no more bits, now exit bit.b #F3_MEMPLAY,&flags+3 ; memory flag jnc mrs_lp2 mov #0838h,r15 call #out16 bis.b #PO_TRANSMIT ; P1.3 Transmit enable mrs_lp2: call #clr_r5 bis.b #F0_SIDETONE,&flags ; enable sidetone rlc r14 ; get next bit (1=dah 0=dit) jc mdash mdot: cmp #DIT_WAIT,r5 ; dit jlo mdot jmp mspace mdash: cmp #DIT_WAIT*3,r5 ; dah jlo mdash mspace: bit.b #F3_MEMPLAY,&flags+3 ; Memory flag jnc msp1 bic.b #PO_TRANSMIT ; P1.3 Transmit disable call #clr_r6 tw_lp: cmp #9,r6 jlo tw_lp mov #02000h,r15 call #out16 ; close dds serial line msp1: bic.b #F0_SIDETONE,&flags ; space call #clr_r5 ms_lp: cmp #DIT_WAIT,r5 jlo ms_lp jmp mrs_lp3 ; loop till done mrs_ext: cmp #DIT_WAIT*3,r5 ; exit jlo mrs_ext #ifdef MULTI_MUTE bit.b #F2_AFA,&flags+2 jc mrs_lp7 #endif bis.b #PO_MUTE ; P1.7 Mute off mrs_lp7: bis.b #LED_BLANK,&P3OUT ret ;---------------------------------------- ;change code speed ; ; input: r7 points to index ; output: r7 points to new index ;---------------------------------------- spd_command: mov &keyer_speed,&command_speed jmp spd_out ;;; mov #command_speed,r7 ;;; jmp spd_entry spd_keyer: mov #keyer_speed,r7 jmp spd_entry spd_lut: mov #0200h+LED_e,r14 ; 'e' spd_lut_announce: call #mrsout spd_entry: call #isDit jnc spddn call #isDah jnc spdup ; bit.b #F1_STRAIGHTKEY,&flags+1 ; straight key ; jc spd_lp2 ; bit.b #PI_DAH ; P2.0 Dah ; jnc spdup ; bit.b #PI_DIT ; P2.1 Dit ; jnc spddn ;spd_lp2: bit.b #PI_TUNEUP ; P2.2 Tune Up ; jnc spdup ; bit.b #PI_TUNEDN ; P1.2 Tune Down ; jnc spddn bit.b #PI_MENU jc spd_entry spd_out: call #wrsup ; save to flash br #waitr ; out an 'r' spdup: decd 0(r7) cmp #sp_lut-2,0(r7) jne spd_lut incd 0(r7) jmp sp_end spddn: incd 0(r7) cmp #sp_lut_end,0(r7) jne spd_lut decd 0(r7) sp_end: mov #0400h,r14 ; 'i' jmp spd_lut_announce ; ; code speed timer LUT ; ; if you think the standard word "PARIS" has 50 dits (7 DITs per word space) then #define SPEED_CONSTANT 32768*60/50/DIT_WAIT ; if you think the standard word "PARIS" has 48 dits (5 DITs per word space) then ;#define SPEED_CONSTANT 32768*60/48/DIT_WAIT sp_lut: DW (SPEED_CONSTANT/50) ; 50 wpm DW (SPEED_CONSTANT/48) ; 48 wpm DW (SPEED_CONSTANT/46) ; 46 wpm DW (SPEED_CONSTANT/44) ; 44 wpm DW (SPEED_CONSTANT/42) ; 42 wpm DW (SPEED_CONSTANT/40) ; 40 wpm DW (SPEED_CONSTANT/38) ; 38 wpm DW (SPEED_CONSTANT/36) ; 36 wpm DW (SPEED_CONSTANT/34) ; 34 wpm DW (SPEED_CONSTANT/32) ; 32 wpm DW (SPEED_CONSTANT/30) ; 30 wpm DW (SPEED_CONSTANT/28) ; 28 wpm DW (SPEED_CONSTANT/26) ; 26 wpm DW (SPEED_CONSTANT/24) ; 24 wpm DW (SPEED_CONSTANT/22) ; 22 wpm default_speed: DW (SPEED_CONSTANT/20) ; 20 wpm DW (SPEED_CONSTANT/18) ; 18 wpm DW (SPEED_CONSTANT/16) ; 16 wpm DW (SPEED_CONSTANT/14) ; 14 wpm DW (SPEED_CONSTANT/12) ; 12 wpm DW (SPEED_CONSTANT/10) ; 10 wpm DW (SPEED_CONSTANT/8) ; 8 wpm DW (SPEED_CONSTANT/6) ; 6 wpm sp_lut_end: ;---------------------------------------- ; Announce frequency in morse ;---------------------------------------- mfrqout: call #clr_r5 #ifdef MULTI_MUTE bis.b #F2_AFA,&flags+2 bic.b #PO_MUTE ; P1.7 Mute on #endif mxxx1: cmp #DIT_WAIT*7,r5 ; word space delay before sending characters jlo mxxx1 ; add check for split/rit bit.b #F1_SPLIT,&flags+1 ; check split/rit flag jnc check_vfo mov #00800h+LED_S,r14 ; 's' call #mrsout check_vfo: ; add the vfo mov #00500h+LED_a,r14 ; "a" bit.b #F1_VFO,&flags+1 ; VFO flag a=0 jnc out_vfo mov #01800h+LED_b,r14 ; "b" out_vfo: call #mrsout call #clr_r5 mxxx: cmp #DIT_WAIT*7,r5 ;word space delay before sending characters jlo mxxx bit.b #BF_MHZ,&bflag ; have we entered MHz mode? jnc no_mhz mov &fbcd+2,r9 call #mconv ; 10MHz, costs too much program space to test for 0 so leave it call #mconv ; 1MHz mov #0a00h+LED_r,r14 ; send 'r' call #mrsout no_mhz: mov.b &fbcd+2,r9 ; this is duplicated elsewhere maybe make a routine for it swpb r9 mov.b &fbcd+1,r8 add r8,r9 call #mconv ;convert BCD digit to morse character and output call #mconv call #mconv mov #0a00h+LED_r,r14 ; send 'r' call #mrsout call #mconv #ifdef ANNOUNCE_10HZ mov.b &fbcd,r9 ; out the 10Hz digit if not zero swpb r9 and #0f000h,r9 jz mfrqout_end call #mconv #endif mfrqout_end: #ifdef MULTI_MUTE bic.b #F2_AFA,&flags+2 ; clr morse flag bis.b #PO_MUTE ; P1.7 Mute off #endif br #wait ;---------------------------------------- ; convert decimal to morse ;---------------------------------------- mconv: clr r7 clrc mov #4,r14 mconv_loop: rlc r9 ;shift upper 4 bits of r9 into lower 4 bits of r7 rlc r7 ;at the same time, positions next BCD nibble in upper dec r14 ;4 bits of r9 jnz mconv_loop mconv1: mov #mlut,r8 ;initalize table pointer add r7,r8 ;add in offset, point to number mov.b @r8,r14 ;get value in table swpb r14 add #(dlut-mlut),r8 ;point to LED value mov.b @r8,r7 ;get value in table add r7,r14 call #mrsout ;send decimal in morse ret ;---------------------------------------- ; decimal to morse LUT ;---------------------------------------- mlut: DW 02f03h ; '1' 't' DW 02327h ; '3' '2' DW 02021h ; '5' '4' DW 03830h ; '7' '6' DW 03e3ch ; '9' '8' dlut: DB LED_0,LED_1 DB LED_2,LED_3 DB LED_4,LED_5 DB LED_6,LED_7 DB LED_8,LED_9 ;---------------------------------------- ; Rotate 4 bits left (nibble) ;---------------------------------------- rot4l: rla r7 rla r7 rla r7 rla r7 ret ;---------------------------------------- ; Enter frequency - dfe mode ;---------------------------------------- fewait: ; mov #00200h+LED_e,r14 ; 'e' ; call #mrsout ;---------------------------------------- ; paddle switch wait ;---------------------------------------- few1: ;;; bit.b #PI_DAH ; P2.0 Dah call #isDah jc few1a br #padin_dah few1a: ;;; bit.b #PI_DIT ; P2.1 Dit call #isDit jc few1b br #padin_dit few1b: bit.b #PI_MENU ; P1.1 Menu jnc fe_ex jmp few1 ;---------------------------------------- ; morse to decimal ;---------------------------------------- decode: bis.b #LED_BLANK,&P3OUT cmp #002fh,r7 jne dcd1 mov #1,r7 bic.b #LED_1,&P3OUT jmp dcdx dcd1: cmp #0003h,r7 jne dcd2 clr r7 bic.b #LED_0,&P3OUT jmp dcdx dcd2: cmp #0027h,r7 jne dcd3 mov #2,r7 bic.b #LED_2,&P3OUT jmp dcdx dcd3: cmp #0023h,r7 jne dcd4 mov #3,r7 bic.b #LED_3,&P3OUT jmp dcdx dcd4: cmp #0021h,r7 jne dcd5 mov #4,r7 bic.b #LED_4,&P3OUT jmp dcdx dcd5: cmp #0020h,r7 jne dcd6 mov #5,r7 bic.b #LED_5,&P3OUT jmp dcdx dcd6: cmp #0030h,r7 jne dcd7 mov #6,r7 bic.b #LED_6,&P3OUT jmp dcdx dcd7: cmp #0038h,r7 jne dcd8 mov #7,r7 bic.b #LED_7,&P3OUT jmp dcdx dcd8: cmp #003ch,r7 jne dcd9 mov #8,r7 bic.b #LED_8,&P3OUT jmp dcdx dcd9: cmp #003eh,r7 jne dcd0 mov #9,r7 bic.b #LED_9,&P3OUT jmp dcdx dcd0: cmp #003fh,r7 jne nngod bic.b #LED_0,&P3OUT clr r7 ;---------------------------------------- ; pack BCD digits ;---------------------------------------- dcdx: inc r8 cmp #1,r8 jne tst2 swpb r7 call #rot4l mov r7,r10 jmp fewait tst2: cmp #2,r8 jne tst3 swpb r7 add r7,r10 jmp fewait tst3: cmp #3,r8 jne tst4 call #rot4l add r7,r10 jmp fewait tst4: add r7,r10 jmp calnf nngod: mov #04c00h+LED_QUESTION,r14 ; '?' call #mrsout jmp few1 ;---------------------------------------- ; calc new freq ;---------------------------------------- calnf: mov.b r10,&fbcd+1 ; move the lb of R10 to the second byte of fbcd swpb r10 mov.b r10,&fbcd+2 ; move the hb of r10 to the third byte of fbcd mov.b #000h,&fbcd ; clr the 10's and 1's Hz fe_ex: bic.b #F2_ENTERFREQ,&flags+2 ; enter freq flag call #calc_new_freq jmp mfrqout ;---------------------------------------- ; isDit ; ;---------------------------------------- isDit: bit.b #BF_STEALTH,&bflag jnc isDit_normal ;;; bit.b #PI_MENU bit.b #PI_TUNEDN ret isDit_normal: bit.b #PI_DIT isDitDah_exit: ret ;---------------------------------------- ; isDah ; ;---------------------------------------- isDah: bit.b #BF_STEALTH,&bflag jnc isDah_normal ;;; bit.b #PI_TUNEDN bit.b #PI_TUNEUP ret isDah_normal: bit.b #F1_STRAIGHTKEY,&flags+1 ; straight key flag jc isDah_straightKey bit.b #PI_DAH isDah_straightKey: ret ;---------------------------------------- ; mult10 - multiply by 10. ; ; inputs: r12,r11 ; outputs: r12,r11 ;---------------------------------------- mult10: rla r11 rlc r12 ; 2* mov r11,r14 mov r12,r15 ; save the 2* temp to add back in later rla r11 rlc r12 ; 2* (cumulative 4*) rla r11 rlc r12 ; 2* (cumulative 8*) clrc add r14,r11 ; add the temp 2* to the 8* to get 10*. addc r15,r12 ret ;---------------------------------------- ; bcd2bin ; ; inputs: fbcd+2, fbcd ; outputs: fbc+2, fbc ; ; where number is abcdefgh here is the formula ; ((((((((((((((a*10)+b)*10)+c)*10)+d)*10)+e)*10)+f)*10)+g)*10)+h) ; 8 shifts ; 7 mult10 ; 7 add's plus 1 at the beginning where the zero is added, making 8 adds ;---------------------------------------- bcd2bin: mov &fbcd,r8 mov &fbcd+2,r9 clr r11 ; to hold the accumulations clr r12 mov #8,r13 ; counter bcd2bin_loop: clr r10 ; to hold the bcd nibble mov #4,r14 bcd2bin_loop1: clrc rla r8 rlc r9 rlc r10 dec r14 jnz bcd2bin_loop1 ; r10 now has the next nibble in lsb clrc add r10,r11 ; since r12,r11 clr'd at beginning so the extra add of 0 is OK adc r12 dec r13 jz bcd2bin_exit call #mult10 jmp bcd2bin_loop bcd2bin_exit: mov r11,&fbc mov r12,&fbc+2 ; jmp bindiv ; fall thru ;---------------------------------------- ; bindiv - mult by 2^28 and div by fref ;---------------------------------------- bindiv: clr r7 clr r8 mov &fbc,r9 mov &fbc+2,r10 clr r11 clr r12 mov #65,r15 ; load up counter for 65 bits (8 bytes or so) clrc d28_1: rlc r7 ; originally cleared rlc r8 ; originally cleared rlc r9 ; originally fbc rlc r10 ; originally fbc+2 push sr dec r15 jnz d28_2 pop sr ; prep to exit bindiv mov #4,r14 d28_1_1: clrc rrc r8 rrc r7 dec r14 jnz d28_1_1 mov r7,&fbin mov r8,&fbin+2 ret d28_2: pop sr ; do this 64 times (2^64 ?) rlc r11 ; originally cleared rlc r12 ; originally cleared, complete left shift through all 6 words r12-r7 sub &fref,r11 ; subtract from fref (dividing) subc &fref+2,r12 jc d28_3 ; only if bit set add &fref,r11 ; otherwise add it back addc &fref+2,r12 clrc ; push a 0 on the output (r8,r7) jmp d28_1 d28_3: setc ; push a 1 on the output line (r8,r7) jmp d28_1 ;---------------------------------------- ; Calibration mode - dds ref freq ;---------------------------------------- calref: mov #01a00h+LED_C,r14 ; "c" call #mrsout ;;; mov #01200h+LED_F,r14 ; "f" ;;; call #mrsout mov #08700h,&fref ; load start freq ref mov #0393h,&fref+2 ; 03938700h = 60,000,000. mov #01000h,&fbcd+2 mov #00000h,&fbcd call #bcd2bin bic.b #PO_MUTE ; P1.7 Mute on call #txdds mov #02838h,r15 call #out16 cfw: bit.b #PI_TUNEUP ; P2.2 Tune Up jnc cfw cfwait: bit.b #PI_TUNEUP ; P2.2 Tune Up jnc cfdn bit.b #PI_TUNEDN ; P1.2 Tune Down jnc cfup bit.b #PI_MENU ; P1.1 Menu jnc adjoff ; continue to calibrate offset jmp cfwait cfup: add #10,&fref ; fref + 10Hz addc #0,&fref+2 jmp cfwait1 cfdn: sub #10,&fref ; fref - 10Hz subc #0,&fref+2 cfwait1: call #bindiv call #txdds call #clr_r6 cfdly: cmp #300,r6 jlo cfdly jmp cfwait ;---------------------------------------- ; Write to flash ; write all 080h bytes in this routine ; r12 points to ram (copy from) ; r13 points to flash (copy to) ;---------------------------------------- wr_flsh: dint nop mov #FWKEY+FSSEL0+FN3+FN2+FN0,&FCTL2 mov #FWKEY,&FCTL3 mov #FWKEY+WRT,&FCTL1 mov #080h,r8 ; 128 bytes wr_loop: mov @r12+,0(r13) ; write 2 bytes at a time incd r13 decd r8 ; dec by 2 cmp #0,r8 jne wr_loop mov #FWKEY,&FCTL1 mov #FWKEY+LOCK,&FCTL3 enable_int: ; must add a few ticks to the TACCRx's because the writing takes longer than SIDETONE_DELAY ticks mov #TASSEL_1+MC_0+ID_0,&TACTL ; ACLK+MODE0 (stopped) push &TAR mov #TASSEL_1+MC_2+ID_0,&TACTL ; ACLK+MODE2 (start continous up) add #SIDETONE_DELAY,0(SP) pop &TACCR1 mov &TACCR1,&TACCR2 mov &TACCR1,&TACCR0 eint ret ;---------------------------------------- ; Clear flash - memory ; r13 tells us which bank to clear 01000h ; or 01080h ;---------------------------------------- cl_flash: dint nop mov #FWKEY+FSSEL0+FN3+FN2+FN0,&FCTL2 mov #FWKEY,&FCTL3 mov #FWKEY+ERASE,&FCTL1 clr 0(r13) mov #FWKEY+LOCK,&FCTL3 jmp enable_int ;---------------------------------------- ; Calibrate IF freq offset ;---------------------------------------- adjoff: ;;; mov #01a8dh,r14 ; "c" ;;; call #mrsout mov #00f00h+LED_O,r14 ; "o" call #mrsout ad_lp: bit.b #PI_MENU jnc ad_lp mov #0829bh,&fbin ; put init value 4914700Hz mov #014fh,&fbin+2; for 60Mhz clock #ifdef MULTI_MUTE bis.b #PO_MUTE ; P1.7 Mute off #endif call #txdds mov #02800h,r15 call #out16 ofwait: bit.b #PI_TUNEUP jnc ofup bit.b #PI_TUNEDN jnc ofdn bit.b #PI_MENU jnc ofdone jmp ofwait ofup: add #016h,&fbin ; 5Hz for 60MHz clock addc #0,&fbin+2 jmp ofwait1 ofdn: sub #016h,&fbin ; 5Hz for 60MHz clock subc #0,&fbin+2 ofwait1: call #txdds call #clr_r6 ofdly: cmp #300,r6 jlo ofdly jmp ofwait ofdone: mov &fbin,&ofst mov &fbin+2,&ofst+2 call #wrsup br #rst2 ;---------------------------------------- ; write user prefs to flash ;---------------------------------------- wrsup: ; write user prefs (cal constants + iambic flags + morse speed constants) to flash #ifdef OTHER_STUFF_IN_B_FLASH mov #ENDOFVARRAM,r14 ; get ram start address so can save some of the flash stuff first mov #STATIC_LUTS,r13 ; get flash address of start of LUT's su_lp: mov @r13+,0(r14) ; copy LUT's from flash to ram incd r14 ; cmp #ENDOFFLASH,r13 ; jne su_lp ; loop #endif mov #fref,r12 ; start of ram to copy to flash mov #flash_fref,r13 ; where to copy to in flash call #cl_flash ; clear flash call #wr_flsh ; write flash, write 2 bytes at a time ; must use multiples of 2 bytes !!! ; mov r14,0(r13) ;;; bis.b #PO_MUTE ; P1.7 Mute off ret ;---------------------------------------- ; Set up initial keyer memory ; ;---------------------------------------- ORG 01000h flash_rammem: #define W1MT_MEMORIES #ifdef W1MT_MEMORIES DW 01d1ah ; q c DW 00800h ; s _ DW 00016h ; _ p DW 02f0bh ; 1 w DW 00307h ; t m DW 00bffh ; w mkr DW 0072fh ; m 1 DW 0ff03h ; mkr t DW 02020h ; 5 5 DW 00006h ; _ n DW 00511h ; a v DW 02700h ; 2 _ DW 0ff0bh ; mkr w DW 0ffffh ; mkr mkr #endif ORG flash_rammem + NUM_KEYER_BYTES DW 0ffffh ; buffer ;---------------------------------------- ; Set up initial flash values, ; saved variable plus all the LUT's ;---------------------------------------- ORG 01080h ;fref flash_fref: DW 08700h DW 00393h ;ofst flash_ofst: DW 0829bh DW 0014fh ;bflags flash_bflags: DW 00000h ;morse ndx's flash_command_speed: DW default_speed flash_keyer_speed: DW default_speed #ifdef OTHER_STUFF_IN_B_FLASH STATIC_LUTS: ENDOFFLASH: #endif DW 0ffffh END