summaryrefslogtreecommitdiffstats
path: root/app/timex.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/timex.c')
-rw-r--r--app/timex.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/app/timex.c b/app/timex.c
new file mode 100644
index 0000000..40f43ad
--- /dev/null
+++ b/app/timex.c
@@ -0,0 +1,248 @@
+#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);
+}