;***************************************************************************************** ; PSK31 Audio Beacon Project ; Application # 1: Basic Tone Generator ; Version 1.0 November 28, 2001 ; George Heron, N2APB ; ; This program is a simple Tone Generator for the Beacon board that uses a look-up-table ; (LUT) technique for putting sine wave values out to the R-2R D/A converter hanging off ; port B of the SX chip. This continuous stream of sine wave values, each separated by a ; short delay, forms a 0-to-5V sine wave signal that's presented to the LM386 audio amp. ; When you run the ToneGen program, you should hear a strong 1 kHz tone coming from the ; speaker hanging off the LM386 output. At this point you could change the value of the ; defined constant FREQUENCY and see how it changes the tone when the program is run again. ; FREQUENCY determines how long of a delay is inserted between each sine wave sample ; that is output to the D/A, hence it changes the frequency of the waveform. ; ; NOTE 1: We actually use a two-byte constant FREQ_HI and FREQ_LO in order to get enough ; timer resolution ; ; Uses SXKey.exe assembler v1.30 and SX-Key rev E with Ubicom SX28AC/DP device using Murata ; 50MHz ceramic resonator. ; ; Version History ; v1.0 released 11/28/2001 ... This was the subject of the Digital QRP Homebrewing column ; in the Fall 2001 issue of QRP Quarterly ; ;***************************************************************************************** ; ; COPYRIGHT 2001 by George L. Heron, N2APB. All rights reserved. ; ; This software may be freely copied and distributed for personal and non-commercial use, ; so long as this author is credited within. ; ;***************************************************************************************** device SX28,oschs3,turbo,stackx_optionx freq 50_000_000 id 'v1.0' reset reset_entry ;***************************************************************************************** ; Global Register definitions org $08 ;start of program registers tabpos ds 1 ;step through table position timer_lo ds 1 timer_hi ds 1 ;****************************************************************************************** ; Debugger variable WATCH statements WATCH tabpos,8,uhex WATCH timer_lo,8,uhex WATCH timer_hi,8,uhex ;***************************************************************************************** ; Port Assignment & setup ra_init equ %00000000 ra_io equ %00000000 RB_init equ %00000000 RB_io equ %00000000 rc_init equ %11111111 rc_io equ %11111111 ; Double byte Frequency constants: FREQ_HI, FREQ_LO ; 0, 92 for about 2000 Hz ; 1, 96 for about 1000 Hz ; 2, 96 for about 500 Hz FREQ_HI equ 1 FREQ_LO equ 96 org $0 ;***************************************************************************************** ; INITIALIZATION -- Program execution begins here on power-up or after a reset reset_entry ;mode port config mov w,#$0f mov m,w ;configure port B as output (R-2R DAC) mov w,#RB_init ; Initialize data latches for port B mov rb,w mov w,#RB_io ; Initialize DDIR for port B mov !rb,w ;configure port A as output (sync pulses for scope) mov w,#ra_init ; Initialize data latches for port A mov ra,w mov w,#ra_io ; Initialize DDIR for port A mov !ra,w ;configure port C as input mov w,#$0E ;point to PLP register mov m,w mov w,#$00 ;enable weak pullups mov !rc,w mov w,#$0F ;point to TRIS register mov m,w mov w,#rc_io ; Initialize DDIR for port C mov !rc,w mov tabpos,#64 ;init the table position jmp @main ;goto mainline on page 1 ;***************************************************************************************** ; MAKE SINE -- output a sample of the sine table. ; Input: pointer TABPOS makesine mov w,tabpos ;get pointer for the table lookup call sinetbP ;get waveform sample from POS starting table retp ;***************************************************************************************** ; sinetbP - a table of sine values - 8 bit entries, centered at 128, table 64 bytes in length ; pointer (W) starts from bottom and works upward ; waveform starts POSITIVE swing first sinetbP jmp pc+w ;compute the jump value retw 128 ; 0 0 retw 115 ; 63 -9.802211E-02 retw 103 ; 62 -.1950951 retw 90 ; 61 -.2902893 retw 79 ; 60 -.3826878 retw 67 ; 59 -.4714009 retw 57 ; 58 -.5555741 retw 47 ; 57 -.6343968 retw 37 ; 56 -.7071099 retw 29 ; 55 -.7730132 retw 21 ; 54 -.831472 retw 15 ; 53 -.8819233 retw 10 ; 52 -.9238811 retw 5 ; 51 -.9569415 retw 2 ; 50 -.980786 retw 1 ; 49 -.9951851 retw 0 ; 48 -1 retw 1 ; 47 -.9951844 retw 2 ; 46 -.9807846 retw 5 ; 45 -.9569393 retw 10 ; 44 -.9238782 retw 15 ; 43 -.8819197 retw 21 ; 42 -.8314677 retw 29 ; 41 -.7730084 retw 37 ; 40 -.7071046 retw 47 ; 39 -.6343909 retw 57 ; 38 -.5555677 retw 67 ; 37 -.4713942 retw 79 ; 36 -.3826808 retw 90 ; 35 -.290282 retw 103 ; 34 -.1950877 retw 115 ; 33 -9.801454E-02 retw 128 ; 32 2.535182E-06 retw 140 ; 31 9.801959E-02 retw 152 ; 30 .1950926 retw 165 ; 29 .2902869 retw 176 ; 28 .3826855 retw 188 ; 27 .4713986 retw 198 ; 26 .555572 retw 208 ; 25 .6343948 retw 218 ; 24 .7071081 retw 226 ; 23 .7730116 retw 234 ; 22 .8314706 retw 240 ; 21 .8819221 retw 245 ; 20 .9238802 retw 250 ; 19 .9569408 retw 253 ; 18 .9807855 retw 254 ; 17 .9951848 retw 255 ; 16 1 retw 254 ; 15 .9951846 retw 253 ; 14 .9807851 retw 250 ; 13 .9569401 retw 245 ; 12 .9238791 retw 240 ; 11 .8819209 retw 234 ; 10 .8314692 retw 226 ; 9 .77301 retw 218 ; 8 .7071064 retw 208 ; 7 .6343929 retw 198 ; 6 .5555698 retw 188 ; 5 .4713964 retw 176 ; 4 .3826831 retw 165 ; 3 .2902845 retw 152 ; 2 .1950902 retw 140 ; 1 9.801706E-02 ;************************************************************************* ;************************************************************************* ; PAGE 1 ;************************************************************************* ;************************************************************************* org $200 ;page 1 memory ;***************************************************************************************** ; MAINLINE ; Construct the sinewave here ; Get the sinewave sample from the LUT, write to port RB, wait a bit, then do it all again main dec tabpos ;"advance" the table pointer up the list call @makesine ;get sample of sine wave mov rb,w ;send it to the DAC on port B test tabpos ;done with carrier sinewave? jnz wait ;not yet mov tabpos,#64 ;yes, reset table pointer wait mov timer_hi,#FREQ_HI wait_1 mov timer_lo,#FREQ_LO wait_2 decsz timer_lo ;decrement timer low byte to zero jmp wait_2 wait_3 test timer_hi ;see if upper byte already zero jz main ;if so, all done with this timer cycle dec timer_hi ;decrement timer high byte jmp wait_1 ;not done, so go do low byte decrement again ;************************************************************************* ;************************************************************************* ; PAGE 2 ;************************************************************************* ;************************************************************************* org $400 ;page 2 memory ;************************************************************************* ;************************************************************************* ; PAGE 3 ;************************************************************************* ;************************************************************************* org $600 ;page 4 memory END