.include "tn45def.inc" ; ; definitions ; .equ so_pin = PB2; (master in) slave out, aka send from me (i'm a slave) .equ si_pin = PB1; (master out) slave in, aka receive. (i'm a slave) .equ nloop = 200 ; number of samples between framing ; ; registers ; .def bit_count = R16; bit counter .def temp = R17; temporary storage .def temp1 = R18; temporary storage .def txbyte = R19; data byte .def rxbyte = R20; .def loop_count = R21 ; loop counter ; ; code segment ; .cseg .org 0 rjmp reset ; bit delay ; serial bit delay ; ;.equ b = 13 ; 9600 baud (clock /8) ;.equ b = 130 ; 9600 baud (clock /1) .equ b = 8 ; 115200 baud (clock /1) ;.equ b = 6 ; crazy speed ;.equ b = 4 ; ludicrous speed bit_delay: ldi temp, b bitloop: dec temp brne bitloop ret ; ; putchar ; assumes no line driver (doesn't invert bits) ; .equ sb = 1; number of stop bits putchar: ldi bit_count, 9+sb; 1+8+sb com txbyte; invert everything sec; set start bit putchar0: brcc putchar1; if carry set sbi PORTB, so_pin; send a '0' rjmp putchar2; else putchar1: cbi PORTB, so_pin ; send a '1' nop ; even out timing putchar2: rcall bit_delay; one bit delay rcall bit_delay lsr txbyte; get next bit dec bit_count; if not all bits sent brne putchar0; send next bit ret; ; ; getchar ; assumes no line driver (doesn't invert bits) ; getchar: ldi bit_count, 8+sb ; 8 data bit + 1 stop bit getchar1: sbis PINB, si_pin ; wait for start bit rjmp getchar1 rcall bit_delay ; 0.5 bit delay getchar2: rcall bit_delay ; 1 bit delay rcall bit_delay ; clc ; clear carry sbis PINB, si_pin ; if RX pin high skip sec ; otherwise set carry dec bit_count breq getchar3 ; return if all bits read ror rxbyte ; otherwise shift bit into receive byte rjmp getchar2 ; go get next bit getchar3: ret ; ; char_delay ; delay between characters ; char_delay: ldi temp, 255 char_delay_loop: ldi temp1, 10 char_delay_loop1: dec temp1 brne char_delay_loop1 dec temp brne char_delay_loop ret ; ; main program ; reset: ; ; set clock divider to /1 ; ldi temp, (1 << CLKPCE) ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0) out CLKPR, temp out CLKPR, temp1 ; ; set stack pointer to top of RAM ; ldi temp, high(RAMEND) out SPH, temp ldi temp, low(RAMEND) out SPL, temp ; ; init comm pin for output ; sbi PORTB, so_pin sbi DDRB, so_pin cbi PORTB, si_pin cbi DDRB, si_pin ; ; set up A/D ; sbi ADMUX, REFS2 ; use 2.56V reference sbi ADMUX, REFS1 ; " cbi ADMUX, REFS0 ; " cbi ADMUX, MUX3 ; 20x differential input on ADC2,3 sbi ADMUX, MUX2 ; sbi ADMUX, MUX1 ; sbi ADMUX, MUX0 ; sbi ADMUX, ADLAR ; left-adjust result sbi ADCSRA, ADEN ; enable A/D cbi ADCSRA, ADATE ; disable auto-trigger sbi ADCSRA, ADPS2 ; set prescaler for /32 cbi ADCSRA, ADPS1 ; " sbi ADCSRA, ADPS0 ; " ; ; PWM ; ldi temp, TCCR0A ldi temp1, TCCR0B cbr temp1, (1 << WGM02) ; set OC0A on fast PWM, 0xFF Bottom sbr temp, (1 << WGM01) ; " sbr temp, (1 << WGM00) ; " sbr temp, (1 << COM0A1) ; set OC0A on compare match, inverting mode sbr temp, (1 << COM0A0) ; " cbr temp, (1 << COM0B1) ; disable OC0B PWM cbr temp, (1 << COM0B0) ; " cbr temp1, (1 << CS02) ; set timer 0 prescaler to 1 cbr temp1, (1 << CS01) ; " sbr temp1, (1 << CS00) ; " out TCCR0A, temp out TCCR0B, temp1 sbi DDRB, PB0 ; enable OC0A output pin ; ; main loop ; ldi txbyte, 0 main_loop: ; ; read A/D ; sbi ADCSRA, ADSC ; start conversion rcall putchar adloopup: sbic ADCSRA, ADSC ; loop until complete rjmp adloopup ; ; send conversion ; in txbyte, ADCH ;rcall getchar ;out OCR0A, rxbyte rjmp main_loop