2 * Copyright © 2015 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include <ao_adc_fast.h>
24 static struct ao_task ao_blink_green_task;
25 static uint8_t ao_blinking_green = 0;
31 while (!ao_blinking_green)
32 ao_sleep(&ao_blinking_green);
33 while (ao_blinking_green) {
34 ao_led_toggle(AO_LED_GREEN);
35 ao_delay(AO_MS_TO_TICKS(1000));
40 static struct ao_task ao_blink_red_task;
41 static uint8_t ao_failed = 0; /* 0 NOMINAL, 1 FAILED */
42 static uint8_t ao_post = 0; /* 0 POST needed, 1 powered up */
44 /* On handling failure, keithp said:
45 We could disconnect from USB easily enough, or disconnect and come back
46 with a different setup that the kernel driver could report as an
47 error. Lots of options.
54 ao_wakeup(&ao_failed);
59 static uint16_t ao_fail_ring_tail;
60 static uint32_t ao_fail_adc;
61 static uint32_t fail_ring[AO_ADC_RING_SIZE >> 1];
66 static uint16_t *buffer[2];
73 uint32_t *rnd = (uint32_t *) ao_adc_ring;
76 uint8_t prev_set = 0; /* prev has been set */
79 buffer[0] = ao_usb_alloc();
80 buffer[1] = ao_usb_alloc();
86 if (ao_cmd_status == ao_cmd_success)
87 kbytes = ao_cmd_lex_u32;
89 ao_cmd_status = ao_cmd_success;
91 count = kbytes * (1024/AO_USB_IN_SIZE);
95 ao_led_on(AO_LED_TRNG_ACTIVE);
96 while (!ao_failed && count--) {
97 t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
98 buf = buffer[usb_buf_id];
99 for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
102 if (prev_set && (cur == prev)) {
104 ao_fail_ring_tail = t;
108 *buf++ = ao_crc_in_32_out_16(cur);
109 t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
113 ao_adc_ack(AO_USB_IN_SIZE);
114 ao_led_toggle(AO_LED_TRNG_ACTIVE);
115 ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
116 ao_led_toggle(AO_LED_TRNG_ACTIVE);
117 usb_buf_id = 1-usb_buf_id;
119 ao_led_off(AO_LED_TRNG_ACTIVE);
124 ao_trng_fetch_cmd(void)
135 uint32_t *rnd = (uint32_t *) ao_adc_ring;
137 printf("FAILED at ring_tail: %3d, adc = %08x\n", ao_fail_ring_tail, ao_fail_adc);
138 for (i = 0; i < (AO_ADC_RING_SIZE >> 1); i += 4) {
139 printf("%3d: %08x ", i, rnd[i]);
140 printf("%3d: %08x ", i+1, rnd[i+1]);
141 printf("%3d: %08x ", i+2, rnd[i+2]);
142 printf("%3d: %08x\n", i+3, rnd[i+3]);
144 printf("COPY fail_ring: %3d, adc = %08x\n", ao_fail_ring_tail, ao_fail_adc);
145 for (i = 0; i < (AO_ADC_RING_SIZE >> 1); i += 4) {
146 printf("%3d: %08x ", i, fail_ring[i]);
147 printf("%3d: %08x ", i+1, fail_ring[i+1]);
148 printf("%3d: %08x ", i+2, fail_ring[i+2]);
149 printf("%3d: %08x\n", i+3, fail_ring[i+3]);
155 void ao_trng_reset(void); /* forward declaration */
158 ao_blink_green_toggle(void)
160 ao_blinking_green = !ao_blinking_green;
161 if (!ao_blinking_green)
162 ao_led_off(AO_LED_GREEN);
163 ao_wakeup(&ao_blinking_green);
166 static const struct ao_cmds ao_trng_cmds[] = {
167 { ao_trng_fetch_cmd, "f <kbytes>\0Fetch a block of numbers" },
168 { ao_trng_reset, "R\0Reset" },
169 { ao_blink_green_toggle, "G\0Toggle green LED blinking" },
170 { ao_trng_status, "s\0Show status" },
171 { ao_trng_failure, "z\0Simulate failure" },
180 static uint16_t *buffer[2];
185 uint32_t *rnd = (uint32_t *) ao_adc_ring;
188 buffer[0] = ao_usb_alloc();
189 buffer[1] = ao_usb_alloc();
199 ao_led_on(AO_LED_TRNG_ACTIVE);
200 t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
201 buf = buffer[usb_buf_id];
202 for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
203 *buf++ = ao_crc_in_32_out_16(rnd[t]);
204 t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
206 ao_adc_ack(AO_USB_IN_SIZE);
207 ao_led_off(AO_LED_TRNG_ACTIVE);
208 ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
209 usb_buf_id = 1-usb_buf_id;
213 static struct ao_task ao_trng_send_task;
216 ao_bootloader_cmd(void)
219 getchar(); /* any char will do */
220 /* give feedback we are going into bootloader mode */
221 ao_led_on(AO_LED_GREEN);
222 ao_delay(AO_MS_TO_TICKS(500));
223 ao_led_off(AO_LED_GREEN);
224 ao_delay(AO_MS_TO_TICKS(500));
225 ao_led_on(AO_LED_GREEN);
226 ao_delay(AO_MS_TO_TICKS(500));
227 ao_led_off(AO_LED_GREEN);
228 ao_delay(AO_MS_TO_TICKS(500));
229 ao_led_on(AO_LED_GREEN);
230 ao_delay(AO_MS_TO_TICKS(500));
231 ao_led_off(AO_LED_GREEN);
236 static struct ao_task ao_bootloader_cmd_task;
241 /* NOTE: the reset function also functions as the Power On Self Test */
245 /* printf("Resetting...\n"); */
247 ao_led_off(AO_LED_RED);
248 ao_wakeup(&ao_failed);
249 /* get the first 1k bits and ensure there are no duplicates */
250 /* FIXME ao_trng_fetch(); */
252 ao_led_on(AO_LED_GREEN);
253 ao_delay(AO_MS_TO_TICKS(1000));
254 ao_led_off(AO_LED_GREEN);
262 ao_trng_reset(); /* POST */
267 ao_sleep(&ao_failed);
269 ao_led_toggle(AO_LED_RED);
270 ao_delay(AO_MS_TO_TICKS(500));
278 ao_add_task(&ao_blink_red_task, ao_blink_red, "blink_red");
279 ao_add_task(&ao_blink_green_task, ao_blink_green, "blink_green");
281 ao_cmd_register(ao_trng_cmds);
283 ao_add_task(&ao_bootloader_cmd_task, ao_bootloader_cmd, "bootloader_cmd");
284 ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send");