fw_app.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * fw_app.c
  3. *
  4. * Copyright (C) 2019 Sylvain Munaut
  5. * All rights reserved.
  6. *
  7. * LGPL v3+, see LICENSE.lgpl3
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 3 of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with this program; if not, write to the Free Software Foundation,
  21. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22. */
  23. #include <stdint.h>
  24. #include <stdbool.h>
  25. #include <string.h>
  26. #include "console.h"
  27. #include "led.h"
  28. #include "mini-printf.h"
  29. #include "spi.h"
  30. #include "utils.h"
  31. #include "registers.h"
  32. #include "generation.h"
  33. /* FLASH */
  34. #define FLASH_MAILBOX_STORAGE 0x0F0000
  35. static uint32_t copy_array[16];
  36. /*
  37. double dupa;
  38. float kupa;
  39. */
  40. /* Local generation params for tweaking actual HW generation params */
  41. static tweaked_params_union_s out_params;
  42. static inline uint32_t rdcycle(void)
  43. {
  44. uint32_t cycle;
  45. __asm__ volatile ("rdcycle %0" : "=r" (cycle));
  46. return cycle;
  47. }
  48. /* Timer fuction */
  49. #define CYCLES_DIV 24000000.0f
  50. #define UPDATE_MS 0.1f
  51. // TODO: integers not floats?
  52. static uint32_t last_rdcycle;
  53. static bool timer_expired()
  54. {
  55. bool success = false;
  56. uint32_t current = rdcycle();
  57. uint32_t diff = current - last_rdcycle;
  58. //printf(" diff %d last: %d current: %d\n", diff, last_rdcycle, current);
  59. // TODO: overflow handling
  60. float elapsed_seconds = (float)(diff) / CYCLES_DIV;
  61. if (elapsed_seconds > UPDATE_MS)
  62. {
  63. last_rdcycle = current;
  64. //printf("Timer expired!\n");
  65. success = true;;
  66. }
  67. return success;
  68. }
  69. static void write_regs_to_mailbox()
  70. {
  71. mailbox_regs->regs.period1 = out_params.regs._period1;
  72. // TODO: seems like period2 etc are missing
  73. mailbox_regs->regs.delay1 = out_params.regs.D1 / FXP_SCALING;
  74. //mailbox_regs->regs.period2 = out_params.regs._period2;
  75. mailbox_regs->regs.delay2 = out_params.regs.D2 / FXP_SCALING;
  76. //mailbox_regs->regs.duty3 = out_params.regs._du
  77. mailbox_regs->regs.delay3 = out_params.regs.D3 / FXP_SCALING;
  78. mailbox_regs->regs.npuls3 = out_params.regs.N3;
  79. mailbox_regs->regs.odd_train_flag = N_PULSE_TRAINS; // TODO: is this proper?
  80. mailbox_regs->regs.ena_odd_out3 = out_params.regs.ena;
  81. }
  82. static void clear_button_regs()
  83. {
  84. for (int i = 0; i < 16; ++i)
  85. mailbox_button_regs->data[i] = 0x0;
  86. }
  87. static void print_mailbox_contents()
  88. {
  89. int i = 0;
  90. printf("Mailbox contents:\n");
  91. for(i = 0; i < 16; ++i)
  92. printf("Mailbox[%d]: %d\n", i, mailbox_regs->data[i]);
  93. }
  94. static void read_generation_values_from_flash()
  95. {
  96. flash_read((void*)copy_array, FLASH_MAILBOX_STORAGE, sizeof(copy_array));
  97. // Copy data to actual registers
  98. for (int i = 0; i < 14; ++i)
  99. out_params.data[i] = copy_array[i];
  100. }
  101. static void store_generation_values_flash()
  102. {
  103. // TODO: can we remove it already as we don't read directly to mailbox
  104. // Copy current mailbox array to a temporary array for bulk memory write
  105. // our Wishbone implementation does not support bulk writes
  106. for (int i = 0; i < 16; ++i)
  107. copy_array[i] = out_params.data[i];
  108. flash_write_enable();
  109. flash_sector_erase(FLASH_MAILBOX_STORAGE);
  110. // Wait for flash to finish (poll status register)
  111. while (flash_read_sr() & 0x01) /* WIP bit */;
  112. flash_write_enable();
  113. flash_page_program((void*)copy_array, FLASH_MAILBOX_STORAGE, sizeof(copy_array));
  114. while (flash_read_sr() & 0x01) /* WIP bit */;
  115. }
  116. static void
  117. serial_no_init()
  118. {
  119. uint8_t buf[8];
  120. flash_manuf_id(buf);
  121. printf("Flash Manufacturer : %s\n", hexstr(buf, 3, true));
  122. flash_unique_id(buf);
  123. printf("Flash Unique ID : %s\n", hexstr(buf, 8, true));
  124. //dummy_write_to_flash();
  125. /* Testing floats TODO: test if calculation is correct
  126. dupa = 3.1415;
  127. kupa = 2.74f;
  128. dupa *= kupa;
  129. printf("Pi * e: %.3f\n", dupa);
  130. */
  131. }
  132. //static char _printf_buf[128];
  133. static void write_period1()
  134. {
  135. printf("Writing period1 0x1\n");
  136. mailbox_regs->regs.period1 = 0x1;
  137. printf("Done writing\n");
  138. print_mailbox_contents();
  139. //store_mailbox_regs_flash();
  140. }
  141. static void write_period1_2()
  142. {
  143. printf("Writing period1 0x2\n");
  144. mailbox_regs->regs.period1 = 0x2;
  145. printf("Done writing\n");
  146. print_mailbox_contents();
  147. //store_mailbox_regs_flash();
  148. }
  149. static void write_period1_4()
  150. {
  151. printf("Writing period1 0x4\n");
  152. mailbox_regs->regs.period1 = 0x4;
  153. printf("Done writing\n");
  154. printf("Reading now \n");
  155. printf("value: %d\n", mailbox_regs->regs.period1);
  156. print_mailbox_contents();
  157. //store_mailbox_regs_flash();
  158. }
  159. static void clear_period1()
  160. {
  161. printf("Clearing period1 val: %d\n", mailbox_regs->regs.period1);
  162. mailbox_regs->regs.period1 = 0x0;
  163. printf("Done clearing\n");
  164. }
  165. static void write_delay1()
  166. {
  167. printf("Writing delay1 0x1234\n");
  168. mailbox_regs->regs.delay1 = 0x1234;
  169. printf("Done writing\n");
  170. //store_mailbox_regs_flash();
  171. }
  172. static void clear_delay1()
  173. {
  174. printf("Clearing delay1 val: %d\n", mailbox_regs->regs.delay1);
  175. mailbox_regs->regs.delay1 = 0x0;
  176. printf("Done clearing\n");
  177. }
  178. static void print_flash_contents()
  179. {
  180. read_generation_values_from_flash();
  181. print_mailbox_contents();
  182. }
  183. static void
  184. boot_dfu(void)
  185. {
  186. /* Boot firmware */
  187. volatile uint32_t *boot = (void*)0x80000000;
  188. *boot = (1 << 2) | (1 << 0);
  189. }
  190. void
  191. usb_dfu_rt_cb_reboot(void)
  192. {
  193. boot_dfu();
  194. }
  195. void main()
  196. {
  197. int cmd = 0;
  198. /* Init console IO */
  199. console_init();
  200. puts("Booting App image..\n");
  201. /* LED */
  202. led_init();
  203. led_color(48, 96, 5);
  204. led_blink(true, 200, 1000);
  205. led_breathe(true, 100, 200);
  206. led_state(true);
  207. /* SPI */
  208. spi_init();
  209. /* Enable USB directly */
  210. serial_no_init();
  211. /* Read generation reg values from flash */
  212. read_generation_values_from_flash();
  213. /* If values are wrong - fill defaults */
  214. if (validate_generation_values(&out_params.regs) != 0)
  215. init_params(&out_params.regs);
  216. write_regs_to_mailbox();
  217. /* Main loop */
  218. while (1)
  219. {
  220. /* Run the timer for button updates periodically */
  221. if (timer_expired())
  222. {
  223. update_three_signal_values(&out_params.regs, mailbox_button_regs);
  224. // button registers have to be cleared upon reading
  225. clear_button_regs();
  226. write_regs_to_mailbox();
  227. if (mailbox_regs->regs.write_flash)
  228. {
  229. store_generation_values_flash();
  230. mailbox_regs->regs.write_flash = 0x0;
  231. }
  232. }
  233. // TODO: Add incrementing/decrementing values from console
  234. #ifdef USE_KEYBOARD
  235. /* Prompt ? */
  236. if (cmd >= 0)
  237. printf("Command> ");
  238. /* Poll for command */
  239. cmd = getchar_nowait();
  240. if (cmd >= 0) {
  241. if (cmd > 32 && cmd < 127) {
  242. putchar(cmd);
  243. putchar('\r');
  244. putchar('\n');
  245. }
  246. switch (cmd)
  247. {
  248. case 'q':
  249. printf("Current rdcycle %d\n", rdcycle());
  250. break;
  251. case 'b':
  252. boot_dfu();
  253. break;
  254. case 'w':
  255. write_period1();
  256. break;
  257. case 'k':
  258. clear_period1();
  259. break;
  260. case 'a':
  261. write_period1_2();
  262. break;
  263. case 's':
  264. write_period1_4();
  265. break;
  266. case 'o':
  267. write_delay1();
  268. break;
  269. case 'm':
  270. clear_delay1();
  271. break;
  272. case 'f':
  273. print_flash_contents();
  274. break;
  275. default:
  276. break;
  277. }
  278. }
  279. #endif
  280. }
  281. }