; Copyright 2003 Richard Cappels, projects@cappels.org ;********************************************************************* ;* AT90S2313-10 2313 waveform capture & send to terminal ;* file: wfcao030326.asm ;* More information/updates may be posted at http://www.projects.cappels.org ;* Feedback welcome at " projects at cappels.org" (Please replace "at" with "@") ;********************************************************************* ;This is firmware for a minimum mass waveform capture system ; based on the Atmel AT90S2313-10 microcontroller. ; ; ; ; HOW TO USE THIS FIRMWARE; ; ; The controller needs to operated from a 10 MHz clock - the ; on-chip crystal oscillator was used in the prototype ; applications. Inverting EIA-232 buffers, such as the Maxim ; MAX232 are expected on pin 3 (TXD) and pin 2 (RXD). To obtain ; an input signal range of 0 to 1 volt D.C., connect one end a ; 330k resistor to pin 15, the PWM output, and connect the ; other end of the 330k resistor to pin 13 (the comparator ; inverting input), an 82k resistor to ground, and a .047 uf ; capacitor to ground. Connect the signal to be captured to ; pin 12 (the comparator's noninverting input) and the trigger ; signal to pin 11 (PD6). Remember to supply +5 volts and a ; decoupling capacitor to pin 20 and ground pin 10. Transient ; and over voltage protection on the input pins is ; recommended. Connect an EIA-232 ASCII terminal to the ; EIA-232 lines, switch on the power, and you are ready to ; capture waveforms. The terminal should be set to 9600 baud ; no parity, and either one or two stop bits are ok. ; ; Upon application of power, the chip will send a greeting ; message that looks very much like the one below: ; ---------------------------- ; * ; Waveform capture 03.03.26 Dick Cappels, projects@cappels.org ; ; C..Capture & dump ; I..Increase sample time ; D..Decarese sample time ; T..Triggered mode ; F..Free run mode ; P..Trig. Polarity toggle ; V..Voltage res ; L..Settle time toggle ; E..Toggle line feed ; M..Save settings ; R..Recall saved settings ; !..Default settings ; S..Status ; ?..Menu & status ; ; 5 us 255 steps F + Stl=5 Linefeed = 1: ; ---------------------------- ; Here is a line-by-line breakdown of the contents of the ; screen. ; ; * ; The asterisk, if present, indicates that previously stored ; operating parameters: sampling rate, trigger polarity, ; voltage resolution (6,7, or 8 bits), and PWM DAC settling ; time have been retrieved from the chips EEPROM and used to ; preset the system to the state that was last saved. A ; checksum of relevant EEPROM data is compared with the stored ; checksum before writing the operating parameters. ; ; Waveform capture 03.03.26 Dick Cappels, projects@cappels.org ; projects@cappels.org ; A heading will be typed. The date and version of the ; firmware is contained in the header, as well as the URL of ; my projects web site. ; ; The next 13 entries are the command menu: ; ; C..Capture & dump ; When C is received, the waveform capture cycle will be ; started. At the end of the cycle, the contents will be ; dumped to the screen in ASCII format. A terminal program ; with a text capture feature can capture the tab-delimited ; data for display on a spreadsheet. The cycle can be ; interrupted before completion by pressing any key after the ; cycle has started. If interrupted, the capture cycle will ; abort and the contents of the buffer will be dumped to the ; terminal. ; ; I..Increase sample time ; The letter I increases the sampling time. The possible ; values are in a 1-2-5 sequence from 1 microsecond to 10 ; milliseconds. After the maximum value of 10 milliseconds per ; sample is reached, it will not increment further. ; ; D..Decarese sample time ; The letter D decreases the sampling time. The possible ; values are in a 1-2-5 sequence from 1 microsecond to 10 ; milliseconds. After the minimum, value of 1 microsecond per ; sample is reached, it will not decrement further. ; ; T..Triggered mode ; When T is received, the waveform capture cycle is ; synchronized with the trigger signal on pin 11. ; ; F..Free run mode ; When F is received, the waveform capture cycle free runs ; without regard to the trigger signal. This is useful in ; checking DC level. ; ; ; P..Trig. Polarity toggle ; The P key toggles between triggering on the positive and ; negative edges of the trigger signal. ; ; V..Voltage res ; Voltage resolution cycles among the three choices, 64 step, ; 128 step, and 255 steps each time the V key is pressed. The ; cycling of these values depends on correct values being in ; memory. If, for some reason this data becomes corrupted, ; control can be regained by pressing ! to restore the ; default settings. ; ; L..Settle time toggle ; The L key toggles between 3 milliseconds per sample (1X) and ; 15 milliseonds (5X) settling times after each change of the ; PWM voltage. ; ; E..Toggle line feed ; Pressing E in response to the command prompt toggles the line ; feed turning the data dump on and off. When on (flag = 1), line ; feeds are sent after each data value and tabs are inserted between ; the sample number and the data value. When off (flag = 0), linefeeds ; are suppressed and spaces are inserted between the sample number and ; the data value. Linefeed on works well with most terminal programs ; and linefeed off makes the captured text file more compatible with ; spreadsheet programs. ; ; M..Save settings ; Pressing M in response to the command prompt causes the ; current operating parameters (sampling rate, trigger ; polarity, voltage resolution (6,7, or 8 bits), and PWM DAC ; settling time) to be stored in EEPROM, overwriting any ; previously stored information. ; ; R..Recall saved settings ; Pressing the R key causes previously stored operating ; parameters: sampling rate, trigger polarity, voltage ; resolution (6,7, or 8 bits), and PWM DAC settling time have ; been retrieved from the chips EEPROM and used to preset the ; system to the state that was last saved. A checksum of ; relevant EEPROM values from the EEPROM will not be written ; to the operating parameters. ; ; !..Default settings ; Pressing ! causes the default operating parameters to be set ; and the operating parameters to be typed to the screen. The ; default parameters are 5 microsecond sampling time, 255 step ; voltage resolution, free run (DC measurements only), ; positive edge for triggering when triggering is selected, ; and settling time of 5 times. ; ; S..Status ; Displays the operating parameters (see Menu & status below) ; ; ?..Menu & status ; When the question mark is pressed, the menu will be ; displayed and the operating parameters will be typed. The ; operating parameters (status) display is shown below: ; ; 10 us 255 steps T - Stl=5 : ; ; 10 us means the sampling period is 10 microseconds ; 255 steps means the voltage resolution is 8 bit (255 steps) ; T means waveform capture is synchronized with the trigger ; signal ; (if F it would mean free run, not synchronized) ; - means that it will trigger on the negative edge of the ; trigger signal ; (if + it would mean triggering will be on positive ; edge) ; stl=5 means that the steeling time is 5X (if it said stl=1 ; then settling ; time would be 1X) ; ; A header is sent at the start of each data dump. ; Waveform capture 03.03.26 Dick Cappels, projects@cappels.org ; 1 us, MINIMUM 255 steps T - Stl=5 Meas ID=1.52 ; ; The header includes the version of the firmware, the operating parameters, ; and a measurement ID which is kept in EEPROM and incremented every time ; a waveform capture cycle is initiated. The digit on the left of the decimal point ; is the number of times the digit to the right overflowed beyond 255. The sample ; header above shows that this was this chip's 308th capture cycle. ; ; All characters sent to the terminal are deliberately delayed ; so as not to ; overrun input buffers on low performance computers when ; dumping data. ; ;Good luck in your experimentation. See my web site for ;contact information http://www.projects.cappels.org ; ; ; Start of Minimum Mass Waveform Capture demonstration program .include "2313def.inc" ;The main routines are: ; scanspan -This is routine that organizes the collection of the waveform. ; capture - Does the actual waveform capture. ; MainLoop - Interprets control panel commands and returns status. ; dumparray - Formats and dumps data to terminal. ;UART baud rate calculation .equ clock = 10000000 ;clock frequency .equ baudrate = 9600 ;choose a baudrate .equ baudconstant = (clock/(16*baudrate))-1 ;Assign space for array of sample values in RAM .equ arraystart = $60 ;First byte of data array .equ arrayend = $C3 ;Last byte of data array .equ defaultflags = $0F ;Assign working registers .def delayselect = r02 ;index into list of sampling delays .def dx1 = r03 ;delay counter .def dx2 = r04 ;delay counter .def dx3 = r05 ;delay counter .def temp = r16 ;general purpose variable .def innerrloopc = r17 ;delay counter, innermost loop .def outerloopc = r18 ;delay counter, outer loop .def flagreg = r19 ;Flags for control. See definitions below .def pwmval = r21 ;PWM value .def H = r22 ;Used to send decimal ascii .def T = r23 ;Used to send decimal ascii .def U = r24 ;Used to send decimal ascii .def pwmstartval = r25 ;Intial value for voltage measurement. ;Assignment of flagreg bits ;bit 0 if set, linefeeds are sent during dump to screen and spaces ($20) instead of a tab char. ;bit 1 if set, selects for settling time to be 5X, if clear, 1X. ;bit 2 if set, selects for triggering on positive edge of trigger signal ;bit 3 if set, selects for free run (non-triggered operation) ;bit 4 ;bit 5 ;bit 6 ;bit 7 ;Assign EEPROM locations ;Lowest bytes avoided to reduce chances of corruption. .equ checksumE = $20 .equ pwmstartvalE = $21 .equ flagregE = $22 .equ delayselectE = $23 .equ serialhighE = $30 .equ seriallowE = $31 .org $000 init: ldi temp,low(ramend) out spl,temp ;Set spl. ldi temp,baudconstant out ubrr,temp ;Load baudrate. sbi ucr,rxen ;Enable WAUT receive sbi ucr,txen ;Enable UART Transmit ldi pwmval,$FF rcall pwm8setup ;Start up PWM DAC. ldi temp,$02 ;Default scan rate is 10 us per sample mov delayselect,temp ldi flagreg,defaultflags ;Set flag to free run, trigger set to positive edge, ;and settling time of 5X (5 ms filter) ldi pwmstartval,255 ;Initialize voltage resolution rcall readsettings rcall menu ;Send Hello message rjmp MainLoop ;Main sampling control and I/O loop. pwm8setup: ;Set up AT90S2313 Timer 1 as 8 bit PWM. ldi temp,$81 out TCCR1A,temp ;Preload with $FF ldi temp,$01 out TCCR1B,temp ldi temp,$00 out OCR1AH,temp ldi temp,$FF out OCR1AL,temp ;Write PWM data sbi DDRB,3 ;Set PWM output pin as output ret ;To update PWM value, write a byte to OCR1AL assignsampledelay: ;Set pointer to sample delay entry point ldi ZH,high(2*delaylist) ;Load high part of byte address into ZH ldi ZL,low(2*delaylist) ;Load low part of byte address into ZL mov temp,delayselect lsl temp add ZL,temp brcc nca ;If carry results, take care of it. inc ZH nca: lpm ;Get address from pointer (r0) into ZH.ZL push r0 adiw ZL,1 lpm mov ZH,r0 pop ZL ret delaylist: ;Pointer table to entrances to generic delay routine. Used to select ;time scale for waveform sampling. The delay is delay time between ;individual samples. .dw delay1us .dw delay2us .dw delay5us .dw delay10us .dw delay20us .dw delay50us .dw delay100us .dw delay200us .dw delay500us .dw delay1000us .dw delay2000us .dw delay5000us .dw delay10000us delay2us: ;Total delay for 2.00 us (based on 10 mhz clock). nop nop ldi innerrloopc,$02 l2: dec innerrloopc brne l2 rjmp delay1us delay5us: ;Total sample delay for 5.00 us (based on 10 mhz clock), nop ;Before terminal priority accomodated two noops removed ldi innerrloopc,$01 ldi outerloopc,$07 rjmp genericdelay delay10us: ;Total sample delay for 10.0 us (based on 10 mhz clock). nop ;For terminal priority accomodatioon 6 nops added nop nop nop nop nop nop ldi innerrloopc,$01 ;Before terminal priority accomodated was $01 ldi outerloopc,$12 ;Before terminal priority accomodated was $12 rjmp genericdelay delay20us: ;Total sample delay for 20.0 us (based on 10 mhz clock). nop ;Before terminal priority accomodated was just one nop nop nop ldi innerrloopc,$01 ldi outerloopc,$2C ;Before terminal priority accomodated was $2D rjmp genericdelay delay50us: ;Total sample delay for 50.00 us (based on 10 mhz clock). nop ;Before terminal priority accomodated was just one nop nop nop ldi innerrloopc,$01 ldi outerloopc,$77 ;Before terminal priority accomodated was 78 rjmp genericdelay delay100us: ;delay for 100.1 us (based on 10 mhz clock. Trash innerrloopc and outerloopc. ldi innerrloopc,$01 ldi outerloopc,$F5 ;Before terminal priority accomodated was $F6 rjmp genericdelay delay200us: ;delay for 199.4 us (based on 10 mhz clock. Trash innerrloopc and outerloopc. ldi innerrloopc,$02 ldi outerloopc,$F6 rjmp genericdelay delay500us: ;delay for 500.1 us (based on 10 mhz clock. Trash innerrloopc and outerloopc. ldi innerrloopc,$05 ldi outerloopc,$F8 rjmp genericdelay delay1000us: ;delay for 1006 us (based on 10 mhz clock. Trash innerrloopc and outerloopc. ldi innerrloopc,$0C ldi outerloopc,$D0 rjmp genericdelay delay2000us: ;delay for 2010.4 us (based on 10 mhz clock. Trash innerrloopc and outerloopc. ldi innerrloopc,$18 ldi outerloopc,$D0 rjmp genericdelay delay5000us: ;delay for 5023.6 us (based on 10 mhz clock. Trash innerrloopc and outerloopc. ldi innerrloopc,$3C ldi outerloopc,$D0 rjmp genericdelay delay10000us: ;delay for 10045.6 us (based on 10 mhz clock. Trash innerrloopc and outerloopc. ldi innerrloopc,$78 ldi outerloopc,$D0 rjmp genericdelay ;This instruction not really needed but kept for uniformity. genericdelay: ;Actual sampling delay routine as set up by calling routine ;Enter with outer loop value in innerrloopc and ;outer loop value in outerloopc. outergeneric: sbic usr,rxc ;Check for byte in UART from terminal rjmp delay1us ;and if char is waiting, shorten loop ; mov temp,outerloopc innergeneric: nop dec temp brne innergeneric dec innerrloopc brne outergeneric nop rjmp delay1us wait1ms: ;delay for 1.003 ms (based on 10 mhz clock). including call and return). Trash innerrloopc and outerloopc. ldi innerrloopc,$0D outerloop1: ldi outerloopc,0 innerloop1: dec outerloopc brne innerloop1 dec innerrloopc brne outerloop1 ret wait5ms: ;delay for 5.0122 ms (based on 10 mhz clock). including call and return). Trash innerrloopc and outerloopc. ldi innerrloopc,$41 outerloop3: ldi outerloopc,0 innerloop3: dec outerloopc brne innerloop3 dec innerrloopc brne outerloop3 ret wait1000ms: ;delay for 1000ms (based on 10 mhz clock). including call and return). Trash innerrloopc and outerloopc. ldi temp,$36 mostouter: ldi innerrloopc,$0 outerloop31: ldi outerloopc,0 innerloop31: dec outerloopc brne innerloop31 dec innerrloopc brne outerloop31 dec temp brne mostouter ret FillArray: ;Fill array with pwmstartval ldi YL,arraystart ldi YH,$00 ;Corrected -was ldi YH,$FF mov temp,pwmstartval fillmore: st Y+,temp cpi YL,arrayend+1 brne fillmore ret scanspan: ;Fill array with analog measurements rcall assignsampledelay rcall capture rcall dumparray rjmp MainLoop capture: ;Enter with ZH,ZL pointing to delay routine ;For 1 microsecond sampling interval, point to oneus ;Values of samples are stored in RAM from location ;arratystart to arrayend. rcall FillArray ;Preset array. mov pwmval,pwmstartval ;PWM = 64 ldi temp,$00 out OCR1AH,temp ;Zero high register mov temp,pwmval cpi pwmstartval,255 ;If 255 steps, don't shift left breq ds1 lsl temp cpi pwmstartval,$128 ;If 128 steps, shift left once breq ds1 lsl temp ;If 64 steps, shift left twice ds1: out OCR1AL,temp ;Set pwm value rcall wait5ms sbrs flagreg,1 rjmp us2 rcall wait5ms rcall wait5ms rcall wait5ms rcall wait5ms us2: decpwm: dec pwmval ;PWM = PWM 1 1. cpi pwmval,$FF ;If PWM = -1 then finshed capturing. breq capturefinsihed ldi temp,$00 out OCR1AH,temp ;Zero high register mov temp,pwmval cpi pwmstartval,255 ;If 255 steps, don't shift left breq ds2 lsl temp cpi pwmstartval,128 ;If 128 steps, shift left once breq ds2 lsl temp ;If 64 steps, shift left twice ds2: out OCR1AL,temp ;Set pwm value rcall wait1ms ;Wait for small step settling time sbrs flagreg,1 rjmp us1 rcall wait1ms rcall wait1ms rcall wait1ms rcall wait1ms us1: ldi YH,$00 ;Y = array start. ldi YL,arraystart-1 rcall waitingfortrigger nextydelay: ;Includes NOPs come here if pwmval is not to be stored on this cycle inc YL ;Inc YL and see if array boundary has been exceeded. cpi YL,arrayend+1 breq decpwm nop ;Equalize time between samples for pwmval saved and not saved nop nexty: ijmp ;Jump to delay routine - address already loaded into Z reigster delay1us: sbic ACSR,$05 ;CAPTURE COMPARITOR OUTPUT STATE rjmp nextydelay st Y+,pwmval cpi YL,arrayend+1 breq decpwm rjmp nexty capturefinsihed: ret waitingfortrigger: sbrc flagreg,3 rjmp notriggerneeded sbrc flagreg,2 rjmp waitingforpostrigger waitingfornegtrigger: waitforhigh1: sbic usr,rxc ;Check for byte in UART from terminal rjmp quittrigger ; and return if char waiting (no trigger) sbis pind,$06 rjmp waitforhigh1 waitforlow1: sbic usr,rxc ;Check for byte in UART from terminal rjmp quittrigger ; and return if char waiting (no trigger) sbic pind,$06 rjmp waitforlow1 ret waitingforpostrigger: waitforlow: sbic usr,rxc ;Check for byte in UART from terminal rjmp quittrigger ; and return if char waiting (no trigger) sbic pind,$06 rjmp waitforlow waitforhigh: sbic usr,rxc ;Check for byte in UART from terminal rjmp quittrigger ; and return if char waiting (no trigger) sbis pind,$06 rjmp waitforhigh ret notriggerneeded: ;Come here when in free run ret quittrigger: ;Quit trigger routine and data collection ldi YL,arrayend ;Set YL to look like all points tried ret MainLoop: ldi temp,':' ;Emit prompt rcall emitchar mlw: sbis usr,rxc ;Check for byte in UART from terminal rjmp mlw ;Get and handle incoming byte from terminal. ;Results in rage 0..$D use as index to select sampling ;delay and results above $D interpret as command. in temp,udr ;Read byte rcall emitchar ;Echo byte andi temp,$5F ;Upper-case character cpi temp,'C' ;Is it an "C"? brne nc2 rjmp scanspan ;If C capture waveform nc2: cpi temp,'I' ;Is it an "I"? brne nc3 rjmp incrementds ;If I Increment delayselect nc3: cpi temp,'D' ;Is it an "D"? brne nc4 rjmp decrementds ;If D decrement delayselect nc4: cpi temp,'P' ;Is it an "P"? brne nc5 rjmp toggletrigger ;If P toggle trigger polarity nc5: cpi temp,'F' ;Is it an "F"? brne nc6 rjmp setfreerun ;If F set to free run nc6: cpi temp,'V' ;Is it an "V"? brne nc7 rjmp changeres ;If V change voltage resolution nc7: cpi temp,'T' ;Is it an "T"? brne nc8 rjmp settriggered ;If T set trigger/free run flag to triggered nc8: cpi temp,'S' ;Is it an "S"? brne nc9 rcall status ;If S display status rjmp MainLoop nc9: cpi temp,'L' brne nc10 rjmp togglesettle ;If L toggle settling time between 1X and 5X nc10: cpi temp,$1F ;If ? show menu and status brne nc11 rcall menu rjmp MainLoop nc11: cpi temp,'M' ;If M save settings brne nc12 rjmp savesettings nc12: cpi temp,$01 ;If ! restore default settings brne nc13 rjmp restoredefault nc13: cpi temp,'R' ;If R recall stored settings brne nc14 rcall readsettings rcall status rjmp MainLoop nc14: cpi temp,'E' brne nc15 rjmp togglelinefeed ;If E toggle linefeed during dump on/off nc15: rcall crlf rjmp MainLoop decrementds: rcall crlf mov temp,delayselect cpi temp,$00 brne ns6 rjmp ns7 ns6: dec delayselect ns7: ldi ZH,high(2*timebasemessage) ; Load high part of byte address into ZH ldi ZL,low(2*timebasemessage) ; Load low part of byte address into ZL rcall sendstring rcall sendtimebasestring rjmp MainLoop incrementds: rcall crlf mov temp,delayselect cpi temp,$0C brne ns4 rjmp ns5 ns4: inc delayselect ns5: ldi ZH,high(2*timebasemessage) ; Load high part of byte address into ZH ldi ZL,low(2*timebasemessage) ; Load low part of byte address into ZL rcall sendstring rcall sendtimebasestring rjmp MainLoop togglesettle: ;Toggle settling time between 1X and 5X rcall crlf sbrs flagreg,1 rjmp nsx8 andi flagreg,$FD rjmp nsx9 nsx8: ori flagreg,$02 nsx9: ldi ZH,high(2*settletimemessage) ; Load high part of byte address into ZH ldi ZL,low(2*settletimemessage) ; Load low part of byte address into ZL rcall sendstring ldi temp,'5' sbrc flagreg,1 rjmp notfive ldi temp,'1' notfive: rcall emitchar ldi temp,$20 rcall emitchar rjmp MainLoop toggletrigger: ;Topggle trigger polarity rcall crlf sbrs flagreg,2 rjmp ns8 andi flagreg,$FB rjmp ns9 ns8: ori flagreg,$04 ns9: ldi ZH,high(2*triggermessage) ; Load high part of byte address into ZH ldi ZL,low(2*triggermessage) ; Load low part of byte address into ZL rcall sendstring ldi temp,'+' sbrc flagreg,2 rjmp notminus ldi temp,'-' notminus: rcall emitchar ldi temp,$20 rcall emitchar rjmp MainLoop togglelinefeed: ;Topggle linefeed character during dump on/off rcall crlf sbrs flagreg,0 rjmp nis8 andi flagreg,$FE rjmp nis9 nis8: ori flagreg,$01 nis9: ldi ZH,high(2*lfmessage) ; Load high part of byte address into ZH ldi ZL,low(2*lfmessage) ; Load low part of byte address into ZL rcall sendstring ldi temp,'1' sbrc flagreg,0 rjmp notminusi ldi temp,'0' notminusi: rcall emitchar ldi temp,$20 rcall emitchar rjmp MainLoop setfreerun: ;Set to Free Run rcall crlf ori flagreg,$08 ldi ZH,high(2*freerunmessage) ; Load high part of byte address into ZH ldi ZL,low(2*freerunmessage) ; Load low part of byte address into ZL rcall sendstring rjmp MainLoop settriggered: ;Set to Free Run rcall crlf andi flagreg,$F7 ldi ZH,high(2*triggeredmessage) ; Load high part of byte address into ZH ldi ZL,low(2*triggeredmessage) ; Load low part of byte address into ZL rcall sendstring rjmp MainLoop emitchar: ;Send character with two stop bits + extended delay push temp sbis usr,udre ;wait until the register is cleared rjmp emitchar cbi ucr,0 ;Set 9th bit to zero (second stop bit) sbi ucr,2 ;Set to send 9 data bits out udr,temp ;send the character ldi temp,$18 ;TIME DELAY ROUTINE STARTS HERE mov dx2,temp ld2a: clr dx1 ; (To reduce receiver buffer overrun) ld1a: dec dx1 brne ld1a dec dx2 brne ld2a ;TIME DELAY ROUTINE ENDS HERE pop temp ret sendstring: ; Call with location of string in Z push temp ; Preserve temp in case its needed morestring: lpm ; Load byte from program memory into r0 tst r0 ; Check if we've reached the end of the message breq finishsendstering ; If so, return mov temp,r0 rcall emitchar adiw ZL,1 ; Increment Z registers rjmp morestring finishsendstering: pop temp ret sendnumber: ;Enter with value to be sent in temp, sends as three digit ascii ;via serial port. mov U,temp ;Enter with 8 bit value in U, Exits with numerals in H,T,U clr H ;(Hundreds, Tens, and Units). clr T anotherh: subi U,100 ;Find out how many hundreds in U. brcs hdone inc H rjmp anotherh hdone: subi U,-100 ;Subtracted one too many -add back. anothert: subi U,10 brcs tdone inc T rjmp anotherT tdone: subi U,-10 cpi H,0 breq dontsendh subi H,-48 mov temp,H rcall emitchar cpi t,0 brne dontsendh ldi temp,$30 ;If U=0 then don't emit this zero rcall emitchar dontsendh: cpi t,0 breq dontsendt subi T,-48 mov temp,T rcall emitchar dontsendt: subi U,-48 mov temp,U rcall emitchar ret dumparray: ;Dump contents of array: Y location, comma, data value. ldi ZH,high(2*idmessage) ; Load high part of byte address into ZH ldi ZL,low(2*idmessage) ; Load low part of byte address into ZL rcall sendstring rcall status ;Dump status ldi temp,$20 ;Send a space rcall emitchar ldi ZL,seriallowE ;Get sequence number from EEPROM int Y register rcall LoadEEByte mov YL,temp ldi ZL,serialhighE rcall LoadEEByte mov YH,temp adiw YL,1 ;Increment sequence number mov temp,YH ;Save sequence number in EEPROM rcall SaveEEByte ldi ZL,seriallowE mov temp,YL rcall SaveEEByte ldi ZH,high(2*sequencemessage) ; Load high part of byte address into ZH ldi ZL,low(2*sequencemessage) ; Load low part of byte address into ZL rcall sendstring mov temp,YH ;Print new sequence number to screen rcall sendnumber ldi temp,'.' rcall emitchar mov temp,YL rcall sendnumber ldi pwmval,1 ;Sample number for output. ldi YL,arraystart ;Pointer to data. ldi YH,$00 dumpmore1: ldi temp,$0D rcall emitchar ldi temp,$0A sbrc flagreg,0 rcall emitchar ;Send line feed if flagreg 0 is set mov temp,pwmval ;Send sample number. rcall sendnumber ldi temp,$20 sbrc flagreg,0 ;If linefeed flag is clear, don't send space rcall emitchar ldi temp,$09 sbrs flagreg,0 rcall emitchar ;If linefeed flag is set, don't send tab ld temp,Y+ rcall sendnumber inc pwmval cpi YL,arrayend+1 ;For this to work, array has to be completely within one page brne dumpmore1 rcall crlf ret crlf: ;Send return and linefeed ldi temp,$0A ;Send return and line feed for each point rcall emitchar ldi temp,$0D rcall emitchar ret changeres: ;Change voltage resolution ;Effectively interpret pwmstartval and ;change based on its current content. ;Allowed values:64, 128, and 255 rcall crlf cpi pwmstartval,64 brne not64 ldi pwmstartval,128 ldi ZH,high(2*msg128) ; Load high part of byte address into ZH ldi ZL,low(2*msg128) ; Load low part of byte address into ZL rcall sendstring rjmp donechangeres not64: cpi pwmstartval,128 brne not128 ldi pwmstartval,255 ldi ZH,high(2*msg255) ; Load high part of byte address into ZH ldi ZL,low(2*msg255) ; Load low part of byte address into ZL rcall sendstring rjmp donechangeres not128: cpi pwmstartval,255 brne not255 ldi pwmstartval,64 ldi ZH,high(2*msg64) ; Load high part of byte address into ZH ldi ZL,low(2*msg64) ; Load low part of byte address into ZL rcall sendstring rjmp donechangeres not255: donechangeres: rjmp MainLoop msg64: .db "64 steps" .db 00,00 msg128: .db "128 steps " .db 00,00 msg255: .db "255 steps " .db 00,00 showdelaylist: ;Pointer into strings .dw showdelay1us .dw showdelay2us .dw showdelay5us .dw showdelay10us .dw showdelay20us .dw showdelay50us .dw showdelay100us .dw showdelay200us .dw showdelay500us .dw showdelay1000us .dw showdelay2000us .dw showdelay5000us .dw showdelay10000us showdelay1us: .db "1 us, MINIMUM" .db 00,00 showdelay2us: .db "2 us" .db 00,00 showdelay5us: .db "5 us" .db 00,00 showdelay10us: .db "10 us " .db 00,00 showdelay20us: .db "20 us " .db 00,00 showdelay50us: .db "50 us " .db 00,00 showdelay100us: .db "100 us" .db 00,00 showdelay200us: .db "200 us" .db 00,00 showdelay500us: .db "500 us" .db 00,00 showdelay1000us: .db "1 ms" .db 00,00 showdelay2000us: .db "2 ms" .db 00,00 showdelay5000us: .db "5 ms" .db 00,00 showdelay10000us: .db "10 ms, MAXIMUM " .db 00,00 idmessage: .db $0A,$0D .db "Waveform capture 03.03.26 Dick Cappels, projects@cappels.org" .db $00,$00 hellomessage: .db $0A,$0D .db $0A,$0D .db "C..Capture & dump " .db $0A,$0D .db "I..Increase sample time " .db $0A,$0D .db "D..Decarese sample time " .db $0A,$0D .db "T..Triggered mode " .db $0A,$0D .db "F..Free run mode" .db $0A,$0D .db "P..Trig. Polarity toggle" .db $0A,$0D .db "V..Voltage res" .db $0A,$0D .db "L..Settle time toggle " .db $0A,$0D .db "E..Toggle line feed " .db $0A,$0D .db "M..Save settings" .db $0A,$0D .db "R..Recall saved settings" .db $0A,$0D .db "!..Default settings " .db $0A,$0D .db "S..Status " .db $0A,$0D .db "?..Menu & status" .db $0A,$0D .db 00,00 lfmessage: .db "Linefeed = " .db 00,00 timebasemessage: .db "Timebase = " .db 00,00 triggermessage: .db "Trigger polarity = " .db 00,00 triggeredmessage: .db "Triggerred" .db 00,00 freerunmessage: .db "Free Run" .db 00,00 settletimemessage: .db "Settling time = " .db 00,00 shsetmsg: .db "Stl=" .db 00,00 sequencemessage: .db " Meas ID=" .db 00,00 sendtimebasestring: push temp ; Preserve temp in case its needed ldi ZH,high(2*showdelaylist) ;Load high part of byte address into ZH ldi ZL,low(2*showdelaylist) ;Load low part of byte address into ZL mov temp,delayselect lsl temp add ZL,temp brcc nca1 ;If carry results, take care of it. inc ZH nca1: lpm ;Get address from pointer (r0) into ZH.ZL push r0 adiw ZL,1 lpm mov ZH,r0 pop ZL ;Now, ZL should be pointing to the string lsl ZL ;Move left one position to point to word rol ZH moestring: lpm ; Load byte from program memory into r0 tst r0 ; Check if we've reached the end of the message breq finishsendstering1 ; If so, return mov temp,r0 rcall emitchar adiw ZL,1 ; Increment Z registers rjmp moestring finishsendstering1: pop temp ret menu: ;Show commands and status ldi ZH,high(2*idmessage) ; Load high part of byte address into ZH ldi ZL,low(2*idmessage) ; Load low part of byte address into ZL rcall sendstring ldi ZH,high(2*hellomessage) ; Load high part of byte address into ZH ldi ZL,low(2*hellomessage) ; Load low part of byte address into ZL rcall sendstring rcall status ret status: rcall crlf rcall sendtimebasestring ldi temp,$20 rcall emitchar cpi pwmstartval,64 brne not641 ldi ZH,high(2*msg64) ; Load high part of byte address into ZH ldi ZL,low(2*msg64) ; Load low part of byte address into ZL rcall sendstring rjmp donechangeres1 not641: cpi pwmstartval,128 brne not1281 ldi ZH,high(2*msg128) ; Load high part of byte address into ZH ldi ZL,low(2*msg128) ; Load low part of byte address into ZL rcall sendstring rjmp donechangeres1 not1281: cpi pwmstartval,255 brne not2551 ldi ZH,high(2*msg255) ; Load high part of byte address into ZH ldi ZL,low(2*msg255) ; Load low part of byte address into ZL rcall sendstring rjmp donechangeres1 not2551: donechangeres1: ldi temp,$20 rcall emitchar ldi temp,'F' sbrs flagreg,3 ldi temp,'T' rcall emitchar ldi temp,$20 rcall emitchar ldi temp,'+' sbrs flagreg,2 ldi temp,'-' rcall emitchar ldi temp,$20 rcall emitchar ldi ZH,high(2*shsetmsg) ; Load high part of byte address into ZH ldi ZL,low(2*shsetmsg) ; Load low part of byte address into ZL rcall sendstring ldi temp,'5' sbrs flagreg,1 ldi temp,'1' rcall emitchar ldi temp,$20 rcall emitchar ; Status of Linefeed flag ldi ZH,high(2*lfmessage) ; Load high part of byte address into ZH ldi ZL,low(2*lfmessage) ; Load low part of byte address into ZL rcall sendstring ldi temp,'1' sbrs flagreg,0 ldi temp,'0' rcall emitchar ret savesettings: rcall crlf mov temp,delayselect ;Store sampling rate ldi ZL,delayselectE rcall saveEEByte mov temp,pwmstartval ldi ZL,pwmstartvalE rcall saveEEByte ;Store pwmstartval (voltage resolution). mov temp,flagreg ;Store flagreg. ldi ZL,flagregE rcall saveEEByte mov temp,pwmstartval ;Create checksum by subtracting flagreg then samplerate from pwmstartval without carry. sub temp,flagreg sub temp,delayselect ldi ZL,checksumE rcall saveEEByte ;Store checksum. ldi temp, $20 rcall emitchar ;Send "OK" to terminal ldi temp,'O' rcall emitchar ldi temp,'K' rcall emitchar rjmp MainLoop readsettings: ;Restore machine state if saved and contents of EEPROM are ok. ldi ZL,pwmstartvalE rcall loadEEByte ;Read pwmstartval (voltage resolution). mov YL,temp ldi ZL,flagregE rcall loadEEByte mov YH,temp ;Read flagreg. ldi ZL,delayselectE rcall loadEEByte mov XH,temp ;Read delay select register .. mov XL,YL sub XL,YH ;Data checksum is in XL. sub XL,XH ldi ZL,checksumE rcall loadEEByte ;Read stored checksum. cp temp,XL ;If checksum is good,then store otherwise, skip. brne dontload mov pwmstartval,YL mov flagreg,YH mov delayselect,XH ldi temp,'*' ;Type asterisk to terminal after loading. rcall emitchar dontload: ret restoredefault: ldi temp,$02 ;Default scan rate is 10 us per sample. mov delayselect,temp ldi flagreg,defaultflags ;Set flag to free run, trigger set to positive edge, ;and settling time of 5X (5 ms filter) ldi pwmstartval,255 ;Initialize voltage resolution rcall status rjmp MainLoop SaveEEByte: ;Save byte to EEPROM ;Enter with data in temp and address in ZL. wrat1: sbic eecr,eewe ;Wait for EEPROM write to not be busy rjmp wrat1 out eear,ZL out eedr,temp ;Set up the write data sbi eecr,eemwe sbi eecr,eewe ;Trigger the write dec ZL ret LoadEEByte: ;Read byte from EEPROM ;Enter with address in ZL. Exits with data in temp wratz1: sbic eecr,eewe ;Wait for EEPROM write to not be busy rjmp wratz1 out eear,ZL ;move to EEPROM address register sbi eecr,eere ;Trigger the read in temp,eedr ;Get the data into temp ret ; End of Minimum Mass Waveform Capture demonstration program ; http://www.projects.cappels.org