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