summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c196
1 files changed, 134 insertions, 62 deletions
diff --git a/main.c b/main.c
index 481757b..f812e4e 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,128 @@
#include <avr/io.h>
#include <avr/delay.h>
-
+
+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(
+ "recv_wait_low_initial_loop: \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<len; i++)
+ for (int j=0x80; j!=0; j=j>>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
+ WAIT10
+ OUT1
+ "; done :) \n"
+ "pop r30 \n"
+ "pop r31 \n"
+
+ :
+ : "I" (_SFR_IO_ADDR(DDRC)),
+ "I" (_SFR_IO_ADDR(PINC)),
+ "w" (len),
+ "z" ((unsigned char volatile*) buffer)
+ : "r16"
+ );
+
+}
+
+
int main (void)
{
DDRC=0x00;
@@ -9,73 +131,23 @@ int main (void)
DDRB=0xFF;
PORTB=0x55;
-#define OUT0 "sbi %0, 5 \n" /* pull line to GND */
-#define OUT1 "cbi %0, 5 \n" /* tristate the line */
-#define NOP "nop \n"
-#define NOP10 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
-#define NOP12 NOP10 NOP NOP
-#define WAIT10 "ldi r16, 1 \n rcall loop \n"
-#define WAIT34 "ldi r16, 9 \n rcall loop \n"
+ PORTB=0x55;
+
+ int temp=0;
-//#define BIT0 OUT0 NOP10 NOP12 NOP12 OUT1 NOP10
-//#define BIT1 OUT0 NOP10 OUT1 NOP10 NOP12 NOP12
-#define BIT0 OUT0 WAIT34 OUT1 WAIT10
-#define BIT1 OUT0 WAIT10 OUT1 WAIT34
+ while(1)
+ {
+ temp++;
+// PORTB=~(1 << ((temp>>9)%6));
+PORTB=~temp;
+ _delay_ms(1);
- PORTB=0x55;
+ char foo[] = { 0x40, 0x03, 0x02 };
- int temp=0;
+ send_gc(foo, 3);
- while(1)
- {
- temp++;
- PORTB=~(1 << ((temp>>9)%6));
- _delay_ms(1);
- asm volatile(
- BIT0
- BIT1
- BIT0
- BIT0
-
- BIT0
- BIT0
- BIT0
- BIT0
-
- BIT0
- BIT0
- BIT0
- BIT0
-
- BIT0
- BIT0
- BIT1
- BIT1
-
- BIT0
- BIT0
- BIT0
- BIT0
-
- BIT0
- BIT0
- BIT1
- BIT0
-
-
- BIT1
- "rjmp done \n"
- "loop:\n"
- "dec r16\n"
- "brne loop\n"
- "ret\n"
- "done: \n"
- :
- : "I" (_SFR_IO_ADDR(DDRC)), "I" (_SFR_IO_ADDR(PINC))
- : "r16"
- );
}