altos: Make micropeak 'serial' interface work
[fw/altos] / src / micropeak / ao_async.c
index 04bba9e81fa7669e5f3347b58077d7a6f68e64fc..3556f54c00d511932baabad43a3d358311233d0f 100644 (file)
 #define AO_ASYNC_BAUD  38400l
 #define AO_ASYNC_DELAY (uint8_t) (1000000l / AO_ASYNC_BAUD)
 
+#define LED_PORT       PORTB
+
+void
+ao_async_start(void)
+{
+       LED_PORT |= (1 << AO_LED_SERIAL);
+}
+
+void
+ao_async_stop(void)
+{
+       LED_PORT &= ~(1 << AO_LED_SERIAL);
+}
+
 void
 ao_async_byte(uint8_t byte)
 {
        uint8_t         b;
        uint16_t        w;
 
-       /* start bit */
-
-       /* start     data         stop */
-       w = 0x001 | (byte << 1) | 0x000;
+       /*    start           data           stop */
+       w = (0x000 << 0) | (byte << 1) | (0x001 << 9);
 
+       ao_arch_block_interrupts();
        for (b = 0; b < 10; b++) {
-               ao_led_set((w & 1) << AO_LED_SERIAL);
+               uint8_t v = LED_PORT & ~(1 << AO_LED_SERIAL);
+               v |= (w & 1) << AO_LED_SERIAL;
+               LED_PORT = v;
                w >>= 1;
-               ao_delay_us(26);
+
+               /* Carefully timed to hit around 9600 baud */
+               asm volatile ("nop");
+               asm volatile ("nop");
+
+               asm volatile ("nop");
+               asm volatile ("nop");
+               asm volatile ("nop");
+               asm volatile ("nop");
+               asm volatile ("nop");
+
+               asm volatile ("nop");
+               asm volatile ("nop");
+               asm volatile ("nop");
+               asm volatile ("nop");
+               asm volatile ("nop");
        }
+       ao_arch_release_interrupts();
 }