#include "project.h" /* * VGA 640x480 mode timings are * * 48 640 16 96 * 10 480 33 2 * * at 25.175 Hz * */ /* * Two bytes are shown per video frame one starting at * scanline 70, the other at 255, and there are 15 * scanlines between bits. * */ #define SL_BYTE_1_START 70 #define SL_BIT 15 #define SL_BYTE_2_START 255 #undef PAD #undef EX #define SL_ON(byte,bit) ((SL_BYTE_ ## byte ## _START) + (SL_BIT * (bit))) #define SL_OFF(byte,bit) (SL_ON(byte,bit) + 1) #define SEND_BIT(byte,bit,data) \ case SL_ON(byte,bit): \ timex_led((data) & 1); \ break; \ case SL_OFF(byte,bit): \ timex_led(1); \ break #define SEND_BIT_SHIFT(byte,bit,data) \ case SL_ON(byte,bit): \ timex_led((data) & 1); \ data>>=1; \ break; \ case SL_OFF(byte,bit): \ timex_led(1); \ break #define SEND_BYTE(byte, start, data) \ SEND_BIT(byte,0,start); \ SEND_BIT_SHIFT(byte,1,data); \ SEND_BIT_SHIFT(byte,2,data); \ SEND_BIT_SHIFT(byte,3,data); \ SEND_BIT_SHIFT(byte,4,data); \ SEND_BIT_SHIFT(byte,5,data); \ SEND_BIT_SHIFT(byte,6,data); \ SEND_BIT_SHIFT(byte,7,data); \ SEND_BIT_SHIFT(byte,8,data) /* * We ignore the horizontal front/back/sync and drive the system timer at * the horizontal sync frequency of 31.46875kHz or as close as we can manage */ #define BUFFER_SIZE 512 #define TIMEX_BANK GPIOB #define TIMEX_GPIO GPIO9 ring_t timex_ring; static uint8_t timex_ring_buf[BUFFER_SIZE]; static inline void timex_led (int v) { if (v) gpio_set (TIMEX_BANK, TIMEX_GPIO); else gpio_clear (TIMEX_BANK, TIMEX_GPIO); } #define SYNCS 200 typedef enum { STATE_MAGIC1, STATE_MAGIC2, STATE_MAGIC3, STATE_MAGIC4, STATE_IDLE, STATE_SYNC1, STATE_SYNC2, STATE_PACKET_HEADER, STATE_PACKET_DATA, STATE_PACKET_PAD, STATE_PACKET_RECOVERY, } Timex_state; static int get_data (uint8_t *start, uint8_t *data) { static Timex_state state = STATE_MAGIC1; static unsigned len; static unsigned pad; *start = 0; switch (state) { case STATE_MAGIC1: if (ring_empty (&timex_ring)) return 1; case STATE_IDLE: if (ring_empty (&timex_ring)) return 1; state = STATE_SYNC1; len = SYNCS; break; case STATE_SYNC1: *data = 0x55; len--; if (!len) state = STATE_SYNC2; break; case STATE_SYNC2: *data = 0xaa; state = STATE_PACKET_HEADER; break; case STATE_PACKET_HEADER: if (ring_read_byte (&timex_ring, data)) { /*No more data*/ state = STATE_MAGIC1; return 1; } len = *data -1 ; state = STATE_PACKET_DATA; #ifdef PAD pad =(*data &1); #else pad=0; #endif break; case STATE_PACKET_DATA: ring_read_byte (&timex_ring, data); len--; if (!len) { #ifdef PAD len = 20; #else len = 10; #endif if (pad) state = STATE_PACKET_PAD; else state = STATE_PACKET_RECOVERY; } break; case STATE_PACKET_PAD: *data=0x00; state = STATE_PACKET_RECOVERY; break; case STATE_PACKET_RECOVERY: *start = 1; *data = 0xff; len--; if (!len) state = STATE_PACKET_HEADER; break; } return 0; } void timex_tick (void) { static unsigned line = 0; static uint8_t data, start; switch (line) { case (SL_BYTE_1_START-2): if (get_data (&start, &data)) { line = 0; return; } break; SEND_BYTE (1, start, data); #ifdef PAD case (SL_BYTE_2_START-2): if (get_data (&start, &data)) { line = 0; return; } break; SEND_BYTE (2, start, data); #endif } line++; if (line == 525) line = 0; } #ifdef EX uint8_t ex[]={ #include "/root/projects/timex_datalink/datalink-1.0.1/fish.h" }; #endif void timex_init (void) { ring_init (&timex_ring, timex_ring_buf, sizeof (timex_ring_buf)); #ifdef EX ring_write(&timex_ring,ex,sizeof(ex)); #endif gpio_set_mode (TIMEX_BANK, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, TIMEX_GPIO); timex_led (1); }