#include #include static char buffer[300]; #define OUT0 "sbi %2, 5 \n" /* pull line to GND */ #define OUT1 "cbi %2, 5 \n" /* tristate the line */ #define WAIT10 "ldi r16, 1 \n rcall delay_loop \n" #define WAIT34 "ldi r16, 9 \n rcall delay_loop \n" #define WAIT10MINUS10 "" #define WAIT34MINUS10 "ldi r16,5 \n rcall delay_loop \n nop \n nop \n" int send_recv_gc(char* bytes, int len) { char* buf_ptr = buffer; /****** SEND PART ******/ int k=0; for (int i=0; i>1, k++) buffer[k] = ((bytes[i] & j)!=0)?1:0 ; len=len*8+1; asm volatile( "push r31 ; save Z\n" "push r30 \n\n" ";;;;;;;; SEND PART ;;;;;;;;\n\n" "send_loop: \n" "sbiw %3, 1 \n" // 2 "breq send_done \n" // 1 if not done, 2 if done "ld r16, z+ \n" // 2 "tst r16 \n" // 1 "brne send_one \n\n" // 1 if zero, 2 if nonzero "; otherwise, send zero \n" "nop \n" // 1 OUT0 WAIT34 OUT1 WAIT10MINUS10 "rjmp send_loop \n\n" // 2 "send_one: \n" OUT0 WAIT10 OUT1 WAIT34MINUS10 "rjmp send_loop \n\n" "delay_loop:\n" "; this costs 7 + 3*(r16) cycles \n" "dec r16\n" "brne delay_loop\n" "ret\n\n" "send_done: \n" "; now send the stop bit and release the line \n" "nop \n nop \n nop \n" OUT0 "; instead of WAIT10, do sensible work \n" "pop r30 ; restore Z \n" // 2 "pop r31 \n" // 2 "clr r16 \n" // 1 "nop \n nop \n nop \n nop \n nop \n" // 5 OUT1 "; done :) \n\n\n" "; now the final thing is to wait for DATA become high again (should be immediately anyway) \n" "send_final_loop: \n" "inc r16 \n" "breq timeout \n" "sbis %1, 5 \n" "rjmp send_final_loop \n\n\n" ";;;;;;;; RECEIVE PART ;;;;;;;;\n\n" "clr r16 \n" "recv_wait_low_initial_loop: \n" "inc r16 \n" "breq timeout \n" "sbic %1, 5 \n" "rjmp recv_wait_low_initial_loop \n" // from low to the start of counting: 6 cycles = 0.5us "nop \n" "nop \n" "nop \n" "nop \n" "recv_loop: \n" "recv_low_begin: \n" "ldi r16, 128 \n" // 1 "recv_low_loop: \n" "inc r16 \n" // 1 "breq timeout \n" // 1 if no timeout "sbis %1, 5 \n" // 1 // von high auf dec: 6 "rjmp recv_low_loop \n\n" // 2 if executed, 1 if skipped. "nop \n" // to account for the rjmp recv_loop below. "nop \n" "nop \n" "nop \n" "recv_high_begin: \n" "nop \n" // to account for the ldi in recv_low_begin. "recv_high_loop: \n" "dec r16 \n" // 1 "breq timeout \n" // 1 if no timeout "sbic %1, 5 \n" // 1 // von low auf inc: 6 "rjmp recv_high_loop \n\n" // 2 if executed, 1 if skipped "st z+, r16 \n" // 2 "rjmp recv_loop \n\n" // 2 "timeout: \n" : "+z" ((unsigned char volatile*) buf_ptr) : "I" (_SFR_IO_ADDR(PINC)), "I" (_SFR_IO_ADDR(DDRC)), "w" (len) : "r16", "memory" ); return buf_ptr-buffer; // a value of >=128 means "0", <127 means "1" bit. } int main (void) { DDRC=0x00; PORTC=0x00; DDRB=0xFF; DDRD=0x00; PORTB=0x55; int temp=0; int n_received; while(1) { temp++; if (!(PIND & 0x08)) { //PORTB=~(1 << ((temp>>9)%6)); PORTB=~temp; } else if (!(PIND & 0x20)) { PORTB=~n_received>>3; } else if (!(PIND & 0x40)) { PORTB=~0x00; } else { //PORTB=~buffer[4]; char tmp=0; for (int i=0;i<8;i++) tmp|= ( (buffer[i]&0x80)?0:(1<