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);
62 static uint16_t *buffer[2];
69 uint32_t *rnd = (uint32_t *) ao_adc_ring;
72 uint8_t prev_set = 0; /* prev has been set */
75 buffer[0] = ao_usb_alloc();
76 buffer[1] = ao_usb_alloc();
82 if (ao_cmd_status == ao_cmd_success)
83 kbytes = ao_cmd_lex_u32;
85 ao_cmd_status = ao_cmd_success;
87 count = kbytes * (1024/AO_USB_IN_SIZE);
91 ao_led_on(AO_LED_TRNG_READ);
93 t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
94 buf = buffer[usb_buf_id];
95 for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
97 if (prev_set && (cur == prev))
99 *buf++ = ao_crc_in_32_out_16(cur);
100 t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
104 ao_adc_ack(AO_USB_IN_SIZE);
105 ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
106 ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
107 ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
108 usb_buf_id = 1-usb_buf_id;
110 ao_led_off(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
115 ao_trng_fetch_cmd(void)
130 void ao_trng_reset(void); /* forward declaration */
133 ao_blink_green_toggle(void)
135 ao_blinking_green = !ao_blinking_green;
136 if (!ao_blinking_green)
137 ao_led_off(AO_LED_GREEN);
138 ao_wakeup(&ao_blinking_green);
141 static const struct ao_cmds ao_trng_cmds[] = {
142 { ao_trng_fetch_cmd, "f <kbytes>\0Fetch a block of numbers" },
143 { ao_trng_reset, "R\0Reset" },
144 { ao_blink_green_toggle, "G\0Toggle green LED blinking" },
145 { ao_trng_status, "s\0Show status" },
146 { ao_trng_failure, "z\0Simulate failure" },
155 static uint16_t *buffer[2];
160 uint32_t *rnd = (uint32_t *) ao_adc_ring;
163 buffer[0] = ao_usb_alloc();
164 buffer[1] = ao_usb_alloc();
174 ao_led_on(AO_LED_TRNG_ACTIVE);
175 t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
176 buf = buffer[usb_buf_id];
177 for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
178 *buf++ = ao_crc_in_32_out_16(rnd[t]);
179 t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
181 ao_adc_ack(AO_USB_IN_SIZE);
182 ao_led_off(AO_LED_TRNG_ACTIVE);
183 ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
184 usb_buf_id = 1-usb_buf_id;
188 static struct ao_task ao_trng_send_task;
191 ao_bootloader_cmd(void)
194 getchar(); /* any char will do */
195 /* give feedback we are going into bootloader mode */
196 ao_led_on(AO_LED_GREEN);
197 ao_delay(AO_MS_TO_TICKS(500));
198 ao_led_off(AO_LED_GREEN);
199 ao_delay(AO_MS_TO_TICKS(500));
200 ao_led_on(AO_LED_GREEN);
201 ao_delay(AO_MS_TO_TICKS(500));
202 ao_led_off(AO_LED_GREEN);
203 ao_delay(AO_MS_TO_TICKS(500));
204 ao_led_on(AO_LED_GREEN);
205 ao_delay(AO_MS_TO_TICKS(500));
206 ao_led_off(AO_LED_GREEN);
211 static struct ao_task ao_bootloader_cmd_task;
216 /* NOTE: the reset function also functions as the Power On Self Test */
220 /* printf("Resetting...\n"); */
222 ao_led_off(AO_LED_RED);
223 ao_wakeup(&ao_failed);
224 /* get the first 1k bits and ensure there are no duplicates */
225 /* FIXME ao_trng_fetch(); */
227 ao_led_on(AO_LED_GREEN);
228 ao_delay(AO_MS_TO_TICKS(1000));
229 ao_led_off(AO_LED_GREEN);
237 ao_trng_reset(); /* POST */
242 ao_sleep(&ao_failed);
244 ao_led_toggle(AO_LED_RED);
245 ao_delay(AO_MS_TO_TICKS(500));
253 ao_add_task(&ao_blink_red_task, ao_blink_red, "blink_red");
254 ao_add_task(&ao_blink_green_task, ao_blink_green, "blink_green");
256 ao_cmd_register(ao_trng_cmds);
258 ao_add_task(&ao_bootloader_cmd_task, ao_bootloader_cmd, "bootloader_cmd");
259 ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send");