.nolist ;Copyright 2005 Dick Cappels, projects@cappels.org www.projects.cappels.org ;Function/Sweep Generator Button interface ;Note: Expects to use AVR with about 1 MHz clock (AT90S1200A with on-chip clock.) ;In this case, an ATtiny2313 running with internal 8 MHz clock divided by 8. ;To use the AT90S1200, remove the stack initialiaztion right after "START:" ; and change the name of the include file below. ;****************************************************** .include "tn2313def.inc" ;"1200def.inc" <===only use one .inc file. ;****************************************************** ;Version fsgen13060305A Added EEPROM write enable. NOT TESTED. ;Version fsgen13050527A Attiny2313 version. Use 8 MHz internal clock divided by 8. .equ waitL = 0 .equ waitH = 18 ;waitH is the number of 10 second increments. 24 = 4 minutes. .def temp = r16 ;Scratch register. .def temp2 = r17 ;Scratch register. .def delayone = r18 ;Used for button filtering delay. .def delaytwo = r19 ;Used for button filtering delay. .def Dreg = r20 ;PORTD data output buffer .def EEPROMpntr = r21 ;Pointer to EEPOROM location to be read/written. Bits zero ;through 6 indicate corresponding bit status. Bit 7 speficies the state of DDRD,0. .def flagreg = r22 ;Flags for firmware. ;Note: ZH,ZL used for EEPROM write delay. ;flagreg bit assignments ;0 ;1 ;2 ;3 ;4 ;5 ;6 ;7 If set, data in dreg needs to be written to EEPROM. .org $0000 rjmp START LowFreqMode: ;Set VCO input mux to accept Low Freuqency (FLOW) pot as control. andi Dreg, 0b11111100 ori Dreg, 0b10000000 rjmp Buttonack HighFreqMode: ;Set VCO input mux to accept High Freuqency (FHIGHH) pot as control. andi Dreg, 0b11111101 ori Dreg, 0b10000001 rjmp Buttonack START: ldi temp,RAMEND ;ATtin2313 only -- Init Stack Pointer; out SPL,temp ;Omit this line and one above for AT90S1200A ldi temp, 00 ;Set PORTD as output, set bits to initial value out PORTD, temp ldi temp, $FF out DDRD, temp ldi temp, $FF ;Set PORTB as input with weak pullups. out PORTB, temp ldi temp, $00 out DDRB, temp clr flagreg ldi ZL, waitL ldi ZH, waitH rcall ReadNextEE mov dreg,temp ldi temp,255 rcall Buzzloop Loadbuttons: ;Main loop entry point. dec ZL brne noprog dec ZH brne noprog ldi ZL, waitL ldi ZH, waitH sbrs flagreg,7 rjmp noprog mov temp2, dreg ori temp2, 0b01000000 rcall WriteNextEE andi flagreg,0b01111111 noprog: out PORTD, dreg ;Output PORTD data to the output port. sbrs dreg, 7 ;Set DDRD,0 according to dreg,7 rjmp D0Low sbi DDRD ,0 rjmp D0Done D0Low: cbi DDRD, 0 D0Done: in temp ,PINB ;Get the button status. rcall delay ;Wait debounce period. in temp2, pinB ;If button changed, start over cp temp, temp2 brne loadbuttons rcall InterpretButtons rjmp loadbuttons InterpretButtons: ;Interpret buttons routines called by this must terminate with ret instruction. cpi temp, 0b11111110 ;Low frequency pot button pressed. breq LowFreqMode cpi temp, 0b11111101 ;Sweep button pressed. breq sweepmode cpi temp, 0b11111011 ;High frequency pot button pressed. breq HighFreqMode cpi temp, 0b11110111 ;Marker one button pressed. breq MarkerOne cpi temp, 0b11101111 ;Marker two button pressed. breq Markertwo cpi temp, 0b11011111 ;Marker mode button pressed. breq MarkerModeOn cpi temp, 0b10111111 ;Show Marker button pressed. breq ToggleShowMarker cpi temp, 0b01111111 ;Waveform change button is pressed. breq ChangeWaveform cpi temp, 0b10011111 ;Waveform change and Show Marker buttons are pressed. breq zeroEErelay ;Zero the EEPROM. ret ToggleShowMarker: ;Toggle Marker On/Off signal sbrc dreg, 5 rjmp MarkerIs1 rcall MarkerOff rjmp Buttonack MarkerIs1: Rcall MarkerOn rjmp Buttonack zeroEErelay: clr temp2 rjmp zeroEE ;Relaying execution for branch that was out of reach. ChangeWaveform: ;flagreg 2 Change Wavefore bit A0 ;flagreg 3 Change Waveform bit A1 ;flagreg 3 2 ; 1 X Sine ; 0 0 Square ; 0 1 Triangle mov temp, dreg ;Check status of control bits and change to the next in sequence. andi temp, 0b0001100 cpi temp, 0b0001000 brne Nosine rcall SquareOut rjmp Buttonack Nosine: cpi temp, 0b0000000 brne NoSquare rcall TriangleOut rjmp Buttonack NoSquare: ;If its not a sine or square, it must be a triangle, rcall SineOut ;so change it to a sinewave. rjmp Buttonack MarkerOne: ;Set marker mux to connect Marker1 pot. ori dreg,0b0010000 rjmp Buttonack MarkerTwo: ;Set marker mux to connect Marker2 pot. cbr dreg,0b0010000 rjmp Buttonack MarkerOn: ;Enable Marker signals in signal output andi dreg,0b11011111 ret MarkerOff: ori dreg,0b00100000 ;Inhibit Marker signals in signal output ret MarkerModeOn: ;Set VCO input mux to use output of Marker mux. rcall MarkerOff andi dreg, 0b11111110 ori dreg, 0b10000010 rjmp Buttonack Sweepmode: ;Make PortD bit 0 into an input without an pullup so. andi dreg, 0b01111100 ;VCO input sees a sawtooth, set VCO input mux. rjmp Buttonack SineOut: ;Set A0 and A1 input of MAX038 so output is a sinewave. ori dreg, 0b00001000 andi dreg, 0b11111011 ret SquareOut: ;Set A0 and A1 input of MAX038 so output is a squarewave. andi dreg, 0b11110011 ret TriangleOut: ;Set A0 and A1 input of MAX038 so output is a trianglewave. ori dreg, 0b00000100 andi dreg, 0b11110111 ret delay: ;Delay for button debounce and noise filtering. ldi delayone,50 ;Count of 50 for about 39 ms for electrical noise. 20 Was ok for button debounce. outerloop: ldi delaytwo,0 innerloop: dec delaytwo brne innerloop dec delayone brne outerloop ret WriteNextEE: ;Write data in temp2 into next available EEPROM location starting from zer0. ldi EEPROMpntr,255 ;Initialize pointer. Nextwritloc: inc EEPROMpntr rcall EERead ;Check to see if empty cpi temp,0 breq writenow ;Write to first empty location you find. cpi EEPROMpntr,63 ;If we just read the last byte, the EEPROM is fill. Time to erase. brne Nextwritloc ;If not full, go back and try the next location. zeroEE: ldi EEPROMpntr,63 ;Write zeros throughout the EEPROM. zeromore: clr temp zerobusy: sbic EECR,EEWE ;if EEWE not clear rjmp zerobusy ;Wait. out EEAR,EEPROMpntr ;Output address out EEDR,temp ;Output data sbi EECR,EEWE ;Set EEPROM Write strobe dec EEPROMpntr cpi EEPROMpntr,$FF ;Keep going until after location 0 is zeroed. brne zeromore rjmp WriteNextEE writenow: ;Write data in temp2 to location EEPROMpntr points to. sbic EECR,EEWE ;If EEWE not clear, rjmp writenow ;Wait. out EEAR,EEPROMpntr ;Output address out EEDR,temp2 ;Output data sbi EECR,EEMWE ;Set master write enable. *** This line of code not tested. sbi EECR,EEWE ;Set EEPROM Write strobe ldi temp,75 rcall Buzzloop ret ReadNextEE: ;Read first nonzero EEPROM byte found starting from byte 63, scanning down, to temp. LDI EEPROMpntr,64 readmore: dec EEPROMpntr rcall EERead cpi temp, 0 breq noData ret NoData: cpi EEPROMpntr, 0 ;If at the bottom of memory,and still no data, then load zero into temp and return. brne readmore clr temp ret EERead: ;Read from EERPOM. Enter with address in EEPROMpntr. Returns with data in temp.. sbic EECR,EEWE ;If EEWE not clear rjmp EERead ;Wait more out EEAR,EEPROMpntr ;Output address sbi EECR,EERE ;Set EEPROM Read strobe in temp,EEDR ;Get data ret Buttonack: ;Emit a keyclick, set EEPROM write flag & timer, output PORTD, then wait for button up. ldi ZL, waitL ;Set waiting time until programming the EEPROM ldi ZH, waitH ori flagreg,0b10000000 ;Set flag to write to EEPROM after time is up. ldi temp,6 ;;;;;;start keyclick code. Buzzloop: ;Emit a tone out of D6, the number of cycles = contents of temp. sbi PORTD,6 rcall delay2 cbi PORTD,6 rcall delay2 dec temp brne Buzzloop ;;;;;;end keyclick code. out PORTD, dreg ;Output PORTD data to the output port. sbrs dreg, 7 ;Set DDRD,0 according to dreg,7 rjmp D0Low2 sbi DDRD ,0 rjmp D0Done2 D0Low2: cbi DDRD, 0 D0Done2: Wait4ButtonsUp: in temp, PINB ;Wait for all buttons to be up before proceeding. rcall delay ;Debounce in temp2, PINB cp temp, temp2 brne Wait4ButtonsUp cpi temp,0b11111111 ;All up? brne Wait4ButtonsUp; ret delay2: ldi delayone,1 ;Delay for 1/2 cycle of button click. outerloop2: ldi delaytwo,0 innerloop2: dec delaytwo brne innerloop2 dec delayone brne outerloop2 ret .exit