MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 1 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00001 ; **************************************************************************** 00002 ; * Signal Generator (VFO) with Direct Digital Synthesis * 00003 ; * Version 3a * 00004 ; * April 21, 1999 * 00005 ; * * 00006 ; **************************************************************************** 00007 ; Description: 00008 ; This is the control program for a DDS VFO built with an AD9850 DDS chip, a 00009 ; shaft encoder, a push button switch and an Liquid crystal display. 00010 ; 00011 ; Features: 00012 ; VARIABLE RATE TUNING based on the speed at which the encoder is turned. The 00013 ; encoder also has a built in switch which will change the step size from 1Hz 00014 ; to 1kHz if the encoder shaft is pressed down while turning. 00015 ; 00016 ; BAND MEMORIES an external push button switch allows the frequency to be 00017 ; cycled around the HF ham bands. 00018 ; 00019 ; CALIBRATE MODE is entered if the external push button is pressed during 00020 ; power on. The display is set to 10,000.000 CAL and remains fixed, even as 00021 ; adjustments are being made. If the push button is held pressed, then turning 00022 ; the shaft encoder will increase or decrease the value "osc" used to 00023 ; calculate the DDS control word. The basic calibrate adjustment rate is very 00024 ; low (on the order of a few cycles per turn of the encoder). A somewhat 00025 ; faster adjustment speed is available by pressing the encoder shaft down 00026 ; while turning. An external frequency counter on the DDS output is required 00027 ; to observe this adjustment. To exit calibrate mode, release the external 00028 ; push button and turn the shaft encoder one more time. The calibrated value 00029 ; of "osc" will then be stored in EEPROM memory. 00030 ; 00031 ;****************************************************************************** 00032 ; Author - Curtis W. Preuss - WB2V 00033 ; 00034 ; Modification History 00035 ; 8/19/98 - Version 1 - Initial Version by Curtis W. Preuss - WB2V 00036 ; 12/xx/98 - Version 2 - Converted to MPASM by Bruce Stough, AA0ED 00037 ; 4/21/99 - Version 3 - Fixed and modified by Bruce Stough, AA0ED and 00038 ; Craig Johnson, AA0ZZ 00039 ; FIXES: 00040 ; 1) Fix a bug which caused the frequency to jump to 00041 ; the maximum when going towards zero. 00042 ; 2) Fix several SMASM to MPASM translation bugs. 00043 ; - Code worked, but several cases of "hard coded" 00044 ; constants remained that should have been 00045 ; changed to labels to allow data tables to 00046 ; be moved and/or modified. This bug could 00047 ; cause a reference to a wrong variable. 00048 ; - PortB vs TRISB causing confusion. 00049 ; MODIFICATIONS/ADDITIONS: 00050 ; 1) The lower frequency is changed from 1Khz to zero. 00051 ; 2) Added band table entries of 0 Hz and 30 MHz. 00052 ; 3) Changed wait routine names for clarity. 00053 ; 4) Added comments throughout. MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 2 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00054 ; 5) Subroutine headers added. 00055 ; - Inputs and Outputs specified 00056 ; 6) Changed some data labels for clarity. 00057 ; 7) Changed some routines for efficiency. 00058 ; - Improve path length and save memory 00059 ; NOTE: OUR GOAL was to make this code clear and 00060 ; easy to understand so that it can be used as 00061 ; a springboard for additional changes. 00062 ; By documenting subroutines as clearly as 00063 ; possible, we hope readers will be able to 00064 ; easily use the subroutines in other projects. 00065 ; 00066 ;***************************************************************************** 00067 ; 00068 ; Target Controller - PIC16F84 00069 ; __________ 00070 ; ENCODER SWITCH--RA2 |1 18| RA1---------ENCODER A 00071 ; PB SWITCH-------RA3 |2 17| RA0---------ENCODER B 00072 ; +5V-------------RA4 |3 16| OSC1--------XTAL 00073 ; Ground--------!MCLR |4 15| OSC2--------XTAL 00074 ; Ground----------Vss |5 14| VDD---------+5 V 00075 ; DDS LOAD--------RB0 |6 13| RB7---------DDS DATA/LCD 14 00076 ; LCD_rs----------RB1 |7 12| RB6---------LCD 13 00077 ; LCD_rw----------RB2 |8 11| RB5---------DDS CLOCK/LCD 12 00078 ; LCD_e-----------RB3 |9 10| RB4---------LCD 11 00079 ; ---------- 00080 ; 00081 ;***************************************************************************** 00082 ; 00083 ; ********** HARDWARE CHANGES NEEDED TO FAR CIRCUITS BOARD ********** 00084 ; 00085 ; The circuit board available from FAR Circuits is based on the original 00086 ; QEX article (7/97) by Curt, WB2V, and works with the original dds_vfo 00087 ; code. Subsequently, Curt modified the code to add the calibrate 00088 ; and band select functions. 00089 ; 00090 ; This enhanced PIC code requires a hardware change to allow for the push 00091 ; button which is used to select the calibrate mode and to do band 00092 ; selection. The change removes the +5 volt connection to pin 2 of 00093 ; the PIC chip, and connects a 10K ohm pull-up resistor to pin 2. The 00094 ; push button is connected between pin 2 and ground, so that the pin is 00095 ; grounded when the button is pressed and held high when the button is 00096 ; released. In addition, instead of using the output of Pin 2 to power 00097 ; the LCD and control the LCD contrast, the LCD is connected directly to 00098 ; +5 volts. 00099 ; 00100 ; The change can be done as follows: 00101 ; 00102 ; 1. Locate the PC trace which connects pin 2 of the PIC chip to the 00103 ; LCD contrast control pot. This was originally used to power the 00104 ; LCD by setting bit 3 of Port A (pin 2) high. Drill a small hole 00105 ; (#60 - .040") through this trace as near as possible (1/16") to 00106 ; pin 2 of the PIC socket. MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 3 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00107 ; 00108 ; 2. Near pin 2 of the PIC socket, cut the trace about 1/8" beyond the 00109 ; new hole. Using a 1/4" drill, remove the foil around the hole 00110 ; on the ground plane side of the board to avoid shorting pin 2 to 00111 ; ground when the resistor gets inserted in the hole (Step 4). 00112 ; 00113 ; 3. Locate the +5 volt trace that passes between pin 1 and pin 2 of the 00114 ; PIC socket. Drill a new hole through this trace in the place where 00115 ; it is close to pin 1. Remove the ground side foil from around this 00116 ; hole with a 1/4" drill to avoid shorting +5 v to ground when the 00117 ; resistor lead is inserted. 00118 ; 00119 ; 4. Install a 10K resistor in the new PC board holes. Mount it vertically, 00120 ; with the short resistor lead in the +5 v trace hole and the other end 00121 ; bent close to the resistor body and down into the hole near pin 2 of 00122 ; the PIC socket. Make the solder connection to the traces only, not to 00123 ; ground plane foil on the other side of the board. Make sure both sides 00124 ; of the +5 v trace are soldered to the resistor lead. 00125 ; 00126 ; 5. Connect a wire from one side of the push button to the pin 2 side of 00127 ; the new 10K resistor. This can be done by connecting the wire to the 00128 ; top of the vertically mounted resistor. Connect another wire from the 00129 ; other side of the push button to ground. 00130 ; 00131 ; 6. Using a bit of solid wire, connect the pin of the LCD contrast 00132 ; pot that used to be connected to pin 2 of the PIC socket to the 00133 ; +5 volt trace. This now supplies power to the LCD. 00134 ; 00135 ; **************************************************************************** 00136 ; * Device type and options. * 00137 ; **************************************************************************** 00138 ; 00139 PROCESSOR PIC16F84 00140 RADIX DEC 00141 ERRORLEVEL -220 00142 ERRORLEVEL -305 00143 ; 00144 ; **************************************************************************** 00145 ; * Configuration fuse information: * 00146 ; **************************************************************************** 00147 0000000F 00148 _CP_ON EQU H'000F' 00003FFF 00149 _CP_OFF EQU H'3FFF' 00003FF7 00150 _PWRTE_ON EQU H'3FF7' 00003FFF 00151 _PWRTE_OFF EQU H'3FFF' 00003FFF 00152 _WDT_ON EQU H'3FFF' 00003FFB 00153 _WDT_OFF EQU H'3FFB' 00003FFC 00154 _LP_OSC EQU H'3FFC' 00003FFD 00155 _XT_OSC EQU H'3FFD' 00003FFE 00156 _HS_OSC EQU H'3FFE' 00003FFF 00157 _RC_OSC EQU H'3FFF' 00158 ; 2007 3FF5 00159 __CONFIG _CP_OFF & _PWRTE_ON & _WDT_ON & _XT_OSC MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 4 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00160 ; 00161 ; **************************************************************************** 00162 ; * General equates. These may be changed to accommodate the reference clock* 00163 ; * frequency, the desired upper frequency limit, and the default startup * 00164 ; * frequency. * 00165 ; **************************************************************************** 00166 ; 00167 ; ref_osc represents the change in the frequency control word which results 00168 ; in a 1 Hz change in output frequency. It is interpreted as a fixed point 00169 ; integer in the format . 00170 ; 00171 ; The values for common oscillator frequencies are as follows: 00172 ; 00173 ; Frequency ref_osc_3 ref_osc_2 ref_osc_1 ref_osc_0 00174 ; 00175 ; 120.00 MHz 0x23 0xCA 0x98 0xCE 00176 ; 100.00 MHz 0x2A 0xF3 0x1D 0xC4 00177 ; 90.70 MHz 0x2F 0x5A 0x82 0x7A 00178 ; 66.66 MHz 0x40 0x6E 0x52 0xE7 00179 ; 66.00 MHz 0x41 0x13 0x44 0x5F 00180 ; 50.00 MHz 0x55 0xE6 0x3B 0x88 00181 ; 00182 ; To calculate other values: 00183 ; ref_osc_3 = (2^32 / oscillator_freq_in_Hertz). 00184 ; ref_osc_2, ref_osc_1, and ref_osc_0 are the fractional part of 00185 ; (2^32 / oscillator_freq_in_Hertz) times 2^24. 00186 ; Note: 2^32 = 4294967296 and 2^24 = 16777216 00187 ; 00188 ; For example, for a 120 MHz clock: 00189 ; ref_osc_3 is (2^32 / 120 x 10^6) = 35.791394133 truncated to 35 (0x23) 00190 ; ref_osc_2 is the high byte of (.791394133 x 2^24) = 13277390.32 00191 ; 13277390.32 = 0xCA98CE, so high byte is CA. 00192 ; ref_osc_1 is the next byte of 0xCA98CE, or 98 00193 ; ref_osc_0 is the last byte of 0xCA98CE, or CE 00194 ; 00195 ;==== Currently set for 100 MHz Oscillator ======= 0000002A 00196 REF_OSC_3 EQU 0X2A ; Most significant osc byte 000000F3 00197 REF_OSC_2 EQU 0XF3 ; Next byte 0000001D 00198 REF_OSC_1 EQU 0X1D ; Next byte 000000C4 00199 REF_OSC_0 EQU 0XC4 ; Least significant byte 00200 ; 00201 ; Limit contains the upper limit frequency as a 32 bit integer. 00202 ; This should not be set to more than one third of the reference oscillator 00203 ; frequency. The output filter of the DDS board must be designed to pass 00204 ; frequencies up to the maximum. 00205 ; 00000001 00206 LIMIT_3 EQU 0X01 ; Most significant byte for 30 MHz 000000C9 00207 LIMIT_2 EQU 0XC9 ; Next byte 000000C3 00208 LIMIT_1 EQU 0XC3 ; Next byte 00000080 00209 LIMIT_0 EQU 0X80 ; Least significant byte 00210 ; 00211 ; Default contains the default startup frequency as a 32 bit integer. 00212 ; MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 5 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00000000 00213 DEFAULT_3 EQU 0X00 ; Most significant byte for 14.025 MHz 000000D6 00214 DEFAULT_2 EQU 0XD6 ; Next byte 00000001 00215 DEFAULT_1 EQU 0X01 ; Next byte 00000028 00216 DEFAULT_0 EQU 0X28 ; Least significant byte 00217 ; 00000028 00218 BAND_END EQU 0X28 ; The offset to the last band table entry 00219 ; 00220 ; **************************************************************************** 00221 ; * Port and EEPROM Constants * 00222 ; **************************************************************************** 00223 ; 00000005 00224 PORTA EQU 0X05 00000006 00225 PORTB EQU 0X06 00000005 00226 TRISA EQU 0X05 00000006 00227 TRISB EQU 0X06 00000008 00228 EEDATA EQU 0X08 00000009 00229 EEADR EQU 0X09 00000002 00230 WREN EQU 0X02 00000001 00231 WR EQU 0X01 00000000 00232 RD EQU 0X00 00233 ; 00234 ; **************************************************************************** 00235 ; * ID location information: * 00236 ; * (MPASM warns about DW here, don't worry) * 00237 ; **************************************************************************** 00238 ; 2000 00239 ORG 0X2000 2000 007F 00240 DATA 0X007F 2001 007F 00241 DATA 0X007F 2002 007F 00242 DATA 0X007F 2003 007F 00243 DATA 0X007F 00244 ; 00245 ; 00246 ; **************************************************************************** 00247 ; * Setup the initial constant, based on the frequency of the reference * 00248 ; * oscillator. This can be tweaked with the calibrate function. * 00249 ; **************************************************************************** 00250 ; 2100 00251 ORG 0X2100 2100 00C4 00252 DATA REF_OSC_0 2101 001D 00253 DATA REF_OSC_1 2102 00F3 00254 DATA REF_OSC_2 2103 002A 00255 DATA REF_OSC_3 00256 ; 00257 ; Clear unused EEPROM bytes. 00258 ; 2104 0000 0000 0000 00259 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 6 LOC OBJECT CODE LINE SOURCE TEXT VALUE 0000 0000 0000 0000 0000 0000 0000 0000 0000 2122 0000 0000 0000 00260 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00261 ; 00262 ; **************************************************************************** 00263 ; * RAM page independent file registers: * 00264 ; **************************************************************************** 00265 ; 00000000 00266 INDF EQU 0X00 00000002 00267 PCL EQU 0X02 00000003 00268 STATUS EQU 0X03 00000004 00269 FSR EQU 0X04 0000000A 00270 PCLATH EQU 0X0A 0000000B 00271 INTCON EQU 0X0B 00272 ; 00273 ; ***************************************************************************** 00274 ; * Bit numbers for the STATUS file register: * 00275 ; ***************************************************************************** 00276 ; 00000005 00277 B_RP0 EQU 5 00000004 00278 B_NTO EQU 4 00000003 00279 B_NPD EQU 3 00000002 00280 B_Z EQU 2 00000001 00281 B_DC EQU 1 00000000 00282 B_C EQU 0 00283 ; 00284 ; **************************************************************************** 00285 ; * Assign names to IO pins. * 00286 ; **************************************************************************** 00287 ; 00288 ; B register bits: 00289 ; 00000000 00290 DDS_LOAD EQU 0X00 ; Update pin on AD9850 00000001 00291 LCD_RS EQU 0X01 ; 0=instruction, 1=data 00000002 00292 LCD_RW EQU 0X02 ; 0=write, 1=read 00000003 00293 LCD_E EQU 0X03 ; 0=disable, 1=enable 00000005 00294 DDS_CLK EQU 0X05 ; AD9850 write clock 00000007 00295 DDS_DAT EQU 0X07 ; AD9850 serial data input 00296 ; 00297 ; A register bits: 00298 ; 00000003 00299 PB_SWITCH EQU 0X03 ; Calibrate Push Button, (active low) 00300 ; MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 7 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00301 ; **************************************************************************** 00302 ; * Allocate variables in general purpose register space * 00303 ; **************************************************************************** 00304 ; 00305 CBLOCK 0X0C ; Start Data Block 00306 ; 0000000C 00307 FREQ_0 ; Display frequency (hex) 0000000D 00308 FREQ_1 ; (4 bytes) 0000000E 00309 FREQ_2 0000000F 00310 FREQ_3 00000010 00311 BCD_0 ; Display frequency (BCD) 00000011 00312 BCD_1 ; (5 bytes) 00000012 00313 BCD_2 00000013 00314 BCD_3 00000014 00315 BCD_4 00000015 00316 AD9850_0 ; AD9850 control word 00000016 00317 AD9850_1 ; (5 bytes) 00000017 00318 AD9850_2 00000018 00319 AD9850_3 00000019 00320 AD9850_4 0000001A 00321 FSTEP_0 ; Frequency inc/dec 0000001B 00322 FSTEP_1 ; (4 bytes) 0000001C 00323 FSTEP_2 0000001D 00324 FSTEP_3 0000001E 00325 BCD_COUNT ; Used in bin2BCD routine 0000001F 00326 BCD_TEMP ; " 00000020 00327 MULT_COUNT ; Used in calc_dds_word 00000021 00328 BIT_COUNT ; " 00000022 00329 BYTE2SEND ; 00000023 00330 OSC_0 ; Current oscillator 00000024 00331 OSC_1 ; (4 bytes) 00000025 00332 OSC_2 00000026 00333 OSC_3 00000027 00334 OSC_TEMP_0 ; Oscillator frequency 00000028 00335 OSC_TEMP_1 ; (4 bytes) 00000029 00336 OSC_TEMP_2 0000002A 00337 OSC_TEMP_3 0000002B 00338 LCD_CHAR ; Character being sent to the LCD 0000002C 00339 LCD_READ ; Character read from the LCD 0000002D 00340 TIMER1 ; Used in delay routines 0000002E 00341 TIMER2 ; " 0000002F 00342 REN_TIMER_0 ; For variable rate tuning 00000030 00343 REN_TIMER_1 ; (2 bytes) 00000031 00344 REN_NEW ; New value of encoder pins A and B 00000032 00345 REN_OLD ; Old value of encoder pins A and B 00000033 00346 REN_READ ; Encoder pins A and B and switch pin 00000034 00347 LAST_DIR ; Indicates last direction of encoder 00000035 00348 NEXT_DIR ; Indicates expected direction 00000036 00349 COUNT ; loop counter (gets reused) 00000037 00350 BAND ; Used to index a table of frequencies 00000038 00351 RS_VALUE ; The LCD rs line flag value 00352 ; 00353 ENDC ; End of Data Block MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 8 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00354 ; 00355 ; **************************************************************************** 00356 ; * The 16F84 resets to 0x00. * 00357 ; * The Interrupt vector is at 0x04. (Unused) * 00358 ; **************************************************************************** 00359 ; 0000 00360 ORG 0X0000 0000 00361 RESET_ENTRY 0000 282E 00362 GOTO START ; Jump around the band table to main program 00363 ; 00364 ; **************************************************************************** 00365 ; * This is the band table. Each entry is four instructions long, with each * 00366 ; * group of four literals representing the frequency as a 32 bit integer. * 00367 ; * New entries can be added to the end of the table or between existing * 00368 ; * entries. The constant band_end must be incremented by 4 for each entry * 00369 ; * added. * 00370 ; * * 00371 ; * This table is placed near the top of the program to allow as large a * 00372 ; * a table as possible to be indexed with the eight bit value in W. * 00373 ; * * 00374 ; **************************************************************************** 00375 ; 0001 00376 BAND_TABLE 0001 0782 00377 ADDWF PCL,F ; 0002 3400 00378 RETLW 0X00 ; 0 Hz 0003 3400 00379 RETLW 0X00 ; 0004 3400 00380 RETLW 0X00 ; 0005 3400 00381 RETLW 0X00 ; 0006 3400 00382 RETLW 0X00 ; 160 meters 0007 341B 00383 RETLW 0X1B ; 0008 3477 00384 RETLW 0X77 ; 0009 3440 00385 RETLW 0X40 ; 000A 3400 00386 RETLW 0X00 ; 80 meters 000B 3435 00387 RETLW 0X35 ; 000C 3467 00388 RETLW 0X67 ; 000D 34E0 00389 RETLW 0XE0 ; 000E 3400 00390 RETLW 0X00 ; 40 meters 000F 346A 00391 RETLW 0X6A ; 0010 34CF 00392 RETLW 0XCF ; 0011 34C0 00393 RETLW 0XC0 ; 0012 3400 00394 RETLW 0X00 ; 30 meters 0013 349A 00395 RETLW 0X9A ; 0014 341D 00396 RETLW 0X1D ; 0015 3420 00397 RETLW 0X20 ; 0016 3400 00398 RETLW 0X00 ; 20 meters 0017 34D5 00399 RETLW 0XD5 ; 0018 349F 00400 RETLW 0X9F ; 0019 3480 00401 RETLW 0X80 ; 001A 3401 00402 RETLW 0X01 ; 17 meters 001B 3413 00403 RETLW 0X13 ; 001C 34B2 00404 RETLW 0XB2 ; 001D 3420 00405 RETLW 0X20 ; 001E 3401 00406 RETLW 0X01 ; 15 meters MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 9 LOC OBJECT CODE LINE SOURCE TEXT VALUE 001F 3440 00407 RETLW 0X40 ; 0020 346F 00408 RETLW 0X6F ; 0021 3440 00409 RETLW 0X40 ; 0022 3401 00410 RETLW 0X01 ; 12 meters 0023 347B 00411 RETLW 0X7B ; 0024 34CA 00412 RETLW 0XCA ; 0025 3490 00413 RETLW 0X90 ; 0026 3401 00414 RETLW 0X01 ; 10 meters 0027 34AB 00415 RETLW 0XAB ; 0028 343F 00416 RETLW 0X3F ; 0029 3400 00417 RETLW 0X00 ; 002A 3401 00418 RETLW 0X01 ; 30 MHz 002B 34C9 00419 RETLW 0XC9 ; 002C 34C3 00420 RETLW 0XC3 ; 002D 3480 00421 RETLW 0X80 ; 00422 ; 00423 ; ***************************************************************************** 00424 ; * * 00425 ; * Purpose: This is the start of the program. It initializes the LCD and * 00426 ; * detects whether to enter calibrate mode. If so, it calls the * 00427 ; * Calibrate routine. Otherwise, it sets the power-on frequency * 00428 ; * and enters the loop to poll the encoder. * 00429 ; * * 00430 ; * Input: The start up frequency is defined in the default_3 ... * 00431 ; * definitions above, and relies on the reference oscillator * 00432 ; * constant defined in ref_osc_3 ... ref_osc_0. * 00433 ; * * 00434 ; * Output: Normal VFO operation. * 00435 ; * * 00436 ; ***************************************************************************** 00437 ; 002E 00438 START 002E 018B 00439 CLRF INTCON ; No interrupts for now 002F 1683 00440 BSF STATUS,B_RP0 ; Switch to bank 1 0030 1781 00441 BSF 0X01,7 ; Disable weak pullups 0031 30FF 00442 MOVLW 0XFF ; Tristate port A 0032 0085 00443 MOVWF TRISA ; 0033 0186 00444 CLRF TRISB ; Set port B to all outputs 0034 1283 00445 BCF STATUS,B_RP0 ; Switch back to bank 0 0035 20A5 00446 CALL INIT_LCD ; Initialize the LCD 00447 ; 00448 ; Enter Calibrate Mode if push button is pressed while turning the 00449 ; power on. 00450 ; 0036 1985 00451 BTFSC PORTA,PB_SWITCH ; Is the switch pressed? 0037 2839 00452 GOTO READ_EEOCS ; No, get clock freq from EEPROM 0038 213F 00453 CALL CALIBRATE ; Yes, calibrate 00454 ; 00455 ; Get the reference oscillator constant from the EEPROM. 00456 ; 0039 00457 READ_EEOCS 0039 0189 00458 CLRF EEADR ; Reset the EEPROM read address 003A 2299 00459 CALL READ_EEPROM ; Read EEPROM MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 10 LOC OBJECT CODE LINE SOURCE TEXT VALUE 003B 0808 00460 MOVF EEDATA,W ; Get the first osc byte 003C 00A3 00461 MOVWF OSC_0 ; Save osc frequency 003D 2299 00462 CALL READ_EEPROM ; Get next byte 003E 0808 00463 MOVF EEDATA,W ; 003F 00A4 00464 MOVWF OSC_1 ; Save it 0040 2299 00465 CALL READ_EEPROM ; Get the third byte 0041 0808 00466 MOVF EEDATA,W ; 0042 00A5 00467 MOVWF OSC_2 ; Save it 0043 2299 00468 CALL READ_EEPROM ; Get the fourth byte 0044 0808 00469 MOVF EEDATA,W ; 0045 00A6 00470 MOVWF OSC_3 ; Save it 00471 ; 00472 ; Set the power on frequency to the defined value. 00473 ; 0046 3028 00474 MOVLW DEFAULT_0 ; Get the least significant byte 0047 008C 00475 MOVWF FREQ_0 ; Save it 0048 3001 00476 MOVLW DEFAULT_1 ; Get the next byte 0049 008D 00477 MOVWF FREQ_1 ; Save it 004A 30D6 00478 MOVLW DEFAULT_2 ; And the next 004B 008E 00479 MOVWF FREQ_2 ; Save it 004C 3000 00480 MOVLW DEFAULT_3 ; Get the most significant byte 004D 008F 00481 MOVWF FREQ_3 ; Save it 00482 ; 00483 ; Display the power on frequency. 00484 ; 004E 21F3 00485 CALL BIN2BCD ; Convert it to BCD 004F 2221 00486 CALL SHOW_FREQ ; Display it 00487 ; 00488 ; Send power on frequency to the DDS chip. 00489 ; 0050 21A3 00490 CALL CALC_DDS_WORD ; Convert to delta value 0051 21D9 00491 CALL SEND_DDS_WORD ; Send the power-on frequency to the 00492 ; AD9850 in serial mode 00493 ; 00494 ; Get the power on encoder value. 00495 ; 0052 0805 00496 MOVF PORTA,W ; Read port A 0053 00B3 00497 MOVWF REN_READ ; Save it in ren_read 0054 3003 00498 MOVLW 0X03 ; Get encoder mask 0055 0533 00499 ANDWF REN_READ,W ; Get encoder bits 0056 00B2 00500 MOVWF REN_OLD ; Save in ren_old 00501 ; 00502 ; Initialize variables. 00503 ; 0057 01B0 00504 CLRF REN_TIMER_1 ; Initialize the encoder speed timer 0058 3040 00505 MOVLW 0X40 ; to 0059 00AF 00506 MOVWF REN_TIMER_0 ; 0x0040 005A 01B4 00507 CLRF LAST_DIR ; Clear the knob direction indicator 005B 01B7 00508 CLRF BAND ; Clear the band indicator 00509 ; 00510 ; Fall into the Main Program Loop 00511 ; 00512 ; ***************************************************************************** MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 11 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00513 ; * * 00514 ; * Purpose: This is the Main Program Loop. The program's main loop * 00515 ; * calls poll_encoder, which continuously polls the rotary shaft * 00516 ; * encoder. When the shaft encoder has changed, the direction * 00517 ; * it moved is determined and stored in last_dir. The subroutine * 00518 ; * then returns to main. * 00519 ; * * 00520 ; * If the push button switch was not pressed, then the variable * 00521 ; * fstep is calculated based on the delay between shaft encoder * 00522 ; * changes. ren_timer contains the delay value determined by * 00523 ; * the poll_encoder subroutine. The variable fstep is added or * 00524 ; * subtracted from the current VFO frequency stored in freq. * 00525 ; * The contents of freq are then converted to a BCD number in * 00526 ; * subroutine bin2BCD. The subroutine show_freq is then called * 00527 ; * to display the result on the Liquid Crystal Display. Next, the * 00528 ; * subroutine calc_dds_word is used to calculate the DDS * 00529 ; * frequency control word from the values in freq and osc. * 00530 ; * The result is stored in AD9850. This data is transferred to * 00531 ; * the AD9850 DDS chip by calling the subroutine send_dds_word. * 00532 ; * * 00533 ; * If the push button is pressed while turning the encoder then * 00534 ; * freq is loaded with a constant stored in band_table. The * 00535 ; * variable band is used as an index into the table. Band * 00536 ; * is incremented or decremented based on the encoder direction. * 00537 ; * * 00538 ; * Input: None. * 00539 ; * * 00540 ; * Output: None. * 00541 ; * * 00542 ; ***************************************************************************** 00543 ; 005C 00544 MAIN 005C 2115 00545 CALL POLL_ENCODER ; Check for knob movement 005D 1DB3 00546 BTFSS REN_READ,3 ; Change band? 005E 287B 00547 GOTO CHANGE_BAND ; Yes, change band 00548 ; 00549 ; Determine step size to use (1 Hz or 1 kHz). 00550 ; 005F 019D 00551 CLRF FSTEP_3 ; Guess that we want 1 Hz steps by 0060 019C 00552 CLRF FSTEP_2 ; setting fstep to one. 0061 019B 00553 CLRF FSTEP_1 ; 0062 3001 00554 MOVLW 0X01 ; 0063 009A 00555 MOVWF FSTEP_0 ; 0064 1933 00556 BTFSC REN_READ,2 ; Is the encoder switch pressed? 0065 2870 00557 GOTO GO_STEP ; No, use the 1 Hz step 0066 30E8 00558 MOVLW 0XE8 ; Yes, set the step value to 1 kHz 0067 009A 00559 MOVWF FSTEP_0 ; by setting fstep_0 to 0xE8 and 0068 3003 00560 MOVLW 0X03 ; fstep_1 to 0x03 0069 009B 00561 MOVWF FSTEP_1 ; 006A 2870 00562 GOTO GO_STEP ; Use the 1 kHz step 00563 ; 00564 ; Adjust the tuning step based on ren_timer. ren_timer is incremented 00565 ; by 8 from its initial value of 0x0040 each time the poll_encoder finds MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 12 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00566 ; no change in the encoder input, until the high bit of ren_timer_1 00567 ; becomes a one. The default fstep of 1 Hz is multiplied by two for 00568 ; each leading zero in ren_timer, up to a maximum of 9 times. (This is 00569 ; because ren_timer starts at 0x0040, only the first nine bits can be 00570 ; zero in a row). The faster the knob is turned, the lower the number 00571 ; in ren_timer will be, and the larger the step value will be. 00572 ; 00573 ; 006B 00574 BUMP_STEP 006B 1003 00575 BCF STATUS,B_C ; Clear the carry flag 006C 0D9A 00576 RLF FSTEP_0,F ; Multiply the step by 2 by rotating left 006D 0D9B 00577 RLF FSTEP_1,F ; 006E 0D9C 00578 RLF FSTEP_2,F ; 006F 0D9D 00579 RLF FSTEP_3,F ; 0070 00580 GO_STEP 0070 0DAF 00581 RLF REN_TIMER_0,F ; Multiply the encoder timer by 2 0071 0DB0 00582 RLF REN_TIMER_1,F ; 0072 1C03 00583 BTFSS STATUS,B_C ; Has a one floated to the carry yet? 0073 286B 00584 GOTO BUMP_STEP ; No, then double the step size 00585 ; 00586 ; Based on the knob direction, either add or subtract the increment, 00587 ; then update the LCD and DDS. 00588 ; 0074 18B4 00589 BTFSC LAST_DIR,1 ; Is the knob going up? 0075 2878 00590 GOTO UP ; Yes, then add the increment 0076 00591 DOWN 0076 2102 00592 CALL SUB_STEP ; Subtract fstep from freq 0077 288E 00593 GOTO WRITE ; Update LCD and DDS 0078 00594 UP 0078 20C5 00595 CALL ADD_STEP ; Add fstep to freq 0079 20DD 00596 CALL CHECK_ADD ; Make sure we did not exceed the maximum 007A 288E 00597 GOTO WRITE ; Update LCD and DDS 00598 ; 00599 ; ***************************************************************************** 00600 ; * * 00601 ; * Purpose: This routine increments through the band table each time the * 00602 ; * knob moves a notch, updating the LCD and DDS, until the band * 00603 ; * button is no longer pushed. * 00604 ; * * 00605 ; * Input: The value of the band push button and the encoder bits * 00606 ; * * 00607 ; * Output: Updated freq value, and new frequency on the LCD and DDS. * 00608 ; * * 00609 ; ***************************************************************************** 00610 ; 007B 00611 CHANGE_BAND 007B 18B4 00612 BTFSC LAST_DIR,1 ; Are we going up in the band list? 007C 2887 00613 GOTO BAND_UP ; Yes, increment band address 007D 3004 00614 MOVLW 0X04 ; No, get 4 bytes to subtract 007E 02B7 00615 SUBWF BAND,F ; Move down in band list 007F 30D7 00616 MOVLW 0XFF-BAND_END ; Check to see if we have fallen off the 0080 0737 00617 ADDWF BAND,W ; bottom of the table. 0081 1C03 00618 BTFSS STATUS,B_C ; Off the bottom? MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 13 LOC OBJECT CODE LINE SOURCE TEXT VALUE 0082 2885 00619 GOTO VALID ; No, continue 0083 3028 00620 MOVLW BAND_END ; Yes, go to highest entry 0084 00B7 00621 MOVWF BAND ; 0085 00622 VALID 0085 2093 00623 CALL GET_BAND ; Get the new band frequency 0086 288E 00624 GOTO WRITE ; Set the frequency and continue 0087 00625 BAND_UP 0087 3004 00626 MOVLW 0X04 ; Table entries are 4 bytes apart 0088 07B7 00627 ADDWF BAND,F ; Increment the band pointer 0089 30D7 00628 MOVLW 0XFF-BAND_END ; Check to see if we have gone over the 008A 0737 00629 ADDWF BAND,W ; top of the table. 008B 1803 00630 BTFSC STATUS,B_C ; Did we go over the top of the table? 008C 01B7 00631 CLRF BAND ; Yes, go to the bottom entry 008D 2093 00632 CALL GET_BAND ; Get the new band frequency 008E 00633 WRITE 008E 21F3 00634 CALL BIN2BCD ; Convert the frequency to BCD 008F 2221 00635 CALL SHOW_FREQ ; Display the frequency on the LCD 0090 21A3 00636 CALL CALC_DDS_WORD ; Find the control word for the DDS chip 0091 21D9 00637 CALL SEND_DDS_WORD ; Send the control word to the DDS chip 0092 285C 00638 GOTO MAIN ; Continue polling the encoder (endless loop) 00639 ; 00640 ; ***************************************************************************** 00641 ; * * 00642 ; * Purpose: This routine reads the frequency value of a band table entry * 00643 ; * pointed to by band and returns it in freq_3...freq_0. * 00644 ; * * 00645 ; * Input: band must contain the index of the desired band entry * 4 * 00646 ; * (with the entries numbered from zero). * 00647 ; * * 00648 ; * Output: The band frequency in freq. * 00649 ; * * 00650 ; ***************************************************************************** 00651 ; 0093 00652 GET_BAND 0093 0837 00653 MOVF BAND,W ; Get the index of the high byte 0094 2001 00654 CALL BAND_TABLE ; Get the value into W 0095 008F 00655 MOVWF FREQ_3 ; Save it in freq_3 0096 0AB7 00656 INCF BAND,F ; Increment index to next byte 0097 0837 00657 MOVF BAND,W ; Get the index of the next byte 0098 2001 00658 CALL BAND_TABLE ; Get the value into W 0099 008E 00659 MOVWF FREQ_2 ; Save it in freq_2 009A 0AB7 00660 INCF BAND,F ; Increment index to the next byte 009B 0837 00661 MOVF BAND,W ; Get the index to the next byte 009C 2001 00662 CALL BAND_TABLE ; Get the value into W 009D 008D 00663 MOVWF FREQ_1 ; Save it in freq_1 009E 0AB7 00664 INCF BAND,F ; Increment index to the low byte 009F 0837 00665 MOVF BAND,W ; Get the index to the low byte 00A0 2001 00666 CALL BAND_TABLE ; Get the value into W 00A1 008C 00667 MOVWF FREQ_0 ; Save it in freq_0 00A2 3003 00668 MOVLW 0X03 ; Get a constant three 00A3 02B7 00669 SUBWF BAND,F ; Restore original value of band 00A4 0008 00670 RETURN ; Return to the caller 00671 ; MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 14 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00672 ; ***************************************************************************** 00673 ; * * 00674 ; * Purpose: Power on initialization of Liquid Crystal Display. The LCD * 00675 ; * controller chip must be equivalent to an Hitachi 44780. The * 00676 ; * LCD is assumed to be a 16 X 1 display. * 00677 ; * * 00678 ; * Input: None * 00679 ; * * 00680 ; * Output: None * 00681 ; * * 00682 ; ***************************************************************************** 00683 ; 00A5 00684 INIT_LCD 00A5 22A1 00685 CALL WAIT_64MS ; Wait for LCD to power up 00A6 3030 00686 MOVLW 0X30 ; LCD init instruction (First) 00A7 0086 00687 MOVWF PORTB ; Send to LCD via RB7..RB0 00A8 1586 00688 BSF PORTB,LCD_E ; Set the LCD E line high, 00A9 22A1 00689 CALL WAIT_64MS ; wait a "long" time, 00AA 1186 00690 BCF PORTB,LCD_E ; and then Clear E 00AB 3030 00691 MOVLW 0X30 ; LCD init instruction (Second) 00AC 0086 00692 MOVWF PORTB ; Send to LCD via RB7..RB0 00AD 1586 00693 BSF PORTB,LCD_E ; Set E high, 00AE 22A4 00694 CALL WAIT_32MS ; wait a while, 00AF 1186 00695 BCF PORTB,LCD_E ; and then Clear E 00B0 3030 00696 MOVLW 0X30 ; LCD init instruction (Third) 00B1 0086 00697 MOVWF PORTB ; Send to LCD via RB7..RB0 00B2 1586 00698 BSF PORTB,LCD_E ; Set E high, 00B3 22A4 00699 CALL WAIT_32MS ; wait a while, 00B4 1186 00700 BCF PORTB,LCD_E ; and then Clear E 00B5 3020 00701 MOVLW 0X20 ; 4-bit mode instruction 00B6 0086 00702 MOVWF PORTB ; Send to LCD via RB7..RB0 00B7 1586 00703 BSF PORTB,LCD_E ; Set E high, 00B8 22A7 00704 CALL WAIT_16MS ; wait a while, 00B9 1186 00705 BCF PORTB,LCD_E ; and then Clear E 00BA 3028 00706 MOVLW 0X28 ; 1/16 duty cycle, 5x8 matrix 00BB 226A 00707 CALL CMND2LCD ; Send command in w to LCD 00BC 3008 00708 MOVLW 0X08 ; Display off, cursor and blink off 00BD 226A 00709 CALL CMND2LCD ; Send command to LCD 00BE 3001 00710 MOVLW 0X01 ; Clear and reset cursor 00BF 226A 00711 CALL CMND2LCD ; Send command in w to LCD 00C0 3006 00712 MOVLW 0X06 ; Set cursor to move right, no shift 00C1 226A 00713 CALL CMND2LCD ; Send command in w to LCD 00C2 300C 00714 MOVLW 0X0C ; Display on, cursor and blink off 00C3 226A 00715 CALL CMND2LCD ; Send command in w to LCD 00C4 0008 00716 RETURN ; 00717 ; 00718 ; ***************************************************************************** 00719 ; * * 00720 ; * Purpose: This routine adds the 32 bit value of fstep to the 32 bit * 00721 ; * value in freq. When incrementing, the fstep value is a * 00722 ; * positive integer. When decrementing, fstep is the complement * 00723 ; * of the value being subtracted. * 00724 ; * * MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 15 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00725 ; * Input: The 32 bit values in fstep and freq * 00726 ; * * 00727 ; * Output: The sum of fstep and freq is stored in freq. When incrementing * 00728 ; * this value may exceed the maximum. When decrementing, it may * 00729 ; * go negative. * 00730 ; * * 00731 ; ***************************************************************************** 00C5 00732 ADD_STEP 00C5 081A 00733 MOVF FSTEP_0,W ; Get low byte of the increment 00C6 078C 00734 ADDWF FREQ_0,F ; Add it to the low byte of freq 00C7 1C03 00735 BTFSS STATUS,B_C ; Any carry? 00C8 28CE 00736 GOTO ADD1 ; No, add next byte 00C9 0F8D 00737 INCFSZ FREQ_1,F ; Ripple carry up to the next byte 00CA 28CE 00738 GOTO ADD1 ; No new carry, add next byte 00CB 0F8E 00739 INCFSZ FREQ_2,F ; Ripple carry up to the next byte 00CC 28CE 00740 GOTO ADD1 ; No new carry, add next byte 00CD 0A8F 00741 INCF FREQ_3,F ; Ripple carry up to the highest byte 00CE 00742 ADD1 00CE 081B 00743 MOVF FSTEP_1,W ; Get the next increment byte 00CF 078D 00744 ADDWF FREQ_1,F ; Add it to the next higher byte 00D0 1C03 00745 BTFSS STATUS,B_C ; Any carry? 00D1 28D5 00746 GOTO ADD2 ; No, add next byte 00D2 0F8E 00747 INCFSZ FREQ_2,F ; Ripple carry up to the next byte 00D3 28D5 00748 GOTO ADD2 ; No new carry, add next byte 00D4 0A8F 00749 INCF FREQ_3,F ; Ripple carry up to the highest byte 00D5 00750 ADD2 00D5 081C 00751 MOVF FSTEP_2,W ; Get the next to most significant increment 00D6 078E 00752 ADDWF FREQ_2,F ; Add it to the freq byte 00D7 1C03 00753 BTFSS STATUS,B_C ; Any carry? 00D8 28DA 00754 GOTO ADD3 ; No, add last byte 00D9 0A8F 00755 INCF FREQ_3,F ; Ripple carry up to the highest byte 00DA 00756 ADD3 00DA 081D 00757 MOVF FSTEP_3,W ; Get the most significant increment byte 00DB 078F 00758 ADDWF FREQ_3,F ; Add it to the most significant freq 00DC 0008 00759 RETURN ; Return to the caller 00760 ; 00761 ; ***************************************************************************** 00762 ; * * 00763 ; * Purpose: Check if freq exceeds the upper limit. * 00764 ; * * 00765 ; * Input: The 32 bit values in freq * 00766 ; * * 00767 ; * Output: If freq is below the limit, it is unchanged. Otherwise, it is * 00768 ; * set to equal the upper limit. * 00769 ; * * 00770 ; ***************************************************************************** 00771 ; 00DD 00772 CHECK_ADD 00773 ; 00774 ; Check the most significant byte. 00775 ; 00DD 30FE 00776 MOVLW 0XFF-LIMIT_3 ; Get (FF - limit of high byte) 00DE 070F 00777 ADDWF FREQ_3,W ; Add it to the current high byte MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 16 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00DF 1803 00778 BTFSC STATUS,B_C ; Was high byte too large? 00E0 28F9 00779 GOTO SET_MAX ; Yes, apply limit 00E1 3001 00780 MOVLW LIMIT_3 ; Get high limit value 00E2 020F 00781 SUBWF FREQ_3,W ; Subtract the limit value 00E3 1C03 00782 BTFSS STATUS,B_C ; Are we at the limit for the byte? 00E4 2901 00783 GOTO EXIT1 ; No, below. Checks are done. 00784 ; 00785 ; Check the second most significant byte. 00786 ; 00E5 3036 00787 MOVLW 0XFF-LIMIT_2 ; Get (FF - limit of next byte) 00E6 070E 00788 ADDWF FREQ_2,W ; Add it to the current byte 00E7 1803 00789 BTFSC STATUS,B_C ; Is the current value too high? 00E8 28F9 00790 GOTO SET_MAX ; Yes, apply the limit 00E9 30C9 00791 MOVLW LIMIT_2 ; Second limit byte 00EA 020E 00792 SUBWF FREQ_2,W ; Subtract limit value 00EB 1C03 00793 BTFSS STATUS,B_C ; Are we at the limit for the byte? 00EC 2901 00794 GOTO EXIT1 ; No, below. Checks are done. 00795 ; 00796 ; Check the third most significant byte. 00797 ; 00ED 303C 00798 MOVLW 0XFF-LIMIT_1 ; Get (FF - limit of next byte) 00EE 070D 00799 ADDWF FREQ_1,W ; Add it to the current byte 00EF 1803 00800 BTFSC STATUS,B_C ; Is the current value too high? 00F0 28F9 00801 GOTO SET_MAX ; Yes, apply the limit 00F1 30C3 00802 MOVLW LIMIT_1 ; Third limit byte 00F2 020D 00803 SUBWF FREQ_1,W ; Subtract limit value 00F3 1C03 00804 BTFSS STATUS,B_C ; Are we at the limit for the byte? 00F4 2901 00805 GOTO EXIT1 ; No, below. Checks are done. 00806 ; 00807 ; Check the least significant byte. 00808 ; 00F5 3080 00809 MOVLW LIMIT_0 ; Fourth limit byte 00F6 020C 00810 SUBWF FREQ_0,W ; Subtract limit value 00F7 1C03 00811 BTFSS STATUS,B_C ; Are we at the limit for the byte? 00F8 2901 00812 GOTO EXIT1 ; No, below. Checks are done. 00F9 00813 SET_MAX 00F9 3080 00814 MOVLW LIMIT_0 ; Get least significant limit 00FA 008C 00815 MOVWF FREQ_0 ; Set it in freq 00FB 30C3 00816 MOVLW LIMIT_1 ; Get the next byte limit 00FC 008D 00817 MOVWF FREQ_1 ; Set it in freq_1 00FD 30C9 00818 MOVLW LIMIT_2 ; Get the next byte limit 00FE 008E 00819 MOVWF FREQ_2 ; Set it in freq_2 00FF 3001 00820 MOVLW LIMIT_3 ; Get the most significant limit 0100 008F 00821 MOVWF FREQ_3 ; Set it in freq_3 0101 00822 EXIT1 0101 0008 00823 RETURN ; Return to the caller 00824 ; 00825 ; ***************************************************************************** 00826 ; * * 00827 ; * Purpose: Subtract the increment step from freq, checking that it does * 00828 ; * not go below zero. * 00829 ; * * 00830 ; * Input: The values in fstep and freq. * MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 17 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00831 ; * * 00832 ; * Output: The updated value in freq. * 00833 ; * * 00834 ; ***************************************************************************** 00835 ; 0102 00836 SUB_STEP 0102 099A 00837 COMF FSTEP_0,F ; Subtraction of fstep from 0103 099B 00838 COMF FSTEP_1,F ; freq is done by adding the 0104 099C 00839 COMF FSTEP_2,F ; twos compliment of fstep to 0105 099D 00840 COMF FSTEP_3,F ; freq. 0106 0F9A 00841 INCFSZ FSTEP_0,F ; Increment last byte 0107 290D 00842 GOTO COMP_DONE ; Non-zero, continue 0108 0F9B 00843 INCFSZ FSTEP_1,F ; Increment next byte 0109 290D 00844 GOTO COMP_DONE ; Non-zero, continue 010A 0F9C 00845 INCFSZ FSTEP_2,F ; Increment next byte 010B 290D 00846 GOTO COMP_DONE ; Non-zero, continue 010C 0A9D 00847 INCF FSTEP_3,F ; Increment the high byte 010D 00848 COMP_DONE 010D 20C5 00849 CALL ADD_STEP ; Add the compliment to do the subtraction 00850 ; 00851 ; If the frequency has gone negative, clear it to zero. 00852 ; 010E 1F8F 00853 BTFSS FREQ_3,7 ; Is high order frequency byte "negative"? 010F 2914 00854 GOTO EXIT2 ; No, keep going 0110 00855 SET_MIN 0110 018C 00856 CLRF FREQ_0 ; Yes, set the frequency to zero 0111 018D 00857 CLRF FREQ_1 ; 0112 018E 00858 CLRF FREQ_2 ; 0113 018F 00859 CLRF FREQ_3 ; 0114 00860 EXIT2 0114 0008 00861 RETURN ; Return to the caller 00862 ; 00863 ; ***************************************************************************** 00864 ; * * 00865 ; * Purpose: This routine does the following: * 00866 ; * 1. Records how long it took for the knob to move a notch * 00867 ; * in ren_timer. * 00868 ; * 2. Clears the watchdog timer. * 00869 ; * 3. Reads the encoder bits until a change is detected, then * 00870 ; * determines the direction the knob was moved. * 00871 ; * * 00872 ; * Input: Knob input read from port A * 00873 ; * ren_old -> the last encoder bits read * 00874 ; * last_dir -> the last direction moved * 00875 ; * * 00876 ; * Output: ren_timer -> an indication the speed of the knob. * 00877 ; * ren_new -> the current encoder bits * 00878 ; * last_dir -> the last direction (0 = down, 2 = up) * 00879 ; * * 00880 ; ***************************************************************************** 00881 ; 0115 00882 POLL_ENCODER 0115 01B0 00883 CLRF REN_TIMER_1 ; Put starting values in ren_timer MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 18 LOC OBJECT CODE LINE SOURCE TEXT VALUE 0116 3040 00884 MOVLW 0X40 ; Start with the high bit set in ren_timer 0117 00AF 00885 MOVWF REN_TIMER_0 ; 0118 00886 READ_ENCODER 0118 0064 00887 CLRWDT ; Reset the watchdog timer 0119 1BB0 00888 BTFSC REN_TIMER_1,7 ; Has the bit floated to bottom of ren_timer? 011A 291F 00889 GOTO NO_INC ; Yes, don't move it any further 011B 3008 00890 MOVLW 0X08 ; 011C 07AF 00891 ADDWF REN_TIMER_0,F ; 011D 1803 00892 BTFSC STATUS,B_C ; Did the add force a carry? 011E 0AB0 00893 INCF REN_TIMER_1,F ; Yes, then add one to ren_timer_1 011F 00894 NO_INC ; 011F 0805 00895 MOVF PORTA,W ; Get the current encoder value 0120 00B3 00896 MOVWF REN_READ ; Save it 0121 3003 00897 MOVLW 0X03 ; Get encoder mask 0122 0533 00898 ANDWF REN_READ,W ; Isolate encoder bits 0123 00B1 00899 MOVWF REN_NEW ; Save new value 0124 0632 00900 XORWF REN_OLD,W ; Has it changed? 0125 1903 00901 BTFSC STATUS,B_Z ; 0126 2918 00902 GOTO READ_ENCODER ; No, keep looking until it changes 00903 ; 00904 ; Determine which direction the encoder turned. 00905 ; 0127 1003 00906 BCF STATUS,B_C ; Clear the carry bit 0128 0DB2 00907 RLF REN_OLD,F ; 0129 0831 00908 MOVF REN_NEW,W ; 012A 06B2 00909 XORWF REN_OLD,F ; 012B 0832 00910 MOVF REN_OLD,W ; 012C 3902 00911 ANDLW 0X02 ; 012D 00B5 00912 MOVWF NEXT_DIR ; 012E 0634 00913 XORWF LAST_DIR,W ; 00914 ; 00915 ; Prevent encoder slip from giving a false change in direction. 00916 ; 012F 1903 00917 BTFSC STATUS,B_Z ; Zero? 0130 2936 00918 GOTO PE_CONTINUE ; No slip; keep going 0131 0835 00919 MOVF NEXT_DIR,W ; Yes, update direction 0132 00B4 00920 MOVWF LAST_DIR ; 0133 0831 00921 MOVF REN_NEW,W ; Save the current encoder bits for next time 0134 00B2 00922 MOVWF REN_OLD ; 0135 2918 00923 GOTO READ_ENCODER ; Try again 0136 00924 PE_CONTINUE 0136 18B2 00925 BTFSC REN_OLD,1 ; Are we going down? 0137 293A 00926 GOTO UP2 ; No, indicate we are going up 0138 01B4 00927 CLRF LAST_DIR ; Yes, clear last_dir 0139 293C 00928 GOTO EXIT3 ; Finish and return 013A 00929 UP2 013A 3002 00930 MOVLW 0X02 ; Set UP value in last_dir 013B 00B4 00931 MOVWF LAST_DIR ; 013C 00932 EXIT3 013C 0831 00933 MOVF REN_NEW,W ; Get the current encoder bits 013D 00B2 00934 MOVWF REN_OLD ; Save them in ren_old for the next time 013E 0008 00935 RETURN ; Return to the caller 00936 ; MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 19 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00937 ; ***************************************************************************** 00938 ; * * 00939 ; * Purpose: This routine is entered at start up if the push button is * 00940 ; * pressed. "10,000.00 CAL" is displayed on the LCD, and the * 00941 ; * the DDS chip is programmed to produce 10 MHz, based on the * 00942 ; * osc value stored in the EEPROM. As long as the button is * 00943 ; * pressed, the osc value is slowly altered to allow the output * 00944 ; * to be trimmed to exactly 10 MHz. Once the encoder is turned * 00945 ; * after the button is released, the new osc value is stored in * 00946 ; * the EEPROM and normal operation begins. * 00947 ; * * 00948 ; * Input: The original osc constant in EEPROM * 00949 ; * * 00950 ; * Output: The corrected osc constant in EEPROM * 00951 ; * * 00952 ; ***************************************************************************** 00953 ; 013F 00954 CALIBRATE 013F 3080 00955 MOVLW 0X80 ; Set frequency to 10MHz by 0140 008C 00956 MOVWF FREQ_0 ; setting freq to the binary equivalent 0141 3096 00957 MOVLW 0X96 ; of 10,000,000. 0142 008D 00958 MOVWF FREQ_1 ; . 0143 3098 00959 MOVLW 0X98 ; . 0144 008E 00960 MOVWF FREQ_2 ; . 0145 3000 00961 MOVLW 0X00 ; . 0146 008F 00962 MOVWF FREQ_3 ; . 00963 ; 00964 ; Read the starting reference oscillator value form EEPROM. 00965 ; 0147 0189 00966 CLRF EEADR ; Reset the EEPROM read address 0148 2299 00967 CALL READ_EEPROM ; Read EEPROM 0149 0808 00968 MOVF EEDATA,W ; Get the first osc byte 014A 00A3 00969 MOVWF OSC_0 ; Save osc frequency 014B 2299 00970 CALL READ_EEPROM ; Get next byte 014C 0808 00971 MOVF EEDATA,W ; 014D 00A4 00972 MOVWF OSC_1 ; Save it 014E 2299 00973 CALL READ_EEPROM ; Get the third byte 014F 0808 00974 MOVF EEDATA,W ; 0150 00A5 00975 MOVWF OSC_2 ; Save it 0151 2299 00976 CALL READ_EEPROM ; Get the fourth byte 0152 0808 00977 MOVF EEDATA,W ; 0153 00A6 00978 MOVWF OSC_3 ; Save it 0154 21F3 00979 CALL BIN2BCD ; Calculate BCD version of 10,000.00 0155 2221 00980 CALL SHOW_FREQ ; Display the frequency on the LCD 0156 30C4 00981 MOVLW 0XC4 ; Point LCD at digit 14 0157 00AB 00982 MOVWF LCD_CHAR ; 0158 226A 00983 CALL CMND2LCD ; 0159 3043 00984 MOVLW 'C' ; Send a C 015A 00AB 00985 MOVWF LCD_CHAR ; 015B 226E 00986 CALL DATA2LCD ; 015C 3041 00987 MOVLW 'A' ; Send an A 015D 00AB 00988 MOVWF LCD_CHAR ; 015E 226E 00989 CALL DATA2LCD ; MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 20 LOC OBJECT CODE LINE SOURCE TEXT VALUE 015F 304C 00990 MOVLW 'L' ; Send an L 0160 00AB 00991 MOVWF LCD_CHAR ; 0161 226E 00992 CALL DATA2LCD ; 0162 00993 CAL_LOOP 0162 21A3 00994 CALL CALC_DDS_WORD ; Calculate DDS value based on current osc 0163 21D9 00995 CALL SEND_DDS_WORD ; Update the DDS chip 0164 2115 00996 CALL POLL_ENCODER ; Wait until the encoder has moved. 0165 019D 00997 CLRF FSTEP_3 ; Clear the three most significant 0166 019C 00998 CLRF FSTEP_2 ; bytes of fstep 0167 019B 00999 CLRF FSTEP_1 ; 0168 3010 01000 MOVLW 0X10 ; Assume that we are adjusting slowly 0169 009A 01001 MOVWF FSTEP_0 ; Use small increment 016A 1933 01002 BTFSC REN_READ,2 ; Was the encoder changing slowly? 016B 296E 01003 GOTO UPDATE_OSC ; Yes, then continue with small increment 016C 3080 01004 MOVLW 0X80 ; No, then use the large increment 016D 009A 01005 MOVWF FSTEP_0 ; 016E 01006 UPDATE_OSC 016E 0000 01007 NOP ; Wait a cycle 016F 18B4 01008 BTFSC LAST_DIR,1 ; Are we moving down? 0170 297C 01009 GOTO FASTER ; No, increase the osc value 01010 ; 01011 ; slower 01012 ; 0171 099A 01013 COMF FSTEP_0,F ; Subtraction of fstep is done by 0172 099B 01014 COMF FSTEP_1,F ; adding the twos compliment of fsetp 0173 099C 01015 COMF FSTEP_2,F ; to osc 0174 099D 01016 COMF FSTEP_3,F ; 0175 0F9A 01017 INCFSZ FSTEP_0,F ; Increment last byte 0176 297C 01018 GOTO FASTER ; Non-zero, continue 0177 0F9B 01019 INCFSZ FSTEP_1,F ; Increment next byte 0178 297C 01020 GOTO FASTER ; Non-zero, continue 0179 0F9C 01021 INCFSZ FSTEP_2,F ; Increment next byte 017A 297C 01022 GOTO FASTER ; Non-zero, continue 017B 0A9D 01023 INCF FSTEP_3,F ; Increment the high byte 017C 01024 FASTER 017C 081A 01025 MOVF FSTEP_0,W ; Get the low byte increment 017D 07A3 01026 ADDWF OSC_0,F ; Add it to the low osc byte 017E 1C03 01027 BTFSS STATUS,B_C ; Was there a carry? 017F 2985 01028 GOTO ADD4 ; No, add the next bytes 0180 0FA4 01029 INCFSZ OSC_1,F ; Ripple carry up to the next byte 0181 2985 01030 GOTO ADD4 ; No new carry, add the next bytes 0182 0FA5 01031 INCFSZ OSC_2,F ; Ripple carry up to the next byte 0183 2985 01032 GOTO ADD4 ; No new carry, add the next bytes 0184 0AA6 01033 INCF OSC_3,F ; Ripple carry up to the highest byte 0185 01034 ADD4 0185 081B 01035 MOVF FSTEP_1,W ; Get the second byte increment 0186 07A4 01036 ADDWF OSC_1,F ; Add it to the second osc byte 0187 1C03 01037 BTFSS STATUS,B_C ; Was there a carry? 0188 298C 01038 GOTO ADD5 ; No, add the third bytes 0189 0FA5 01039 INCFSZ OSC_2,F ; Ripple carry up to the next byte 018A 298C 01040 GOTO ADD5 ; No new carry, add the third bytes 018B 0AA6 01041 INCF OSC_3,F ; Ripple carry up to the highest byte 018C 01042 ADD5 MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 21 LOC OBJECT CODE LINE SOURCE TEXT VALUE 018C 081C 01043 MOVF FSTEP_2,W ; Get the third byte increment 018D 07A5 01044 ADDWF OSC_2,F ; Add it to the third osc byte 018E 1C03 01045 BTFSS STATUS,B_C ; Was there a carry? 018F 2991 01046 GOTO ADD6 ; No, add the fourth bytes 0190 0AA6 01047 INCF OSC_3,F ; Ripple carry up to the highest byte 0191 01048 ADD6 0191 081D 01049 MOVF FSTEP_3,W ; Get the fourth byte increment 0192 07A6 01050 ADDWF OSC_3,F ; Add it to the fourth byte 0193 1DB3 01051 BTFSS REN_READ,3 ; Is the button still pressed? 0194 2962 01052 GOTO CAL_LOOP ; Yes, stay in calibrate mode 0195 0189 01053 CLRF EEADR ; Write final value to EEPROM 0196 0823 01054 MOVF OSC_0,W ; Record the first 0197 0088 01055 MOVWF EEDATA ; osc 0198 228C 01056 CALL WRITE_EEPROM ; byte 0199 0824 01057 MOVF OSC_1,W ; Record the second 019A 0088 01058 MOVWF EEDATA ; osc 019B 228C 01059 CALL WRITE_EEPROM ; byte 019C 0825 01060 MOVF OSC_2,W ; Record the third 019D 0088 01061 MOVWF EEDATA ; osc 019E 228C 01062 CALL WRITE_EEPROM ; byte 019F 0826 01063 MOVF OSC_3,W ; Record the fourth 01A0 0088 01064 MOVWF EEDATA ; osc 01A1 228C 01065 CALL WRITE_EEPROM ; byte 01A2 0008 01066 RETURN ; Return to the caller 01067 ; 01068 ; ***************************************************************************** 01069 ; * * 01070 ; * Purpose: Multiply the 32 bit number for oscillator frequency times the * 01071 ; * 32 bit number for the displayed frequency. * 01072 ; * * 01073 ; * * 01074 ; * Input: The reference oscillator value in osc_3 ... osc_0 and the * 01075 ; * current frequency stored in freq_3 ... freq_0. The reference * 01076 ; * oscillator value is treated as a fixed point real, with a 24 * 01077 ; * bit mantissa. * 01078 ; * * 01079 ; * Output: The result is stored in AD9850_3 ... AD9850_0. * 01080 ; * * 01081 ; ***************************************************************************** 01082 ; 01A3 01083 CALC_DDS_WORD 01A3 0195 01084 CLRF AD9850_0 ; Clear the AD9850 control word bytes 01A4 0196 01085 CLRF AD9850_1 ; 01A5 0197 01086 CLRF AD9850_2 ; 01A6 0198 01087 CLRF AD9850_3 ; 01A7 0199 01088 CLRF AD9850_4 ; 01A8 3020 01089 MOVLW 0X20 ; Set count to 32 (4 osc bytes of 8 bits) 01A9 00A0 01090 MOVWF MULT_COUNT ; Keep running count 01AA 0823 01091 MOVF OSC_0,W ; Move the four osc bytes 01AB 00A7 01092 MOVWF OSC_TEMP_0 ; to temporary storage for this multiply 01AC 0824 01093 MOVF OSC_1,W ; (Don't disturb original osc bytes) 01AD 00A8 01094 MOVWF OSC_TEMP_1 ; 01AE 0825 01095 MOVF OSC_2,W ; MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 22 LOC OBJECT CODE LINE SOURCE TEXT VALUE 01AF 00A9 01096 MOVWF OSC_TEMP_2 ; 01B0 0826 01097 MOVF OSC_3,W ; 01B1 00AA 01098 MOVWF OSC_TEMP_3 ; 01B2 01099 MULT_LOOP 01B2 1003 01100 BCF STATUS,B_C ; Start with Carry clear 01B3 1C27 01101 BTFSS OSC_TEMP_0,0 ; Is bit 0 (Least Significant bit) set? 01B4 29CC 01102 GOTO NOADD ; No, don't need to add freq term to total 01B5 080C 01103 MOVF FREQ_0,W ; Yes, get the freq_0 term 01B6 0796 01104 ADDWF AD9850_1,F ; and add it in to total 01B7 1C03 01105 BTFSS STATUS,B_C ; Does this addition result in a carry? 01B8 29BE 01106 GOTO ADD7 ; No, continue with next freq term 01B9 0F97 01107 INCFSZ AD9850_2,F ; Yes, add one and check for another carry 01BA 29BE 01108 GOTO ADD7 ; No, continue with next freq term 01BB 0F98 01109 INCFSZ AD9850_3,F ; Yes, add one and check for another carry 01BC 29BE 01110 GOTO ADD7 ; No, continue with next freq term 01BD 0A99 01111 INCF AD9850_4,F ; Yes, add one and continue 01BE 01112 ADD7 01BE 080D 01113 MOVF FREQ_1,W ; Use the freq_1 term 01BF 0797 01114 ADDWF AD9850_2,F ; Add freq term to total in correct position 01C0 1C03 01115 BTFSS STATUS,B_C ; Does this addition result in a carry? 01C1 29C5 01116 GOTO ADD8 ; No, continue with next freq term 01C2 0F98 01117 INCFSZ AD9850_3,F ; Yes, add one and check for another carry 01C3 29C5 01118 GOTO ADD8 ; No, continue with next freq term 01C4 0A99 01119 INCF AD9850_4,F ; Yes, add one and continue 01C5 01120 ADD8 01C5 080E 01121 MOVF FREQ_2,W ; Use the freq_2 term 01C6 0798 01122 ADDWF AD9850_3,F ; Add freq term to total in correct position 01C7 1C03 01123 BTFSS STATUS,B_C ; Does this addition result in a carry? 01C8 29CA 01124 GOTO ADD9 ; No, continue with next freq term 01C9 0A99 01125 INCF AD9850_4,F ; Yes, add one and continue 01CA 01126 ADD9 01CA 080F 01127 MOVF FREQ_3,W ; Use the freq_3 term 01CB 0799 01128 ADDWF AD9850_4,F ; Add freq term to total in correct position 01CC 01129 NOADD 01CC 0C99 01130 RRF AD9850_4,F ; Shift next multiplier bit into position 01CD 0C98 01131 RRF AD9850_3,F ; Rotate bits to right from byte to byte 01CE 0C97 01132 RRF AD9850_2,F ; 01CF 0C96 01133 RRF AD9850_1,F ; 01D0 0C95 01134 RRF AD9850_0,F ; 01D1 0CAA 01135 RRF OSC_TEMP_3,F ; Shift next multiplicand bit into position 01D2 0CA9 01136 RRF OSC_TEMP_2,F ; Rotate bits to right from byte to byte 01D3 0CA8 01137 RRF OSC_TEMP_1,F ; 01D4 0CA7 01138 RRF OSC_TEMP_0,F ; 01D5 0BA0 01139 DECFSZ MULT_COUNT,F ; One more bit has been done. Are we done? 01D6 29B2 01140 GOTO MULT_LOOP ; No, go back to use this bit 01D7 0199 01141 CLRF AD9850_4 ; Yes, clear _4. Answer is in bytes _3 .. _0 01D8 0008 01142 RETURN ; Done. 01143 ; 01144 ; ***************************************************************************** 01145 ; * * 01146 ; * Purpose: This routine sends the AD9850 control word to the DDS chip * 01147 ; * using a serial data transfer. * 01148 ; * * MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 23 LOC OBJECT CODE LINE SOURCE TEXT VALUE 01149 ; * Input: AD9850_4 ... AD9850_0 * 01150 ; * * 01151 ; * Output: The DDS chip register is updated. * 01152 ; * * 01153 ; ***************************************************************************** 01154 ; 01D9 01155 SEND_DDS_WORD 01D9 3015 01156 MOVLW AD9850_0 ; Point FSR at AD9850 01DA 0084 01157 MOVWF FSR ; 01DB 01158 NEXT_BYTE 01DB 0800 01159 MOVF INDF,W ; 01DC 00A2 01160 MOVWF BYTE2SEND ; 01DD 3008 01161 MOVLW 0X08 ; Set counter to 8 01DE 00A1 01162 MOVWF BIT_COUNT ; 01DF 01163 NEXT_BIT 01DF 0CA2 01164 RRF BYTE2SEND,F ; Test if next bit is 1 or 0 01E0 1C03 01165 BTFSS STATUS,B_C ; Was it zero? 01E1 29E6 01166 GOTO SEND0 ; Yes, send zero 01E2 1786 01167 BSF PORTB,7 ; No, send one 01E3 1686 01168 BSF PORTB,5 ; Toggle write clock 01E4 1286 01169 BCF PORTB,5 ; 01E5 29E9 01170 GOTO BREAK ; 01E6 01171 SEND0 01E6 1386 01172 BCF PORTB,7 ; Send zero 01E7 1686 01173 BSF PORTB,5 ; Toggle write clock 01E8 1286 01174 BCF PORTB,5 ; 01E9 01175 BREAK 01E9 0BA1 01176 DECFSZ BIT_COUNT,F ; Has the whole byte been sent? 01EA 29DF 01177 GOTO NEXT_BIT ; No, keep going. 01EB 0A84 01178 INCF FSR,F ; Start the next byte unless finished 01EC 301A 01179 MOVLW AD9850_4+1 ; Next byte (past the end) 01ED 0204 01180 SUBWF FSR,W ; 01EE 1C03 01181 BTFSS STATUS,B_C ; 01EF 29DB 01182 GOTO NEXT_BYTE ; 01F0 1406 01183 BSF PORTB,0 ; Send load signal to the AD9850 01F1 1006 01184 BCF PORTB,0 ; 01F2 0008 01185 RETURN ; 01186 ; 01187 ; ***************************************************************************** 01188 ; * * 01189 ; * Purpose: This subroutine converts a 32 bit binary number to a 10 digit * 01190 ; * BCD number. The input value taken from freq(0 to 3) is * 01191 ; * preserved. The output is in BCD(0 to 4), each byte holds => * 01192 ; * (hi_digit,lo_digit), most significant digits are in BCD_4. * 01193 ; * This routine is a modified version of one described in * 01194 ; * MicroChip application note AN526. * 01195 ; * * 01196 ; * Input: The value in freq_0 ... freq_3 * 01197 ; * * 01198 ; * Output: The BCD number in BCD_0 ... BCD_4 * 01199 ; * * 01200 ; ***************************************************************************** 01201 ; MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 24 LOC OBJECT CODE LINE SOURCE TEXT VALUE 01F3 01202 BIN2BCD 01F3 3020 01203 MOVLW 0X20 ; Set loop counter 01F4 009E 01204 MOVWF BCD_COUNT ; to 32 01F5 0190 01205 CLRF BCD_0 ; Clear output 01F6 0191 01206 CLRF BCD_1 ; " " 01F7 0192 01207 CLRF BCD_2 ; " " 01F8 0193 01208 CLRF BCD_3 ; " " 01F9 0194 01209 CLRF BCD_4 ; " " 01FA 01210 BIN_LOOP 01FA 1003 01211 BCF STATUS,B_C ; Clear carry bit in STATUS 01212 ; 01213 ; Rotate bits in freq bytes. Move from LS byte (freq_0) to next byte (freq_1). 01214 ; Likewise, move from freq_1 to freq_2 and from freq_2 to freq_3. 01215 ; 01FB 0D8C 01216 RLF FREQ_0,F ; Rotate left, 0 -> LS bit, MS bit -> Carry 01FC 0D8D 01217 RLF FREQ_1,F ; Rotate left, Carry->LS bit, MS bit->Carry 01FD 0D8E 01218 RLF FREQ_2,F ; Rotate left, Carry->LS bit, MS bit->Carry 01FE 0D8F 01219 RLF FREQ_3,F ; Rotate left, Carry->LS bit, MS bit->Carry 01FF 1803 01220 BTFSC STATUS,B_C ; Is Carry clear? If so, skip next instruction 0200 140C 01221 BSF FREQ_0,0 ; Carry is set so wrap and set bit 0 in freq_0 01222 ; 01223 ; Build BCD bytes. Move into LS bit of BCD bytes (LS of BCD_0) from MS bit of 01224 ; freq_3 via the Carry bit. 01225 ; 0201 0D90 01226 RLF BCD_0,F ; Rotate left, Carry->LS bit, MS bit->Carry 0202 0D91 01227 RLF BCD_1,F ; Rotate left, Carry->LS bit, MS bit->Carry 0203 0D92 01228 RLF BCD_2,F ; Rotate left, Carry->LS bit, MS bit->Carry 0204 0D93 01229 RLF BCD_3,F ; Rotate left, Carry->LS bit, MS bit->Carry 0205 0D94 01230 RLF BCD_4,F ; Rotate left, Carry->LS bit, MS bit->Carry 0206 039E 01231 DECF BCD_COUNT,F ; Decrement loop count 0207 1D03 01232 BTFSS STATUS,B_Z ; Is loop count now zero? 0208 2A0A 01233 GOTO ADJUST ; No, go to adjust 0209 0008 01234 RETURN ; Yes, EXIT 01235 ; ============================================================================ 020A 01236 ADJUST ; Internal subroutine, called by bin2BCD main loop only 01237 ; 01238 ; As BCD bytes are being built, make sure the nibbles do not grow larger than 9. 01239 ; If a nibble gets larger than 9, increment to next higher nibble. 01240 ; (If the LS nibble of a byte overflows, increment the MS nibble of that byte.) 01241 ; (If the MS nibble of a byte overflows, increment the LS nibble of next byte.) 01242 ; 020A 3010 01243 MOVLW BCD_0 ; Get pointer to BCD_0 020B 0084 01244 MOVWF FSR ; Put pointer in FSR for indirect addressing 020C 2216 01245 CALL ADJ_BCD ; 020D 0A84 01246 INCF FSR,F ; Move indirect addressing pointer to BCD_1 020E 2216 01247 CALL ADJ_BCD ; 020F 0A84 01248 INCF FSR,F ; Move indirect addressing pointer to BCD_2 0210 2216 01249 CALL ADJ_BCD ; 0211 0A84 01250 INCF FSR,F ; Move indirect addressing pointer to BCD_3 0212 2216 01251 CALL ADJ_BCD ; 0213 0A84 01252 INCF FSR,F ; Move indirect addressing pointer to BCD_4 0214 2216 01253 CALL ADJ_BCD ; 0215 29FA 01254 GOTO BIN_LOOP ; Back to main loop of bin2BCD MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 25 LOC OBJECT CODE LINE SOURCE TEXT VALUE 01255 ; ============================================================================ 0216 01256 ADJ_BCD ; Internal subroutine, called by adjust only 0216 3003 01257 MOVLW 3 ; Add 3 0217 0700 01258 ADDWF INDF,W ; to LS digit 0218 009F 01259 MOVWF BCD_TEMP ; Save in temp 0219 199F 01260 BTFSC BCD_TEMP,3 ; Is LS digit + 3 > 7 (Bit 3 set) 021A 0080 01261 MOVWF INDF ; Yes, save incremented value as LS digit 021B 3030 01262 MOVLW 0X30 ; Add 3 021C 0700 01263 ADDWF INDF,W ; to MS digit 021D 009F 01264 MOVWF BCD_TEMP ; Save as temp 021E 1B9F 01265 BTFSC BCD_TEMP,7 ; Is MS digit + 3 > 7 (Bit 7 set) 021F 0080 01266 MOVWF INDF ; Yes, save incremented value as MS digit 0220 0008 01267 RETURN ; Return to adjust subroutine 01268 ; 01269 ; ***************************************************************************** 01270 ; * * 01271 ; * Purpose: Display the frequency setting on the LCD. * 01272 ; * * 01273 ; * Input: The values in BCD_4 ... BCD_0 * 01274 ; * * 01275 ; * Output: The number displayed on the LCD * 01276 ; * * 01277 ; ***************************************************************************** 01278 ; 0221 01279 SHOW_FREQ 0221 3081 01280 MOVLW 0X81 ; Point the LCD to first LCD digit location 0222 226A 01281 CALL CMND2LCD ; Send starting digit location to LCD 01282 ; 01283 ; Running 4-bit mode, so need to send Most Significant Nibble first. 01284 ; 01285 ; Extract and send "XXXX" from byte containing "XXXXYYYY" 01286 ; - Swap halves to get YYYYXXXX 01287 ; - Mask with 0x0F to get 0000XXXX 01288 ; - Add ASCII bias (0030XXXX) 01289 ; 0223 0E13 01290 SWAPF BCD_3,W ; Swap 10MHz BCD digit into lower nibble of W 0224 390F 01291 ANDLW 0X0F ; Mask for lower nibble only (0000XXXX) 0225 3E30 01292 ADDLW 0X30 ; Add offset for ASCII char set (0030XXXX) 0226 226E 01293 CALL DATA2LCD ; Send byte in W to LCD 01294 ; 01295 ; Extract and send "YYYY" from byte containing "XXXXYYYY" 01296 ; - Mask with 0x0F to get 0000YYYY 01297 ; - Add offset for ASCII character set in LCD (0030YYYY) 01298 ; 0227 0813 01299 MOVF BCD_3,W ; Put 1MHz BCD digit into lower nibble of W 0228 390F 01300 ANDLW 0X0F ; Mask for lower nibble only (0000YYYY) 0229 3E30 01301 ADDLW 0X30 ; Add offset for ASCII char set (0030YYYY) 022A 226E 01302 CALL DATA2LCD ; Send byte in W to LCD 01303 ; 022B 302C 01304 MOVLW ',' ; Get a comma 022C 226E 01305 CALL DATA2LCD ; Send byte in W to LCD 01306 ; 022D 0E12 01307 SWAPF BCD_2,W ; Swap 100KHz BCD digit into lower nibble of W MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 26 LOC OBJECT CODE LINE SOURCE TEXT VALUE 022E 390F 01308 ANDLW 0X0F ; Mask for lower nibble only (0000XXXX) 022F 3E30 01309 ADDLW 0X30 ; Add offset for ASCII char set (0030XXXX) 0230 226E 01310 CALL DATA2LCD ; Send byte in W to LCD 01311 ; 0231 0812 01312 MOVF BCD_2,W ; Put 10KHz BCD digit into lower nibble of W 0232 390F 01313 ANDLW 0X0F ; Mask for lower nibble only (0000YYYY) 0233 3E30 01314 ADDLW 0X30 ; Add offset for ASCII char set (0030YYYY) 0234 226E 01315 CALL DATA2LCD ; Send byte in W to LCD 01316 ; 0235 0E11 01317 SWAPF BCD_1,W ; Swap 1KHz BCD digit into lower nibble of W 0236 390F 01318 ANDLW 0X0F ; Mask for lower nibble only (0000XXXX) 0237 3E30 01319 ADDLW 0X30 ; Add offset for ASCII char set (0030XXXX) 0238 226E 01320 CALL DATA2LCD ; Send byte in W to LCD 01321 ; 0239 302E 01322 MOVLW '.' ; Set up W with ASCII Period 023A 226E 01323 CALL DATA2LCD ; Send data byte in W to LCD 01324 ; 023B 30C0 01325 MOVLW 0XC0 ; Point to LCD digit number nine 023C 226A 01326 CALL CMND2LCD ; Send command byte in W to LCD 01327 ; 023D 0811 01328 MOVF BCD_1,W ; Put 100 Hz BCD digit into lower nibble of W 023E 390F 01329 ANDLW 0X0F ; Mask for lower nibble only (0000YYYY) 023F 3E30 01330 ADDLW 0X30 ; Add offset for ASCII char set (0030YYYY) 0240 226E 01331 CALL DATA2LCD ; Send data byte in W to LCD 01332 ; 0241 0E10 01333 SWAPF BCD_0,W ; Swap 10 Hz BCD digit into lower nibble of W 0242 390F 01334 ANDLW 0X0F ; Mask for lower nibble only (0000XXXX) 0243 3E30 01335 ADDLW 0X30 ; Add offset for ASCII char set (0030XXXX) 0244 226E 01336 CALL DATA2LCD ; Send data byte in W to LCD 01337 ; 0245 0810 01338 MOVF BCD_0,W ; Put 1 Hz BCD digit into lower nibble of W 0246 390F 01339 ANDLW 0X0F ; Mask for lower nibble only (0000YYYY) 0247 3E30 01340 ADDLW 0X30 ; Add offset for ASCII char set (0030YYYY) 0248 226E 01341 CALL DATA2LCD ; Send byte in W to LCD 01342 ; 0249 3020 01343 MOVLW ' ' ; Send a space 024A 226E 01344 CALL DATA2LCD ; to LCD 01345 ; 024B 306B 01346 MOVLW 'k' ; Send a 'k' 024C 226E 01347 CALL DATA2LCD ; to LCD 01348 ; 024D 3048 01349 MOVLW 'H' ; Send an "H" 024E 226E 01350 CALL DATA2LCD ; to LCD 01351 ; 024F 307A 01352 MOVLW 'z' ; Send a 'z' 0250 226E 01353 CALL DATA2LCD ; to LCD 01354 ; 0251 0008 01355 RETURN ; 01356 ; 01357 ; ***************************************************************************** 01358 ; * * 01359 ; * Purpose: Check if LCD is done with the last operation. * 01360 ; * This subroutine polls the LCD busy flag to determine if * MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 27 LOC OBJECT CODE LINE SOURCE TEXT VALUE 01361 ; * previous operations are completed. * 01362 ; * * 01363 ; * Input: None * 01364 ; * * 01365 ; * Output: PortB set as: RB7..RB4 inputs * 01366 ; * RB3..RB0 outputs * 01367 ; ***************************************************************************** 01368 ; 0252 01369 BUSY_CHECK 0252 0186 01370 CLRF PORTB ; Clear all outputs on PortB 0253 1683 01371 BSF STATUS,B_RP0 ; Switch to bank 1 for Tristate operation 0254 30F0 01372 MOVLW B'11110000' ; Set RB7..RB4 as inputs, RB3..RB0 outputs 0255 0086 01373 MOVWF TRISB ; via Tristate 0256 1283 01374 BCF STATUS,B_RP0 ; Switch back to bank 0 0257 1086 01375 BCF PORTB,LCD_RS ; Set up LCD for Read Busy Flag (RS = 0) 0258 1506 01376 BSF PORTB,LCD_RW ; Set up LCD for Read (RW = 1) 0259 30FF 01377 MOVLW 0XFF ; Set up constant 255 025A 00AD 01378 MOVWF TIMER1 ; for timer loop counter 025B 01379 LCD_IS_BUSY 025B 1586 01380 BSF PORTB,LCD_E ; Set E high 025C 0806 01381 MOVF PORTB,W ; Read PortB into W 025D 00AC 01382 MOVWF LCD_READ ; Save W for later testing 025E 1186 01383 BCF PORTB,LCD_E ; Drop E again 025F 0000 01384 NOP ; Wait a 0260 0000 01385 NOP ; while 0261 1586 01386 BSF PORTB,LCD_E ; Pulse E high (dummy read of lower nibble), 0262 0000 01387 NOP ; wait, 0263 1186 01388 BCF PORTB,LCD_E ; and drop E again 0264 03AD 01389 DECF TIMER1,F ; Decrement loop counter 0265 1903 01390 BTFSC STATUS,B_Z ; Is loop counter down to zero? 0266 2A69 01391 GOTO NOT_BUSY ; If yes, return regardless 0267 1BAC 01392 BTFSC LCD_READ,7 ; Is Busy Flag (RB7) in save byte clear? 0268 2A5B 01393 GOTO LCD_IS_BUSY ; If not, it is busy so jump back 0269 01394 NOT_BUSY 0269 0008 01395 RETURN ; 01396 ; 01397 ; ***************************************************************************** 01398 ; * Purpose: Send Command or Data byte to the LCD * 01399 ; * Entry point cmnd2LCD: Send a Command to the LCD * 01400 ; * Entry Point data2LCD: Send a Data byte to the LCD * 01401 ; * * 01402 ; * Input: W has the command or data byte to be sent to the LCD. * 01403 ; * * 01404 ; * Output: None * 01405 ; ***************************************************************************** 01406 ; 026A 01407 CMND2LCD ; ****** Entry point ****** 026A 00AB 01408 MOVWF LCD_CHAR ; Save byte to write to LCD 026B 01B8 01409 CLRF RS_VALUE ; Remember to clear RS (clear rs_value) 026C 1086 01410 BCF PORTB,LCD_RS ; Set RS for Command to LCD 026D 2A71 01411 GOTO WRITE2LCD ; Go to common code 026E 01412 DATA2LCD ; ****** Entry point ******** 026E 00AB 01413 MOVWF LCD_CHAR ; Save byte to write to LCD MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 28 LOC OBJECT CODE LINE SOURCE TEXT VALUE 026F 1438 01414 BSF RS_VALUE,0 ; Remember to set RS (set bit 0 of rs_value) 0270 1486 01415 BSF PORTB,LCD_RS ; Set RS for Data to LCD 0271 01416 WRITE2LCD 0271 2252 01417 CALL BUSY_CHECK ; Check to see if LCD is ready for new data 0272 0186 01418 CLRF PORTB ; Clear all of Port B (inputs and outputs) 0273 1683 01419 BSF STATUS,B_RP0 ; Switch to bank 1 for Tristate operation 0274 3000 01420 MOVLW 0X00 ; Set up to enable PortB data pins 0275 0086 01421 MOVWF TRISB ; All pins (RB7..RB0) are back to outputs 0276 1283 01422 BCF STATUS,B_RP0 ; Switch to bank 0 0277 1106 01423 BCF PORTB,LCD_RW ; Set LCD back to Write mode (RW = 0) 0278 1086 01424 BCF PORTB,LCD_RS ; Guess RS should be clear 0279 1838 01425 BTFSC RS_VALUE,0 ; Should RS be clear? (is bit 0 == 0?) 027A 1486 01426 BSF PORTB,LCD_RS ; No, set RS 01427 ; 01428 ; Transfer Most Significant nibble (XXXX portion of XXXXYYYY) 01429 ; 027B 300F 01430 MOVLW 0X0F ; Set up mask 027C 0586 01431 ANDWF PORTB,F ; Clear old RB7..RB4 027D 082B 01432 MOVF LCD_CHAR,W ; Put byte of data into W 027E 39F0 01433 ANDLW 0XF0 ; Mask to give XXXX0000 in W 027F 0486 01434 IORWF PORTB,F ; Send to RB7..RB4 without changing RB3..RB0 0280 1586 01435 BSF PORTB,LCD_E ; Pulse the E line high, 0281 0000 01436 NOP ; wait, 0282 1186 01437 BCF PORTB,LCD_E ; and drop it again 01438 ; 01439 ; Transfer Least Significant nibble (YYYY portion of XXXXYYYY) 01440 ; 0283 300F 01441 MOVLW 0X0F ; Set up mask 0284 0586 01442 ANDWF PORTB,F ; Clear old RB7..RB4 0285 0E2B 01443 SWAPF LCD_CHAR,W ; Move LS nibble of data to MS position in W 0286 39F0 01444 ANDLW 0XF0 ; Mask to give YYYY0000 in W 0287 0486 01445 IORWF PORTB ; Send to RB7..RB4 without changing RB3..RB0 0288 1586 01446 BSF PORTB,LCD_E ; Pulse the E line high, 0289 0000 01447 NOP ; wait, 028A 1186 01448 BCF PORTB,LCD_E ; and drop it again 028B 0008 01449 RETURN 01450 ; 01451 ; ***************************************************************************** 01452 ; * * 01453 ; * Purpose: Write the byte of data at EEdata to the EEPROM at address * 01454 ; * EEadr. * 01455 ; * * 01456 ; * Input: The values at EEdata and EEadr. * 01457 ; * * 01458 ; * Output: The EEPROM value is updated. * 01459 ; * * 01460 ; ***************************************************************************** 01461 ; 028C 01462 WRITE_EEPROM 028C 1683 01463 BSF STATUS,B_RP0 ; Switch to bank 1 028D 1508 01464 BSF EEDATA,WREN ; Set the EEPROM write enable bit 028E 3055 01465 MOVLW 0X55 ; Write 0x55 and 0xAA to EEPROM 028F 0089 01466 MOVWF EEADR ; control register, as required MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 29 LOC OBJECT CODE LINE SOURCE TEXT VALUE 0290 30AA 01467 MOVLW 0XAA ; for the write 0291 0089 01468 MOVWF EEADR ; 0292 1488 01469 BSF EEDATA,WR ; Set WR to initiate write 0293 01470 BIT_CHECK 0293 1888 01471 BTFSC EEDATA,WR ; Has the write completed? 0294 2A93 01472 GOTO BIT_CHECK ; No, keep checking 0295 1108 01473 BCF EEDATA,WREN ; Clear the EEPROM write enable bit 0296 1283 01474 BCF STATUS,B_RP0 ; Switch to bank 0 0297 0A89 01475 INCF EEADR,F ; Increment the EE write address 0298 0008 01476 RETURN ; Return to the caller 01477 ; 01478 ; ***************************************************************************** 01479 ; * * 01480 ; * Purpose: Read a byte of EEPROM data at address EEadr into EEdata. * 01481 ; * * 01482 ; * Input: The address EEadr. * 01483 ; * * 01484 ; * Output: The value in EEdata. * 01485 ; * * 01486 ; ***************************************************************************** 01487 ; 0299 01488 READ_EEPROM 0299 1683 01489 BSF STATUS,B_RP0 ; Switch to bank 1 029A 1408 01490 BSF EEDATA,RD ; Request the read 029B 1283 01491 BCF STATUS,B_RP0 ; Switch to bank 0 029C 0A89 01492 INCF EEADR,F ; Increment the read address 029D 0008 01493 RETURN ; Return to the caller 01494 ; 01495 ; ***************************************************************************** 01496 ; * * 01497 ; * Purpose: Wait for a specified number of milliseconds. * 01498 ; * * 01499 ; * Entry point wait_128ms: Wait for 128 msec * 01500 ; * Entry point wait_64ms : Wait for 64 msec * 01501 ; * Entry point wait_32ms : Wait for 32 msec * 01502 ; * Entry point wait_16ms : Wait for 16 msec * 01503 ; * Entry point wait_8ms : Wait for 8 msec * 01504 ; * * 01505 ; * Input: None * 01506 ; * * 01507 ; * Output: None * 01508 ; * * 01509 ; ***************************************************************************** 01510 ; 029E 01511 WAIT_128MS ; ****** Entry point ****** 029E 30FF 01512 MOVLW 0XFF ; Set up outer loop 029F 00AD 01513 MOVWF TIMER1 ; counter to 255 02A0 2AAC 01514 GOTO OUTER_LOOP ; Go to wait loops 02A1 01515 WAIT_64MS ; ****** Entry point ****** 02A1 3080 01516 MOVLW 0X80 ; Set up outer loop 02A2 00AD 01517 MOVWF TIMER1 ; counter to 128 02A3 2AAC 01518 GOTO OUTER_LOOP ; Go to wait loops 02A4 01519 WAIT_32MS ; ****** Entry point ****** MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 30 LOC OBJECT CODE LINE SOURCE TEXT VALUE 02A4 3040 01520 MOVLW 0X40 ; Set up outer loop 02A5 00AD 01521 MOVWF TIMER1 ; counter to 64 02A6 2AAC 01522 GOTO OUTER_LOOP ; Go to wait loops 02A7 01523 WAIT_16MS ; ****** Entry point ****** 02A7 3020 01524 MOVLW 0X20 ; Set up outer loop 02A8 00AD 01525 MOVWF TIMER1 ; counter to 32 02A9 2AAC 01526 GOTO OUTER_LOOP ; Go to wait loops 02AA 01527 WAIT_8MS ; ****** Entry point ****** 02AA 3010 01528 MOVLW 0X10 ; Set up outer loop 02AB 00AD 01529 MOVWF TIMER1 ; counter to 16 01530 ; Fall through into wait loops 01531 ; 01532 ; Wait loops used by other wait routines 01533 ; - 1 microsecond per instruction (with a 4 MHz microprocessor crystal) 01534 ; - 510 instructions per inner loop 01535 ; - (Timer1 * 514) instructions (.514 msec) per outer loop 01536 ; - Round off to .5 ms per outer loop 01537 ; 02AC 01538 OUTER_LOOP 02AC 30FF 01539 MOVLW 0XFF ; Set up inner loop counter 02AD 00AE 01540 MOVWF TIMER2 ; to 255 02AE 01541 INNER_LOOP 02AE 0BAE 01542 DECFSZ TIMER2,F ; Decrement inner loop counter 02AF 2AAE 01543 GOTO INNER_LOOP ; If inner loop counter not down to zero, 01544 ; then go back to inner loop again 02B0 0BAD 01545 DECFSZ TIMER1,F ; Yes, Decrement outer loop counter 02B1 2AAC 01546 GOTO OUTER_LOOP ; If outer loop counter not down to zero, 01547 ; then go back to outer loop again 02B2 0008 01548 RETURN ; Yes, return to caller 01549 ; 01550 ; ***************************************************************************** 01551 ; 01552 END MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 31 SYMBOL TABLE LABEL VALUE AD9850_0 00000015 AD9850_1 00000016 AD9850_2 00000017 AD9850_3 00000018 AD9850_4 00000019 ADD1 000000CE ADD2 000000D5 ADD3 000000DA ADD4 00000185 ADD5 0000018C ADD6 00000191 ADD7 000001BE ADD8 000001C5 ADD9 000001CA ADD_STEP 000000C5 ADJUST 0000020A ADJ_BCD 00000216 BAND 00000037 BAND_END 00000028 BAND_TABLE 00000001 BAND_UP 00000087 BCD_0 00000010 BCD_1 00000011 BCD_2 00000012 BCD_3 00000013 BCD_4 00000014 BCD_COUNT 0000001E BCD_TEMP 0000001F BIN2BCD 000001F3 BIN_LOOP 000001FA BIT_CHECK 00000293 BIT_COUNT 00000021 BREAK 000001E9 BUMP_STEP 0000006B BUSY_CHECK 00000252 BYTE2SEND 00000022 B_C 00000000 B_DC 00000001 B_NPD 00000003 B_NTO 00000004 B_RP0 00000005 B_Z 00000002 CALC_DDS_WORD 000001A3 CALIBRATE 0000013F CAL_LOOP 00000162 CHANGE_BAND 0000007B CHECK_ADD 000000DD CMND2LCD 0000026A COMP_DONE 0000010D COUNT 00000036 DATA2LCD 0000026E DDS_CLK 00000005 DDS_DAT 00000007 MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 32 SYMBOL TABLE LABEL VALUE DDS_LOAD 00000000 DEFAULT_0 00000028 DEFAULT_1 00000001 DEFAULT_2 000000D6 DEFAULT_3 00000000 DOWN 00000076 EEADR 00000009 EEDATA 00000008 EXIT1 00000101 EXIT2 00000114 EXIT3 0000013C FASTER 0000017C FREQ_0 0000000C FREQ_1 0000000D FREQ_2 0000000E FREQ_3 0000000F FSR 00000004 FSTEP_0 0000001A FSTEP_1 0000001B FSTEP_2 0000001C FSTEP_3 0000001D GET_BAND 00000093 GO_STEP 00000070 INDF 00000000 INIT_LCD 000000A5 INNER_LOOP 000002AE INTCON 0000000B LAST_DIR 00000034 LCD_CHAR 0000002B LCD_E 00000003 LCD_IS_BUSY 0000025B LCD_READ 0000002C LCD_RS 00000001 LCD_RW 00000002 LIMIT_0 00000080 LIMIT_1 000000C3 LIMIT_2 000000C9 LIMIT_3 00000001 MAIN 0000005C MULT_COUNT 00000020 MULT_LOOP 000001B2 NEXT_BIT 000001DF NEXT_BYTE 000001DB NEXT_DIR 00000035 NOADD 000001CC NOT_BUSY 00000269 NO_INC 0000011F OSC_0 00000023 OSC_1 00000024 OSC_2 00000025 OSC_3 00000026 OSC_TEMP_0 00000027 OSC_TEMP_1 00000028 MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 33 SYMBOL TABLE LABEL VALUE OSC_TEMP_2 00000029 OSC_TEMP_3 0000002A OUTER_LOOP 000002AC PB_SWITCH 00000003 PCL 00000002 PCLATH 0000000A PE_CONTINUE 00000136 POLL_ENCODER 00000115 PORTA 00000005 PORTB 00000006 RD 00000000 READ_EEOCS 00000039 READ_EEPROM 00000299 READ_ENCODER 00000118 REF_OSC_0 000000C4 REF_OSC_1 0000001D REF_OSC_2 000000F3 REF_OSC_3 0000002A REN_NEW 00000031 REN_OLD 00000032 REN_READ 00000033 REN_TIMER_0 0000002F REN_TIMER_1 00000030 RESET_ENTRY 00000000 RS_VALUE 00000038 SEND0 000001E6 SEND_DDS_WORD 000001D9 SET_MAX 000000F9 SET_MIN 00000110 SHOW_FREQ 00000221 START 0000002E STATUS 00000003 SUB_STEP 00000102 TIMER1 0000002D TIMER2 0000002E TRISA 00000005 TRISB 00000006 UP 00000078 UP2 0000013A UPDATE_OSC 0000016E VALID 00000085 WAIT_128MS 0000029E WAIT_16MS 000002A7 WAIT_32MS 000002A4 WAIT_64MS 000002A1 WAIT_8MS 000002AA WR 00000001 WREN 00000002 WRITE 0000008E WRITE2LCD 00000271 WRITE_EEPROM 0000028C _CP_OFF 00003FFF _CP_ON 0000000F MPASM 02.80 Released SIGGEN3A.ASM 11-6-2001 10:36:41 PAGE 34 SYMBOL TABLE LABEL VALUE _HS_OSC 00003FFE _LP_OSC 00003FFC _PWRTE_OFF 00003FFF _PWRTE_ON 00003FF7 _RC_OSC 00003FFF _WDT_OFF 00003FFB _WDT_ON 00003FFF _XT_OSC 00003FFD __16F84A 00000001 MEMORY USAGE MAP ('X' = Used, '-' = Unused) 0000 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 00C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0140 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0180 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 01C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX 0280 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXX------------- 2000 : XXXX---X-------- ---------------- ---------------- ---------------- 2100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX All other memory blocks unused. Program Memory Words Used: 691 Program Memory Words Free: 333 Errors : 0 Warnings : 0 reported, 4 suppressed Messages : 0 reported, 1 suppressed