struct cc_usb *cc = NULL;
char *tty = NULL;
int verbose = 0;
+ int reset = 0;
int ret = 0;
int kbytes = 0; /* 0 == continuous */
int written;
uint8_t bits[1024];
- while ((c = getopt_long(argc, argv, "vT:D:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "vRT:D:", options, NULL)) != -1) {
switch (c) {
case 'T':
tty = optarg;
case 'D':
device = optarg;
break;
+ case 'R':
+ reset++;
+ break;
case 'v':
verbose++;
break;
if (!cc)
exit(1);
- if (kbytes) {
- cc_usb_printf(cc, "f %d\n", kbytes);
+ if (reset) {
+ cc_usb_printf(cc, "R\n");
+ } else {
+ if (kbytes) {
+ cc_usb_printf(cc, "f %d\n", kbytes);
- while (kbytes--) {
- for (i = 0; i < 1024; i++)
- bits[i] = cc_usb_getchar(cc);
- write(1, bits, 1024);
- }
- } else { /* 0 == continuous */
- written = 0;
- while (written >= 0) {
- cc_usb_printf(cc, "f 1\n");
- for (i = 0; i < 1024; i++)
- bits[i] = cc_usb_getchar(cc);
- written = write(1, bits, 1024);
+ while (kbytes--) {
+ for (i = 0; i < 1024; i++)
+ bits[i] = cc_usb_getchar(cc);
+ write(1, bits, 1024);
+ }
+ } else { /* 0 == continuous */
+ written = 0;
+ while (written >= 0) {
+ cc_usb_printf(cc, "f\n");
+ for (i = 0; i < 1024; i++)
+ bits[i] = cc_usb_getchar(cc);
+ written = write(1, bits, 1024);
+ }
}
- }
-
+ }
done(cc, ret);
}
#include <ao_crc.h>
#include <ao_trng.h>
+/* It is difficult to know exactly when we are connected.
+ This flag will be set once one of *our* commands has been called */
+static uint8_t ao_connected = 0;
+
+/* note: refactor this with ao_monitor.c? see ao_cmd_put16() */
+static const char xdigit[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+};
+
+#define byte_to_hex(b) ((xdigit[(b) >> 4] << 8 ) | xdigit[(b) & 0xf])
+
static struct ao_task ao_blink_green_task;
static uint8_t ao_blinking_green = 0;
static void
ao_blink_green_toggle(void)
{
+ ao_connected = 1;
ao_blinking_green = !ao_blinking_green;
if (!ao_blinking_green)
ao_led_off(AO_LED_GREEN);
}
static struct ao_task ao_blink_red_task;
-static int8_t ao_failed = -1; /* -1 need POST, 0 NOMINAL, 1 FAILED */
+static uint8_t ao_failed = 0; /* 0 NOMINAL, 1 FAILED */
+static uint8_t ao_post = 0; /* 0 POST needed, 1 powered up */
/* On handling failure, keithp said:
We could disconnect from USB easily enough, or disconnect and come back
error. Lots of options.
*/
void
-ao_trng_failure(void)
+ao_trng_failure()
{
ao_failed = 1;
ao_wakeup(&ao_failed);
}
+void
+ao_trng_failure_cmd(void)
+{
+ ao_trng_failure();
+}
+
static void
-ao_trng_fetch(uint32_t kbytes)
+ao_trng_fetch(uint32_t kbytes, uint8_t printhex)
{
static uint16_t *buffer[2];
uint32_t count;
int usb_buf_id;
uint16_t i;
+ uint32_t cur;
+ uint32_t prev = 0;
+ uint32_t prev_set = 0; /* prev has been set */
uint16_t *buf;
uint32_t *rnd;
- uint32_t prev, cur;
+ uint16_t r; /* random word */
if (!buffer[0]) {
buffer[0] = ao_usb_alloc();
}
usb_buf_id = 0;
- count = kbytes * (1024/AO_USB_IN_SIZE);
+ /* if we print in hex each byte requires two bytes output */
+ count = (kbytes * (1024/AO_USB_IN_SIZE)) << printhex;
ao_crc_reset();
ao_led_on(AO_LED_TRNG_READ);
while (count--) {
/* one 16-bit value per output byte */
- rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE + 2);
+ rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE);
buf = buffer[usb_buf_id];
- prev = *rnd++;
for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
cur = *rnd++;
- if (cur == prev)
+ if (prev_set && (cur == prev))
ao_trng_failure();
- *buf++ = ao_crc_in_32_out_16(cur);
+ r = ao_crc_in_32_out_16(cur);
+ if (printhex) {
+ *buf++ = byte_to_hex(r >> 8);
+ *buf++ = byte_to_hex(r & 0xff);
+ i++;
+ } else {
+ *buf++ = r;
+ }
prev = cur;
+ prev_set++;
}
ao_adc_ack(AO_USB_IN_SIZE);
- ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
- ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
- ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
+ if (ao_connected) {
+ ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
+ ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
+ }
usb_buf_id = 1-usb_buf_id;
}
ao_led_off(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
- flush();
+ if (ao_connected)
+ flush();
}
-static void
-ao_trng_fetch_cmd(void)
+static uint32_t
+ao_trng_get_kbytes(void)
{
uint32_t kbytes = 1;
kbytes = ao_cmd_lex_u32;
else
ao_cmd_status = ao_cmd_success;
- ao_trng_fetch(kbytes);
+ return kbytes;
+}
+
+static void
+ao_trng_fetch_cmd(void)
+{
+ ao_connected = 1;
+ if (!ao_failed)
+ ao_trng_fetch(ao_trng_get_kbytes(), 0);
+}
+
+static void
+ao_trng_fetch_hex(void)
+{
+ ao_connected = 1;
+ if (!ao_failed)
+ ao_trng_fetch(ao_trng_get_kbytes(), 1);
+ putchar('\n');
}
/* NOTE: the reset function also functions as the Power On Self Test */
void
ao_trng_reset(void)
{
- printf("Power On Self Test\n"); /* DEBUGGING */
+ if (ao_connected)
+ printf("Resetting...\n");
ao_failed = 0;
ao_led_off(AO_LED_RED);
ao_wakeup(&ao_failed);
/* get the first 1k bits and ensure there are no duplicates */
- ao_trng_fetch(1);
+ ao_trng_fetch(1, 1);
+ if (ao_connected)
+ putchar('\n');
if (ao_failed) { /* show failure */
- printf("FAILED self test\n");
+ if (ao_connected)
+ printf("FAILED self test\n");
} else { /* show success */
- printf("PASS - operation NOMINAL\n");
+ if (ao_connected)
+ printf("PASS - operation NOMINAL\n");
/* this blocks! */
ao_led_on(AO_LED_GREEN);
ao_delay(AO_MS_TO_TICKS(1000));
}
}
+void
+ao_trng_reset_cmd(void)
+{
+ ao_connected = 1;
+ ao_trng_reset();
+}
+
static void
ao_blink_red(void)
{
- if (ao_failed < 0)
- ao_trng_reset(); /* lazy POST */
+ if (!ao_post) {
+ ao_trng_reset(); /* POST */
+ ao_post = 1;
+ }
for (;;) {
while (!ao_failed)
ao_sleep(&ao_failed);
static void
ao_trng_status(void)
{
+ ao_connected = 1;
if (ao_failed)
printf("FAILED\n");
else
static const struct ao_cmds ao_trng_cmds[] = {
{ ao_trng_fetch_cmd, "f <kbytes>\0Fetch a block of numbers" },
- { ao_trng_reset, "R\0Reset" },
+ { ao_trng_fetch_hex, "F <kbytes>\0Fetch a block of numbers (in hex)" },
+ { ao_trng_reset_cmd, "R\0Reset" },
{ ao_blink_green_toggle, "G\0Toggle green LED blinking" },
{ ao_trng_status, "s\0Show status" },
- { ao_trng_failure, "z\0Simulate failure" },
+ { ao_trng_failure_cmd, "z\0Simulate failure" },
{ 0, NULL },
};