flabbergast's ARM/STM32 examples using libopencm3
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

serplus.c 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. /* {{{ LICENSES
  2. * Original serplus code by jcw https://github.com/jeelabs/embello/tree/master/explore/1649-f103/serplus
  3. * Modified for F072 by flabbergast
  4. */
  5. /*
  6. * WS2821 code originally from https://github.com/hwhw/stm32-projects
  7. */
  8. /*
  9. * This code is derived from example code in the libopencm3 project:
  10. *
  11. * https://github.com/libopencm3/libopencm3-examples/tree/master/
  12. * examples/stm32/f1/stm32-h103/usart_irq_printf
  13. * and examples/stm32/f1/stm32-h103/usb_cdcacm
  14. *
  15. * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
  16. * Copyright (C) 2010, 2013 Gareth McMullin <gareth@blacksphere.co.nz>
  17. * Copyright (C) 2011 Piotr Esden-Tempski <piotr@esden.net>
  18. * Copyright (C) 2016 Jean-Claude Wippler <jc@wippler.nl>
  19. *
  20. * This code is free software: you can redistribute it and/or modify
  21. * it under the terms of the GNU Lesser General Public License as published by
  22. * the Free Software Foundation, either version 3 of the License, or
  23. * (at your option) any later version.
  24. *
  25. * This code is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. * GNU Lesser General Public License for more details.
  29. *
  30. * You should have received a copy of the GNU Lesser General Public License
  31. * along with this code. If not, see <http://www.gnu.org/licenses/>.
  32. * }}} */
  33. // {{{ software configuration
  34. #define HAVE_MODES
  35. #define HAVE_ADC
  36. #define HAVE_NEOPIX
  37. // }}}
  38. // {{{ includes
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <libopencm3/stm32/rcc.h>
  42. #include <libopencm3/stm32/gpio.h>
  43. #include <libopencm3/stm32/usart.h>
  44. #include <libopencm3/stm32/crs.h>
  45. #include <libopencm3/stm32/dma.h>
  46. #include <libopencm3/stm32/timer.h>
  47. #include <libopencm3/cm3/nvic.h>
  48. #include <libopencm3/cm3/systick.h>
  49. #include <libopencm3/usb/usbd.h>
  50. #include <libopencm3/usb/cdc.h>
  51. #include <libopencm3/stm32/adc.h>
  52. // }}}
  53. // {{{ global variables
  54. #define BUFFER_SIZE 256
  55. struct ring input_ring, output_ring;
  56. uint8_t input_ring_buffer[BUFFER_SIZE], output_ring_buffer[BUFFER_SIZE];
  57. volatile uint32_t ticks;
  58. uint8_t extbut_state, extbut_laststate, extbut_changed, extbut_acted;
  59. uint32_t extbut_time, extbut_lastchange;
  60. #ifdef HAVE_MODES
  61. volatile uint16_t usart_mode; // messes up the USB driver if it's uint8_t
  62. #endif // HAVE_MODES
  63. volatile uint32_t usart_serplus_baudrate, usart_serplus_databits, usart_serplus_stopbits, usart_serplus_parity, usart_serplus_flowcontrol;
  64. // }}}
  65. // {{{ ringbuffer
  66. /******************************************************************************
  67. * Simple ringbuffer implementation from open-bldc's libgovernor that
  68. * you can find at:
  69. * https://github.com/open-bldc/open-bldc/tree/master/source/libgovernor
  70. *****************************************************************************/
  71. typedef int32_t ring_size_t;
  72. struct ring {
  73. uint8_t *data;
  74. ring_size_t size;
  75. uint32_t begin;
  76. uint32_t end;
  77. };
  78. #define RING_SIZE(RING) ((RING)->size - 1)
  79. #define RING_DATA(RING) (RING)->data
  80. #define RING_EMPTY(RING) ((RING)->begin == (RING)->end)
  81. static void ring_init(struct ring *ring, uint8_t *buf, ring_size_t size)
  82. {
  83. ring->data = buf;
  84. ring->size = size;
  85. ring->begin = 0;
  86. ring->end = 0;
  87. }
  88. static int32_t ring_write_ch(struct ring *ring, uint8_t ch)
  89. {
  90. if (((ring->end + 1) % ring->size) != ring->begin) {
  91. ring->data[ring->end++] = ch;
  92. ring->end %= ring->size;
  93. return (uint32_t)ch;
  94. }
  95. return -1;
  96. }
  97. static int32_t ring_write(struct ring *ring, uint8_t *data, ring_size_t size)
  98. {
  99. int32_t i;
  100. for (i = 0; i < size; i++) {
  101. if (ring_write_ch(ring, data[i]) < 0)
  102. return -i;
  103. }
  104. return i;
  105. }
  106. static int32_t ring_read_ch(struct ring *ring, uint8_t *ch)
  107. {
  108. int32_t ret = -1;
  109. if (ring->begin != ring->end) {
  110. ret = ring->data[ring->begin++];
  111. ring->begin %= ring->size;
  112. if (ch)
  113. *ch = ret;
  114. }
  115. return ret;
  116. }
  117. static int32_t ring_read(struct ring *ring, uint8_t *data, ring_size_t size)
  118. {
  119. int32_t i;
  120. for (i = 0; i < size; i++) {
  121. if (ring_read_ch(ring, data + i) < 0)
  122. return i;
  123. }
  124. return -i;
  125. }
  126. // }}}
  127. // {{{ clock setup
  128. static void clock_setup(void)
  129. {
  130. rcc_clock_setup_in_hsi_out_48mhz();
  131. crs_autotrim_usb_enable();
  132. rcc_set_usbclk_source(RCC_HSI48);
  133. // for gpio, usart
  134. rcc_periph_clock_enable(RCC_GPIOA);
  135. rcc_periph_clock_enable(RCC_GPIOB);
  136. rcc_periph_clock_enable(RCC_USART1);
  137. #ifdef HAVE_NEOPIX
  138. // for WS2812 (pwm/dma)
  139. rcc_periph_clock_enable(RCC_TIM3);
  140. rcc_periph_clock_enable(RCC_DMA);
  141. #endif // HAVE_NEOPIX
  142. #ifdef HAVE_ADC
  143. // ADC
  144. rcc_periph_clock_enable(RCC_ADC);
  145. #endif // HAVE_ADC
  146. }
  147. // }}}
  148. // {{{ gpio
  149. // Bat Board
  150. #define LED_GPIO GPIOA
  151. #define LED_PIN GPIO15
  152. #define LED_ON gpio_set(LED_GPIO, LED_PIN)
  153. #define LED_OFF gpio_clear(LED_GPIO, LED_PIN)
  154. #define LED_TOGGLE gpio_toggle(LED_GPIO, LED_PIN)
  155. #define BOOTBUT_GPIO GPIOA
  156. #define BOOTBUT_PIN GPIO1
  157. #define BOOTBUT_PRESSED (gpio_get(BOOTBUT_GPIO,BOOTBUT_PIN)!=0)
  158. #define EXTBUT_GPIO GPIOA
  159. #define EXTBUT_PIN GPIO6
  160. #define EXTBUT_PRESSED (gpio_get(EXTBUT_GPIO,EXTBUT_PIN)==0)
  161. #define FET_ON (gpio_clear(GPIOB,GPIO3))
  162. #define FET_OFF (gpio_set(GPIOB,GPIO3))
  163. #define RTS_GPIO GPIOB
  164. #define RTS_PIN GPIO11
  165. #define DTR_GPIO GPIOB
  166. #define DTR_PIN GPIO10
  167. static void usart_dtr_rts_serplus_setup(void) {
  168. gpio_mode_setup(DTR_GPIO, GPIO_MODE_OUTPUT,
  169. GPIO_PUPD_NONE, DTR_PIN); // serplus: dtr: default high
  170. gpio_set(DTR_GPIO, DTR_PIN);
  171. gpio_mode_setup(RTS_GPIO, GPIO_MODE_OUTPUT,
  172. GPIO_PUPD_NONE, RTS_PIN); // serplus: rts: default low
  173. gpio_clear(RTS_GPIO, RTS_PIN);
  174. }
  175. #ifdef HAVE_MODES
  176. static void usart_dtr_rts_raw_setup(void) {
  177. gpio_mode_setup(DTR_GPIO, GPIO_MODE_OUTPUT,
  178. GPIO_PUPD_NONE, DTR_PIN); // serplus: dtr: default high
  179. gpio_set(DTR_GPIO, DTR_PIN);
  180. gpio_mode_setup(RTS_GPIO, GPIO_MODE_INPUT,
  181. GPIO_PUPD_NONE, RTS_PIN); // serplus: rts ignored: floating
  182. }
  183. #endif // HAVE_MODES
  184. static void gpio_setup(void) {
  185. gpio_mode_setup(LED_GPIO, GPIO_MODE_OUTPUT,
  186. GPIO_PUPD_NONE, LED_PIN); // bat: LED
  187. LED_OFF;
  188. gpio_mode_setup(BOOTBUT_GPIO, GPIO_MODE_INPUT,
  189. GPIO_PUPD_NONE, BOOTBUT_PIN); // bat: button (has ext pull-down)
  190. gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT,
  191. GPIO_PUPD_NONE, GPIO3); // serplus: P-FET
  192. gpio_set_output_options(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_LOW, GPIO3);
  193. usart_dtr_rts_serplus_setup();
  194. // serplus: button (int pull-up)
  195. gpio_mode_setup(EXTBUT_GPIO, GPIO_MODE_INPUT,
  196. GPIO_PUPD_PULLUP, EXTBUT_PIN);
  197. extbut_time = ticks;
  198. extbut_state = EXTBUT_PRESSED;
  199. extbut_laststate = extbut_state;
  200. extbut_changed = 0;
  201. extbut_lastchange = extbut_time;
  202. extbut_acted = 0;
  203. }
  204. #define DEBOUNCE_MS 50
  205. static uint8_t service_extbut(void) {
  206. static uint8_t pinval;
  207. pinval = EXTBUT_PRESSED;
  208. if(ticks - extbut_lastchange < DEBOUNCE_MS) {
  209. extbut_time = ticks;
  210. extbut_changed = 0;
  211. return extbut_state;
  212. } else {
  213. extbut_laststate = extbut_state;
  214. extbut_state = pinval;
  215. extbut_time = ticks;
  216. if(extbut_state != extbut_laststate) {
  217. extbut_lastchange = ticks;
  218. extbut_changed = 1;
  219. } else {
  220. extbut_changed = 0;
  221. }
  222. return extbut_state;
  223. }
  224. }
  225. // }}}
  226. // {{{ WS2812
  227. /**************************************************
  228. ******************** WS2812 **********************
  229. **************************************************/
  230. #ifdef HAVE_NEOPIX
  231. // maximum is at about 4000
  232. #define LED_COUNT 1
  233. // minimum ID offset is 0x100 (first ID byte mustn't be 0x00)
  234. #define ID_OFFSET 0xA000
  235. // for the purposes of computing the delays
  236. #define CPU_MHZ 48
  237. #define TICK_NS (1000/CPU_MHZ)
  238. #define WS0 (350 / TICK_NS)
  239. #define WS1 (800 / TICK_NS)
  240. #define WSP (1300 / TICK_NS)
  241. #define WSL (20000 / TICK_NS)
  242. #define DMA_BANK_SIZE 2 * 8 * 3 // 2 = number of LEDs; 8*3 = bits*colours
  243. #define DMA_SIZE (DMA_BANK_SIZE*2)
  244. static uint8_t dma_data[DMA_SIZE];
  245. static volatile uint32_t led_data[LED_COUNT];
  246. static volatile uint32_t led_cur = 0;
  247. static void pwm_setup(void) {
  248. // Configure GPIOs: OUT=PA7
  249. gpio_mode_setup(GPIOA, GPIO_MODE_AF,
  250. GPIO_PUPD_NONE, GPIO7 );
  251. gpio_set_af(GPIOA, GPIO_AF1, GPIO7 );
  252. timer_reset(TIM3);
  253. timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
  254. timer_disable_oc_output(TIM3, TIM_OC2);
  255. timer_set_oc_mode(TIM3, TIM_OC2, TIM_OCM_PWM1);
  256. timer_disable_oc_clear(TIM3, TIM_OC2);
  257. timer_set_oc_value(TIM3, TIM_OC2, 0);
  258. timer_enable_oc_preload(TIM3, TIM_OC2);
  259. timer_set_oc_polarity_high(TIM3, TIM_OC2);
  260. timer_enable_oc_output(TIM3, TIM_OC2);
  261. timer_set_dma_on_update_event(TIM3);
  262. timer_enable_irq(TIM3, TIM_DIER_UDE); // in fact, enable DMA on update
  263. timer_enable_preload(TIM3);
  264. timer_continuous_mode(TIM3);
  265. timer_set_period(TIM3, WSP);
  266. timer_enable_counter(TIM3);
  267. }
  268. static void populate_dma_data(uint8_t *dma_data_bank) {
  269. for(int i=0; i<DMA_BANK_SIZE;) {
  270. led_cur = led_cur % (LED_COUNT+3);
  271. if(led_cur < LED_COUNT) {
  272. uint32_t v = led_data[led_cur];
  273. for(int j=0; j<24; j++) {
  274. dma_data_bank[i++] = (v & 0x800000) ? WS1 : WS0;
  275. v <<= 1;
  276. }
  277. } else {
  278. for(int j=0; j<24; j++) {
  279. dma_data_bank[i++] = 0;
  280. }
  281. }
  282. led_cur++;
  283. }
  284. }
  285. static void dma_int_enable(void) {
  286. // SPI1 TX on DMA1 Channel 3
  287. nvic_set_priority(NVIC_DMA1_CHANNEL2_3_IRQ, 0);
  288. nvic_enable_irq(NVIC_DMA1_CHANNEL2_3_IRQ);
  289. }
  290. /* Not used in this example
  291. static void dma_int_disable(void) {
  292. nvic_disable_irq(NVIC_DMA1_CHANNEL2_3_IRQ);
  293. }
  294. */
  295. static int timer_dma(uint8_t *tx_buf, int tx_len)
  296. {
  297. dma_int_enable();
  298. // Reset DMA channels
  299. dma_channel_reset(DMA1, DMA_CHANNEL3);
  300. // Set up tx dma
  301. dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&TIM_CCR2(TIM3));
  302. dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)tx_buf);
  303. dma_set_number_of_data(DMA1, DMA_CHANNEL3, tx_len);
  304. dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
  305. dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
  306. dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_32BIT);
  307. dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
  308. dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
  309. dma_enable_circular_mode(DMA1, DMA_CHANNEL3);
  310. dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
  311. dma_enable_half_transfer_interrupt(DMA1, DMA_CHANNEL3);
  312. dma_enable_channel(DMA1, DMA_CHANNEL3);
  313. return 0;
  314. }
  315. // SPI transmit completed with DMA
  316. void dma1_channel2_3_isr(void)
  317. {
  318. if ((DMA1_ISR & DMA_ISR_TCIF3) != 0) {
  319. DMA1_IFCR |= DMA_IFCR_CTCIF3;
  320. populate_dma_data(&dma_data[DMA_BANK_SIZE]);
  321. }
  322. if ((DMA1_ISR & DMA_ISR_HTIF3) != 0) {
  323. DMA1_IFCR |= DMA_IFCR_CHTIF3;
  324. populate_dma_data(dma_data);
  325. }
  326. }
  327. static void ws2812_pre(void) {
  328. memset(dma_data, 0, DMA_SIZE);
  329. memset((void*)led_data, 0, LED_COUNT*sizeof(*led_data));
  330. //populate_dma_data(dma_data);
  331. //populate_dma_data(&dma_data[DMA_BANK_SIZE]);
  332. timer_dma(dma_data, DMA_SIZE);
  333. }
  334. static void neopix_green(uint8_t intens) {
  335. led_data[0] = (led_data[0]&0x00FFFF)|(intens<<16);
  336. }
  337. static void neopix_red(uint8_t intens) {
  338. led_data[0] = (led_data[0]&0xFF00FF)|(intens<<8);
  339. }
  340. static void neopix_blue(uint8_t intens) {
  341. led_data[0] = (led_data[0]&0xFFFF00)|(intens);
  342. }
  343. #endif // HAVE_NEOPIX
  344. // }}}
  345. // {{{ usart
  346. #ifdef HAVE_MODES
  347. // global modes for USART
  348. #define MODE_SERPLUS 1
  349. #define MODE_RAW 2
  350. #endif // HAVE_MODES
  351. static void usart_set_serplus_params(void) {
  352. usart_set_baudrate(USART1, usart_serplus_baudrate);
  353. usart_set_databits(USART1, usart_serplus_databits);
  354. usart_set_stopbits(USART1, usart_serplus_stopbits);
  355. usart_set_parity(USART1, usart_serplus_parity);
  356. usart_set_flow_control(USART1, usart_serplus_flowcontrol);
  357. }
  358. static void usart_setup(void) {
  359. // Initialize input and output ring buffers.
  360. ring_init(&input_ring, input_ring_buffer, BUFFER_SIZE);
  361. ring_init(&output_ring, output_ring_buffer, BUFFER_SIZE);
  362. // Disable the USART, in case this gets called more than once
  363. usart_disable(USART1);
  364. // Enable the USART1 interrupt.
  365. nvic_enable_irq(NVIC_USART1_IRQ);
  366. // Setup PA9 pin for USART1 transmit.
  367. gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9);
  368. gpio_set_af(GPIOA, GPIO_AF1, GPIO9);
  369. // Setup PA10 pin for USART1 receive.
  370. gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO10); // weak pull-up avoids picking up noise
  371. gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO10);
  372. gpio_set_output_options(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_HIGH, GPIO10);
  373. gpio_set_af(GPIOA, GPIO_AF1, GPIO10);
  374. // Setup UART parameters.
  375. usart_serplus_baudrate = 115200;
  376. usart_serplus_databits = 8;
  377. usart_serplus_stopbits = USART_STOPBITS_1;
  378. usart_serplus_parity = USART_PARITY_NONE;
  379. usart_serplus_flowcontrol = USART_FLOWCONTROL_NONE;
  380. usart_set_serplus_params();
  381. usart_set_mode(USART1, USART_MODE_TX_RX);
  382. // Enable USART1 Receive interrupt.
  383. USART_CR1(USART1) |= USART_CR1_RXNEIE;
  384. // Finally enable the USART.
  385. usart_enable(USART1);
  386. }
  387. // telnet escape codes and special values:
  388. enum {
  389. IAC=255, WILL=251, SB=250, SE=240,
  390. CPO=44, SETPAR=3, SETCTL=5,
  391. PAR_NONE=1, PAR_ODD=2, PAR_EVEN=3,
  392. DTR_ON=8, DTR_OFF=9, RTS_ON=11, RTS_OFF=12,
  393. };
  394. void usart1_isr(void)
  395. {
  396. // Check if we were called because of RXNE.
  397. if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
  398. ((USART_ISR(USART1) & USART_ISR_RXNE) != 0)) {
  399. // Retrieve the data from the peripheral.
  400. uint8_t c = usart_recv(USART1);
  401. ring_write_ch(&input_ring, c);
  402. // Indicate that we got data.
  403. #ifdef HAVE_NEOPIX
  404. neopix_green(c>>2);
  405. #else // ! HAVE_NEOPIX
  406. LED_TOGGLE;
  407. #endif // HAVE_NEOPIX
  408. #ifdef HAVE_MODES
  409. if( usart_mode == MODE_SERPLUS ) {
  410. #endif // HAVE_MODES
  411. // telnet: escape the escape character, i.e. send it twice
  412. if (c == IAC)
  413. ring_write_ch(&input_ring, c);
  414. #ifdef HAVE_MODES
  415. }
  416. #endif // HAVE_MODES
  417. }
  418. // Check if we were called because of TXE.
  419. if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
  420. ((USART_ISR(USART1) & USART_ISR_TXE) != 0)) {
  421. int32_t data = ring_read_ch(&output_ring, NULL);
  422. if (data == -1) {
  423. // Disable the TXE interrupt, it's no longer needed.
  424. USART_CR1(USART1) &= ~USART_CR1_TXEIE;
  425. } else {
  426. #ifdef HAVE_MODES
  427. if( usart_mode == MODE_SERPLUS ) {
  428. #endif // HAVE_MODES
  429. // state machine to decode telnet request before sending it on
  430. static int state = 0;
  431. switch (state) {
  432. default: // default state
  433. if (data == IAC)
  434. state = 1;
  435. else
  436. usart_send(USART1, data);
  437. break;
  438. case 1: // IAC seen
  439. state = 0;
  440. if (data == IAC)
  441. usart_send(USART1, data);
  442. else
  443. state = data == SB ? 3 : data >= WILL ? 2 : 0;
  444. break;
  445. case 2: // IAC, WILL (or WONT/DO/DONT) seen
  446. state = 0;
  447. break;
  448. case 3: // IAC, SB seen
  449. state = data == CPO ? 4 : 5;
  450. break;
  451. case 4: // IAC, SB, CPO seen
  452. state = data == SETPAR ? 7 :
  453. data == SETCTL ? 8 : 5;
  454. break;
  455. case 5: // wait for IAC + SE
  456. if (data == IAC)
  457. state = 6;
  458. break;
  459. case 6: // wait for SE
  460. if (data != IAC)
  461. state = data == SE ? 0 : data == SB ? 3 : 5;
  462. break;
  463. case 7: // set parity
  464. state = 5;
  465. switch (data) {
  466. case PAR_NONE:
  467. usart_serplus_databits = 8;
  468. usart_serplus_parity = USART_PARITY_NONE;
  469. usart_disable(USART1);
  470. usart_set_serplus_params();
  471. usart_enable(USART1); break;
  472. case PAR_ODD:
  473. usart_serplus_databits = 9;
  474. usart_serplus_parity = USART_PARITY_ODD;
  475. usart_disable(USART1);
  476. usart_set_serplus_params();
  477. usart_enable(USART1); break;
  478. case PAR_EVEN:
  479. usart_serplus_databits = 9;
  480. usart_serplus_parity = USART_PARITY_EVEN;
  481. usart_disable(USART1);
  482. usart_set_serplus_params();
  483. usart_enable(USART1); break;
  484. }
  485. break;
  486. case 8: // set control
  487. state = 5;
  488. switch (data) {
  489. case DTR_ON:
  490. gpio_clear(DTR_GPIO, DTR_PIN);
  491. break;
  492. case DTR_OFF:
  493. gpio_set(DTR_GPIO, DTR_PIN);
  494. break;
  495. case RTS_ON:
  496. gpio_clear(RTS_GPIO, RTS_PIN);
  497. break;
  498. case RTS_OFF:
  499. gpio_set(RTS_GPIO, RTS_PIN);
  500. break;
  501. }
  502. break;
  503. }
  504. #ifdef HAVE_MODES
  505. } else if( usart_mode == MODE_RAW ) {
  506. usart_send(USART1, data);
  507. }
  508. #endif // HAVE_MODES
  509. }
  510. }
  511. }
  512. // }}}
  513. // {{{ systick
  514. static void systick_setup(void)
  515. {
  516. systick_set_clocksource(STK_CSR_CLKSOURCE_EXT);
  517. // clear counter so it starts right away
  518. STK_CVR = 0;
  519. systick_set_reload((rcc_ahb_frequency/8000)-1); // every ms
  520. systick_counter_enable();
  521. systick_interrupt_enable();
  522. }
  523. void sys_tick_handler(void)
  524. {
  525. ++ticks;
  526. }
  527. // }}}
  528. // {{{ USB serial
  529. static const struct usb_device_descriptor dev = {
  530. .bLength = USB_DT_DEVICE_SIZE,
  531. .bDescriptorType = USB_DT_DEVICE,
  532. .bcdUSB = 0x0200,
  533. .bDeviceClass = USB_CLASS_CDC,
  534. .bDeviceSubClass = 0,
  535. .bDeviceProtocol = 0,
  536. .bMaxPacketSize0 = 64,
  537. .idVendor = 0x0483,
  538. .idProduct = 0x5740,
  539. .bcdDevice = 0x0200,
  540. .iManufacturer = 1,
  541. .iProduct = 2,
  542. .iSerialNumber = 3,
  543. .bNumConfigurations = 1,
  544. };
  545. /*
  546. * This notification endpoint isn't implemented. According to CDC spec its
  547. * optional, but its absence causes a NULL pointer dereference in Linux
  548. * cdc_acm driver.
  549. */
  550. static const struct usb_endpoint_descriptor comm_endp[] = {{
  551. .bLength = USB_DT_ENDPOINT_SIZE,
  552. .bDescriptorType = USB_DT_ENDPOINT,
  553. .bEndpointAddress = 0x83,
  554. .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
  555. .wMaxPacketSize = 16,
  556. .bInterval = 255,
  557. }};
  558. static const struct usb_endpoint_descriptor data_endp[] = {{
  559. .bLength = USB_DT_ENDPOINT_SIZE,
  560. .bDescriptorType = USB_DT_ENDPOINT,
  561. .bEndpointAddress = 0x01,
  562. .bmAttributes = USB_ENDPOINT_ATTR_BULK,
  563. .wMaxPacketSize = 64,
  564. .bInterval = 1,
  565. }, {
  566. .bLength = USB_DT_ENDPOINT_SIZE,
  567. .bDescriptorType = USB_DT_ENDPOINT,
  568. .bEndpointAddress = 0x82,
  569. .bmAttributes = USB_ENDPOINT_ATTR_BULK,
  570. .wMaxPacketSize = 64,
  571. .bInterval = 1,
  572. }};
  573. static const struct {
  574. struct usb_cdc_header_descriptor header;
  575. struct usb_cdc_call_management_descriptor call_mgmt;
  576. struct usb_cdc_acm_descriptor acm;
  577. struct usb_cdc_union_descriptor cdc_union;
  578. } __attribute__((packed)) cdcacm_functional_descriptors = {
  579. .header = {
  580. .bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
  581. .bDescriptorType = CS_INTERFACE,
  582. .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
  583. .bcdCDC = 0x0110,
  584. },
  585. .call_mgmt = {
  586. .bFunctionLength =
  587. sizeof(struct usb_cdc_call_management_descriptor),
  588. .bDescriptorType = CS_INTERFACE,
  589. .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
  590. .bmCapabilities = 0,
  591. .bDataInterface = 1,
  592. },
  593. .acm = {
  594. .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
  595. .bDescriptorType = CS_INTERFACE,
  596. .bDescriptorSubtype = USB_CDC_TYPE_ACM,
  597. .bmCapabilities = 0,
  598. },
  599. .cdc_union = {
  600. .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
  601. .bDescriptorType = CS_INTERFACE,
  602. .bDescriptorSubtype = USB_CDC_TYPE_UNION,
  603. .bControlInterface = 0,
  604. .bSubordinateInterface0 = 1,
  605. },
  606. };
  607. static const struct usb_interface_descriptor comm_iface[] = {{
  608. .bLength = USB_DT_INTERFACE_SIZE,
  609. .bDescriptorType = USB_DT_INTERFACE,
  610. .bInterfaceNumber = 0,
  611. .bAlternateSetting = 0,
  612. .bNumEndpoints = 1,
  613. .bInterfaceClass = USB_CLASS_CDC,
  614. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  615. .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
  616. .iInterface = 0,
  617. .endpoint = comm_endp,
  618. .extra = &cdcacm_functional_descriptors,
  619. .extralen = sizeof(cdcacm_functional_descriptors),
  620. }};
  621. static const struct usb_interface_descriptor data_iface[] = {{
  622. .bLength = USB_DT_INTERFACE_SIZE,
  623. .bDescriptorType = USB_DT_INTERFACE,
  624. .bInterfaceNumber = 1,
  625. .bAlternateSetting = 0,
  626. .bNumEndpoints = 2,
  627. .bInterfaceClass = USB_CLASS_DATA,
  628. .bInterfaceSubClass = 0,
  629. .bInterfaceProtocol = 0,
  630. .iInterface = 0,
  631. .endpoint = data_endp,
  632. }};
  633. static const struct usb_interface ifaces[] = {{
  634. .num_altsetting = 1,
  635. .altsetting = comm_iface,
  636. }, {
  637. .num_altsetting = 1,
  638. .altsetting = data_iface,
  639. }};
  640. static const struct usb_config_descriptor config = {
  641. .bLength = USB_DT_CONFIGURATION_SIZE,
  642. .bDescriptorType = USB_DT_CONFIGURATION,
  643. .wTotalLength = 0,
  644. .bNumInterfaces = 2,
  645. .bConfigurationValue = 1,
  646. .iConfiguration = 0,
  647. .bmAttributes = 0x80,
  648. .bMaxPower = 0x32,
  649. .interface = ifaces,
  650. };
  651. static char serial_no[9] = "killbill";
  652. static const char *usb_strings[] = {
  653. "JeeLabs",
  654. "SerPlus",
  655. serial_no,
  656. };
  657. // Buffer to be used for control requests.
  658. uint8_t usbd_control_buffer[128];
  659. static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf,
  660. uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
  661. {
  662. (void)complete;
  663. #ifndef HAVE_MODES
  664. (void)buf;
  665. #endif // ! HAVE_MODES
  666. (void)usbd_dev;
  667. switch (req->bRequest) {
  668. case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
  669. #ifdef HAVE_MODES
  670. if( usart_mode == MODE_RAW ) {
  671. if(req->wValue & (1 << 0)) { // dtr set
  672. gpio_clear(DTR_GPIO, DTR_PIN);
  673. } else {
  674. gpio_set(DTR_GPIO, DTR_PIN);
  675. }
  676. //if(req->wValue & (1 << 1)) { // rts set
  677. //}
  678. }
  679. #else // HAVE_MODES
  680. // original code from SerPlus:
  681. /*
  682. * This Linux cdc_acm driver requires this to be implemented
  683. * even though it's optional in the CDC spec, and we don't
  684. * advertise it in the ACM functional descriptor.
  685. */
  686. char local_buf[10];
  687. struct usb_cdc_notification *notif = (void *)local_buf;
  688. // We echo signals back to host as notification.
  689. notif->bmRequestType = 0xA1;
  690. notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
  691. notif->wValue = 0;
  692. notif->wIndex = 0;
  693. notif->wLength = 2;
  694. local_buf[8] = req->wValue & 3;
  695. local_buf[9] = 0;
  696. // usbd_ep_write_packet(0x83, buf, 10);
  697. #endif // HAVE_MODES
  698. return 1;
  699. }
  700. case USB_CDC_REQ_SET_LINE_CODING: {
  701. if (*len < sizeof(struct usb_cdc_line_coding))
  702. return 0;
  703. #ifdef HAVE_MODES
  704. if( usart_mode == MODE_RAW ) {
  705. struct usb_cdc_line_coding *coding;
  706. coding = (struct usb_cdc_line_coding *)*buf;
  707. uint8_t databits;
  708. usart_disable(USART1);
  709. usart_set_baudrate(USART1,coding->dwDTERate);
  710. //do the databits ourselves, because the routine isn't yet adjusted to F072 (M1 reg)
  711. //usart_set_databits(USART1,coding->bDataBits);
  712. databits = coding->bDataBits;
  713. USART_CR1(USART1) &= ~(USART_CR1_M0|USART_CR1_M1);
  714. // at least 'stm32flash' expects the parity to be an extra bit in
  715. // addition to these; but the MCU includes them in "databits"
  716. // not sure what the actual USB_CDC standard is
  717. if((databits < 9) && (coding->bParityType == USB_CDC_EVEN_PARITY ||
  718. coding->bParityType == USB_CDC_ODD_PARITY)) {
  719. databits++;
  720. }
  721. switch(databits) {
  722. case 7: USART_CR1(USART1) |= USART_CR1_M1; break;
  723. case 9: USART_CR1(USART1) |= USART_CR1_M0; break;
  724. }
  725. switch(coding->bCharFormat) {
  726. case USB_CDC_1_STOP_BITS: usart_set_stopbits(USART1, USART_STOPBITS_1); break;
  727. case USB_CDC_1_5_STOP_BITS: usart_set_stopbits(USART1, USART_STOPBITS_1_5); break;
  728. case USB_CDC_2_STOP_BITS: usart_set_stopbits(USART1, USART_STOPBITS_2); break;
  729. }
  730. switch(coding->bParityType) {
  731. case USB_CDC_NO_PARITY: usart_set_parity(USART1, USART_PARITY_NONE); break;
  732. case USB_CDC_ODD_PARITY: usart_set_parity(USART1, USART_PARITY_ODD); break;
  733. case USB_CDC_EVEN_PARITY: usart_set_parity(USART1, USART_PARITY_EVEN); break;
  734. }
  735. usart_enable(USART1);
  736. }
  737. #endif // HAVE_MODES
  738. return 1;
  739. }
  740. }
  741. return 0;
  742. }
  743. static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
  744. {
  745. (void)ep;
  746. (void)usbd_dev;
  747. // back pressure: don't read the packet if there's not enough room in ring
  748. if ((output_ring.begin - (output_ring.end+1)) % BUFFER_SIZE <= 64)
  749. return;
  750. uint8_t buf[64];
  751. int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, sizeof buf);
  752. if (len) {
  753. // Retrieve the data from the peripheral.
  754. ring_write(&output_ring, buf, len);
  755. // Enable usart transmit interrupt so it sends out the data.
  756. USART_CR1(USART1) |= USART_CR1_TXEIE;
  757. }
  758. }
  759. static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
  760. {
  761. (void)wValue;
  762. (void)usbd_dev;
  763. usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
  764. usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
  765. usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
  766. usbd_register_control_callback(
  767. usbd_dev,
  768. USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
  769. USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
  770. cdcacm_control_request);
  771. }
  772. static char *get_dev_unique_id(char *s)
  773. {
  774. #if defined(STM32F4) || defined(STM32F2)
  775. # define UNIQUE_SERIAL_R 0x1FFF7A10
  776. # define FLASH_SIZE_R 0x1fff7A22
  777. #elif defined(STM32F3)
  778. # define UNIQUE_SERIAL_R 0x1FFFF7AC
  779. # define FLASH_SIZE_R 0x1fff77cc
  780. #elif defined(STM32L1)
  781. # define UNIQUE_SERIAL_R 0x1ff80050
  782. # define FLASH_SIZE_R 0x1FF8004C
  783. #elif defined(STM32F0)
  784. # define UNIQUE_SERIAL_R 0x1FFFF7AC
  785. # define FLASH_SIZE_R 0x1FFFF7CC
  786. #else
  787. # define UNIQUE_SERIAL_R 0x1FFFF7E8;
  788. # define FLASH_SIZE_R 0x1ffff7e0
  789. #endif
  790. volatile uint32_t *unique_id_p = (volatile uint32_t *)UNIQUE_SERIAL_R;
  791. uint32_t unique_id = *unique_id_p ^ // was "+" in original BMP
  792. *(unique_id_p + 1) ^ // was "+" in original BMP
  793. *(unique_id_p + 2);
  794. int i;
  795. // Calculated the upper flash limit from the exported data
  796. // in theparameter block
  797. //max_address = (*(uint32_t *) FLASH_SIZE_R) <<10;
  798. // Fetch serial number from chip's unique ID
  799. for(i = 0; i < 8; i++) {
  800. s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0';
  801. }
  802. for(i = 0; i < 8; i++)
  803. if(s[i] > '9')
  804. s[i] += 'A' - '9' - 1;
  805. s[8] = 0;
  806. return s;
  807. }
  808. // }}}
  809. // {{{ ADC
  810. /**************************************************
  811. ********************* ADC ************************
  812. **************************************************/
  813. #ifdef HAVE_ADC
  814. static void adc_setup(void) {
  815. gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG,
  816. GPIO_PUPD_NONE, GPIO4); // serplus: detect pwr
  817. //gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0);
  818. //gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1);
  819. adc_power_off(ADC1);
  820. adc_set_clk_source(ADC1, ADC_CLKSOURCE_ADC);
  821. adc_calibrate(ADC1);
  822. adc_set_operation_mode(ADC1, ADC_MODE_SCAN);
  823. adc_disable_external_trigger_regular(ADC1);
  824. adc_set_right_aligned(ADC1);
  825. adc_enable_temperature_sensor();
  826. adc_set_sample_time_on_all_channels(ADC1, ADC_SMPTIME_071DOT5);
  827. uint8_t channel_array[] = { 4 }; // which channels to enable // ADC_CHANNEL_TEMP
  828. adc_set_regular_sequence(ADC1, 1, channel_array); // mid param = num_of_chan
  829. adc_set_resolution(ADC1, ADC_RESOLUTION_12BIT);
  830. adc_disable_analog_watchdog(ADC1);
  831. adc_power_on(ADC1);
  832. // Wait for ADC starting up.
  833. int i;
  834. for (i = 0; i < 800000; i++) { // Wait a bit.
  835. __asm__("nop");
  836. }
  837. }
  838. #endif // HAVE_ADC
  839. // }}}
  840. // {{{ main
  841. int main(void) {
  842. clock_setup();
  843. systick_setup();
  844. gpio_setup();
  845. #ifdef HAVE_ADC
  846. uint16_t volts; // ADC reading (PA4, 10k/10k divider to PWR_OUT)
  847. adc_setup();
  848. #endif // HAVE_ADC
  849. #ifdef HAVE_MODES
  850. // begin in serplus mode
  851. usart_mode = MODE_SERPLUS;
  852. #endif // HAVE_MODES
  853. #ifdef HAVE_NEOPIX
  854. // WS2812 setup
  855. ws2812_pre();
  856. pwm_setup();
  857. #endif // HAVE_NEOPIX
  858. FET_ON;
  859. for (int i = 0; i < 1000000; i++)
  860. __asm__("");
  861. get_dev_unique_id(serial_no);
  862. usbd_device *usbd_dev = usbd_init(&st_usbfs_v2_usb_driver, &dev, &config,
  863. usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
  864. usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
  865. for (int i = 0; i < 1000000; i++)
  866. __asm__("");
  867. usart_setup(); // late config to allow USB setup to complete first
  868. LED_TOGGLE;
  869. while (1) {
  870. // poll USB while waiting for 2 ms to elapse
  871. // it takes 2.7 ms to send 64 bytes at 230400 baud 8N1
  872. for (int i = 0; i < 2; ++i) {
  873. uint32_t lastTick = ticks;
  874. while (ticks == lastTick)
  875. usbd_poll(usbd_dev);
  876. }
  877. // put up to 64 pending bytes into the USB send packet buffer
  878. uint8_t buf[64];
  879. int len = ring_read(&input_ring, buf, sizeof buf);
  880. if (len > 0) {
  881. usbd_ep_write_packet(usbd_dev, 0x82, buf, len);
  882. //buf[len] = 0;
  883. }
  884. #ifdef HAVE_ADC
  885. // ADC
  886. adc_start_conversion_regular(ADC1);
  887. while (!(adc_eoc(ADC1)));
  888. volts = adc_read_regular(ADC1);
  889. if( volts >= 0x7A0 && volts <= 0x890 ) { // around 3v3
  890. #ifdef HAVE_NEOPIX
  891. neopix_red(0x06);
  892. #endif // HAVE_NEOPIX
  893. } else if( volts >= 0xc00 && volts <= 0xd00 ) { // around 5v
  894. #ifdef HAVE_NEOPIX
  895. neopix_red(0x33);
  896. #endif // HAVE_NEOPIX
  897. } else if( volts <= 0x100 ) { // around 0v
  898. #ifdef HAVE_NEOPIX
  899. neopix_red(0);
  900. #endif // HAVE_NEOPIX
  901. } else {
  902. #ifdef HAVE_NEOPIX
  903. neopix_red(0xFF);
  904. #endif // HAVE_NEOPIX
  905. }
  906. #endif // HAVE_ADC
  907. // buttons
  908. service_extbut();
  909. if(extbut_state == 1 && (extbut_time - extbut_lastchange) >= 1000) { // long press
  910. if( extbut_acted == 0) {
  911. #ifdef HAVE_MODES
  912. if(usart_mode == MODE_SERPLUS) { // switching to RAW
  913. usart_mode = MODE_RAW;
  914. usart_dtr_rts_raw_setup();
  915. } else { // switching to SERPLUS
  916. usart_mode = MODE_SERPLUS;
  917. usart_dtr_rts_serplus_setup();
  918. usart_disable(USART1);
  919. usart_set_serplus_params();
  920. usart_enable(USART1);
  921. }
  922. #endif // HAVE_MODES
  923. extbut_acted = 1;
  924. }
  925. } else {
  926. extbut_acted = 0;
  927. }
  928. #ifdef HAVE_MODES
  929. #ifdef HAVE_NEOPIX
  930. neopix_blue(usart_mode == MODE_SERPLUS ? 0 : 0x20);
  931. #endif // HAVE_NEOPIX
  932. #endif // HAVE_MODES
  933. }
  934. }
  935. // }}}
  936. // vim: shiftwidth=4:tabstop=4:noexpandtab:foldmethod=marker: