Advertisement
Cochese3

Untitled

Aug 9th, 2021
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 50.05 KB | None | 0 0
  1. /*
  2. ProffieOS: Control software for lightsabers and other props.
  3. http://fredrik.hubbe.net/lightsaber/teensy_saber.html
  4. Copyright (c) 2016-2019 Fredrik Hubinette
  5. Additional copyright holders listed inline below.
  6.  
  7. This program is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21. // You can have multiple configuration files, and specify which one
  22. // to use here.
  23.  
  24. #define CONFIG_FILE "config/YOURSABER.h"
  25.  
  26. //
  27.  
  28. #ifdef CONFIG_FILE_T<Layers<MixEST
  29. #undef CONFIG_FILE
  30. #define CONFIG_FILE CONFIG_FILE_TEST
  31. #endif
  32.  
  33. #define CONFIG_TOP
  34. #include CONFIG_FILE
  35. #undef CONFIG_TOP
  36.  
  37. #ifdef SAVE_STATE
  38. #define SAVE_VOLUME
  39. #define SAVE_PRESET
  40. #define SAVE_COLOR_CHANGE
  41. #endif
  42.  
  43. // #define ENABLE_DEBUG
  44.  
  45.  
  46. //
  47. // OVERVIEW
  48. //
  49. // Here explain some general code concepts to make it easier
  50. // to understand the code below.
  51. //
  52. // Most things start with the ProbBase class. Depending on the
  53. // configuration, this class is extended by the Saber class,
  54. // the Detonator class, or some other class. The extended class
  55. // is instantiated as "prop", and is responsible for handling
  56. // button clicks, clashes, swings and other events. These events
  57. // are then send to all registered SaberBase classes.
  58. ///
  59. // Generally speaking, there are usually two registered SaberBase
  60. // classes listening for events. One for sound and one for
  61. // the blade. Sound and blade effects are generally executed
  62. // separately by separate clases.
  63. //
  64. // Blades are generally handled by one of the child-classes of
  65. // BladeBase. These classes know how many LEDs the current
  66. // blade has, and how to set those LEDs to a given color, but
  67. // they don't actually decide what the blade should look like.
  68. // Instead they just call the current BladeStyle class and
  69. // asks it to set the colors. The BladeStyle classes don't
  70. // need to know what kind of blade is attached, although
  71. // some combinations of BladeBases and BladeStyles just don't
  72. // make any sense.
  73. //
  74. // Sounds are also abstracted. It starts with scanning a directory
  75. // on the SD card for files that match known patterns of file names.
  76. // The Effect class is responsible for keeping track of all numbered
  77. // files that for a particular filename prefix.
  78. //
  79. // Once the directory has been scanned, we'll decide how to play
  80. // sounds. In the past, there was one class for handling NEC style
  81. // fonts and another for handling Plecter style fonts. However,
  82. // both of those have now been merged into the HybridFont class
  83. // which can do both. It is also capable of doing some mix and matching,
  84. // so you can use a plecter style hum together with a NEC style
  85. // swing if you so desire. The HybridFont class inherit from
  86. // SaberBase and listen on on/off/clash/etc. events, just like
  87. // BladeBase classes do.
  88. //
  89. // HybridFont tells the audio subsystem
  90. // to trigger and mix sounds as aproperiate. The sound subsystem
  91. // starts with an DMA channel which feeds data to a digital-to-analog
  92. // converter. Once the data buffer is half-gone, and interrupt is
  93. // triggered in the DAC class, which tries to fill it up by
  94. // reading data from a int16_t AudioStream. Generally, that data
  95. // stream is hooked up to the AudioDynamicMixer class. This
  96. // class is responsible for taking multiple audio inputs,
  97. // summing them up and then adjusting the volume to minimize
  98. // clipping.
  99.  
  100. // TODO LIST:
  101. // stab detect/effect
  102. //
  103. // Audio work items:
  104. // select clash from force
  105. // stab effect
  106. // Blade stuff
  107. // better clash
  108. // Allow several blades to share power pins.
  109.  
  110. // If defined, DAC vref will be 3 volts, resulting in louder sound. (teensy only)
  111. #define LOUD
  112.  
  113. // You can get better SD card performance by
  114. // activating the USE_TEENSY3_OPTIMIZED_CODE define
  115. // in SD.h in the teensy library, however, my sd card
  116. // did not work with that define.
  117.  
  118. #include <Arduino.h>
  119.  
  120. #ifdef TEENSYDUINO
  121. #include <DMAChannel.h>
  122. #include <usb_dev.h>
  123.  
  124. #ifndef USE_TEENSY4
  125. #include <kinetis.h>
  126. #endif
  127.  
  128. #include <i2c_t3.h>
  129. #include <SD.h>
  130. #include <SPI.h>
  131.  
  132. #define INPUT_ANALOG INPUT
  133. #else
  134.  
  135. // This is a hack to let me access the internal stuff..
  136. #define private public
  137. #include <Wire.h>
  138. #undef private
  139.  
  140. #include <FS.h>
  141. #define digitalWriteFast digitalWrite
  142. #include <stm32l4_wiring_private.h>
  143. #include <stm32l4xx.h>
  144. #include <armv7m.h>
  145. #include <stm32l4_gpio.h>
  146. #include <stm32l4_sai.h>
  147. #include <stm32l4_dma.h>
  148. #include <stm32l4_system.h>
  149. #include <arm_math.h>
  150. #include <STM32.h>
  151. #define DMAChannel stm32l4_dma_t
  152. #define DMAMEM
  153. #define NVIC_SET_PRIORITY(X,Y) NVIC_SetPriority((X), (IRQn_Type)(Y))
  154.  
  155. #endif
  156.  
  157. #include <math.h>
  158. #include <malloc.h>
  159.  
  160. #ifdef ENABLE_SERIALFLASH
  161.  
  162. // This is a hack to let me access the internal stuff..
  163. #define private public
  164. #define protected public
  165.  
  166. #include <SerialFlash.h>
  167.  
  168. #undef private
  169. #undef protected
  170. #endif
  171.  
  172. #ifdef ENABLE_SNOOZE
  173. #define startup_early_hook DISABLE_startup_early_hook
  174. #include <Snooze.h>
  175. #undef startup_early_hook
  176.  
  177. SnoozeTimer snooze_timer;
  178. SnoozeDigital snooze_digital;
  179. SnoozeTouch snooze_touch;
  180. SnoozeBlock snooze_config(snooze_touch, snooze_digital, snooze_timer);
  181. #endif
  182.  
  183. const char version[] = "v5.9";
  184. const char install_time[] = __DATE__ " " __TIME__;
  185.  
  186. #include "common/state_machine.h"
  187. #include "common/monitoring.h"
  188. #include "common/stdout.h"
  189.  
  190. Monitoring monitor;
  191. DEFINE_COMMON_STDOUT_GLOBALS;
  192.  
  193. void PrintQuotedValue(const char *name, const char* str) {
  194. STDOUT.print(name);
  195. STDOUT.write('=');
  196. if (str) {
  197. while (*str) {
  198. switch (*str) {
  199. case '\n':
  200. STDOUT.print("\\n");
  201. break;
  202. case '\t':
  203. STDOUT.print("\\t");
  204. break;
  205. case '\\':
  206. STDOUT.write('\\');
  207. default:
  208. STDOUT.write(*str);
  209. }
  210. ++str;
  211. }
  212. }
  213. STDOUT.write('\n');
  214. }
  215.  
  216. #ifdef ENABLE_DEBUG
  217.  
  218. // This class is really useful for finding crashes
  219. // basically, the pin you give it will be held high
  220. // while this function is running. After that it will
  221. // be set to low. If a crash occurs in this function
  222. // it will stay high.
  223. class ScopedPinTracer {
  224. public:
  225. explicit ScopedPinTracer(int pin) : pin_(pin) {
  226. pinMode(pin_, OUTPUT);
  227. digitalWriteFast(pin, HIGH);
  228. }
  229. ~ScopedPinTracer() {
  230. digitalWriteFast(pin_, LOW);
  231. }
  232. private:
  233. int pin_;
  234. };
  235.  
  236. class ScopedTracer3 {
  237. public:
  238. explicit ScopedTracer3(int code) {
  239. pinMode(bladePowerPin1, OUTPUT);
  240. pinMode(bladePowerPin2, OUTPUT);
  241. pinMode(bladePowerPin3, OUTPUT);
  242. digitalWriteFast(bladePowerPin1, !!(code & 1));
  243. digitalWriteFast(bladePowerPin2, !!(code & 2));
  244. digitalWriteFast(bladePowerPin3, !!(code & 4));
  245. }
  246. ~ScopedTracer3() {
  247. digitalWriteFast(bladePowerPin1, LOW);
  248. digitalWriteFast(bladePowerPin2, LOW);
  249. digitalWriteFast(bladePowerPin3, LOW);
  250. }
  251. };
  252.  
  253. #endif
  254.  
  255. #include "common/scoped_cycle_counter.h"
  256. #include "common/profiling.h"
  257.  
  258. uint64_t audio_dma_interrupt_cycles = 0;
  259. uint64_t pixel_dma_interrupt_cycles = 0;
  260. uint64_t wav_interrupt_cycles = 0;
  261. uint64_t loop_cycles = 0;
  262.  
  263. #include "common/loop_counter.h"
  264.  
  265. #define NELEM(X) (sizeof(X)/sizeof((X)[0]))
  266.  
  267. #include "common/linked_list.h"
  268. #include "common/looper.h"
  269. #include "common/command_parser.h"
  270. #include "common/monitor_helper.h"
  271.  
  272. CommandParser* parsers = NULL;
  273. MonitorHelper monitor_helper;
  274.  
  275. #include "common/vec3.h"
  276. #include "common/quat.h"
  277. #include "common/ref.h"
  278. #include "common/events.h"
  279. #include "common/saber_base.h"
  280. #include "common/saber_base_passthrough.h"
  281.  
  282. SaberBase* saberbases = NULL;
  283. SaberBase::LockupType SaberBase::lockup_ = SaberBase::LOCKUP_NONE;
  284. SaberBase::ColorChangeMode SaberBase::color_change_mode_ =
  285. SaberBase::COLOR_CHANGE_MODE_NONE;
  286. bool SaberBase::on_ = false;
  287. uint32_t SaberBase::last_motion_request_ = 0;
  288. uint32_t SaberBase::current_variation_ = 0;
  289.  
  290. #include "common/box_filter.h"
  291.  
  292. // Returns the decimals of a number, ie 12.2134 -> 0.2134
  293. float fract(float x) { return x - floorf(x); }
  294.  
  295. // clamp(x, a, b) makes sure that x is between a and b.
  296. float clamp(float x, float a, float b) {
  297. if (x < a) return a;
  298. if (x > b) return b;
  299. return x;
  300. }
  301. float Fmod(float a, float b) {
  302. return a - floorf(a / b) * b;
  303. }
  304.  
  305. int32_t clampi32(int32_t x, int32_t a, int32_t b) {
  306. if (x < a) return a;
  307. if (x > b) return b;
  308. return x;
  309. }
  310. int16_t clamptoi16(int32_t x) {
  311. return clampi32(x, -32768, 32767);
  312. }
  313. int32_t clamptoi24(int32_t x) {
  314. return clampi32(x, -8388608, 8388607);
  315. }
  316.  
  317. #include "common/sin_table.h"
  318.  
  319. void EnableBooster();
  320. void EnableAmplifier();
  321. bool AmplifierIsActive();
  322. void MountSDCard();
  323. const char* GetSaveDir();
  324.  
  325. #include "common/lsfs.h"
  326. #include "common/strfun.h"
  327.  
  328. // Double-zero terminated array of search paths.
  329. // No trailing slashes!
  330. char current_directory[128];
  331. const char* next_current_directory(const char* dir) {
  332. dir += strlen(dir);
  333. dir ++;
  334. if (!*dir) return NULL;
  335. return dir;
  336. }
  337.  
  338. #include "sound/sound.h"
  339. #include "common/battery_monitor.h"
  340. #include "common/color.h"
  341. #include "common/range.h"
  342. #include "common/fuse.h"
  343. #include "blades/blade_base.h"
  344. #include "blades/blade_wrapper.h"
  345.  
  346. class MicroEventTime {
  347. void SetToNow() { micros_ = micros(); millis_ = millis(); }
  348. uint32_t millis_since() { return millis() - millis_; }
  349. uint32_t micros_since() {
  350. if (millis_since() > (0xFFFF0000UL / 1000)) return 0xFFFFFFFFUL;
  351. return micros() - micros_;
  352. }
  353. private:
  354. uint32_t millis_;
  355. uint32_t micros_;
  356. };
  357.  
  358. template<class T, class U>
  359. struct is_same_type { static const bool value = false; };
  360.  
  361. template<class T>
  362. struct is_same_type<T, T> { static const bool value = true; };
  363.  
  364. // This really ought to be a typedef, but it causes problems I don't understand.
  365. #define StyleAllocator class StyleFactory*
  366.  
  367. #include "styles/rgb.h"
  368. #include "styles/rgb_arg.h"
  369. #include "styles/charging.h"
  370. #include "styles/fire.h"
  371. #include "styles/sparkle.h"
  372. #include "styles/gradient.h"
  373. #include "styles/random_flicker.h"
  374. #include "styles/random_per_led_flicker.h"
  375. #include "styles/audio_flicker.h"
  376. #include "styles/brown_noise_flicker.h"
  377. #include "styles/hump_flicker.h"
  378. #include "styles/rainbow.h"
  379. #include "styles/color_cycle.h"
  380. #include "styles/cylon.h"
  381. #include "styles/ignition_delay.h"
  382. #include "styles/retraction_delay.h"
  383. #include "styles/pulsing.h"
  384. #include "styles/blinking.h"
  385. #include "styles/on_spark.h"
  386. #include "styles/rgb_cycle.h"
  387. #include "styles/clash.h"
  388. #include "styles/lockup.h" // Also does "drag"
  389. #include "styles/blast.h"
  390. #include "styles/strobe.h"
  391. #include "styles/inout_helper.h"
  392. #include "styles/inout_sparktip.h"
  393. #include "styles/colors.h"
  394. #include "styles/mix.h"
  395. #include "styles/style_ptr.h"
  396. #include "styles/file.h"
  397. #include "styles/stripes.h"
  398. #include "styles/random_blink.h"
  399. #include "styles/sequence.h"
  400. #include "styles/byteorder.h"
  401. #include "styles/rotate_color.h"
  402. #include "styles/colorchange.h"
  403. #include "styles/transition_effect.h"
  404. #include "styles/transition_loop.h"
  405. #include "styles/effect_sequence.h"
  406.  
  407. // functions
  408. #include "functions/ifon.h"
  409. #include "functions/change_slowly.h"
  410. #include "functions/int.h"
  411. #include "functions/int_arg.h"
  412. #include "functions/sin.h"
  413. #include "functions/scale.h"
  414. #include "functions/battery_level.h"
  415. #include "functions/trigger.h"
  416. #include "functions/bump.h"
  417. #include "functions/smoothstep.h"
  418. #include "functions/swing_speed.h"
  419. #include "functions/sound_level.h"
  420. #include "functions/blade_angle.h"
  421. #include "functions/variation.h"
  422. #include "functions/twist_angle.h"
  423. #include "functions/layer_functions.h"
  424. #include "functions/islessthan.h"
  425. #include "functions/circular_section.h"
  426. #include "functions/marble.h"
  427. #include "functions/slice.h"
  428. #include "functions/mult.h"
  429.  
  430. // transitions
  431. #include "transitions/fade.h"
  432. #include "transitions/join.h"
  433. #include "transitions/concat.h"
  434. #include "transitions/instant.h"
  435. #include "transitions/delay.h"
  436. #include "transitions/wipe.h"
  437. #include "transitions/join.h"
  438. #include "transitions/boing.h"
  439. #include "transitions/random.h"
  440. #include "transitions/colorcycle.h"
  441. #include "transitions/wave.h"
  442.  
  443. //responsive styles
  444. #include "styles/responsive_styles.h"
  445.  
  446. // This macro has a problem with commas, please don't use it.
  447. #define EASYBLADE(COLOR, CLASH_COLOR) \
  448. SimpleClash<Lockup<Blast<COLOR, WHITE>, AudioFlicker<COLOR, WHITE> >, CLASH_COLOR>
  449.  
  450. // Use EasyBlade<COLOR, CLASH_COLOR> instead of EASYBLADE(COLOR, CLASH_COLOR)
  451. template<class color, class clash_color, class lockup_flicker_color = WHITE>
  452. using EasyBlade = SimpleClash<Lockup<Blast<color, WHITE>, AudioFlicker<color, lockup_flicker_color> >, clash_color>;
  453.  
  454. // The following functions are mostly for illustration.
  455. // The templates above gives you more power and functionality.
  456.  
  457. // Arguments: color, clash color, turn-on/off time
  458. template<class base_color,
  459. class clash_color,
  460. int out_millis,
  461. int in_millis,
  462. class lockup_flicker_color = WHITE,
  463. class blast_color = WHITE>
  464. StyleAllocator StyleNormalPtr() {
  465. #if 0
  466. typedef AudioFlicker<base_color, lockup_flicker_color> AddFlicker;
  467. typedef Blast<base_color, blast_color> AddBlast;
  468. typedef Lockup<AddBlast, AddFlicker> AddLockup;
  469. typedef SimpleClash<AddLockup, clash_color> AddClash;
  470. return StylePtr<InOutHelper<AddClash, out_millis, in_millis> >();
  471. #else
  472. typedef Layers<base_color,
  473. SimpleClashL<clash_color>,
  474. LockupL<AudioFlickerL<lockup_flicker_color> >,
  475. BlastL<blast_color> > Blade;
  476. return StylePtr<InOutHelper<Blade, out_millis, in_millis> >();
  477. #endif
  478. }
  479.  
  480. // Arguments: color, clash color, turn-on/off time
  481. template<class base_color,
  482. class clash_color,
  483. class out_millis,
  484. class in_millis,
  485. class lockup_flicker_color = WHITE,
  486. class blast_color = WHITE>
  487. StyleAllocator StyleNormalPtrX() {
  488. typedef AudioFlicker<base_color, lockup_flicker_color> AddFlicker;
  489. typedef Blast<base_color, blast_color> AddBlast;
  490. typedef Lockup<AddBlast, AddFlicker> AddLockup;
  491. typedef SimpleClash<AddLockup, clash_color> AddClash;
  492. return StylePtr<InOutHelperX<AddClash, InOutFuncX<out_millis, in_millis>> >();
  493. }
  494.  
  495. // Rainbow blade.
  496. // Arguments: color, clash color, turn-on/off time
  497. template<int out_millis,
  498. int in_millis,
  499. class clash_color = WHITE,
  500. class lockup_flicker_color = WHITE>
  501. StyleAllocator StyleRainbowPtr() {
  502. typedef AudioFlicker<Rainbow, lockup_flicker_color> AddFlicker;
  503. typedef Lockup<Rainbow, AddFlicker> AddLockup;
  504. typedef SimpleClash<AddLockup, clash_color> AddClash;
  505. return StylePtr<InOutHelper<AddClash, out_millis, in_millis> >();
  506. }
  507.  
  508. // Rainbow blade.
  509. // Arguments: color, clash color, turn-on/off time
  510. template<class out_millis,
  511. class in_millis,
  512. class clash_color = WHITE,
  513. class lockup_flicker_color = WHITE>
  514. StyleAllocator StyleRainbowPtrX() {
  515. typedef AudioFlicker<Rainbow, lockup_flicker_color> AddFlicker;
  516. typedef Lockup<Rainbow, AddFlicker> AddLockup;
  517. typedef SimpleClash<AddLockup, clash_color> AddClash;
  518. return StylePtr<InOutHelperX<AddClash, InOutFuncX<out_millis, in_millis>> >();
  519. }
  520.  
  521. // Stroboscope, flickers the blade at the desired frequency.
  522. // Arguments: color, clash color, turn-on/off time
  523. template<class strobe_color,
  524. class clash_color,
  525. int frequency,
  526. int out_millis,
  527. int in_millis>
  528. StyleAllocator StyleStrobePtr() {
  529. typedef Strobe<BLACK, strobe_color, frequency, 1> strobe;
  530. typedef Strobe<BLACK, strobe_color, 3* frequency, 1> fast_strobe;
  531. typedef Lockup<strobe, fast_strobe> AddLockup;
  532. typedef SimpleClash<AddLockup, clash_color> clash;
  533. return StylePtr<InOutHelper<clash, out_millis, in_millis> >();
  534. }
  535.  
  536. #include "styles/pov.h"
  537.  
  538. class NoLED;
  539.  
  540. #include "blades/power_pin.h"
  541. #include "blades/drive_logic.h"
  542. #include "blades/pwm_pin.h"
  543. #include "blades/ws2811_blade.h"
  544. #include "blades/fastled_blade.h"
  545. #include "blades/simple_blade.h"
  546. #include "blades/sub_blade.h"
  547. #include "blades/dim_blade.h"
  548. #include "blades/leds.h"
  549. #include "blades/blade_id.h"
  550. #include "common/preset.h"
  551. #include "common/blade_config.h"
  552. #include "common/current_preset.h"
  553. #include "styles/style_parser.h"
  554. #include "styles/length_finder.h"
  555.  
  556. BladeConfig* current_config = nullptr;
  557. class BladeBase* GetPrimaryBlade() {
  558. #if NUM_BLADES == 0
  559. return nullptr;
  560. #else
  561. return current_config->blade1;
  562. #endif
  563. }
  564. const char* GetSaveDir() {
  565. if (!current_config) return "";
  566. if (!current_config->save_dir) return "";
  567. return current_config->save_dir;
  568. }
  569.  
  570. ArgParserInterface* CurrentArgParser;
  571.  
  572. #define CONFIG_PRESETS
  573. #include CONFIG_FILE
  574. #undef CONFIG_PRESETS
  575.  
  576. #define CONFIG_PROP
  577. #include CONFIG_FILE
  578. #undef CONFIG_PROP
  579.  
  580. #ifndef PROP_TYPE
  581. #include "props/saber.h"
  582. #endif
  583.  
  584. PROP_TYPE prop;
  585.  
  586. #if 0
  587. #include "scripts/v3_test_script.h"
  588. #warning !!! V3 TEST SCRIPT ACTIVE !!!
  589. V3TestScript script;
  590. #endif
  591.  
  592. #if 0
  593. #include "scripts/proffieboard_test_script.h"
  594. #warning !!! PROFFIEBOARD TEST SCRIPT ACTIVE !!!
  595. V4TestScript script;
  596. Blinker1 blinker1;
  597. Blinker2 blinker2;
  598. CapTest captest;
  599. #endif
  600.  
  601. #include "buttons/floating_button.h"
  602. #include "buttons/latching_button.h"
  603. #include "buttons/button.h"
  604. #ifdef TEENSYDUINO
  605. #include "buttons/touchbutton.h"
  606. #else
  607. #include "buttons/stm32l4_touchbutton.h"
  608. #endif
  609.  
  610. #include "ir/ir.h"
  611. #include "ir/receiver.h"
  612. #include "ir/blaster.h"
  613. #include "ir/print.h"
  614. #include "ir/nec.h"
  615. #include "ir/rc6.h"
  616. #include "ir/stm32_ir.h"
  617.  
  618. #ifndef TEENSYDUINO
  619.  
  620. uint32_t startup_AHB1ENR;
  621. uint32_t startup_AHB2ENR;
  622. uint32_t startup_AHB3ENR;
  623. uint32_t startup_APB1ENR1;
  624. uint32_t startup_APB1ENR2;
  625. uint32_t startup_APB2ENR;
  626. uint32_t startup_MODER[4];
  627.  
  628. #endif
  629.  
  630. #define CONFIG_BUTTONS
  631. #include CONFIG_FILE
  632. #undef CONFIG_BUTTONS
  633.  
  634. #ifdef BLADE_DETECT_PIN
  635. LatchingButtonTemplate<FloatingButtonBase<BLADE_DETECT_PIN>>
  636. BladeDetect(BUTTON_BLADE_DETECT, BLADE_DETECT_PIN, "blade_detect");
  637. #endif
  638.  
  639. #include "common/sd_test.h"
  640.  
  641. class Commands : public CommandParser {
  642. public:
  643. enum PinType {
  644. PinTypeFloating,
  645. PinTypePulldown,
  646. PinTypeCap,
  647. PinTypeOther,
  648. };
  649.  
  650. bool TestPin(int pin, PinType t) {
  651. int ret = 0;
  652. pinMode(pin, OUTPUT);
  653. digitalWrite(pin, LOW);
  654. delayMicroseconds(20);
  655. ret <<= 1;
  656. ret |= digitalRead(pin);
  657.  
  658. digitalWrite(pin, HIGH);
  659. delayMicroseconds(20);
  660. ret <<= 1;
  661. ret |= digitalRead(pin);
  662.  
  663. // Discharge time
  664. pinMode(pin, INPUT_PULLDOWN);
  665. uint32_t start = micros();
  666. uint32_t end;
  667. while (digitalRead(pin)) {
  668. end = micros();
  669. if (end - start > 32768) break; // 32 millis
  670. }
  671. ret <<= 16;
  672. ret |= (end - start);
  673.  
  674. pinMode(pin, INPUT_PULLUP);
  675. delayMicroseconds(20);
  676. ret <<= 1;
  677. ret |= digitalRead(pin);
  678. pinMode(pin, INPUT);
  679.  
  680. return ret;
  681. }
  682. bool Parse(const char* cmd, const char* e) override {
  683. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  684. if (!strcmp(cmd, "help")) {
  685. CommandParser::DoHelp();
  686. return true;
  687. }
  688. #endif
  689.  
  690. #ifdef ENABLE_SERIALFLASH
  691. if (!strcmp(cmd, "ls")) {
  692. char tmp[128];
  693. SerialFlashChip::opendir();
  694. uint32_t size;
  695. while (SerialFlashChip::readdir(tmp, sizeof(tmp), size)) {
  696. STDOUT.print(tmp);
  697. STDOUT.print(" ");
  698. STDOUT.println(size);
  699. }
  700. STDOUT.println("Done listing files.");
  701. return true;
  702. }
  703. if (!strcmp(cmd, "rm")) {
  704. if (SerialFlashChip::remove(e)) {
  705. STDOUT.println("Removed.\n");
  706. } else {
  707. STDOUT.println("No such file.\n");
  708. }
  709. return true;
  710. }
  711. if (!strcmp(cmd, "format")) {
  712. STDOUT.print("Erasing ... ");
  713. SerialFlashChip::eraseAll();
  714. while (!SerialFlashChip::ready());
  715. STDOUT.println("Done");
  716. return true;
  717. }
  718. #endif
  719. #ifdef ENABLE_SD
  720.  
  721. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  722. if (!strcmp(cmd, "dir")) {
  723. LOCK_SD(true);
  724. if (!e || LSFS::Exists(e)) {
  725. for (LSFS::Iterator dir(e ? e : ""); dir; ++dir) {
  726. STDOUT.print(dir.name());
  727. STDOUT.print(" ");
  728. STDOUT.println(dir.size());
  729. }
  730. STDOUT.println("Done listing files.");
  731. } else {
  732. STDOUT.println("No such directory.");
  733. }
  734. LOCK_SD(false);
  735. return true;
  736. }
  737. #endif
  738.  
  739. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  740. if (!strcmp(cmd, "cat") && e) {
  741. LOCK_SD(true);
  742. File f = LSFS::Open(e);
  743. while (f.available()) {
  744. STDOUT.write(f.read());
  745. }
  746. f.close();
  747. LOCK_SD(false);
  748. return true;
  749. }
  750. #endif
  751.  
  752. if (!strcmp(cmd, "del") && e) {
  753. LOCK_SD(true);
  754. LSFS::Remove(e);
  755. LOCK_SD(false);
  756. return true;
  757. }
  758.  
  759. #ifdef ENABLE_DEVELOPER_COMMANDS
  760. if (!strcmp(cmd, "readalot")) {
  761. uint8_t tmp[10];
  762. LOCK_SD(true);
  763. File f = LSFS::Open(e);
  764. for (int i = 0; i < 10000; i++) {
  765. f.seek(0);
  766. f.read(tmp, 10);
  767. f.seek(1000);
  768. f.read(tmp, 10);
  769. }
  770. f.close();
  771. LOCK_SD(false);
  772. STDOUT.println("Done");
  773. return true;
  774. }
  775. #endif // ENABLE_DEVELOPER_COMMANDS
  776.  
  777. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  778. if (!strcmp(cmd, "sdtest")) {
  779. SDTestHelper sdtester;
  780. if (e && !strcmp(e, "all")) {
  781. sdtester.TestDir("");
  782. } else {
  783. sdtester.TestFont();
  784. }
  785. return true;
  786. }
  787. #endif
  788.  
  789. #endif // ENABLE_SD
  790.  
  791. #if defined(ENABLE_SD) && defined(ENABLE_SERIALFLASH)
  792. if (!strcmp(cmd, "cache")) {
  793. LOCK_SD(true);
  794. File f = LSFS::Open(e);
  795. if (!f) {
  796. STDOUT.println("File not found.");
  797. return true;
  798. }
  799. int bytes = f.size();
  800. if (!SerialFlashChip::create(e, bytes)) {
  801. STDOUT.println("Not enough space on serial flash chip.");
  802. return true;
  803. }
  804. SerialFlashFile o = SerialFlashChip::open(e);
  805. while (bytes) {
  806. char tmp[256];
  807. int b = f.read(tmp, min(bytes, (int)NELEM(tmp)));
  808. o.write(tmp, b);
  809. bytes -= b;
  810. }
  811. LOCK_SD(false);
  812. STDOUT.println("Cached!");
  813. return true;
  814. }
  815. #endif
  816. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  817. if (!strcmp(cmd, "effects")) {
  818. Effect::ShowAll();
  819. return true;
  820. }
  821. #endif
  822. #if 0
  823. if (!strcmp(cmd, "df")) {
  824. STDOUT.print(SerialFlashChip::capacity());
  825. STDOUT.println(" bytes available.");
  826. return true;
  827. }
  828. #endif
  829. #ifdef ENABLE_DEVELOPER_COMMANDS
  830. if (!strcmp(cmd, "high") && e) {
  831. pinMode(atoi(e), OUTPUT);
  832. digitalWrite(atoi(e), HIGH);
  833. STDOUT.println("Ok.");
  834. return true;
  835. }
  836. #endif // ENABLE_DEVELOPER_COMMANDS
  837. #ifdef ENABLE_DEVELOPER_COMMANDS
  838. if (!strcmp(cmd, "low") && e) {
  839. pinMode(atoi(e), OUTPUT);
  840. digitalWrite(atoi(e), LOW);
  841. STDOUT.println("Ok.");
  842. return true;
  843. }
  844. #endif // ENABLE_DEVELOPER_COMMANDS
  845.  
  846. #if VERSION_MAJOR >= 4
  847. if (!strcmp(cmd, "booster")) {
  848. if (!strcmp(e, "on")) {
  849. digitalWrite(boosterPin, HIGH);
  850. STDOUT.println("Booster on.");
  851. return true;
  852. }
  853. if (!strcmp(e, "off")) {
  854. digitalWrite(boosterPin, LOW);
  855. STDOUT.println("Booster off.");
  856. return true;
  857. }
  858. }
  859. #endif
  860. #ifdef ENABLE_AUDIO
  861. #if 0
  862. if (!strcmp(cmd, "ton")) {
  863. EnableAmplifier();
  864. dac.SetStream(&saber_synth);
  865. saber_synth.on_ = true;
  866. return true;
  867. }
  868. if (!strcmp(cmd, "tof")) {
  869. saber_synth.on_ = false;
  870. return true;
  871. }
  872. #endif
  873. #ifdef ENABLE_DEVELOPER_COMMANDS
  874. if (!strcmp(cmd, "dumpwav")) {
  875. int16_t tmp[32];
  876. wav_players[0].Stop();
  877. wav_players[0].read(tmp, NELEM(tmp));
  878. wav_players[0].Play(e);
  879. for (int j = 0; j < 64; j++) {
  880. int k = wav_players[0].read(tmp, NELEM(tmp));
  881. for (int i = 0; i < k; i++) {
  882. STDOUT.print(tmp[i]);
  883. STDOUT.print(" ");
  884. }
  885. STDOUT.println("");
  886. }
  887. wav_players[0].Stop();
  888. return true;
  889. }
  890. #endif // ENABLE_DEVELOPER_COMMANDS
  891. #endif
  892. #ifdef ENABLE_DEVELOPER_COMMANDS
  893. if (!strcmp(cmd, "twiddle")) {
  894. int pin = strtol(e, NULL, 0);
  895. STDOUT.print("twiddling ");
  896. STDOUT.println(pin);
  897. pinMode(pin, OUTPUT);
  898. for (int i = 0; i < 1000; i++) {
  899. digitalWrite(pin, HIGH);
  900. delay(10);
  901. digitalWrite(pin, LOW);
  902. delay(10);
  903. }
  904. STDOUT.println("done");
  905. return true;
  906. }
  907. #endif // ENABLE_DEVELOPER_COMMANDS
  908. #ifdef ENABLE_DEVELOPER_COMMANDS
  909. if (!strcmp(cmd, "twiddle2")) {
  910. int pin = strtol(e, NULL, 0);
  911. STDOUT.print("twiddling ");
  912. STDOUT.println(pin);
  913. pinMode(pin, OUTPUT);
  914. for (int i = 0; i < 1000; i++) {
  915. for (int i = 0; i < 500; i++) {
  916. digitalWrite(pin, HIGH);
  917. delayMicroseconds(1);
  918. digitalWrite(pin, LOW);
  919. delayMicroseconds(1);
  920. }
  921. delay(10);
  922. }
  923. STDOUT.println("done");
  924. return true;
  925. }
  926. #endif // ENABLE_DEVELOPER_COMMANDS
  927.  
  928. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  929. if (!strcmp(cmd, "malloc")) {
  930. STDOUT.print("alloced: ");
  931. STDOUT.println(mallinfo().uordblks);
  932. STDOUT.print("Free: ");
  933. STDOUT.println(mallinfo().fordblks);
  934. return true;
  935. }
  936. #endif
  937. if (!strcmp(cmd, "make_default_console")) {
  938. default_output = stdout_output;
  939. return true;
  940. }
  941. #if 0
  942. // Not finished yet
  943. if (!strcmp(cmd, "selftest")) {
  944. struct PinDefs { int8_t pin; PinType type; };
  945. static PinDefs pin_defs[] = {
  946. { bladePowerPin1, PinTypePulldown },
  947. { bladePowerPin2, PinTypePulldown },
  948. { bladePowerPin3, PinTypePulldown },
  949. { bladePowerPin4, PinTypePulldown },
  950. { bladePowerPin5, PinTypePulldown },
  951. { bladePowerPin6, PinTypePulldown },
  952. { bladePin, PinTypeOther },
  953. { blade2Pin, PinTypeFloating },
  954. { blade3Pin, PinTypeFloating },
  955. { blade4Pin, PinTypeFloating },
  956. { blade5Pin, PinTypeFloating },
  957. { amplifierPin, PinTypeFloating },
  958. { boosterPin, PinTypeFloating },
  959. { powerButtonPin, PinTypeFloating },
  960. { auxPin, PinTypeFloating },
  961. { aux2Pin, PinTypeFloating },
  962. { rxPin, PinTypeOther },
  963. { txPin, PinTypeFloating },
  964. };
  965. for (size_t test_index = 0; test_index < NELEM(pin_defs); test_index++) {
  966. int pin = pin_defs[test_index].pin;
  967. for (size_t i = 0; i < NELEM(pin_defs); i++)
  968. pinMode(pin_defs[i].pin, INPUT);
  969.  
  970. // test
  971. for (size_t i = 0; i < NELEM(pin_defs); i++) {
  972. pinMode(pin_defs[i].pin, OUTPUT);
  973. digitalWrite(pin_defs[i].pin, HIGH);
  974. // test
  975. digitalWrite(pin_defs[i].pin, LOW);
  976. // test
  977. pinMode(pin_defs[i].pin, INPUT);
  978. }
  979. }
  980. }
  981. #endif
  982.  
  983. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  984. if (!strcmp(cmd, "top")) {
  985. #ifdef TEENSYDUINO
  986. if (!(ARM_DWT_CTRL & ARM_DWT_CTRL_CYCCNTENA)) {
  987. ARM_DEMCR |= ARM_DEMCR_TRCENA;
  988. ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
  989. STDOUT.println("Cycle counting enabled, top will work next time.");
  990. return true;
  991. }
  992. #else
  993. if (!(DWT->CTRL & DWT_CTRL_CYCCNTENA_Msk)) {
  994. CoreDebug->DEMCR |= 1<<24; // DEMCR_TRCENA_Msk;
  995. DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
  996. STDOUT.println("Cycle counting enabled, top will work next time.");
  997. return true;
  998. }
  999. #endif
  1000.  
  1001. // TODO: list cpu usage for various objects.
  1002. float total_cycles =
  1003. (float)(audio_dma_interrupt_cycles +
  1004. pixel_dma_interrupt_cycles +
  1005. wav_interrupt_cycles +
  1006. Looper::CountCycles() +
  1007. CountProfileCycles());
  1008. STDOUT.print("Audio DMA: ");
  1009. STDOUT.print(audio_dma_interrupt_cycles * 100.0f / total_cycles);
  1010. STDOUT.println("%");
  1011. STDOUT.print("Wav reading: ");
  1012. STDOUT.print(wav_interrupt_cycles * 100.0f / total_cycles);
  1013. STDOUT.println("%");
  1014. STDOUT.print("Pixel DMA: ");
  1015. STDOUT.print(pixel_dma_interrupt_cycles * 100.0f / total_cycles);
  1016. STDOUT.println("%");
  1017. STDOUT.print("LOOP: ");
  1018. STDOUT.print(loop_cycles * 100.0f / total_cycles);
  1019. STDOUT.println("%");
  1020. STDOUT.print("Global loops / second: ");
  1021. global_loop_counter.Print();
  1022. STDOUT.println("");
  1023. SaberBase::DoTop(total_cycles);
  1024. Looper::LoopTop(total_cycles);
  1025. DumpProfileLocations(total_cycles);
  1026. noInterrupts();
  1027. audio_dma_interrupt_cycles = 0;
  1028. pixel_dma_interrupt_cycles = 0;
  1029. wav_interrupt_cycles = 0;
  1030. interrupts();
  1031. return true;
  1032. }
  1033. #endif
  1034.  
  1035. if (!strcmp(cmd, "version")) {
  1036. STDOUT.println(version);
  1037. STDOUT.print("Installed: ");
  1038. STDOUT.println(install_time);
  1039. return true;
  1040. }
  1041. if (!strcmp(cmd, "reset")) {
  1042. #ifdef TEENSYDUINO
  1043. SCB_AIRCR = 0x05FA0004;
  1044. #else
  1045. STM32.reset();
  1046. #endif
  1047. STDOUT.println("Reset failed.");
  1048. return true;
  1049. }
  1050. #ifndef TEENSYDUINO
  1051. if (!strcmp(cmd, "shutdown")) {
  1052. STDOUT.println("Sleeping 10 seconds.\n");
  1053. STM32.stop(100000);
  1054. return true;
  1055. }
  1056. if (!strcmp(cmd, "RebootDFU")) {
  1057. stm32l4_system_dfu();
  1058. return true;
  1059. }
  1060. #ifdef ENABLE_DEVELOPER_COMMANDS
  1061. if (!strcmp(cmd, "stm32info")) {
  1062. STDOUT.print("VBAT: ");
  1063. STDOUT.println(STM32.getVBAT());
  1064. STDOUT.print("VREF: ");
  1065. STDOUT.println(STM32.getVREF());
  1066. STDOUT.print("TEMP: ");
  1067. STDOUT.println(STM32.getTemperature());
  1068. return true;
  1069. }
  1070. #endif // ENABLE_DEVELOPER_COMMANDS
  1071. #ifdef ENABLE_DEVELOPER_COMMANDS
  1072. if (!strcmp(cmd, "portstates")) {
  1073. GPIO_TypeDef *GPIO;
  1074. for (int i = 0; i < 4; i++) {
  1075. switch (i) {
  1076. case 0:
  1077. GPIO = (GPIO_TypeDef *)GPIOA_BASE;
  1078. STDOUT.print("PORTA: ");
  1079. break;
  1080. case 1:
  1081. GPIO = (GPIO_TypeDef *)GPIOB_BASE;
  1082. STDOUT.print("PORTB: ");
  1083. break;
  1084. case 2:
  1085. GPIO = (GPIO_TypeDef *)GPIOC_BASE;
  1086. STDOUT.print("PORTC: ");
  1087. break;
  1088. case 3:
  1089. GPIO = (GPIO_TypeDef *)GPIOH_BASE;
  1090. STDOUT.print("PORTH: ");
  1091. break;
  1092. }
  1093. for (int j = 15; j >= 0; j--) {
  1094. uint32_t now = (GPIO->MODER >> (j * 2)) & 3;
  1095. uint32_t saved = (startup_MODER[i] >> (j * 2)) & 3;
  1096. STDOUT.print((now == saved ? "ioga" : "IOGA")[now]);
  1097. if (!(j & 3)) STDOUT.print(" ");
  1098. }
  1099. STDOUT.print(" ");
  1100. for (int j = 15; j >= 0; j--) {
  1101. uint32_t now = (GPIO->PUPDR >> (j * 2)) & 3;
  1102. STDOUT.print("-ud?"[now]);
  1103. if (!(j & 3)) STDOUT.print(" ");
  1104. }
  1105. STDOUT.print(" ");
  1106. for (int j = 15; j >= 0; j--) {
  1107. uint32_t now = ((GPIO->IDR >> j) & 1) | (((GPIO->ODR >> j) & 1) << 1);
  1108. STDOUT.print("lhLH"[now]);
  1109. if (!(j & 3)) STDOUT.print(" ");
  1110. }
  1111. STDOUT.println("");
  1112. }
  1113. return true;
  1114. }
  1115. #endif // ENABLE_DEVELOPER_COMMANDS
  1116. #ifdef ENABLE_DEVELOPER_COMMANDS
  1117. if (!strcmp(cmd, "CLK")) {
  1118. if (e) {
  1119. uint32_t c = atoi(e) * 1000000;
  1120. stm32l4_system_sysclk_configure(c, c/2, c/2);
  1121. }
  1122. STDOUT.print("Clocks: hse=");
  1123. STDOUT.print(stm32l4_system_hseclk());
  1124. STDOUT.print(" lse=");
  1125. STDOUT.print(stm32l4_system_lseclk());
  1126. STDOUT.print(" sys=");
  1127. STDOUT.print(stm32l4_system_sysclk());
  1128. STDOUT.print(" f=");
  1129. STDOUT.print(stm32l4_system_fclk());
  1130. STDOUT.print(" h=");
  1131. STDOUT.print(stm32l4_system_hclk());
  1132. STDOUT.print(" p1=");
  1133. STDOUT.print(stm32l4_system_pclk1());
  1134. STDOUT.print(" p2=");
  1135. STDOUT.print(stm32l4_system_pclk2());
  1136. STDOUT.print(" sai=");
  1137. STDOUT.println(stm32l4_system_saiclk());
  1138. return true;
  1139. }
  1140. #endif // ENABLE_DEVELOPER_COMMANDS
  1141. #ifdef ENABLE_DEVELOPER_COMMANDS
  1142. if (!strcmp(cmd, "whatispowered")) {
  1143. STDOUT.print("ON: ");
  1144. #define PRINTIFON(REG, BIT) do { \
  1145. if (RCC->REG & RCC_##REG##_##BIT##EN) { \
  1146. STDOUT.print(" " #BIT); \
  1147. if (!(startup_##REG & RCC_##REG##_##BIT##EN)) STDOUT.print("+"); \
  1148. } \
  1149. } while(0)
  1150.  
  1151. PRINTIFON(AHB1ENR,FLASH);
  1152. PRINTIFON(AHB1ENR,DMA1);
  1153. PRINTIFON(AHB1ENR,DMA2);
  1154. PRINTIFON(AHB2ENR,GPIOA);
  1155. PRINTIFON(AHB2ENR,GPIOB);
  1156. #if defined(STM32L433xx) || defined(STM32L476xx) || defined(STM32L496xx)
  1157. PRINTIFON(AHB2ENR,GPIOC);
  1158. PRINTIFON(AHB2ENR,GPIOD);
  1159. PRINTIFON(AHB2ENR,GPIOE);
  1160. #endif
  1161. #if defined(STM32L476xx) || defined(STM32L496xx)
  1162. PRINTIFON(AHB2ENR,GPIOF);
  1163. PRINTIFON(AHB2ENR,GPIOG);
  1164. #endif
  1165. PRINTIFON(AHB2ENR,GPIOH);
  1166. #if defined(STM32L496xx)
  1167. PRINTIFON(AHB2ENR,GPIOI);
  1168. #endif
  1169. PRINTIFON(AHB2ENR,ADC);
  1170. PRINTIFON(APB1ENR1,DAC1);
  1171. #if defined(STM32L476xx) || defined(STM32L496xx)
  1172. PRINTIFON(AHB2ENR,OTGFS);
  1173. #else
  1174. PRINTIFON(APB1ENR1,USBFS);
  1175. #endif
  1176. PRINTIFON(APB2ENR,USART1);
  1177. PRINTIFON(APB1ENR1,USART2);
  1178. #if defined(STM32L433xx) || defined(STM32L476xx) || defined(STM32L496xx)
  1179. PRINTIFON(APB1ENR1,USART3);
  1180. #endif
  1181. #if defined(STM32L476xx) || defined(STM32L496xx)
  1182. PRINTIFON(APB1ENR1,UART4);
  1183. PRINTIFON(APB1ENR1,UART5);
  1184. #endif
  1185. PRINTIFON(APB1ENR2,LPUART1);
  1186. PRINTIFON(APB1ENR1,I2C1);
  1187. #if defined(STM32L433xx) || defined(STM32L476xx) || defined(STM32L496xx)
  1188. PRINTIFON(APB1ENR1,I2C2);
  1189. #endif
  1190. PRINTIFON(APB1ENR1,I2C3);
  1191. #if defined(STM32L496xx)
  1192. PRINTIFON(APB1ENR2,I2C4);
  1193. #endif
  1194. PRINTIFON(APB2ENR,SPI1);
  1195. #if defined(STM32L433xx) || defined(STM32L476xx) || defined(STM32L496xx)
  1196. PRINTIFON(APB1ENR1,SPI2);
  1197. #endif
  1198. PRINTIFON(APB1ENR1,SPI3);
  1199. PRINTIFON(APB1ENR1,CAN1);
  1200. #if defined(STM32L496xx)
  1201. PRINTIFON(APB1ENR1,CAN2);
  1202. #endif
  1203. PRINTIFON(AHB3ENR,QSPI);
  1204. #if defined(STM32L433xx) || defined(STM32L476xx) || defined(STM32L496xx)
  1205. PRINTIFON(APB2ENR,SDMMC1);
  1206. #endif
  1207. PRINTIFON(APB2ENR,SAI1);
  1208. #if defined(STM32L476xx) || defined(STM32L496xx)
  1209. PRINTIFON(APB2ENR,SAI2);
  1210. PRINTIFON(APB2ENR,DFSDM1);
  1211. #endif
  1212. PRINTIFON(APB2ENR,TIM1);
  1213. PRINTIFON(APB1ENR1,TIM2);
  1214. #if defined(STM32L476xx) || defined(STM32L496xx)
  1215. PRINTIFON(APB1ENR1,TIM3);
  1216. PRINTIFON(APB1ENR1,TIM4);
  1217. PRINTIFON(APB1ENR1,TIM5);
  1218. #endif
  1219. PRINTIFON(APB1ENR1,TIM6);
  1220. PRINTIFON(APB1ENR1,TIM7);
  1221. #if defined(STM32L476xx) || defined(STM32L496xx)
  1222. PRINTIFON(APB2ENR,TIM8);
  1223. #endif
  1224. PRINTIFON(APB2ENR,TIM15);
  1225. PRINTIFON(APB2ENR,TIM16);
  1226. #if defined(STM32L476xx) || defined(STM32L496xx)
  1227. PRINTIFON(APB2ENR,TIM17);
  1228. #endif
  1229. PRINTIFON(APB1ENR1,LPTIM1);
  1230. PRINTIFON(APB1ENR2,LPTIM2);
  1231.  
  1232. // Not sure what CPUs implement these
  1233. PRINTIFON(AHB1ENR, CRC);
  1234. PRINTIFON(AHB1ENR, TSC);
  1235. PRINTIFON(AHB2ENR, RNG);
  1236. PRINTIFON(APB1ENR1, LCD);
  1237. PRINTIFON(APB1ENR1, RTCAPB);
  1238. PRINTIFON(APB1ENR1, WWDG);
  1239. PRINTIFON(APB1ENR1, CRS);
  1240. PRINTIFON(APB1ENR1, CAN1);
  1241. PRINTIFON(APB1ENR1, PWR);
  1242. PRINTIFON(APB1ENR1, OPAMP);
  1243. PRINTIFON(APB1ENR2, SWPMI1);
  1244. PRINTIFON(APB2ENR, SYSCFG);
  1245. PRINTIFON(APB2ENR, FW);
  1246.  
  1247. STDOUT.println("");
  1248. STDOUT.print("VBUS: ");
  1249. STDOUT.println(stm32l4_gpio_pin_read(GPIO_PIN_PB2));
  1250. STDOUT.print("USBD connected: ");
  1251. STDOUT.println(USBD_Connected());
  1252. return true;
  1253. }
  1254. #endif // ENABLE_DEVELOPER_COMMANDS
  1255.  
  1256. #ifdef ENABLE_DEVELOPER_COMMANDS
  1257. #ifdef HAVE_STM32L4_DMA_GET
  1258. if (!strcmp(cmd, "dmamap")) {
  1259. for (int channel = 0; channel < 16; channel++) {
  1260. stm32l4_dma_t *dma = stm32l4_dma_get(channel);
  1261. if (dma) {
  1262. STDOUT.print(" DMA");
  1263. STDOUT.print( 1 +(channel / 8) );
  1264. STDOUT.print("_CH");
  1265. STDOUT.print( channel % 8 );
  1266. STDOUT.print(" = ");
  1267. STDOUT.println(dma->channel >> 4, HEX);
  1268. }
  1269. }
  1270. return true;
  1271. }
  1272. #endif // HAVE_STM32L4_DMA_GET
  1273. #endif // ENABLE_DEVELOPER_COMMANDS
  1274.  
  1275. #endif // TEENSYDUINO
  1276.  
  1277. return false;
  1278. }
  1279.  
  1280. void Help() override {
  1281. STDOUT.println(" version - show software version");
  1282. STDOUT.println(" reset - restart software");
  1283. #ifndef DISABLE_DIAGNOSTIC_COMMANDS
  1284. STDOUT.println(" effects - list current effects");
  1285. #endif
  1286. #ifdef ENABLE_SERIALFLASH
  1287. STDOUT.println("Serial Flash memory management:");
  1288. STDOUT.println(" ls, rm <file>, format, play <file>, effects");
  1289. STDOUT.println("To upload files: tar cf - files | uuencode x >/dev/ttyACM0");
  1290. #endif
  1291. #if defined(ENABLE_SD) && !defined(DISABLE_DIAGNOSTIC_COMMANDS)
  1292. STDOUT.println(" dir [directory] - list files on SD card.");
  1293. STDOUT.println(" sdtest - benchmark SD card");
  1294. #endif
  1295. }
  1296. };
  1297.  
  1298. StaticWrapper<Commands> commands;
  1299.  
  1300. class SerialAdapter {
  1301. public:
  1302. static void begin() {
  1303. // Already configured in Setup().
  1304. // Serial.begin(115200);
  1305. }
  1306. static bool Connected() { return !!Serial; }
  1307. static bool AlwaysConnected() { return false; }
  1308. static Stream& stream() { return Serial; }
  1309. static const char* response_header() { return ""; }
  1310. static const char* response_footer() { return ""; }
  1311. };
  1312.  
  1313. class Serial3Adapter {
  1314. public:
  1315. static void begin() { Serial3.begin(115200); }
  1316. static bool Connected() { return true; }
  1317. static bool AlwaysConnected() { return true; }
  1318. static Stream& stream() { return Serial3; }
  1319. static const char* response_header() { return "-+=BEGIN_OUTPUT=+-\n"; }
  1320. static const char* response_footer() { return "-+=END_OUTPUT=+-\n"; }
  1321. };
  1322.  
  1323. #ifdef USB_CLASS_WEBUSB
  1324. class WebUSBSerialAdapter {
  1325. public:
  1326. static void begin() { WebUSBSerial.begin(115200); }
  1327. // static bool Connected() { return !!WebUSBSerial; }
  1328. static bool Connected() { return true; }
  1329. static bool AlwaysConnected() { return true; }
  1330. static Stream& stream() { return WebUSBSerial; }
  1331. static const char* response_header() { return "-+=BEGIN_OUTPUT=+-\n"; }
  1332. static const char* response_footer() { return "-+=END_OUTPUT=+-\n"; }
  1333. };
  1334. #endif
  1335.  
  1336. #ifdef RFID_SERIAL
  1337. class RFIDParser : public Looper {
  1338. public:
  1339. RFIDParser() : Looper() {}
  1340. const char* name() override { return "Parser"; }
  1341. void Setup() override {
  1342. RFID_SERIAL.begin(9600);
  1343. }
  1344.  
  1345. #define RFID_READCHAR() do { \
  1346. state_machine_.sleep_until_ = millis(); \
  1347. while (!RFID_SERIAL.available()) { \
  1348. if (millis() - state_machine_.sleep_until_ > 200) goto retry; \
  1349. YIELD(); \
  1350. } \
  1351. getc(); \
  1352. } while (0)
  1353.  
  1354. int c, x;
  1355. uint64_t code;
  1356.  
  1357. void getc() {
  1358. c = RFID_SERIAL.read();
  1359. if (monitor.IsMonitoring(Monitoring::MonitorSerial)) {
  1360. default_output->print("SER: ");
  1361. default_output->println(c, HEX);
  1362. }
  1363. }
  1364.  
  1365. void Loop() override {
  1366. STATE_MACHINE_BEGIN();
  1367. while (true) {
  1368. retry:
  1369. RFID_READCHAR();
  1370. if (c != 2) goto retry;
  1371. code = 0;
  1372. for (x = 0; x < 10; x++) {
  1373. RFID_READCHAR();
  1374. code <<= 4;
  1375. if (c >= '0' && c <= '9') {
  1376. code |= c - '0';
  1377. } else if (c >= 'A' && c <= 'F') {
  1378. code |= c - ('A' - 10);
  1379. } else {
  1380. goto retry;
  1381. }
  1382. }
  1383. RFID_READCHAR();
  1384. x = code ^ (code >> 24);
  1385. x ^= (x >> 8) ^ (x >> 16);
  1386. x &= 0xff;
  1387. if (c != x) goto retry;
  1388. RFID_READCHAR();
  1389. if (c == 3) {
  1390. default_output->print("RFID: ");
  1391. for (int i = 36; i >= 0; i-=4) {
  1392. default_output->print((int)((code >> i) & 0xf), HEX);
  1393. }
  1394. default_output->println("");
  1395. for (size_t i = 0; i < NELEM(RFID_Commands); i++) {
  1396. if (code == RFID_Commands[i].id) {
  1397. CommandParser::DoParse(RFID_Commands[i].cmd, RFID_Commands[i].arg);
  1398. }
  1399. }
  1400. }
  1401. }
  1402. STATE_MACHINE_END();
  1403. }
  1404.  
  1405. private:
  1406. StateMachineState state_machine_;
  1407. };
  1408.  
  1409. StaticWrapper<RFIDParser> rfid_parser;
  1410. #endif
  1411.  
  1412. // Command-line parser. Easiest way to use it is to start the arduino
  1413. // serial monitor.
  1414. template<class SA> /* SA = Serial Adapter */
  1415. class Parser : Looper, StateMachine {
  1416. public:
  1417. Parser() : Looper() {}
  1418. const char* name() override { return "Parser"; }
  1419.  
  1420. void Setup() override {
  1421. SA::begin();
  1422. }
  1423.  
  1424. void Loop() override {
  1425. STATE_MACHINE_BEGIN();
  1426. while (true) {
  1427. while (!SA::Connected()) YIELD();
  1428. if (!SA::AlwaysConnected()) {
  1429. STDOUT.println("Welcome to ProffieOS, type 'help' for more info.");
  1430. }
  1431.  
  1432. while (SA::Connected()) {
  1433. while (!SA::stream().available()) YIELD();
  1434. int c = SA::stream().read();
  1435. if (c < 0) { break; }
  1436. #if 0
  1437. STDOUT.print("GOT:");
  1438. STDOUT.println(c);
  1439. #endif
  1440. #if 0
  1441. if (monitor.IsMonitoring(Monitoring::MonitorSerial) &&
  1442. default_output != &SA::stream()) {
  1443. default_output->print("SER: ");
  1444. default_output->println(c, HEX);
  1445. }
  1446. #endif
  1447. if (c == '\n' || c == '\r') {
  1448. if (cmd_) ParseLine();
  1449. len_ = 0;
  1450. space_ = 0;
  1451. free(cmd_);
  1452. cmd_ = nullptr;
  1453. continue;
  1454. }
  1455. if (len_ + 1 >= space_) {
  1456. int new_space = space_ * 3 / 2 + 8;
  1457. char* tmp = (char*)realloc(cmd_, new_space);
  1458. if (tmp) {
  1459. space_ = new_space;
  1460. cmd_ = tmp;
  1461. } else {
  1462. STDOUT.println("Line too long.");
  1463. len_ = 0;
  1464. space_ = 0;
  1465. free(cmd_);
  1466. cmd_ = nullptr;
  1467. continue;
  1468. }
  1469. }
  1470. cmd_[len_] = c;
  1471. cmd_[len_ + 1] = 0;
  1472. len_++;
  1473. }
  1474. len_ = 0;
  1475. space_ = 0;
  1476. free(cmd_);
  1477. cmd_ = nullptr;
  1478. }
  1479. STATE_MACHINE_END();
  1480. }
  1481.  
  1482. void ParseLine() {
  1483. if (len_ == 0) return;
  1484. while (len_ > 0 && (cmd_[len_-1] == '\r' || cmd_[len_-1] == ' ')) {
  1485. len_--;
  1486. cmd_[len_] = 0;
  1487. }
  1488. if (cmd_[0] == '#') {
  1489. Serial.println(cmd_);
  1490. return;
  1491. }
  1492. stdout_output = &SA::stream();
  1493. STDOUT.print(SA::response_header());
  1494. char *cmd = cmd_;
  1495. while (*cmd == ' ') cmd++;
  1496. char *e = cmd;
  1497. while (*e != ' ' && *e) e++;
  1498. if (*e) {
  1499. *e = 0;
  1500. e++; // e is now argument (if any)
  1501. } else {
  1502. e = nullptr;
  1503. }
  1504. if (monitor.IsMonitoring(Monitoring::MonitorSerial) &&
  1505. default_output != &SA::stream()) {
  1506. default_output->print("Received command: ");
  1507. default_output->print(cmd);
  1508. if (e) {
  1509. default_output->print(" arg: ");
  1510. default_output->print(e);
  1511. }
  1512. default_output->print(" HEX ");
  1513. for (size_t i = 0; i < strlen(cmd); i++) {
  1514. default_output->print(cmd[i], HEX);
  1515. default_output->print(" ");
  1516. }
  1517. default_output->println("");
  1518. }
  1519. if (!CommandParser::DoParse(cmd, e)) {
  1520. STDOUT.print("Whut? :");
  1521. STDOUT.println(cmd);
  1522. }
  1523. STDOUT.print(SA::response_footer());
  1524. stdout_output = default_output;
  1525. }
  1526.  
  1527. private:
  1528. int len_ = 0;
  1529. char* cmd_ = nullptr;
  1530. int space_ = 0;
  1531. };
  1532.  
  1533. StaticWrapper<Parser<SerialAdapter>> parser;
  1534.  
  1535. #ifdef ENABLE_SERIAL
  1536. StaticWrapper<Parser<Serial3Adapter>> serial_parser;
  1537. #define ENABLE_SERIAL_COMMANDS
  1538. #endif
  1539.  
  1540. #ifdef USB_CLASS_WEBUSB
  1541. StaticWrapper<Parser<WebUSBSerialAdapter>> webusb_parser;
  1542. #endif
  1543.  
  1544. #ifdef ENABLE_SERIAL_COMMANDS
  1545. class SerialCommands : public CommandParser {
  1546. public:
  1547. void HM1XCmd(const char* cmd) {
  1548. STDOUT.print("Sending: ");
  1549. STDOUT.println(cmd);
  1550. STDOUT.print("Reply: ");
  1551. Serial3.print(cmd);
  1552. uint32_t last_char = millis();
  1553. uint32_t timeout = 300;
  1554. while (millis() - last_char < timeout) {
  1555. if (Serial3.available()) {
  1556. last_char = millis();
  1557. timeout = 100;
  1558. STDOUT.write(Serial3.read());
  1559. }
  1560. }
  1561. STDOUT.println("");
  1562. }
  1563. bool Parse(const char* cmd, const char* e) override {
  1564. #if 0
  1565. if (!strcmp(cmd, "hm1Xpin")) {
  1566. // Doesn't work, pine is 4 chars, pinb is 6
  1567. HM1XCmd("AT+AUTH1");
  1568. HM1XCmd("AT+DUAL1");
  1569. Serial3.write("AT+PINE");
  1570. Serial3.println(e);
  1571. Serial3.write("AT+PINB");
  1572. Serial3.println(e);
  1573. return true;
  1574. }
  1575. if (!strcmp(cmd, "hm1Xname")) {
  1576. Serial3.write("AT+NAME");
  1577. Serial3.println(e);
  1578. Serial3.write("AT+NAMB");
  1579. Serial3.println(e);
  1580. return true;
  1581. }
  1582. #endif
  1583. if (cmd[0] == 'A' && cmd[1] == 'T') {
  1584. HM1XCmd(cmd);
  1585. return true;
  1586. }
  1587. if (!strcmp(cmd, "send") && e) {
  1588. Serial3.println(e);
  1589. STDOUT.print("Wrote: ");
  1590. STDOUT.println(e);
  1591. return true;
  1592. }
  1593. #ifdef BLE_PASSWORD
  1594. if (!strcmp(cmd, "get_ble_config")) {
  1595. PrintQuotedValue("password", BLE_PASSWORD);
  1596. #ifndef BLE_NAME
  1597. #define BLE_NAME "ProffieOS"
  1598. #endif
  1599. PrintQuotedValue("name", BLE_NAME);
  1600. #ifdef BLE_SHORTNAME
  1601. PrintQuotedValue("shortname", BLE_SHORTNAME);
  1602. #else
  1603. if (sizeof(BLE_NAME) - sizeof("") <= 8) {
  1604. PrintQuotedValue("shortname", BLE_NAME);
  1605. } else {
  1606. PrintQuotedValue("shortname", "Saber");
  1607. }
  1608. #endif
  1609. return true;
  1610. }
  1611. #endif
  1612. return false;
  1613. }
  1614. void Help() override {
  1615. // STDOUT.println(" hm13pin PIN - configure HM13 PIN");
  1616. // STDOUT.println(" hm13name NAME - configure HM13 NAME");
  1617. STDOUT.println(" get_ble_config - show BLE PIN");
  1618. if (default_output != stdout_output)
  1619. STDOUT.println(" make_default_console - make this connection the default connection");
  1620. }
  1621. };
  1622.  
  1623. StaticWrapper<SerialCommands> serial_commands;
  1624.  
  1625. #endif
  1626.  
  1627.  
  1628. #if defined(ENABLE_MOTION) || defined(ENABLE_SSD1306)
  1629. #include "common/i2cdevice.h"
  1630. I2CBus i2cbus;
  1631. #endif
  1632.  
  1633. #ifdef ENABLE_SSD1306
  1634. #include "display/ssd1306.h"
  1635. SSD1306 display;
  1636. #endif
  1637.  
  1638. #ifdef ENABLE_MOTION
  1639.  
  1640. #include "motion/motion_util.h"
  1641. #include "motion/mpu6050.h"
  1642. #include "motion/lsm6ds3h.h"
  1643. #include "motion/fxos8700.h"
  1644. #include "motion/fxas21002.h"
  1645.  
  1646. // Define this to record clashes to sd card as CSV files
  1647. // #define CLASH_RECORDER
  1648.  
  1649. #include "scripts/clash_recorder.h"
  1650.  
  1651. #ifdef GYRO_CLASS
  1652. // Can also be gyro+accel.
  1653. StaticWrapper<GYRO_CLASS> gyroscope;
  1654. #endif
  1655.  
  1656. #ifdef ACCEL_CLASS
  1657. StaticWrapper<ACCEL_CLASS> accelerometer;
  1658. #endif
  1659.  
  1660. #endif // ENABLE_MOTION
  1661.  
  1662. #include "sound/amplifier.h"
  1663. #include "common/sd_card.h"
  1664. #include "common/booster.h"
  1665.  
  1666. void setup() {
  1667. #if VERSION_MAJOR >= 4
  1668. #define SAVE_RCC(X) startup_##X = RCC->X
  1669. SAVE_RCC(AHB1ENR);
  1670. SAVE_RCC(AHB2ENR);
  1671. SAVE_RCC(AHB3ENR);
  1672. SAVE_RCC(APB1ENR1);
  1673. SAVE_RCC(APB1ENR2);
  1674. SAVE_RCC(APB2ENR);
  1675. #define SAVE_MODER(PORT, X) startup_MODER[X] = ((GPIO_TypeDef *)GPIO##PORT##_BASE)->MODER
  1676. SAVE_MODER(A, 0);
  1677. SAVE_MODER(B, 1);
  1678. SAVE_MODER(C, 2);
  1679. SAVE_MODER(H, 3);
  1680.  
  1681. // TODO enable/disable as needed
  1682. pinMode(boosterPin, OUTPUT);
  1683. digitalWrite(boosterPin, HIGH);
  1684. #endif
  1685.  
  1686. Serial.begin(9600);
  1687. #if VERSION_MAJOR >= 4
  1688. // TODO: Figure out if we need this.
  1689. // Serial.blockOnOverrun(false);
  1690. #endif
  1691.  
  1692. // Wait for all voltages to settle.
  1693. // Accumulate some entrypy while we wait.
  1694. uint32_t now = millis();
  1695. #ifdef DOSFS_CONFIG_STARTUP_DELAY
  1696. #define PROFFIEOS_SD_STARTUP_DELAY DOSFS_CONFIG_STARTUP_DELAY
  1697. #else
  1698. #define PROFFIEOS_SD_STARTUP_DELAY 1000
  1699. #endif
  1700.  
  1701. #ifndef CONFIG_STARTUP_DELAY
  1702. #define CONFIG_STARTUP_DELAY 0
  1703. #endif
  1704.  
  1705. #if PROFFIEOS_SD_STARTUP_DELAY > CONFIG_STARTUP_DELAY
  1706. #define PROFFIEOS_STARTUP_DELAY PROFFIEOS_SD_STARTUP_DELAY
  1707. #else
  1708. #define PROFFIEOS_STARTUP_DELAY CONFIG_STARTUP_DELAY
  1709. #endif
  1710.  
  1711. while (millis() - now < PROFFIEOS_STARTUP_DELAY) {
  1712. #ifndef NO_BATTERY_MONITOR
  1713. srand((rand() * 917823) ^ LSAnalogRead(batteryLevelPin));
  1714. #endif
  1715.  
  1716. #ifdef BLADE_DETECT_PIN
  1717. // Figure out if blade is connected or not.
  1718. // Note that if PROFFIEOS_STARTUP_DELAY is smaller than
  1719. // the settle time for BladeDetect, this won't work properly.
  1720. BladeDetect.Warmup();
  1721. #endif
  1722. }
  1723.  
  1724. #ifdef ENABLE_SERIALFLASH
  1725. SerialFlashChip::begin(serialFlashSelectPin);
  1726. #endif
  1727. #ifdef ENABLE_SD
  1728. bool sd_card_found = LSFS::Begin();
  1729. if (!sd_card_found) {
  1730. if (sdCardSelectPin >= 0 && sdCardSelectPin < 255) {
  1731. STDOUT.println("No sdcard found.");
  1732. pinMode(sdCardSelectPin, OUTPUT);
  1733. digitalWrite(sdCardSelectPin, 0);
  1734. delayMicroseconds(2);
  1735. pinMode(sdCardSelectPin, INPUT);
  1736. delayMicroseconds(2);
  1737. if (digitalRead(sdCardSelectPin) != HIGH) {
  1738. STDOUT.println("SD select not pulled high!");
  1739. }
  1740. }
  1741. #if VERSION_MAJOR >= 4
  1742. stm32l4_gpio_pin_configure(GPIO_PIN_PA5, (GPIO_PUPD_PULLUP | GPIO_OSPEED_HIGH | GPIO_MODE_INPUT));
  1743. delayMicroseconds(10);
  1744. if (!stm32l4_gpio_pin_read(GPIO_PIN_PA5)) {
  1745. STDOUT.println("SCK won't go high!");
  1746. }
  1747. stm32l4_gpio_pin_configure(GPIO_PIN_PA5, (GPIO_PUPD_PULLDOWN | GPIO_OSPEED_HIGH | GPIO_MODE_INPUT));
  1748. delayMicroseconds(10);
  1749. if (stm32l4_gpio_pin_read(GPIO_PIN_PA5)) {
  1750. STDOUT.println("SCK won't go low!");
  1751. }
  1752. #endif
  1753. } else {
  1754. STDOUT.println("Sdcard found..");
  1755. }
  1756. #endif
  1757.  
  1758. Looper::DoSetup();
  1759. // Time to identify the blade.
  1760. prop.FindBlade();
  1761. SaberBase::DoBoot();
  1762. #if defined(ENABLE_SD) && defined(ENABLE_AUDIO)
  1763. if (!sd_card_found) {
  1764. talkie.Say(talkie_sd_card_15, 15);
  1765. talkie.Say(talkie_not_found_15, 15);
  1766. }
  1767. #endif // ENABLE_AUDIO && ENABLE_SD
  1768. }
  1769.  
  1770. #ifdef MTP_RX_ENDPOINT
  1771.  
  1772. void mtp_yield() { Looper::DoLoop(); }
  1773. void mtp_lock_storage(bool lock) {
  1774. AudioStreamWork::LockSD(lock);
  1775. }
  1776.  
  1777. #include "mtp/mtpd.h"
  1778. MTPD mtpd;
  1779.  
  1780. #ifdef ENABLE_SD
  1781. #include "mtp/mtp_storage_sd.h"
  1782. MTPStorage_SD sd_storage(&mtpd);
  1783. #endif
  1784.  
  1785. #ifdef ENABLE_SERIALFLASH
  1786. #include "mtp/mtp_storage_serialflash.h"
  1787. MTPStorage_SerialFlash serialflash_storage(&mtpd);
  1788. #endif
  1789.  
  1790. #endif // MTP_RX_ENDPOINT
  1791.  
  1792. #include "common/clock_control.h"
  1793.  
  1794. void loop() {
  1795. #ifdef MTP_RX_ENDPOINT
  1796. mtpd.loop();
  1797. #endif
  1798. Looper::DoLoop();
  1799. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement