summaryrefslogtreecommitdiffstats
path: root/app/timex.c
blob: 40f43ad3a9ae4e0e7b520e0487d4ac88beffde37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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);
}