works now
[gnuk/neug.git] / src / main.c
1 /*
2  * main.c - main routine of neug
3  *
4  * Copyright (C) 2011 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of NeuG, a Random Number Generator
8  * implementation.
9  *
10  * NeuG is free software: you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "config.h"
26
27 #include "ch.h"
28 #include "hal.h"
29 #include "board.h"
30 #include "usb_cdc.h"
31
32 /*
33  * We are trying to avoid dependency to C library. 
34  * GCC built-in functions are declared here.
35  */
36 void *memcpy(void *dest, const void *src, size_t n);
37
38 /*
39  * USB Driver structure.
40  */
41 static SerialUSBDriver SDU1;
42
43 /*
44  * USB Device Descriptor.
45  */
46 static const uint8_t vcom_device_descriptor_data[18] = {
47   USB_DESC_DEVICE       (0x0200,        /* bcdUSB (2.0).                    */
48                          0x02,          /* bDeviceClass (CDC).              */
49                          0x00,          /* bDeviceSubClass.                 */
50                          0x00,          /* bDeviceProtocol.                 */
51                          0x40,          /* bMaxPacketSize.                  */
52                          0x234b,        /* idVendor (FSIJ).                   */
53                          0x0001,        /* idProduct.                       */
54                          0x0100,        /* bcdDevice.                       */
55                          1,             /* iManufacturer.                   */
56                          2,             /* iProduct.                        */
57                          3,             /* iSerialNumber.                   */
58                          1)             /* bNumConfigurations.              */
59 };
60
61 /*
62  * Device Descriptor wrapper.
63  */
64 static const USBDescriptor vcom_device_descriptor = {
65   sizeof vcom_device_descriptor_data,
66   vcom_device_descriptor_data
67 };
68
69 /* Configuration Descriptor tree for a CDC.*/
70 static const uint8_t vcom_configuration_descriptor_data[67] = {
71   /* Configuration Descriptor.*/
72   USB_DESC_CONFIGURATION(67,            /* wTotalLength.                    */
73                          0x02,          /* bNumInterfaces.                  */
74                          0x01,          /* bConfigurationValue.             */
75                          0,             /* iConfiguration.                  */
76                          0x80,          /* bmAttributes (bus powered).      */
77                          50),           /* bMaxPower (100mA).               */
78   /* Interface Descriptor.*/
79   USB_DESC_INTERFACE    (0x00,          /* bInterfaceNumber.                */
80                          0x00,          /* bAlternateSetting.               */
81                          0x01,          /* bNumEndpoints.                   */
82                          0x02,          /* bInterfaceClass (Communications
83                                            Interface Class, CDC section
84                                            4.2).                            */
85                          0x02,          /* bInterfaceSubClass (Abstract
86                                          Control Model, CDC section 4.3).   */
87                          0x01,          /* bInterfaceProtocol (AT commands,
88                                            CDC section 4.4).                */
89                          0),            /* iInterface.                      */
90   /* Header Functional Descriptor (CDC section 5.2.3).*/
91   USB_DESC_BYTE         (5),            /* bLength.                         */
92   USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
93   USB_DESC_BYTE         (0x00),         /* bDescriptorSubtype (Header
94                                            Functional Descriptor.           */
95   USB_DESC_BCD          (0x0110),       /* bcdCDC.                          */
96   /* Call Management Functional Descriptor. */
97   USB_DESC_BYTE         (5),            /* bFunctionLength.                 */
98   USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
99   USB_DESC_BYTE         (0x01),         /* bDescriptorSubtype (Call Management
100                                            Functional Descriptor).          */
101   USB_DESC_BYTE         (0x03),         /* bmCapabilities (D0+D1).          */
102   USB_DESC_BYTE         (0x01),         /* bDataInterface.                  */
103   /* ACM Functional Descriptor.*/
104   USB_DESC_BYTE         (4),            /* bFunctionLength.                 */
105   USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
106   USB_DESC_BYTE         (0x02),         /* bDescriptorSubtype (Abstract
107                                            Control Management Descriptor).  */
108   USB_DESC_BYTE         (0x02),         /* bmCapabilities.                  */
109   /* Union Functional Descriptor.*/
110   USB_DESC_BYTE         (5),            /* bFunctionLength.                 */
111   USB_DESC_BYTE         (0x24),         /* bDescriptorType (CS_INTERFACE).  */
112   USB_DESC_BYTE         (0x06),         /* bDescriptorSubtype (Union
113                                            Functional Descriptor).          */
114   USB_DESC_BYTE         (0x00),         /* bMasterInterface (Communication
115                                            Class Interface).                */
116   USB_DESC_BYTE         (0x01),         /* bSlaveInterface0 (Data Class
117                                            Interface).                      */
118   /* Endpoint 2 Descriptor.*/
119   USB_DESC_ENDPOINT     (INTERRUPT_REQUEST_EP|0x80, /* bEndpointAddress.    */
120                          0x03,          /* bmAttributes (Interrupt).        */
121                          0x0008,        /* wMaxPacketSize.                  */
122                          0xFF),         /* bInterval.                       */
123   /* Interface Descriptor.*/
124   USB_DESC_INTERFACE    (0x01,          /* bInterfaceNumber.                */
125                          0x00,          /* bAlternateSetting.               */
126                          0x02,          /* bNumEndpoints.                   */
127                          0x0A,          /* bInterfaceClass (Data Class
128                                            Interface, CDC section 4.5).     */
129                          0x00,          /* bInterfaceSubClass (CDC section
130                                            4.6).                            */
131                          0x00,          /* bInterfaceProtocol (CDC section
132                                            4.7).                            */
133                          0x00),         /* iInterface.                      */
134   /* Endpoint 3 Descriptor.*/
135   USB_DESC_ENDPOINT     (DATA_AVAILABLE_EP,         /* bEndpointAddress.    */
136                          0x02,          /* bmAttributes (Bulk).             */
137                          0x0040,        /* wMaxPacketSize.                  */
138                          0x00),         /* bInterval.                       */
139   /* Endpoint 1 Descriptor.*/
140   USB_DESC_ENDPOINT     (DATA_REQUEST_EP|0x80,      /* bEndpointAddress.    */
141                          0x02,          /* bmAttributes (Bulk).             */
142                          0x0040,        /* wMaxPacketSize.                  */
143                          0x00)          /* bInterval.                       */
144 };
145
146
147 /*
148  * Configuration Descriptor wrapper.
149  */
150 static const USBDescriptor vcom_configuration_descriptor = {
151   sizeof vcom_configuration_descriptor_data,
152   vcom_configuration_descriptor_data
153 };
154
155 /*
156  * U.S. English language identifier.
157  */
158 static const uint8_t vcom_string0[] = {
159   USB_DESC_BYTE(4),                     /* bLength.                         */
160   USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
161   USB_DESC_WORD(0x0409)                 /* wLANGID (U.S. English).          */
162 };
163
164 /*
165  * Vendor string.
166  */
167 static const uint8_t vcom_string1[] = {
168   USB_DESC_BYTE(68),                    /* bLength.                         */
169   USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
170   /* Manufacturer: "Free Software Initiative of Japan" */
171   'F', 0, 'r', 0, 'e', 0, 'e', 0, ' ', 0, 'S', 0, 'o', 0, 'f', 0,
172   't', 0, 'w', 0, 'a', 0, 'r', 0, 'e', 0, ' ', 0, 'I', 0, 'n', 0,
173   'i', 0, 't', 0, 'i', 0, 'a', 0, 't', 0, 'i', 0, 'v', 0, 'e', 0,
174   ' ', 0, 'o', 0, 'f', 0, ' ', 0, 'J', 0, 'a', 0, 'p', 0, 'a', 0,
175   'n', 0
176 };
177
178 /*
179  * Device Description string.
180  */
181 static const uint8_t vcom_string2[] = {
182   USB_DESC_BYTE(18),                    /* bLength.                         */
183   USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
184   /* Product name: "NeuG RNG" */
185   'N', 0, 'e', 0, 'u', 0, 'G', 0, ' ', 0, 'R', 0, 'N', 0, 'G', 0,
186 };
187
188 /*
189  * Serial Number string.
190  */
191 static const uint8_t vcom_string3[] = {
192   USB_DESC_BYTE(8),                     /* bLength.                         */
193   USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType.                 */
194   '0' , 0,  '.' , 0,  '1' , 0
195 };
196
197 /*
198  * Strings wrappers array.
199  */
200 static const USBDescriptor vcom_strings[] = {
201   {sizeof vcom_string0, vcom_string0},
202   {sizeof vcom_string1, vcom_string1},
203   {sizeof vcom_string2, vcom_string2},
204   {sizeof vcom_string3, vcom_string3}
205 };
206
207 /*
208  * Handles the GET_DESCRIPTOR callback. All required descriptors must be
209  * handled here.
210  */
211 static const USBDescriptor *get_descriptor(USBDriver *usbp,
212                                            uint8_t dtype,
213                                            uint8_t dindex,
214                                            uint16_t lang) {
215
216   (void)usbp;
217   (void)lang;
218   switch (dtype) {
219   case USB_DESCRIPTOR_DEVICE:
220     return &vcom_device_descriptor;
221   case USB_DESCRIPTOR_CONFIGURATION:
222     return &vcom_configuration_descriptor;
223   case USB_DESCRIPTOR_STRING:
224     if (dindex < 4)
225       return &vcom_strings[dindex];
226   }
227   return NULL;
228 }
229
230 /**
231  * @brief   EP1 initialization structure (IN only).
232  */
233 static const USBEndpointConfig ep1config = {
234   USB_EP_MODE_TYPE_BULK | USB_EP_MODE_PACKET,
235   NULL,
236   sduDataTransmitted,
237   NULL,
238   0x0040,
239   0x0000,
240   NULL,
241   NULL
242 };
243
244 /**
245  * @brief   EP2 initialization structure (IN only).
246  */
247 static const USBEndpointConfig ep2config = {
248   USB_EP_MODE_TYPE_INTR | USB_EP_MODE_PACKET,
249   NULL,
250   sduInterruptTransmitted,
251   NULL,
252   0x0010,
253   0x0000,
254   NULL,
255   NULL
256 };
257
258 /**
259  * @brief   EP3 initialization structure (OUT only).
260  */
261 static const USBEndpointConfig ep3config = {
262   USB_EP_MODE_TYPE_BULK | USB_EP_MODE_PACKET,
263   NULL,
264   NULL,
265   sduDataReceived,
266   0x0000,
267   0x0040,
268   NULL,
269   NULL
270 };
271
272 /*
273  * Handles the USB driver global events.
274  */
275 static void usb_event(USBDriver *usbp, usbevent_t event) {
276
277   switch (event) {
278   case USB_EVENT_RESET:
279     return;
280   case USB_EVENT_ADDRESS:
281     return;
282   case USB_EVENT_CONFIGURED:
283     /* Enables the endpoints specified into the configuration.
284        Note, this callback is invoked from an ISR so I-Class functions
285        must be used.*/
286     chSysLockFromIsr();
287     usbInitEndpointI(usbp, DATA_REQUEST_EP, &ep1config);
288     usbInitEndpointI(usbp, INTERRUPT_REQUEST_EP, &ep2config);
289     usbInitEndpointI(usbp, DATA_AVAILABLE_EP, &ep3config);
290     chSysUnlockFromIsr();
291     return;
292   case USB_EVENT_SUSPEND:
293     return;
294   case USB_EVENT_WAKEUP:
295     return;
296   case USB_EVENT_STALLED:
297     return;
298   }
299   return;
300 }
301
302
303 /*
304  * Serial over USB driver configuration.
305  */
306 static const SerialUSBConfig serusbcfg = {
307   &USBD1,
308   {
309     usb_event,
310     get_descriptor,
311     sduRequestsHook,
312     NULL
313   }
314 };
315
316 Thread *main_thread;
317
318 /* Total number of channels to be sampled by a single ADC operation.*/
319 #define ADC_GRP1_NUM_CHANNELS   2
320  
321 /* Depth of the conversion buffer, channels are sampled one time each.*/
322 #define ADC_GRP1_BUF_DEPTH      4
323  
324 /*
325  * ADC samples buffer.
326  */
327 static adcsample_t samp[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
328  
329 #define ADC_SAMPLE_1P5          0   /**< @brief 1.5 cycles sampling time.   */
330 #define ADC_SAMPLE_13P5         2   /**< @brief 13.5 cycles sampling time.  */
331 #define ADC_SAMPLE_239P5        7   /**< @brief 239.5 cycles sampling time. */
332
333 static void adccb (ADCDriver *adcp, adcsample_t *buffer, size_t n);
334
335 /*
336  * ADC conversion group.
337  * Mode:        Linear buffer, 4 samples of 2 channels, SW triggered.
338  * Channels:    Vref   (1.5 cycles sample time, violating the spec.)
339  *              Sensor (1.5 cycles sample time, violating the spec.)
340  */
341 static const ADCConversionGroup adcgrpcfg = {
342   FALSE,
343   ADC_GRP1_NUM_CHANNELS,
344   adccb,
345   0,
346   ADC_CR2_EXTSEL_SWSTART | ADC_CR2_TSVREFE | ADC_CR2_CONT,
347   ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_1P5) | ADC_SMPR1_SMP_VREF(ADC_SAMPLE_1P5),
348   0,
349   ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS),
350   0,
351   ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR) | ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT)
352 };
353
354 /*
355  * ADC end conversion callback.
356  */
357 static void adccb (ADCDriver *adcp, adcsample_t *buffer, size_t n)
358 {
359   (void) buffer; (void) n;
360
361   chSysLockFromIsr();
362   if (adcp->state == ADC_COMPLETE)
363     chEvtSignalFlagsI (main_thread, (eventmask_t)1);
364   chSysUnlockFromIsr();
365 }
366 \f
367 static volatile uint8_t fatal_code;
368
369 #define TMT_MAT1 0x8f7011ee
370 #define TMT_MAT2 0xfc78ff1f
371 #define TMT_TMAT 0x3793fdff
372
373 static uint32_t tmt[4] = { 0x56781234, TMT_MAT1, TMT_MAT2, TMT_TMAT };
374
375 #define TMT_CALC_LASTWORD(y,v) (y^v)
376
377 static void tmt_one_step (uint32_t v)
378 {
379   uint32_t x, y;
380
381   y = tmt[3];
382   x = (tmt[0] & 0x7fffffff) ^ tmt[1] ^ tmt[2];
383   x ^= (x << 1);
384   y ^= (y >> 1) ^ x;
385   tmt[0] = tmt[1];
386   tmt[1] = tmt[2];
387   tmt[2] = x ^ (y << 10);
388   tmt[3] = TMT_CALC_LASTWORD(y, v);
389   if ((y & 1))
390     {
391       tmt[1] ^= TMT_MAT1;
392       tmt[2] ^= TMT_MAT2;
393     }
394 }
395
396 static uint32_t tmt_value (void)
397 {
398   uint32_t t0, t1;
399
400   t0 = tmt[3];
401   t1 = tmt[0] + (tmt[2] >> 8);
402   t0 ^= t1;
403   if ((t1 & 1))
404     t0 ^= TMT_TMAT;
405   return t0;
406 }
407
408 /* 8 parallel CRC-16 shift registers */
409 static uint8_t epool[16];       /* Big-endian */
410 static uint8_t ep_count;
411
412 static void ep_add (uint8_t bits)
413 {
414   uint8_t v = epool[ep_count];
415
416   /* CRC-16-CCITT's Polynomial is: x^16 + x^12 + x^5 + 1 */
417   epool[ep_count] ^= bits;
418   epool[(ep_count - 5)& 0x0f] ^= v;
419   epool[(ep_count - 12)& 0x0f] ^= v;
420
421   ep_count = (ep_count + 1) & 0x0f;
422 }
423
424 static uint32_t ep_value (void)
425 {
426   unsigned int v = (epool[ep_count] << 24)
427                     | (epool[(ep_count + 1) & 0x0f] << 16)
428                     | (epool[(ep_count + 2) & 0x0f] << 8)
429                     | epool[(ep_count + 3) & 0x0f];
430   return v;
431 }
432
433
434
435 /*
436  * Entry point.
437  *
438  * NOTE: the main function is already a thread in the system on entry.
439  */
440 int
441 main (int argc, char **argv)
442 {
443   int count = 0;
444
445   (void)argc;
446   (void)argv;
447
448   halInit();
449   chSysInit();
450
451   main_thread = chThdSelf ();
452
453   /*
454    * Activates the USB driver and then the USB bus pull-up on D+.
455    */
456   sduObjectInit(&SDU1);
457   sduStart(&SDU1, &serusbcfg);
458   USB_Cable_Config (ENABLE);
459
460   adcStart (&ADCD1, NULL);
461   adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH);
462
463   while (1)
464     {
465       eventmask_t m;
466
467       count++;
468
469       m = chEvtWaitOne (ALL_EVENTS);
470
471       if (m == (eventmask_t)1)
472         {
473           static uint8_t round;
474           uint8_t b;
475
476           if ((round & 1))
477             b = (((samp[0] & 0x01) << 0) | ((samp[1] & 0x01) << 1)
478                  | ((samp[2] & 0x01) << 2) | ((samp[3] & 0x01) << 3)
479                  | ((samp[4] & 0x01) << 4) | ((samp[5] & 0x01) << 5)
480                  | ((samp[6] & 0x01) << 6) | ((samp[7] & 0x01) << 7));
481           else
482             b = (((samp[0] & 0x01) << 1) | ((samp[1] & 0x01) << 0)
483                  | ((samp[2] & 0x01) << 3) | ((samp[3] & 0x01) << 2)
484                  | ((samp[4] & 0x01) << 5) | ((samp[5] & 0x01) << 4)
485                  | ((samp[6] & 0x01) << 7) | ((samp[7] & 0x01) << 6));
486
487           adcStartConversion (&ADCD1, &adcgrpcfg, samp,
488                               ADC_GRP1_BUF_DEPTH);
489
490           ep_add (b);
491           if (++round >= 7)
492             {
493               static uint8_t r;
494               char s[32];
495               uint32_t x = ep_value ();
496
497               tmt_one_step (((SysTick->VAL) & 6) == 0);
498               x ^= tmt_value ();
499
500               memcpy (s + (r&7)*4, (const char *)&x, 4);
501               r = (r + 1) & 7;
502               if (r == 0 && SDU1.config->usbp->state == USB_ACTIVE)
503                 {
504                   static uint8_t led;
505
506                   led++;
507                   set_led ((led & 0x80) == 0);
508
509                   chIQResetI (&(SDU1.iqueue)); /* Ignore input */
510                   chIOWriteTimeout (&SDU1, (uint8_t *)s, 32, TIME_INFINITE);
511                 }
512
513               round = 0;
514             }
515         }
516     }
517
518   return 0;
519 }
520
521 void
522 fatal (uint8_t code)
523 {
524   fatal_code = code;
525
526   set_led (1);
527   for (;;);
528 }