#include #include static char buffer[300]; #define OUT0 "sbi %0, 5 \n" /* pull line to GND */ #define OUT1 "cbi %0, 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 recv_gc() { char* buf_ptr = buffer; asm volatile( "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)) : "r16", "memory" ); return buf_ptr-buffer; // a value of >=128 means "0", <127 means "1" bit. } void send_gc(char* bytes, int len) { 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 \n" "push r30 \n\n" "send_loop: \n" "sbiw %2, 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 some sensible cleanup work \n" "clr r16 ; needed below \n" "pop r30 \n" "pop r31 \n" "nop \n nop \n nop \n nop \n nop \n" 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 send_timeout \n" "sbis %0, 5 \n" "rjmp send_final_loop \n" "send_timeout: \n" : : "I" (_SFR_IO_ADDR(DDRC)), "I" (_SFR_IO_ADDR(PINC)), "w" (len), "z" ((unsigned char volatile*) buffer) : "r16" ); } 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 & 0x10)) { //PORTB=~buffer[4]; char tmp=0; for (int i=0;i<8;i++) tmp|= ( (buffer[i]&0x80)?(1<>3; } else if (!(PIND & 0x40)) { PORTB=~0x00; } _delay_ms(1); char foo[] = { 0x40, 0x03, 0x02 }; send_gc(foo, 3); n_received=recv_gc(); } return 0; // never reached }