Advertisement
Guest User

badge c 27

a guest
Aug 8th, 2019
2,892
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 95.81 KB | None | 0 0
  1. /*
  2.  
  3. DEFCON 27 Official Badge (2019)
  4.  
  5. Author: Joe Grand, Grand Idea Studio [@joegrand] aka Kingpin
  6.  
  7. Program Description:
  8.  
  9. This program contains the firmware for the DEFCON 27 official badge.
  10.  
  11. Complete design documentation can be found at:
  12. http://www.grandideastudio.com/portfolio/defcon-27-badge
  13.  
  14. */
  15.  
  16. // Portions of this code are subject to the following license:
  17. /*
  18. * The Clear BSD License
  19. * Copyright 2016-2018 NXP Semiconductor, Inc.
  20. * All rights reserved.
  21. *
  22. * Redistribution and use in source and binary forms, with or without modification,
  23. * are permitted provided that the following conditions are met:
  24. *
  25. * o Redistributions of source code must retain the above copyright notice, this list
  26. * of conditions and the following disclaimer.
  27. *
  28. * o Redistributions in binary form must reproduce the above copyright notice, this
  29. * list of conditions and the following disclaimer in the documentation and/or
  30. * other materials provided with the distribution.
  31. *
  32. * o Neither the name of NXP Semiconductor, Inc. nor the names of its
  33. * contributors may be used to endorse or promote products derived from this
  34. * software without specific prior written permission.
  35. *
  36. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  37. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  38. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  40. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  41. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  43. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  44. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  45. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  46. */
  47.  
  48. /**
  49. * @file dc27_badge.c
  50. * @brief Application entry point.
  51. */
  52. #include <stdio.h>
  53. #include "board.h"
  54. #include "peripherals.h"
  55. #include "pin_mux.h"
  56. #include "clock_config.h"
  57. #include "MKL27Z644.h"
  58. #include "fsl_debug_console.h"
  59. #include "fsl_smc.h"
  60. #include "fsl_flash.h"
  61.  
  62. #include "LPBroadcast_NXH_DC27.eep.h" // Pre-compiled firmware blob for NXH2261 (loaded during power-up)
  63.  
  64.  
  65. /***************************************************************************
  66. **************************** Definitions **********************************
  67. ***************************************************************************/
  68.  
  69. #define __BADGE_TYPE HUMAN
  70. //#define __BADGE_TYPE GOON
  71. //#define __BADGE_TYPE SPEAKER
  72. //#define __BADGE_TYPE VENDOR
  73. //#define __BADGE_TYPE PRESS
  74. //#define __BADGE_TYPE VILLAGE
  75. //#define __BADGE_TYPE CONTEST
  76. //#define __BADGE_TYPE ARTIST
  77. //#define __BADGE_TYPE CFP
  78. //#define __BADGE_TYPE UBER
  79.  
  80. #undef __BADGE_MAGIC
  81. //#define __BADGE_MAGIC
  82.  
  83. #define LOW 0U
  84. #define HIGH 1U
  85.  
  86. // LED animation
  87. #define LED_HEARTBEAT_FADE_DELAY 6 // Time (ms) per brightness setting ramp up/down
  88. #define LED_HEARTBEAT_WAIT_DELAY 1000 // Time (ms) to sleep at LED maximum brightness
  89.  
  90. #define LED_SPARKLE_FADE_DELAY 2 // Time (ms) per brightness setting ramp up/down
  91. #define LED_SPARKLE_ON_DELAY 350 // Time (ms) to remain on at LED maximum brightness
  92. #define LED_SPARKLE_WAIT_DELAY 1500 // Time (ms) to sleep between LED updates
  93.  
  94. // Bit masks for badge quest flags
  95. #define FLAG_0_MASK 0x01 // Any Valid Communication
  96. #define FLAG_1_MASK 0x02 // Talk/Speaker
  97. #define FLAG_2_MASK 0x04 // Village
  98. #define FLAG_3_MASK 0x08 // Contest & Events
  99. #define FLAG_4_MASK 0x10 // Arts & Entertainment
  100. #define FLAG_5_MASK 0x20 // Parties
  101. #define FLAG_6_MASK 0x40 // Group Chat
  102. #define FLAG_ALL_MASK 0x7F
  103. #define GROUP_ALL_MASK 0x3F
  104.  
  105. #define CONSOLE_RCVBUF_SIZE 20 // Number of bytes in debug console (interactive mode) receive buffer
  106. #define ART_DEFAULT "DC27" // Default string for ASCII art generator
  107.  
  108. #define NVM_DATA_SIZE 4U // Number of bytes to store in KL27 Flash
  109. #define SECTOR_INDEX_FROM_END 1U // Location of KL27 Flash sector to use for game data storage
  110.  
  111. // CLKOUT
  112. #define SIM_CLKOUT_SEL_OSCERCLK_CLK 6U // CLKOUT pin clock select: OSCERCLK (from clock_config.c)
  113.  
  114. // LPUART0 (to/from NXH2261)
  115. #define LPUART0_RING_BUFFER_SIZE 2048U // Number of bytes in ring buffer for receiving data from NXH
  116.  
  117. // I2C
  118. #define I2C_NXH2261_ADDR 0x10
  119. #define I2C_LP5569_ADDR 0x32
  120.  
  121. // NXH2261
  122. #define NXH2261_DATA_PACKET_SIZE 18U // header + 16 user bytes + footer
  123. #define NXH2261_MAX_CHUNK_SIZE 128U
  124. #define NXH2261_CMD_GET_VERSION 0x0F80 // Get device version information
  125. #define NXH2261_CMD_PREVENT_BOOT 0x0F16 // Aborts automatic boot procedure, puts device into bootloader
  126. #define NXH2261_CMD_EEPROM_ENABLE 0x0F18 // Enables the EEPROM (required before any EEPROM manipulation)
  127. #define NXH2261_CMD_EEPROM_DISABLE 0x0F19 // Disables the EEPROM
  128. #define NXH2261_CMD_EEPROM_UNLOCK 0x0F0C // Unlocks EEPROM memory location for a single write
  129. #define NXH2261_CMD_EEPROM_READ 0x0F0B // Read data from EEPROM
  130. #define NXH2261_CMD_EEPROM_WRITE 0x0F0A // Write data to EEPROM
  131. #define NXH2261_CMD_START_APP 0x0F00 // Executes the application currently in RAM
  132. #define NXH2261_CMD_EEPROM_BOOT 0x0F0F // Copies application from EEPROM into RAM and executes
  133.  
  134. // LP5569
  135. #define LP5569_LED_NUM 6U // Number of LEDs per badge
  136.  
  137. #define LED_CONTROL_RED 0x08 // No master fading, exponential adjustment, LED powered by charge pump
  138. #define LED_CURRENT_RED 0x0A // 1.0mA
  139. #define LED_PWM_RED 0xC0 // 75% duty cycle
  140.  
  141. #define LED_CONTROL_ORANGE 0x08 // No master fading, exponential adjustment, LED powered by charge pump
  142. #define LED_CURRENT_ORANGE 0x07 // 0.7mA
  143. #define LED_PWM_ORANGE 0xC0 // 75% duty cycle
  144.  
  145. #define LED_CONTROL_GREEN 0x08 // No master fading, exponential adjustment, LED powered by charge pump
  146. #define LED_CURRENT_GREEN 0x02 // 0.2mA
  147. #define LED_PWM_GREEN 0xC0 // 75% duty cycle
  148.  
  149. #define LED_CONTROL_BLUE 0x08 // No master fading, exponential adjustment, LED powered by charge pump
  150. #define LED_CURRENT_BLUE 0x07 // 0.7mA
  151. #define LED_PWM_BLUE 0xC0 // 75% duty cycle
  152.  
  153. #define LED_CONTROL_PURPLE 0x08 // No master fading, exponential adjustment, LED powered by charge pump
  154. #define LED_CURRENT_PURPLE 0x07 // 0.7mA
  155. #define LED_PWM_PURPLE 0xC0 // 75% duty cycle
  156.  
  157. #define LED_CONTROL_WHITE 0x08 // No master fading, exponential adjustment, LED powered by charge pump
  158. #define LED_CURRENT_WHITE 0x06 // 0.6mA
  159. #define LED_PWM_WHITE 0xC0 // 75% duty cycle
  160.  
  161. // From Section 8.6: Register Maps
  162. #define LP5569_REG_CONFIG 0x00 // Configuration Register
  163. #define LP5569_REG_LED_ENGINE_CONTROL1 0x01 // Engine Execution Control Register
  164. #define LP5569_REG_LED_ENGINE_CONTROL2 0x02 // Engine Operation Mode Register
  165. #define LP5569_REG_LED0_CONTROL 0x07 // LED0 Control Register
  166. #define LP5569_REG_LED1_CONTROL 0x08 // LED1 Control Register
  167. #define LP5569_REG_LED2_CONTROL 0x09 // LED2 Control Register
  168. #define LP5569_REG_LED3_CONTROL 0x0A // LED3 Control Register
  169. #define LP5569_REG_LED4_CONTROL 0x0B // LED4 Control Register
  170. #define LP5569_REG_LED5_CONTROL 0x0C // LED5 Control Register
  171. #define LP5569_REG_LED6_CONTROL 0x0D // LED6 Control Register
  172. #define LP5569_REG_LED7_CONTROL 0x0E // LED7 Control Register
  173. #define LP5569_REG_LED8_CONTROL 0x0F // LED8 Control Register
  174. #define LP5569_REG_LED0_PWM 0x16 // LED0 PWM Duty Cycle
  175. #define LP5569_REG_LED1_PWM 0x17 // LED1 PWM Duty Cycle
  176. #define LP5569_REG_LED2_PWM 0x18 // LED2 PWM Duty Cycle
  177. #define LP5569_REG_LED3_PWM 0x19 // LED3 PWM Duty Cycle
  178. #define LP5569_REG_LED4_PWM 0x1A // LED4 PWM Duty Cycle
  179. #define LP5569_REG_LED5_PWM 0x1B // LED5 PWM Duty Cycle
  180. #define LP5569_REG_LED6_PWM 0x1C // LED6 PWM Duty Cycle
  181. #define LP5569_REG_LED7_PWM 0x1D // LED7 PWM Duty Cycle
  182. #define LP5569_REG_LED8_PWM 0x1E // LED8 PWM Duty Cycle
  183. #define LP5569_REG_LED0_CURRENT 0x22 // LED0 Current Control
  184. #define LP5569_REG_LED1_CURRENT 0x23 // LED1 Current Control
  185. #define LP5569_REG_LED2_CURRENT 0x24 // LED2 Current Control
  186. #define LP5569_REG_LED3_CURRENT 0x25 // LED3 Current Control
  187. #define LP5569_REG_LED4_CURRENT 0x26 // LED4 Current Control
  188. #define LP5569_REG_LED5_CURRENT 0x27 // LED5 Current Control
  189. #define LP5569_REG_LED6_CURRENT 0x28 // LED6 Current Control
  190. #define LP5569_REG_LED7_CURRENT 0x29 // LED7 Current Control
  191. #define LP5569_REG_LED8_CURRENT 0x2A // LED8 Current Control
  192. #define LP5569_REG_MISC 0x2F // I2C Charge Pump and Clock Configuration
  193. #define LP5569_REG_ENGINE1_PC 0x30 // Engine 1 Program Counter
  194. #define LP5569_REG_ENGINE2_PC 0x31 // Engine 2 Program Counter
  195. #define LP5569_REG_ENGINE3_PC 0x32 // Engine 3 Program Counter
  196. #define LP5569_REG_MISC2 0x33 // Charge Pump and LED Configuration
  197. #define LP5569_REG_ENGINE_STATUS 0x3C // Engine 1/2/3 Status
  198. #define LP5569_REG_IO_CONTROL 0x3D // TRIG/INT/CLK Configuration
  199. #define LP5569_REG_VARIABLE_D 0x3E // Global Variable D
  200. #define LP5569_REG_RESET 0x3F // Software Reset
  201. #define LP5569_REG_ENGINE1_VARIABLE_A 0x42 // Engine 1 Local Variable A
  202. #define LP5569_REG_ENGINE2_VARIABLE_A 0x43 // Engine 2 Local Variable A
  203. #define LP5569_REG_ENGINE3_VARIABLE_A 0x44 // Engine 3 Local Variable A
  204. #define LP5569_REG_MASTER_FADER1 0x46 // Engine 1 Master Fader
  205. #define LP5569_REG_MASTER_FADER2 0x47 // Engine 2 Master Fader
  206. #define LP5569_REG_MASTER_FADER3 0x48 // Engine 3 Master Fader
  207. #define LP5569_REG_MASTER_FADER_PWM 0x4A // PWM Input Duty Cycle
  208. #define LP5569_REG_ENGINE1_PROG_START 0x4B // Engine 1 Program Starting Address
  209. #define LP5569_REG_ENGINE2_PROG_START 0x4C // Engine 2 Program Starting Address
  210. #define LP5569_REG_ENGINE3_PROG_START 0x4D // Engine 3 Program Starting Address
  211. #define LP5569_REG_PROG_MEM_PAGE_SELECT 0x4F // Program Memory Page Select
  212. #define LP5569_REG_PROGRAM_MEM_00 0x50 // MSB 0
  213. #define LP5569_REG_PROGRAM_MEM_01 0x51 // LSB 0
  214. #define LP5569_REG_PROGRAM_MEM_02 0x52 // MSB 1
  215. #define LP5569_REG_PROGRAM_MEM_03 0x53 // LSB 1
  216. #define LP5569_REG_PROGRAM_MEM_04 0x54 // MSB 2
  217. #define LP5569_REG_PROGRAM_MEM_05 0x55 // LSB 2
  218. #define LP5569_REG_PROGRAM_MEM_06 0x56 // MSB 3
  219. #define LP5569_REG_PROGRAM_MEM_07 0x57 // LSB 3
  220. #define LP5569_REG_PROGRAM_MEM_08 0x58 // MSB 4
  221. #define LP5569_REG_PROGRAM_MEM_09 0x59 // LSB 4
  222. #define LP5569_REG_PROGRAM_MEM_10 0x5A // MSB 5
  223. #define LP5569_REG_PROGRAM_MEM_11 0x5B // LSB 5
  224. #define LP5569_REG_PROGRAM_MEM_12 0x5C // MSB 6
  225. #define LP5569_REG_PROGRAM_MEM_13 0x5D // LSB 6
  226. #define LP5569_REG_PROGRAM_MEM_14 0x5E // MSB 7
  227. #define LP5569_REG_PROGRAM_MEM_15 0x5F // LSB 7
  228. #define LP5569_REG_PROGRAM_MEM_16 0x60 // MSB 8
  229. #define LP5569_REG_PROGRAM_MEM_17 0x61 // LSB 8
  230. #define LP5569_REG_PROGRAM_MEM_18 0x62 // MSB 9
  231. #define LP5569_REG_PROGRAM_MEM_19 0x63 // LSB 9
  232. #define LP5569_REG_PROGRAM_MEM_20 0x64 // MSB 10
  233. #define LP5569_REG_PROGRAM_MEM_21 0x65 // LSB 10
  234. #define LP5569_REG_PROGRAM_MEM_22 0x66 // MSB 11
  235. #define LP5569_REG_PROGRAM_MEM_23 0x67 // LSB 11
  236. #define LP5569_REG_PROGRAM_MEM_24 0x68 // MSB 12
  237. #define LP5569_REG_PROGRAM_MEM_25 0x69 // LSB 12
  238. #define LP5569_REG_PROGRAM_MEM_26 0x6A // MSB 13
  239. #define LP5569_REG_PROGRAM_MEM_27 0x6B // LSB 13
  240. #define LP5569_REG_PROGRAM_MEM_28 0x6C // MSB 14
  241. #define LP5569_REG_PROGRAM_MEM_29 0x6D // LSB 14
  242. #define LP5569_REG_PROGRAM_MEM_30 0x6E // MSB 15
  243. #define LP5569_REG_PROGRAM_MEM_31 0x6F // LSB 15
  244. #define LP5569_REG_ENGINE1_MAPPING1 0x70 // Engine 1 LED [8] and Master Fader Mapping
  245. #define LP5569_REG_ENGINE1_MAPPING2 0x71 // Engine 1 LED [7:0] Mapping
  246. #define LP5569_REG_ENGINE2_MAPPING1 0x72 // Engine 2 LED [8] and Master Fader Mapping
  247. #define LP5569_REG_ENGINE2_MAPPING2 0x73 // Engine 2 LED [7:0] Mapping
  248. #define LP5569_REG_ENGINE3_MAPPING1 0x74 // Engine 3 LED [8] and Master Fader Mapping
  249. #define LP5569_REG_ENGINE3_MAPPING2 0x75 // Engine 3 LED [7:0] Mapping
  250. #define LP5569_REG_PWM_CONFIG 0x80 // PWM Input Configuration
  251. #define LP5569_REG_LED_FAULT1 0x81 // LED [8] Fault Status
  252. #define LP5569_REG_LED_FAULT2 0x82 // LED [7:0] Fault Status
  253. #define LP5569_REG_GENERAL_FAULT 0x83 // CP Cap UVLO and TSD Fault Status
  254.  
  255. // Piezo
  256. // Table of notes/pitch (in Hz)
  257. #define NOTE_REST 0
  258. #define NOTE_B0 31
  259. #define NOTE_C1 33
  260. #define NOTE_CS1 35
  261. #define NOTE_D1 37
  262. #define NOTE_DS1 39
  263. #define NOTE_E1 41
  264. #define NOTE_F1 44
  265. #define NOTE_FS1 46
  266. #define NOTE_G1 49
  267. #define NOTE_GS1 52
  268. #define NOTE_A1 55
  269. #define NOTE_AS1 58
  270. #define NOTE_B1 62
  271. #define NOTE_C2 65
  272. #define NOTE_CS2 69
  273. #define NOTE_D2 73
  274. #define NOTE_DS2 78
  275. #define NOTE_E2 82
  276. #define NOTE_F2 87
  277. #define NOTE_FS2 93
  278. #define NOTE_G2 98
  279. #define NOTE_GS2 104
  280. #define NOTE_A2 110
  281. #define NOTE_AS2 117
  282. #define NOTE_B2 123
  283. #define NOTE_C3 131
  284. #define NOTE_CS3 139
  285. #define NOTE_D3 147
  286. #define NOTE_DS3 156
  287. #define NOTE_E3 165
  288. #define NOTE_F3 175
  289. #define NOTE_FS3 185
  290. #define NOTE_G3 196
  291. #define NOTE_GS3 208
  292. #define NOTE_A3 220
  293. #define NOTE_AS3 233
  294. #define NOTE_B3 247
  295. #define NOTE_C4 262
  296. #define NOTE_CS4 277
  297. #define NOTE_D4 294
  298. #define NOTE_DS4 311
  299. #define NOTE_E4 330
  300. #define NOTE_F4 349
  301. #define NOTE_FS4 370
  302. #define NOTE_G4 392
  303. #define NOTE_GS4 415
  304. #define NOTE_A4 440
  305. #define NOTE_AS4 466
  306. #define NOTE_B4 494
  307. #define NOTE_C5 523
  308. #define NOTE_CS5 554
  309. #define NOTE_D5 587
  310. #define NOTE_DS5 622
  311. #define NOTE_E5 659
  312. #define NOTE_F5 698
  313. #define NOTE_FS5 740
  314. #define NOTE_G5 784
  315. #define NOTE_GS5 831
  316. #define NOTE_A5 880
  317. #define NOTE_AS5 932
  318. #define NOTE_B5 988
  319. #define NOTE_C6 1047
  320. #define NOTE_CS6 1109
  321. #define NOTE_D6 1175
  322. #define NOTE_DS6 1245
  323. #define NOTE_E6 1319
  324. #define NOTE_F6 1397
  325. #define NOTE_FS6 1480
  326. #define NOTE_G6 1568
  327. #define NOTE_GS6 1661
  328. #define NOTE_A6 1760
  329. #define NOTE_AS6 1865
  330. #define NOTE_B6 1976
  331. #define NOTE_C7 2093
  332. #define NOTE_CS7 2217
  333. #define NOTE_D7 2349
  334. #define NOTE_DS7 2489
  335. #define NOTE_E7 2637
  336. #define NOTE_F7 2794
  337. #define NOTE_FS7 2960
  338. #define NOTE_G7 3136
  339. #define NOTE_GS7 3322
  340. #define NOTE_A7 3520
  341. #define NOTE_AS7 3729
  342. #define NOTE_B7 3951
  343. #define NOTE_C8 4186
  344. #define NOTE_CS8 4435
  345. #define NOTE_D8 4699
  346. #define NOTE_DS8 4978
  347.  
  348.  
  349. /**************************************************************************
  350. ************************** Macros *****************************************
  351. ***************************************************************************/
  352.  
  353. #define HIGH_BYTE(x) ((x) >> 8)
  354. #define LOW_BYTE(x) ((x) & 0xFF)
  355.  
  356. #define dc27_invalid_cmd() PRINTF("?")
  357.  
  358.  
  359. /**************************************************************************
  360. ************************** Structs ****************************************
  361. ***************************************************************************/
  362.  
  363. typedef enum // badge types
  364. {
  365. HUMAN,
  366. GOON,
  367. SPEAKER,
  368. VENDOR,
  369. PRESS,
  370. VILLAGE,
  371. CONTEST,
  372. ARTIST,
  373. CFP,
  374. UBER
  375. } badge_type_t;
  376.  
  377. typedef enum // badge states
  378. {
  379. ATTRACT,
  380. D,
  381. E,
  382. F,
  383. C,
  384. O,
  385. N,
  386. COMPLETE
  387. } badge_state_t;
  388.  
  389. struct packet_of_infamy // data packet for NFMI transfer
  390. {
  391. uint32_t uid; // unique ID
  392. uint8_t type; // badge type
  393. uint8_t magic; // magic token (1 = enabled)
  394. uint8_t flags; // game flags (packed, MSB unused)
  395. uint8_t unused; // unused
  396. };
  397.  
  398. struct note // sound generation
  399. {
  400. long freq; // frequency (Hz)
  401. long duration; // duration (ms)
  402. char duty; // duty cycle (%)
  403. };
  404.  
  405.  
  406. /****************************************************************************
  407. ************************** Global variables ********************************
  408. ***************************************************************************/
  409.  
  410. // Badge
  411. volatile static badge_state_t badge_state, attract_state;
  412. volatile static badge_type_t badge_type = __BADGE_TYPE;
  413. volatile static uint8_t game_flags, group_flags; // tasks to complete, 1 = done, 0 = not done
  414. volatile unsigned char g_random; // PRNG
  415. volatile bool g_oldRx, g_newRx; // used to detect rising edge transition of KL RX (for interactive mode)
  416.  
  417. // Flash driver/EEPROM
  418. static flash_config_t s_flashDriver;
  419. static ftfx_cache_config_t s_cacheDriver;
  420. static uint32_t pflashBlockBase = 0;
  421. static uint32_t pflashTotalSize = 0;
  422. static uint32_t pflashSectorSize = 0;
  423.  
  424. // Timer
  425. volatile uint32_t g_systickCounter;
  426. volatile bool g_lptmrFlag;
  427.  
  428. // UART2 (to/from host)
  429. extern const uart_config_t UART2_config; // peripherals.c
  430.  
  431. // LPUART0 (to/from NXH2261)
  432. /*
  433. Ring buffer for data input and output
  434. Input data is stored to the ring buffer in IRQ handler
  435. Ring buffer full: (((rxIndex + 1) % RING_BUFFER_SIZE) == txIndex)
  436. Ring buffer empty: (rxIndex == txIndex)
  437. */
  438. volatile static uint8_t nxhRingBuffer[LPUART0_RING_BUFFER_SIZE];
  439. volatile static uint16_t nxhTxIndex; // Index of the data to send out
  440. volatile static uint16_t nxhRxIndex; // Index of the memory to save new received data
  441.  
  442. // LP5569 LED driver default settings
  443. unsigned char LP5569_Control; // Control Register
  444. unsigned char LP5569_Current; // Current Control
  445. unsigned char LP5569_PWM; // PWM Duty Cycle
  446.  
  447. // NHX2261
  448. volatile bool g_nxhDetect = false;
  449. static struct packet_of_infamy nxhTxPacket; // Data packet to transmit
  450. static struct packet_of_infamy nxhRxPacket; // Received data packet
  451.  
  452. // Piezo/PWM
  453. extern const tpm_chnl_pwm_signal_param_t TPM0_pwmSignalParams[]; // peripherals.c
  454.  
  455.  
  456. /****************************************************************************
  457. *************************** Constants **************************************
  458. ***************************************************************************/
  459.  
  460. const char command_prompt[] = "\n\r> ";
  461.  
  462. const char menu_banner[] = "\n\r\
  463. T: Display transmit packet\n\r\
  464. R: Receive packet(s)\n\r\
  465. C: Clear game flags\n\r\
  466. H: Display available commands\n\r\
  467. ^: System reset\n\r\
  468. Ctrl-X: Exit interactive mode\n\r\
  469. ";
  470.  
  471. const char menu_banner_complete[] = "\n\r\
  472. A <string>: ASCII art generator\n\r\
  473. S <freq> <ms>: Tone generator\n\r\
  474. U <hex bytes>: Update transmit packet\n\r\
  475. ";
  476.  
  477. const char msg_welcome[] = "\n\r\n\rWelcome to the DEFCON 27 Official Badge\n\r\n\r";
  478. const char msg_init_start[] = "[*] Starting Initialization\n\r";
  479. const char msg_init_complete[] = "[*] Initialization Complete\n\r";
  480. const char msg_interactive_mode[] = "[*] Entering Interactive Mode [Press 'H' for Commands]\n\r";
  481. const char msg_interactive_exit[] = "\n\r[*] Exiting Interactive Mode\n\r";
  482. const char msg_nfmi_packet_err[] = "[*] NFMI Packet Update Error!\n\r";
  483.  
  484. const char msg_version[] = "\
  485. Designed by Joe Grand [@joegrand] aka Kingpin\n\r\
  486. grandideastudio.com/portfolio/defcon-27-badge/\n\r\n\r\
  487. ";
  488.  
  489. // NES Super Mario Bros. 1-Up
  490. // Sheet music from http://www.mariopiano.com/mario-sheet-music-1-up-mushroom-sound.html
  491. const struct note tune_1up[] = {
  492. {NOTE_E6, 125, 50}, {NOTE_G6, 125, 50}, {NOTE_E7, 125, 50}, {NOTE_C7, 125, 50},
  493. {NOTE_D7, 125, 50}, {NOTE_G7, 125, 50}
  494. };
  495.  
  496. // He Who Shall Not Be Named
  497. // Ported from https://create.arduino.cc/projecthub/slagestee/rickroll-box-3c2245
  498. /*const struct note tune_rickroll_intro[] = {
  499. {NOTE_CS5, 600, 50}, {NOTE_DS5, 1000, 50}, {NOTE_DS5, 600, 50}, {NOTE_F5, 600, 50},
  500. {NOTE_GS5, 100, 50}, {NOTE_FS5, 100, 50}, {NOTE_F5, 100, 50}, {NOTE_DS5, 100, 50},
  501. {NOTE_CS5, 600, 50}, {NOTE_DS5, 1000, 50}, {NOTE_REST, 400, 50}, {NOTE_GS4, 200, 50},
  502. {NOTE_GS4, 1000, 50}
  503. };*/
  504.  
  505. /*const struct note tune_rickroll_verse[] = {
  506. {NOTE_REST, 400, 50}, {NOTE_CS4, 200, 50}, {NOTE_CS4, 200, 50}, {NOTE_CS4, 200, 50},
  507. {NOTE_CS4, 200, 50}, {NOTE_DS4, 400, 50}, {NOTE_REST, 200, 50}, {NOTE_C4, 200, 50},
  508. {NOTE_AS3, 200, 50}, {NOTE_GS3, 1000, 50}, {NOTE_REST, 200, 50}, {NOTE_AS3, 200, 50},
  509. {NOTE_AS3, 200, 50}, {NOTE_C4, 200, 50}, {NOTE_CS4, 600, 50}, {NOTE_GS3, 200, 50},
  510. {NOTE_GS4, 400, 50}, {NOTE_GS4, 200, 50}, {NOTE_DS4, 1000, 50}, {NOTE_REST, 200, 50},
  511. {NOTE_AS3, 200, 50}, {NOTE_AS3, 200, 50}, {NOTE_C4, 200, 50}, {NOTE_CS4, 200, 50},
  512. {NOTE_AS3, 200, 50}, {NOTE_CS4, 200, 50}, {NOTE_DS4, 400, 50}, {NOTE_REST, 200, 50},
  513. {NOTE_C4, 200, 50}, {NOTE_AS3, 200, 50}, {NOTE_AS3, 200, 50}, {NOTE_GS3, 600, 50},
  514. {NOTE_REST, 200, 50}, {NOTE_AS3, 200, 50}, {NOTE_AS3, 200, 50}, {NOTE_C4, 200, 50},
  515. {NOTE_CS4, 400, 50}, {NOTE_GS3, 200, 50}, {NOTE_GS3, 200, 50}, {NOTE_DS4, 200, 50},
  516. {NOTE_DS4, 200, 50}, {NOTE_DS4, 200, 50}, {NOTE_F4, 200, 50}, {NOTE_DS4, 800, 50},
  517. {NOTE_CS4, 1000, 50}, {NOTE_DS4, 200, 50}, {NOTE_F4, 200, 50}, {NOTE_CS4, 200, 50},
  518. {NOTE_DS4, 200, 50}, {NOTE_DS4, 200, 50}, {NOTE_DS4, 200, 50}, {NOTE_F4, 200, 50},
  519. {NOTE_DS4, 400, 50}, {NOTE_GS3, 400, 50}, {NOTE_REST, 400, 50}, {NOTE_AS3, 200, 50},
  520. {NOTE_C4, 200, 50}, {NOTE_CS4, 200, 50}, {NOTE_GS3, 600, 50}, {NOTE_REST, 200, 50},
  521. {NOTE_DS4, 200, 50}, {NOTE_F4, 200, 50}, {NOTE_DS4, 600, 50}
  522. };
  523.  
  524. const char* tune_rickroll_verse_lyrics[] = {
  525. "\n\r", "We're ", "no ", "stran", "gers ", "", "to ", "", "love ", "", "\n\r",
  526. "You ", "know ", "the ", "rules ", "and ", "so ", "do ", "I", "", "\n\r",
  527. "A ", "full ", "com", "mit", "ment's ", "what ", "I'm ", "think", "ing ", "of", "", "\n\r",
  528. "You ", "would", "n't ", "get ", "this ", "from ", "any ", "oth", "er ", "guy", "\n\r",
  529. "I ", "just ", "wan", "na ", "tell ", "you ", "how ", "I'm ", "feel", "ing", "\n\r",
  530. "Got", "ta ", "make ", "you ", "", "un", "der", "stand\n\r\n\r"
  531. };*/
  532.  
  533. const struct note tune_rickroll_chorus[] = {
  534. {NOTE_AS4, 100, 50}, {NOTE_AS4, 100, 50}, {NOTE_GS4, 100, 50}, {NOTE_GS4, 100, 50},
  535. {NOTE_F5, 300, 50}, {NOTE_F5, 300, 50}, {NOTE_DS5, 600, 50}, {NOTE_AS4, 100, 50},
  536. {NOTE_AS4, 100, 50}, {NOTE_GS4, 100, 50}, {NOTE_GS4, 100, 50}, {NOTE_DS5, 300, 50},
  537. {NOTE_DS5, 300, 50}, {NOTE_CS5, 300, 50}, {NOTE_C5, 100, 50}, {NOTE_AS4, 200, 50},
  538. {NOTE_CS5, 100, 50}, {NOTE_CS5, 100, 50}, {NOTE_CS5, 100, 50}, {NOTE_CS5, 100, 50},
  539. {NOTE_CS5, 300, 50}, {NOTE_DS5, 300, 50}, {NOTE_C5, 300, 50}, {NOTE_AS4, 100, 50},
  540. {NOTE_GS4, 200, 50}, {NOTE_GS4, 200, 50}, {NOTE_GS4, 200, 50}, {NOTE_DS5, 400, 50},
  541. {NOTE_CS5, 800, 50}, {NOTE_AS4, 100, 50}, {NOTE_AS4, 100, 50}, {NOTE_GS4, 100, 50},
  542. {NOTE_GS4, 100, 50}, {NOTE_F5, 300, 50}, {NOTE_F5, 300, 50}, {NOTE_DS5, 600, 50},
  543. {NOTE_AS4, 100, 50}, {NOTE_AS4, 100, 50}, {NOTE_GS4, 100, 50}, {NOTE_GS4, 100, 50},
  544. {NOTE_GS5, 300, 50}, {NOTE_C5, 300, 50}, {NOTE_CS5, 300, 50}, {NOTE_C5, 100, 50},
  545. {NOTE_AS4, 200, 50}, {NOTE_CS5, 100, 50}, {NOTE_CS5, 100, 50}, {NOTE_CS5, 100, 50},
  546. {NOTE_CS5, 100, 50}, {NOTE_CS5, 300, 50}, {NOTE_DS5, 300, 50}, {NOTE_C5, 300, 50},
  547. {NOTE_AS4, 100, 50}, {NOTE_GS4, 200, 50}, {NOTE_REST, 200, 50}, {NOTE_GS4, 200, 50},
  548. {NOTE_DS5, 400, 50}, {NOTE_CS5, 800, 50}, {NOTE_REST, 400, 50}
  549. };
  550.  
  551. const char* tune_rickroll_chorus_lyrics[] = {
  552. "Ne", "ver ", "gon", "na ", "give ", "you ", "up", "\n\r",
  553. "Ne", "ver ", "gon", "na ", "let ", "you ", "down", "", "\n\r",
  554. "Ne", "ver ", "gon", "na ", "run ", "a", "round ", "and ", "de", "sert ", "you", "\n\r",
  555. "Ne", "ver ", "gon", "na ", "make ", "you ", "cry", "", "\n\r",
  556. "Ne", "ver ", "gon", "na ", "say ", "good", "bye ", "", "\n\r",
  557. "Ne", "ver ", "gon", "na ", "tell ", "a ", "lie ", "", "and ", "hurt ", "you", "\n\r\n\r"
  558. };
  559.  
  560. // ASCII art for generator
  561. #define ART_WIDTH 67
  562. #define ART_LINES 35
  563. const char ART_DATA[] = {
  564. 25, 17, 25, 19, 29, 19, 16, 35, 16, 13, 41, 13, 10, 19, \
  565. 10, 18, 10, 8, 17, 18, 16, 8, 7, 16, 22, 15, 7, 5, 16, \
  566. 26, 15, 5, 4, 16, 7, 5, 6, 5, 5, 15, 4, 3, 6, 3, 7, 7, \
  567. 7, 4, 7, 5, 15, 3, 2, 6, 6, 5, 8, 5, 6, 5, 7, 7, 3, 5, \
  568. 2, 1, 6, 7, 5, 31, 5, 7, 4, 1, 1, 7, 5, 6, 3, 4, 17, 4, \
  569. 3, 5, 7, 4, 1, 0, 5, 11, 3, 4, 2, 19, 2, 4, 6, 7, 4, 0, \
  570. 4, 20, 2, 17, 2, 4, 3, 13, 2, 0, 5, 5, 3, 12, 2, 15, 2, \
  571. 21, 2, 0, 16, 11, 3, 9, 3, 13, 4, 5, 3, 0, 20, 10, 9, 12, \
  572. 16, 0, 24, 23, 20, 0, 27, 11, 2, 3, 24, 0, 28, 1, 2, 10, \
  573. 26, 1, 23, 8, 2, 11, 21, 1, 1, 19, 11, 7, 10, 18, 1, 2, \
  574. 6, 5, 3, 11, 14, 11, 2, 5, 6, 2, 3, 5, 15, 22, 15, 4, 3, \
  575. 4, 4, 11, 29, 11, 4, 4, 5, 7, 4, 35, 5, 6, 5, 7, 4, 6, 34, \
  576. 5, 4, 7, 8, 3, 6, 34, 5, 3, 8, 10, 3, 2, 42, 10, 13, 41, \
  577. 13, 16, 35, 16, 19, 29, 19, 25, 17, 25 \
  578. };
  579.  
  580. // Alternate ASCII art
  581. /*#define ART_WIDTH 60
  582. #define ART_LINES 36
  583. const char ART_DATA[] = { \
  584. 60, 1, 12, 26, 9, 12, 3, 8, 24, 17, 8, 4, 6, 23, 21, 6, \
  585. 4, 6, 22, 12, 5, 6, 5, 4, 6, 21, 11, 8, 6, 4, 4, 6, 21, \
  586. 10, 10, 5, 4, 4, 6, 21, 9, 11, 5, 4, 4, 6, 21, 8, 11, 6, \
  587. 4, 4, 6, 21, 7, 11, 7, 4, 4, 6, 21, 6, 11, 8, 4, 4, 6, \
  588. 19, 1, 1, 5, 11, 9, 4, 4, 6, 19, 1, 1, 5, 10, 10, 4, 4, \
  589. 6, 18, 2, 1, 6, 8, 11, 4, 4, 6, 17, 3, 1, 7, 5, 13, 4, 4, \
  590. 6, 15, 5, 2, 23, 5, 1, 29, 5, 17, 8, 1, 29, 9, 9, 12, 1, \
  591. 13, 5, 40, 1, 1, 13, 5, 40, 1, 4, 6, 13, 3, 10, 6, 12, 5, \
  592. 1, 5, 6, 11, 3, 11, 6, 14, 3, 1, 5, 6, 11, 3, 11, 6, 15, \
  593. 2, 1, 6, 6, 9, 3, 12, 6, 16, 1, 1, 6, 6, 9, 3, 12, 6, 7, \
  594. 1, 10, 7, 6, 7, 3, 13, 6, 6, 2, 10, 7, 6, 7, 3, 13, 14, \
  595. 10, 8, 6, 5, 3, 14, 6, 6, 2, 10, 8, 6, 5, 3, 14, 6, 7, 1, \
  596. 10, 9, 6, 3, 3, 15, 6, 16, 1, 1, 9, 6, 3, 3, 15, 6, 15, \
  597. 2, 1, 10, 6, 1, 3, 16, 6, 14, 3, 1, 10, 10, 16, 6, 12, 5, \
  598. 1, 11, 8, 13, 27, 1, 11, 8, 13, 27, 1, 60 \
  599. };*/
  600.  
  601.  
  602. /****************************************************************************
  603. ********************* Function Prototypes **********************************
  604. ***************************************************************************/
  605.  
  606. // Badge
  607. void DC27_GameInit(void);
  608. void DC27_UpdateState(void);
  609. void DC27_UpdateDisplay(void);
  610. void DC27_UpdateFlags(bool);
  611. int DC27_IncrementFlag(void);
  612. void DC27_PrintBadgeType(badge_type_t);
  613. void DC27_PrintState(void);
  614. void DC27_PrintPacket(struct packet_of_infamy);
  615. void DC27_ProcessPacket(void);
  616. void DC27_InteractiveMode(void);
  617. void DC27_ASCIIArt(uint8_t *);
  618.  
  619. // I2C
  620. bool I2C_ReadRegister(I2C_Type *, uint8_t, uint8_t, uint8_t *, uint32_t);
  621. bool I2C_WriteRegister(I2C_Type *, uint8_t , uint8_t , uint8_t);
  622. bool I2C_ReadBulk(I2C_Type *, uint8_t, uint8_t *, uint32_t);
  623. bool I2C_WriteBulk(I2C_Type *, uint8_t , uint8_t *, uint32_t);
  624. void I2C_ReleaseBus(void);
  625.  
  626. // LED Driver
  627. int KL_Setup_LP5569(void);
  628. void LP5569_SetLED(unsigned char, unsigned char);
  629. void LP5569_SetLED_AllOn(void);
  630. void LP5569_SetLED_AllOff(void);
  631. void LP5569_SetLED_D(unsigned char);
  632. void LP5569_SetLED_E(unsigned char);
  633. void LP5569_SetLED_F(unsigned char);
  634. void LP5569_SetLED_C(unsigned char);
  635. void LP5569_SetLED_O(unsigned char);
  636. void LP5569_SetLED_N(unsigned char);
  637. void LP5569_RampLED(badge_state_t);
  638.  
  639. // NFMI Radio
  640. int KL_Setup_NXH2261(void);
  641. int KL_Program_NXH2261(const uint32_t, const unsigned char *);
  642. int KL_LoadImage_NXH2261(uint32_t, const uint8_t *, uint32_t);
  643. int KL_GetPacket_NXH2261(struct packet_of_infamy *);
  644. int KL_UpdatePacket_NXH2261(struct packet_of_infamy);
  645. void KL_Reset_NXH2261(void);
  646.  
  647. // Piezo/PWM
  648. void KL_Piezo(uint32_t, uint32_t, uint8_t);
  649. void KL_Piezo_1Up(void);
  650. void KL_Piezo_RickRoll(void);
  651.  
  652. // Utilities
  653. unsigned char Get_Random_Byte(void);
  654. void Print_Bits(uint8_t);
  655. void Reorder_Array(uint8_t *, uint8_t *, uint8_t);
  656. void SysTick_DelayTicks(uint32_t);
  657.  
  658. int KL_Flash_Init(void);
  659. int KL_Flash_Write(uint32_t);
  660. void KL_Flash_Read(uint32_t *);
  661. bool KL_Check_RX(void);
  662. void KL_Sleep(void);
  663. void KL_Error(bool, bool);
  664.  
  665.  
  666. /****************************************************************************
  667. ************************** Functions ***************************************
  668. ***************************************************************************/
  669.  
  670. /*
  671. * @brief Application entry point.
  672. */
  673. int main(void)
  674. {
  675. static int b = 1;
  676.  
  677. // Initialize board hardware
  678. BOARD_InitBootPins();
  679. BOARD_InitBootClocks();
  680. BOARD_InitBootPeripherals();
  681.  
  682. // Initialize host console
  683. DbgConsole_Init(UART2_BASE, UART2_config.baudRate_Bps, DEBUG_CONSOLE_DEVICE_TYPE_UART, UART2_CLOCK_SOURCE);
  684.  
  685. // Disable LPUART interrupts during power-up to avoid receiving data before we're ready
  686. DisableIRQ(LPUART0_SERIAL_RX_TX_IRQN);
  687.  
  688. // Other initialization
  689. SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); // Configure power mode protection settings
  690. CLOCK_SetClkOutClock(0); // Disable CLKOUT on power-up (used for NXH2261 calibration only)
  691. SysTick_Config(SystemCoreClock / 1000U); // Set systick reload value to generate 1ms interrupt (for delay)
  692. SysTick_DelayTicks(1000); // Start-up delay
  693. I2C_ReleaseBus();
  694.  
  695. // Send messages to console
  696. PRINTF(msg_welcome);
  697. PRINTF(msg_version);
  698. PRINTF(msg_init_start);
  699.  
  700. // Display KL27 unique ID
  701. // https://community.nxp.com/thread/309453
  702. PRINTF("[*] MKL27Z64 Unique Identifier: ");
  703. PRINTF("0x%08X%08X%08X [32-bit: ", SIM->UIDMH, SIM->UIDML, SIM->UIDL);
  704. uint32_t idCodeShort = (SIM->UIDMH ^ SIM->UIDML ^ SIM->UIDL ^ SIM->SDID); // condense ID into 32-bit value (collisions may occur between units)
  705. PRINTF("0x%08X]\n\r", idCodeShort);
  706. PRINTF("[*] Core Clock = %dHz\n\r", CLOCK_GetFreq(kCLOCK_CoreSysClk));
  707.  
  708. PRINTF("[*] Initializing Flash Memory");
  709. if (KL_Flash_Init())
  710. PRINTF("...Error!\n\r");
  711.  
  712. // Display badge type and configure default badge-specific parameters
  713. // Different LED colors have different Vf, which affects brightness
  714. // We want all LEDs to visually appear at the same brightness regardless of color
  715. PRINTF("[*] Badge Type = ");
  716. DC27_PrintBadgeType(badge_type);
  717. switch(badge_type)
  718. {
  719. case HUMAN:
  720. LP5569_Control = LED_CONTROL_WHITE; // Control Register
  721. LP5569_Current = LED_CURRENT_WHITE; // Current Control
  722. LP5569_PWM = LED_PWM_WHITE; // PWM Duty Cycle
  723. break;
  724. case GOON:
  725. LP5569_Control = LED_CONTROL_RED;
  726. LP5569_Current = LED_CURRENT_RED;
  727. LP5569_PWM = LED_PWM_RED;
  728. break;
  729. case SPEAKER:
  730. LP5569_Control = LED_CONTROL_BLUE;
  731. LP5569_Current = LED_CURRENT_BLUE;
  732. LP5569_PWM = LED_PWM_BLUE;
  733. break;
  734. case VENDOR:
  735. LP5569_Control = LED_CONTROL_PURPLE;
  736. LP5569_Current = LED_CURRENT_PURPLE;
  737. LP5569_PWM = LED_PWM_PURPLE;
  738. break;
  739. case PRESS:
  740. LP5569_Control = LED_CONTROL_GREEN;
  741. LP5569_Current = LED_CURRENT_GREEN;
  742. LP5569_PWM = LED_PWM_GREEN;
  743. break;
  744. case VILLAGE:
  745. LP5569_Control = LED_CONTROL_ORANGE;
  746. LP5569_Current = LED_CURRENT_ORANGE;
  747. LP5569_PWM = LED_PWM_ORANGE;
  748. break;
  749. case CONTEST:
  750. LP5569_Control = LED_CONTROL_WHITE;
  751. LP5569_Current = LED_CURRENT_WHITE;
  752. LP5569_PWM = LED_PWM_WHITE;
  753. break;
  754. case ARTIST:
  755. LP5569_Control = LED_CONTROL_WHITE;
  756. LP5569_Current = LED_CURRENT_WHITE;
  757. LP5569_PWM = LED_PWM_WHITE;
  758. break;
  759. case CFP:
  760. LP5569_Control = LED_CONTROL_WHITE;
  761. LP5569_Current = LED_CURRENT_WHITE;
  762. LP5569_PWM = LED_PWM_WHITE;
  763. break;
  764. case UBER:
  765. LP5569_Control = LED_CONTROL_WHITE;
  766. LP5569_Current = LED_CURRENT_WHITE;
  767. LP5569_PWM = LED_PWM_WHITE;
  768. break;
  769. default:
  770. LP5569_Control = LED_CONTROL_WHITE;
  771. LP5569_Current = LED_CURRENT_WHITE;
  772. LP5569_PWM = LED_PWM_WHITE;
  773. }
  774.  
  775. DC27_GameInit();
  776.  
  777. PRINTF("[*] Magic Token = ");
  778. #ifdef __BADGE_MAGIC
  779. PRINTF("True\n\r"); // magic token (1 = enabled)
  780. #else
  781. PRINTF("False\n\r"); // magic token (0 = disabled)
  782. #endif
  783.  
  784. PRINTF("[*] Testing Piezo...");
  785. KL_Piezo_1Up();
  786. PRINTF("Done!\n\r");
  787. SysTick_DelayTicks(250);
  788.  
  789. PRINTF("[*] Configuring LED Driver...");
  790. if (!KL_Setup_LP5569())
  791. {
  792. LP5569_SetLED_AllOn();
  793. PRINTF("Done!\n\r");
  794. }
  795. else
  796. {
  797. SysTick_DelayTicks(100);
  798. if (KL_Setup_LP5569()) // Try again...
  799. {
  800. KL_Error(true, false); // Beep the piezo to indicate a failure
  801. PRINTF("Error!\n\r");
  802. }
  803. }
  804.  
  805. // Now that the system is up and running, enable UART interrupts from the NXH
  806. EnableIRQ(LPUART0_SERIAL_RX_TX_IRQN);
  807.  
  808. PRINTF("[*] Configuring NFMI Radio\n\r");
  809. if (KL_Setup_NXH2261())
  810. {
  811. SysTick_DelayTicks(100);
  812. if (KL_Setup_NXH2261()) // Try again...
  813. {
  814. KL_Error(false, true); // Blink the LEDs to indicate a failure
  815. }
  816. }
  817.  
  818. // Craft data packet for radio to transmit
  819. nxhTxPacket.uid = idCodeShort; // unique ID
  820. nxhTxPacket.type = (uint8_t)badge_type; // badge type
  821. #ifdef __BADGE_MAGIC
  822. nxhTxPacket.magic = true; // magic token (1 = enabled)
  823. #else
  824. nxhTxPacket.magic = false; // magic token (0 = disabled)
  825. #endif
  826. nxhTxPacket.flags = game_flags; // game flags (packed, MSB unused)
  827. nxhTxPacket.unused = 0; // unused
  828.  
  829. if (KL_UpdatePacket_NXH2261(nxhTxPacket)) // load transmit packet into the NXH2261
  830. {
  831. if (KL_UpdatePacket_NXH2261(nxhTxPacket))
  832. PRINTF(msg_nfmi_packet_err);
  833. }
  834.  
  835. g_oldRx = KL_Check_RX(); // set current state of KL_RX (if USB-to-serial adapter is connected)
  836.  
  837. LP5569_SetLED(0, 0); // Update start-up progress via LEDs
  838. LP5569_SetLED(5, 0);
  839.  
  840. PRINTF(msg_init_complete);
  841.  
  842. if (badge_state == COMPLETE) // if the quest is done, play a friendly tune
  843. {
  844. SysTick_DelayTicks(100);
  845. PRINTF("\n\r");
  846. KL_Piezo_RickRoll();
  847. SysTick_DelayTicks(500);
  848. }
  849.  
  850. while(1)
  851. {
  852. g_newRx = KL_Check_RX();
  853. if (g_newRx && (!g_oldRx || b)) // if USB-to-Serial adapter has been plugged in, KL_RX pin will go HIGH
  854. {
  855. PRINTF("[*] USB-to-Serial Adapter Detected\n\r");
  856. if (!b) GETCHAR(); // if adapter is plugged in while the system is already active, drop first character
  857. DC27_InteractiveMode();
  858. b = 0; // if we're here for the first time after power-up
  859. }
  860. g_oldRx = g_newRx;
  861.  
  862. if (badge_state != COMPLETE) // do this if all badge tasks have not been completed
  863. {
  864. // enter VLPS (Very Low Power Sleep)
  865. // MCU will wake up on NXH_DETECT external interrupt (when NXH successfully receives a data packet)
  866. // or if USB-to-serial adapter is connected
  867. PRINTF("[*] Sleeping...");
  868. DbgConsole_Flush(); // wait for TX buffer to empty
  869. PORT_SetPinInterruptConfig(BOARD_INITPINS_KL_RX_PORT, BOARD_INITPINS_KL_RX_PIN, kPORT_InterruptRisingEdge);
  870. LPTMR_SetTimerPeriod(LPTMR0_PERIPHERAL, LPTMR0_TICKS); // Set time to sleep between LED update/heartbeat
  871.  
  872. KL_Sleep();
  873.  
  874. PRINTF("Awake!\n\r");
  875. }
  876.  
  877. if (g_lptmrFlag && badge_state != COMPLETE) // we must have woken up from the timer
  878. {
  879. if (badge_state == ATTRACT)
  880. DC27_UpdateDisplay();
  881.  
  882. g_lptmrFlag = false;
  883. }
  884.  
  885. // Check badge state and update if needed
  886. DisableIRQ(LPUART0_SERIAL_RX_TX_IRQN);
  887. DC27_UpdateState();
  888. EnableIRQ(LPUART0_SERIAL_RX_TX_IRQN);
  889. }
  890.  
  891. return 0; // We should never reach here
  892. }
  893.  
  894. /**************************************************************/
  895.  
  896. void DC27_GameInit(void) // Initialize DC27 badge game-related items
  897. {
  898. uint32_t data;
  899.  
  900. #ifdef __BADGE_MAGIC // for magic token, skip attract mode to save battery
  901. badge_state = D;
  902. #else
  903. badge_state = ATTRACT;
  904. attract_state = D; // used for cycling through LED states during attract mode
  905. #endif
  906.  
  907. // Configure game flags (for development/debugging purposes)
  908. //game_flags = 0; // Clear all
  909. //game_flags = 0b00111111; // State N
  910. //game_flags = FLAG_ALL_MASK; // Set all
  911. //DC27_UpdateFlags(false);
  912.  
  913. #ifdef __BADGE_MAGIC // reset game flags, since they're not being used
  914. game_flags = 0;
  915. DC27_UpdateFlags(false);
  916. #endif
  917.  
  918. // read game flags from non-volatile Flash (persists between power cycles)
  919. KL_Flash_Read(&data);
  920. if (data == 0xFFFFFFFF) // on first use/power-up of the badge, the flash area will be uninitialized
  921. {
  922. game_flags = 0; // clear flags
  923. DC27_UpdateFlags(false); // write back to flash
  924. }
  925. else
  926. {
  927. game_flags = (uint8_t)data;
  928. if ((game_flags & FLAG_ALL_MASK) == FLAG_ALL_MASK) // if quest is complete...
  929. {
  930. badge_state = COMPLETE; // go straight to sparkle mode
  931. }
  932. else
  933. {
  934. game_flags &= ~FLAG_0_MASK; // clear flag (require communication with another person on power-up)
  935. }
  936. }
  937.  
  938. DC27_PrintState();
  939. }
  940.  
  941. /**************************************************************/
  942.  
  943. void DC27_UpdateState(void)
  944. {
  945. static int i, j;
  946. uint8_t ch;
  947.  
  948. switch (badge_state)
  949. {
  950. default:
  951. case ATTRACT: // Attract mode: Cycle through D, E, F, C, O, N LED states
  952. if (g_nxhDetect && !KL_GetPacket_NXH2261(&nxhRxPacket)) // if we have packet(s) in the receive buffer
  953. {
  954. DC27_ProcessPacket(); // process the first one
  955. }
  956. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear the rest
  957. g_nxhDetect = false;
  958.  
  959. if ((game_flags & FLAG_0_MASK) == 1) // Communication with anyone
  960. {
  961. // set badge state accordingly based on game flags settings
  962. // flags 1-5 can happen in any order, so badge state is determined
  963. // by how many bits have been set so far
  964. ch = 0;
  965. j = game_flags >> 1;
  966. for (i = 0; i < 5; ++i)
  967. {
  968. ch += (j & 0x01);
  969. j >>= 1;
  970. }
  971.  
  972. switch (ch)
  973. {
  974. case 0:
  975. badge_state = D;
  976. break;
  977. case 1:
  978. badge_state = E;
  979. break;
  980. case 2:
  981. badge_state = F;
  982. break;
  983. case 3:
  984. badge_state = C;
  985. break;
  986. case 4:
  987. badge_state = O;
  988. break;
  989. case 5:
  990. badge_state = N;
  991. break;
  992. }
  993.  
  994. DC27_UpdateDisplay();
  995. KL_Piezo_1Up();
  996. DC27_PrintState();
  997. SysTick_DelayTicks(500);
  998. LP5569_SetLED_AllOff();
  999. DC27_UpdateFlags(true);
  1000. }
  1001. break;
  1002.  
  1003. case D:
  1004. if (g_nxhDetect && !KL_GetPacket_NXH2261(&nxhRxPacket)) // if we have packet(s) in the receive buffer
  1005. {
  1006. DC27_ProcessPacket(); // process the first one
  1007. #ifdef __BADGE_MAGIC
  1008. LP5569_SetLED_AllOn();
  1009. #else
  1010. DC27_UpdateDisplay();
  1011. #endif
  1012. SysTick_DelayTicks(500);
  1013. LP5569_SetLED_AllOff();
  1014. }
  1015. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear the rest
  1016. g_nxhDetect = false;
  1017.  
  1018. #ifndef __BADGE_MAGIC // magic token stays in this state
  1019. if (nxhRxPacket.magic == true) // if we've received data from a magic token
  1020. {
  1021. if (DC27_IncrementFlag()) // if we've received a flag we don't already have, move to the next state
  1022. {
  1023. SysTick_DelayTicks(500);
  1024. badge_state = E;
  1025. DC27_UpdateDisplay();
  1026. KL_Piezo_1Up();
  1027. DC27_PrintState();
  1028. SysTick_DelayTicks(500);
  1029. LP5569_SetLED_AllOff();
  1030. DC27_UpdateFlags(true);
  1031. }
  1032. }
  1033. #endif
  1034. break;
  1035.  
  1036. case E:
  1037. if (g_nxhDetect && !KL_GetPacket_NXH2261(&nxhRxPacket)) // if we have packet(s) in the receive buffer
  1038. {
  1039. DC27_ProcessPacket(); // process the first one
  1040. DC27_UpdateDisplay();
  1041. SysTick_DelayTicks(500);
  1042. LP5569_SetLED_AllOff();
  1043. }
  1044. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear the rest
  1045. g_nxhDetect = false;
  1046.  
  1047. if (nxhRxPacket.magic == true) // if we've received data from a magic token
  1048. {
  1049. if (DC27_IncrementFlag()) // if we've received a flag we don't already have, move to the next state
  1050. {
  1051. SysTick_DelayTicks(500);
  1052. badge_state = F;
  1053. DC27_UpdateDisplay();
  1054. KL_Piezo_1Up();
  1055. DC27_PrintState();
  1056. SysTick_DelayTicks(500);
  1057. LP5569_SetLED_AllOff();
  1058. DC27_UpdateFlags(true);
  1059. }
  1060. }
  1061. break;
  1062.  
  1063. case F:
  1064. if (g_nxhDetect && !KL_GetPacket_NXH2261(&nxhRxPacket)) // if we have packet(s) in the receive buffer
  1065. {
  1066. DC27_ProcessPacket(); // process the first one
  1067. DC27_UpdateDisplay();
  1068. SysTick_DelayTicks(500);
  1069. LP5569_SetLED_AllOff();
  1070. }
  1071. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear the rest
  1072. g_nxhDetect = false;
  1073.  
  1074. if (nxhRxPacket.magic == true) // if we've received data from a magic token
  1075. {
  1076. if (DC27_IncrementFlag()) // if we've received a flag we don't already have, move to the next state
  1077. {
  1078. SysTick_DelayTicks(500);
  1079. badge_state = C;
  1080. DC27_UpdateDisplay();
  1081. KL_Piezo_1Up();
  1082. DC27_PrintState();
  1083. SysTick_DelayTicks(500);
  1084. LP5569_SetLED_AllOff();
  1085. DC27_UpdateFlags(true);
  1086. }
  1087. }
  1088. break;
  1089.  
  1090. case C:
  1091. if (g_nxhDetect && !KL_GetPacket_NXH2261(&nxhRxPacket)) // if we have packet(s) in the receive buffer
  1092. {
  1093. DC27_ProcessPacket(); // process the first one
  1094. DC27_UpdateDisplay();
  1095. SysTick_DelayTicks(500);
  1096. LP5569_SetLED_AllOff();
  1097. }
  1098. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear the rest
  1099. g_nxhDetect = false;
  1100.  
  1101. if (nxhRxPacket.magic == true) // if we've received data from a magic token
  1102. {
  1103. if (DC27_IncrementFlag()) // if we've received a flag we don't already have, move to the next state
  1104. {
  1105. SysTick_DelayTicks(500);
  1106. badge_state = O;
  1107. DC27_UpdateDisplay();
  1108. KL_Piezo_1Up();
  1109. DC27_PrintState();
  1110. SysTick_DelayTicks(500);
  1111. LP5569_SetLED_AllOff();
  1112. DC27_UpdateFlags(true);
  1113. }
  1114. }
  1115. break;
  1116.  
  1117. case O:
  1118. if (g_nxhDetect && !KL_GetPacket_NXH2261(&nxhRxPacket)) // if we have packet(s) in the receive buffer
  1119. {
  1120. DC27_ProcessPacket(); // process the first one
  1121. DC27_UpdateDisplay();
  1122. SysTick_DelayTicks(500);
  1123. LP5569_SetLED_AllOff();
  1124. }
  1125. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear the rest
  1126. g_nxhDetect = false;
  1127.  
  1128. if (nxhRxPacket.magic == true) // if we've received data from a magic token
  1129. {
  1130. if (DC27_IncrementFlag()) // if we've received a flag we don't already have, move to the next state
  1131. {
  1132. SysTick_DelayTicks(500);
  1133. badge_state = N;
  1134. DC27_UpdateDisplay();
  1135. KL_Piezo_1Up();
  1136. DC27_PrintState();
  1137. SysTick_DelayTicks(500);
  1138. LP5569_SetLED_AllOff();
  1139. DC27_UpdateFlags(true);
  1140. group_flags = 0;
  1141. }
  1142. }
  1143. break;
  1144.  
  1145. case N: // Group chat (all 6 gemstone colors: Human/Contest/Artist/CFP/Uber + Goon + Speaker + Vendor + Press + Village)
  1146. if (g_nxhDetect && !KL_GetPacket_NXH2261(&nxhRxPacket)) // if we have packet(s) in the receive buffer
  1147. {
  1148. DC27_ProcessPacket(); // process the first one
  1149. DC27_UpdateDisplay();
  1150. SysTick_DelayTicks(500);
  1151. LP5569_SetLED_AllOff();
  1152. }
  1153. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear the rest
  1154. g_nxhDetect = false;
  1155.  
  1156. switch (nxhRxPacket.type)
  1157. {
  1158. case HUMAN:
  1159. case CONTEST:
  1160. case ARTIST:
  1161. case CFP:
  1162. case UBER:
  1163. group_flags |= FLAG_0_MASK;
  1164. break;
  1165. case GOON:
  1166. group_flags |= FLAG_1_MASK;
  1167. break;
  1168. case SPEAKER:
  1169. group_flags |= FLAG_2_MASK;
  1170. break;
  1171. case VENDOR:
  1172. group_flags |= FLAG_3_MASK;
  1173. break;
  1174. case PRESS:
  1175. group_flags |= FLAG_4_MASK;
  1176. break;
  1177. case VILLAGE:
  1178. group_flags |= FLAG_5_MASK;
  1179. break;
  1180. }
  1181.  
  1182. // win!
  1183. if ((group_flags & GROUP_ALL_MASK) == GROUP_ALL_MASK)
  1184. {
  1185. game_flags |= FLAG_6_MASK;
  1186. badge_state = COMPLETE;
  1187. LP5569_SetLED_AllOff();
  1188. SysTick_DelayTicks(500);
  1189. KL_Piezo_RickRoll();
  1190. DC27_PrintState();
  1191. DC27_UpdateFlags(true);
  1192. SysTick_DelayTicks(1500);
  1193. }
  1194. break;
  1195.  
  1196. case COMPLETE: // Sparkle mode
  1197. DC27_UpdateDisplay();
  1198. LPTMR_SetTimerPeriod(LPTMR0_PERIPHERAL, LED_SPARKLE_WAIT_DELAY); // Set time to sleep between LED updates
  1199. while (!KL_GetPacket_NXH2261(&nxhRxPacket)){}; // clear any packets from buffer so we don't overflow
  1200. g_nxhDetect = false;
  1201. KL_Sleep(); // Go to sleep until our delay period is complete
  1202. break;
  1203. }
  1204. }
  1205.  
  1206. /**************************************************************/
  1207.  
  1208. void DC27_UpdateDisplay(void) // update LEDs based on current state
  1209. {
  1210. static volatile int j;
  1211.  
  1212. switch (badge_state)
  1213. {
  1214. default:
  1215. case ATTRACT: // Attract mode: Cycle through D, E, F, C, O, N LED states
  1216. switch (attract_state)
  1217. {
  1218. case D:
  1219. LP5569_RampLED(D);
  1220. attract_state = E;
  1221. break;
  1222. case E:
  1223. LP5569_RampLED(E);
  1224. attract_state = F;
  1225. break;
  1226. case F:
  1227. LP5569_RampLED(F);
  1228. attract_state = C;
  1229. break;
  1230. case C:
  1231. LP5569_RampLED(C);
  1232. attract_state = O;
  1233. break;
  1234. case O:
  1235. LP5569_RampLED(O);
  1236. attract_state = N;
  1237. break;
  1238. case N:
  1239. LP5569_RampLED(N);
  1240. attract_state = D;
  1241. break;
  1242. case ATTRACT: // unused states
  1243. case COMPLETE:
  1244. default:
  1245. attract_state = D;
  1246. break;
  1247. }
  1248. break;
  1249.  
  1250. case D:
  1251. LP5569_SetLED_D(LP5569_PWM);
  1252. break;
  1253.  
  1254. case E:
  1255. LP5569_SetLED_E(LP5569_PWM);
  1256. break;
  1257.  
  1258. case F:
  1259. LP5569_SetLED_F(LP5569_PWM);
  1260. break;
  1261.  
  1262. case C:
  1263. LP5569_SetLED_C(LP5569_PWM);
  1264. break;
  1265.  
  1266. case O:
  1267. LP5569_SetLED_O(LP5569_PWM);
  1268. break;
  1269.  
  1270. case N:
  1271. LP5569_SetLED_N(LP5569_PWM);
  1272. break;
  1273.  
  1274. case COMPLETE:
  1275. for (j = 0; j <= LP5569_PWM; j++) // ramp up to maximum defined brightness
  1276. {
  1277. LP5569_SetLED(1, j);
  1278. LP5569_SetLED(4, j);
  1279.  
  1280. SysTick_DelayTicks(LED_SPARKLE_FADE_DELAY);
  1281. }
  1282.  
  1283. SysTick_DelayTicks(LED_SPARKLE_ON_DELAY);
  1284.  
  1285. LP5569_SetLED_AllOff(); // clear display
  1286. LP5569_SetLED(0, LP5569_PWM);
  1287. LP5569_SetLED(3, LP5569_PWM);
  1288. SysTick_DelayTicks(LED_SPARKLE_ON_DELAY);
  1289.  
  1290. LP5569_SetLED_AllOff(); // clear display
  1291. LP5569_SetLED(1, LP5569_PWM);
  1292. LP5569_SetLED(4, LP5569_PWM);
  1293. SysTick_DelayTicks(LED_SPARKLE_ON_DELAY);
  1294.  
  1295. LP5569_SetLED_AllOff(); // clear display
  1296. LP5569_SetLED(2, LP5569_PWM);
  1297. LP5569_SetLED(5, LP5569_PWM);
  1298. SysTick_DelayTicks(LED_SPARKLE_ON_DELAY);
  1299.  
  1300. LP5569_SetLED_AllOff(); // clear display
  1301. LP5569_SetLED(1, LP5569_PWM);
  1302. LP5569_SetLED(4, LP5569_PWM);
  1303. SysTick_DelayTicks(LED_SPARKLE_ON_DELAY);
  1304.  
  1305. for (j = LP5569_PWM; j >= 0; j--) // ramp down from maximum defined brightness
  1306. {
  1307. LP5569_SetLED(1, j);
  1308. LP5569_SetLED(4, j);
  1309.  
  1310. SysTick_DelayTicks(LED_SPARKLE_FADE_DELAY);
  1311. }
  1312.  
  1313. break;
  1314. }
  1315. }
  1316.  
  1317. /**************************************************************/
  1318.  
  1319. void DC27_UpdateFlags(bool updateNXH)
  1320. {
  1321. // write game flags to non-volatile Flash (persists between power cycles)
  1322. if (KL_Flash_Write((uint32_t)game_flags))
  1323. {
  1324. if (KL_Flash_Write((uint32_t)game_flags))
  1325. {
  1326. KL_Error(true, false); // Beep the piezo to indicate a failure
  1327. PRINTF("[*] Flash Write Error!\n\r");
  1328. }
  1329. }
  1330.  
  1331. nxhTxPacket.flags = game_flags; // game flags (packed, MSB unused)
  1332.  
  1333. if (updateNXH)
  1334. {
  1335. EnableIRQ(LPUART0_SERIAL_RX_TX_IRQN);
  1336. if (KL_UpdatePacket_NXH2261(nxhTxPacket)) // load updated transmit packet into the NXH2261
  1337. {
  1338. if (KL_UpdatePacket_NXH2261(nxhTxPacket))
  1339. PRINTF(msg_nfmi_packet_err);
  1340. }
  1341. DisableIRQ(LPUART0_SERIAL_RX_TX_IRQN);
  1342. }
  1343. }
  1344.  
  1345. /**************************************************************/
  1346.  
  1347. int DC27_IncrementFlag(void)
  1348. {
  1349. switch (nxhRxPacket.type)
  1350. {
  1351. case SPEAKER:
  1352. if ((game_flags & FLAG_1_MASK) == 0)
  1353. {
  1354. game_flags |= FLAG_1_MASK;
  1355. return 1;
  1356. }
  1357. break;
  1358.  
  1359. case VILLAGE:
  1360. if ((game_flags & FLAG_2_MASK) == 0)
  1361. {
  1362. game_flags |= FLAG_2_MASK;
  1363. return 1;
  1364. }
  1365. break;
  1366.  
  1367. case CONTEST:
  1368. if ((game_flags & FLAG_3_MASK) == 0)
  1369. {
  1370. game_flags |= FLAG_3_MASK;
  1371. return 1;
  1372. }
  1373. break;
  1374.  
  1375. case ARTIST:
  1376. if ((game_flags & FLAG_4_MASK) == 0)
  1377. {
  1378. game_flags |= FLAG_4_MASK;
  1379. return 1;
  1380. }
  1381. break;
  1382.  
  1383. case GOON:
  1384. if ((game_flags & FLAG_5_MASK) == 0)
  1385. {
  1386. game_flags |= FLAG_5_MASK;
  1387. return 1;
  1388. }
  1389. break;
  1390. }
  1391.  
  1392. return 0;
  1393. }
  1394.  
  1395. /**************************************************************/
  1396.  
  1397. void DC27_PrintBadgeType(badge_type_t badge) // print badge type to console
  1398. {
  1399. switch(badge)
  1400. {
  1401. case HUMAN:
  1402. PRINTF("Human");
  1403. break;
  1404. case GOON:
  1405. PRINTF("Goon");
  1406. break;
  1407. case SPEAKER:
  1408. PRINTF("Speaker");
  1409. break;
  1410. case VENDOR:
  1411. PRINTF("Vendor");
  1412. break;
  1413. case PRESS:
  1414. PRINTF("Press");
  1415. break;
  1416. case VILLAGE:
  1417. PRINTF("Village");
  1418. break;
  1419. case CONTEST:
  1420. PRINTF("Contest");
  1421. break;
  1422. case ARTIST:
  1423. PRINTF("Artist");
  1424. break;
  1425. case CFP:
  1426. PRINTF("CFP");
  1427. break;
  1428. case UBER:
  1429. PRINTF("Uber");
  1430. break;
  1431. default:
  1432. PRINTF("Unknown");
  1433. }
  1434.  
  1435. PRINTF("\n\r");
  1436. }
  1437.  
  1438. /**************************************************************/
  1439.  
  1440. void DC27_PrintState(void) // print current state and game flags to console
  1441. {
  1442. PRINTF("[*] Badge State = ");
  1443.  
  1444. switch (badge_state)
  1445. {
  1446. default:
  1447. case ATTRACT:
  1448. PRINTF("Attract");
  1449. break;
  1450.  
  1451. case D:
  1452. PRINTF("D");
  1453. break;
  1454.  
  1455. case E:
  1456. PRINTF("E");
  1457. break;
  1458.  
  1459. case F:
  1460. PRINTF("F");
  1461. break;
  1462.  
  1463. case C:
  1464. PRINTF("C");
  1465. break;
  1466.  
  1467. case O:
  1468. PRINTF("O");
  1469. break;
  1470.  
  1471. case N:
  1472. PRINTF("N");
  1473. break;
  1474.  
  1475. case COMPLETE:
  1476. PRINTF("Hax0r");
  1477. break;
  1478. }
  1479.  
  1480. PRINTF("\n\r");
  1481.  
  1482. PRINTF("[*] Game Flags = ");
  1483. Print_Bits(game_flags);
  1484. PRINTF("\n\r");
  1485. }
  1486.  
  1487. /**************************************************************/
  1488.  
  1489. void DC27_PrintPacket(struct packet_of_infamy packet)
  1490. {
  1491. // display hex data from data packet struct
  1492. const unsigned char *buffer = (unsigned char*)&packet;
  1493.  
  1494. PRINTF("0x%02X%02X%02X%02X%02X%02X%02X%02X\n\r", buffer[3], buffer[2], buffer[1], buffer[0], buffer[4], buffer[5], buffer[6], buffer[7]);
  1495. PRINTF("-> Unique ID: 0x%08X\n\r", packet.uid);
  1496. PRINTF("-> Badge Type: ");
  1497. DC27_PrintBadgeType(packet.type);
  1498. PRINTF("-> Magic Token: ");
  1499. if (packet.magic != 0)
  1500. PRINTF("Yes");
  1501. else
  1502. PRINTF("No");
  1503. PRINTF("\n\r-> Game Flags: ");
  1504. Print_Bits(packet.flags); // MSB unused
  1505. PRINTF("\n\r");
  1506. }
  1507.  
  1508. /**************************************************************/
  1509.  
  1510. void DC27_ProcessPacket(void)
  1511. {
  1512. DC27_PrintPacket(nxhRxPacket); // print packet structure to debug console
  1513. PRINTF("\n\r");
  1514.  
  1515. if ((game_flags & FLAG_0_MASK) == 0) // on first read, set game flag
  1516. {
  1517. game_flags |= FLAG_0_MASK;
  1518. }
  1519. }
  1520.  
  1521. /**************************************************************/
  1522.  
  1523. void DC27_InteractiveMode(void)
  1524. {
  1525. size_t i;
  1526. uint8_t ch, inputString[CONSOLE_RCVBUF_SIZE];
  1527. uint32_t len;
  1528.  
  1529. PRINTF(msg_interactive_mode);
  1530.  
  1531. while(1)
  1532. {
  1533. PRINTF(command_prompt);
  1534. len = 0;
  1535. while(1)
  1536. {
  1537. ch = GETCHAR(); // get character from the user (blocking)
  1538. inputString[len] = ch; // add to input buffer
  1539. len += 1;
  1540. if (ch == 24) // CAN (Ctrl-X)
  1541. {
  1542. PRINTF(msg_interactive_exit);
  1543. return;
  1544. }
  1545. else if (ch == '\n' || ch == '\r' || (len > CONSOLE_RCVBUF_SIZE - 1)) // take input until CR, LF, or maximum length received
  1546. {
  1547. inputString[len - 1] = '\0';
  1548. break;
  1549. }
  1550. }
  1551.  
  1552. len = strlen((char *)inputString);
  1553. switch(inputString[0])
  1554. {
  1555. case 'T': // Display transmit packet
  1556. case 't':
  1557. if (len != 1) // if input string is longer than allowable for this command, ignore it
  1558. dc27_invalid_cmd();
  1559. else
  1560. {
  1561. DC27_PrintPacket(nxhTxPacket); // print packet structure to debug console
  1562. }
  1563. break;
  1564.  
  1565. case 'R': // Receive data packet(s)
  1566. case 'r':
  1567. if (len != 1) // if input string is longer than allowable for this command, ignore it
  1568. dc27_invalid_cmd();
  1569. else
  1570. {
  1571. i = 0;
  1572. while (KL_GetPacket_NXH2261(&nxhRxPacket)) // if there is no available packet...
  1573. {
  1574. if (i == 0) // only print message one time
  1575. {
  1576. PRINTF("Waiting for Packet(s)...\n\r");
  1577. i = 1;
  1578. }
  1579.  
  1580. g_nxhDetect = false;
  1581. while (!g_nxhDetect) // wait here until a new packet has been received
  1582. {
  1583. if (!KL_Check_RX())
  1584. {
  1585. PRINTF(msg_interactive_exit);
  1586. return; // exit interactive mode if USB-to-serial adapter is removed
  1587. }
  1588. }
  1589. g_nxhDetect = false;
  1590. }
  1591.  
  1592. DC27_ProcessPacket();
  1593. if (badge_state == ATTRACT || badge_state == COMPLETE)
  1594. {
  1595. LP5569_SetLED_AllOn();
  1596. }
  1597. else
  1598. {
  1599. DC27_UpdateDisplay(); // update LEDs based on current state
  1600. }
  1601. SysTick_DelayTicks(500);
  1602. LP5569_SetLED_AllOff();
  1603.  
  1604. // get any other packet(s) from the ring buffer
  1605. while (!KL_GetPacket_NXH2261(&nxhRxPacket))
  1606. {
  1607. DC27_ProcessPacket();
  1608. if (badge_state == ATTRACT || badge_state == COMPLETE)
  1609. {
  1610. LP5569_SetLED_AllOn();
  1611. }
  1612. else
  1613. {
  1614. DC27_UpdateDisplay(); // update LEDs based on current state
  1615. }
  1616. SysTick_DelayTicks(500);
  1617. LP5569_SetLED_AllOff();
  1618. }
  1619. }
  1620. break;
  1621.  
  1622. case 'C': // Clear game flags
  1623. case 'c':
  1624. if (len != 1) // if input string is longer than allowable for this command, ignore it
  1625. dc27_invalid_cmd();
  1626. else
  1627. {
  1628. PRINTF("Clear Game Flags? Are You Sure? [y/N] ");
  1629. len = 0;
  1630. while(1)
  1631. {
  1632. ch = GETCHAR(); // get character from the user (blocking)
  1633. inputString[len] = ch; // add to input buffer
  1634. len += 1;
  1635. if (ch == '\n' || ch == '\r' || (len > CONSOLE_RCVBUF_SIZE - 1)) // take input until CR, LF, or maximum length received
  1636. {
  1637. inputString[len - 1] = '\0';
  1638. break;
  1639. }
  1640. }
  1641. len = strlen((char *)inputString);
  1642. if (len == 1 && (inputString[0] == 'Y' || inputString[0] == 'y'))
  1643. {
  1644. game_flags = 0; // Clear game flags
  1645. DC27_UpdateFlags(true);
  1646. PRINTF("-> Game Flags: ");
  1647. Print_Bits(game_flags); // MSB unused
  1648. PRINTF("\n\r");
  1649. }
  1650. }
  1651. break;
  1652.  
  1653. case '^':
  1654. NVIC_SystemReset(); // System reset (does not return)
  1655. break;
  1656.  
  1657. case 'A': // ASCII art generator
  1658. case 'a':
  1659. if (badge_state != COMPLETE)
  1660. dc27_invalid_cmd();
  1661. else if (len <= 2)
  1662. {
  1663. strcpy((char *)inputString, ART_DEFAULT);
  1664. DC27_ASCIIArt(inputString); // use default string if none provided on the command line
  1665. }
  1666. else
  1667. DC27_ASCIIArt(inputString + 2); // send user-defined string to the ASCII art generator
  1668. break;
  1669.  
  1670. case 'S': // Tone generator
  1671. case 's':
  1672. if (len < 5 || badge_state != COMPLETE)
  1673. dc27_invalid_cmd();
  1674. else
  1675. {
  1676. uint32_t freq = 0, duration = 0;
  1677. sscanf((char *)(inputString + 2), "%d %d", &freq, &duration);
  1678. KL_Piezo(freq, duration, 50);
  1679. }
  1680. break;
  1681.  
  1682. case 'U': // Update outgoing data packet
  1683. case 'u':
  1684. if (len < 18 || badge_state != COMPLETE)
  1685. dc27_invalid_cmd();
  1686. else
  1687. {
  1688. // convert all alphabetic characters to upper case
  1689. for (i = 0; i < len; ++i)
  1690. {
  1691. if (inputString[i] >= 'a' && inputString[i] <= 'z')
  1692. inputString[i] -= 0x20;
  1693. }
  1694. unsigned long data_low = strtoul((const char*)(inputString + 10), NULL, 16);
  1695. inputString[10] = '\0';
  1696. unsigned long data_high = strtoul((const char*)(inputString + 2), NULL, 16);
  1697. PRINTF("0x%08X%08X\n\r", data_high, data_low);
  1698. PRINTF("Update Transmit Packet? Are You Sure? [y/N] ");
  1699. len = 0;
  1700. while(1)
  1701. {
  1702. ch = GETCHAR(); // get character from the user (blocking)
  1703. inputString[len] = ch; // add to input buffer
  1704. len += 1;
  1705. if (ch == '\n' || ch == '\r' || (len > CONSOLE_RCVBUF_SIZE - 1)) // take input until CR, LF, or maximum length received
  1706. {
  1707. inputString[len - 1] = '\0';
  1708. break;
  1709. }
  1710. }
  1711. len = strlen((char *)inputString);
  1712. if (len == 1 && (inputString[0] == 'Y' || inputString[0] == 'y'))
  1713. {
  1714. // Craft new data packet for radio to transmit
  1715. nxhTxPacket.uid = data_high; // unique ID
  1716. nxhTxPacket.type = (data_low >> 24) & 0xFF; // badge type
  1717. nxhTxPacket.magic = (data_low >> 16) & 0xFF; // magic token (1 = enabled)
  1718. nxhTxPacket.flags = (data_low >> 8) & 0xFF; // game flags (packed, MSB unused)
  1719. nxhTxPacket.unused = data_low & 0xFF; // unused
  1720.  
  1721. if (KL_UpdatePacket_NXH2261(nxhTxPacket)) // load packet to the NXH2261
  1722. {
  1723. if (KL_UpdatePacket_NXH2261(nxhTxPacket))
  1724. PRINTF(msg_nfmi_packet_err);
  1725. }
  1726. else
  1727. PRINTF("-> Done!\n\r");
  1728. }
  1729. }
  1730. break;
  1731.  
  1732. case 'H': // Display menu
  1733. case 'h':
  1734. case '?':
  1735. if (len != 1) // if input string is longer than allowable for this command, ignore it
  1736. dc27_invalid_cmd();
  1737. else
  1738. {
  1739. PRINTF(menu_banner);
  1740.  
  1741. if (badge_state == COMPLETE) // if badge tasks are complete, display additional menu items
  1742. PRINTF(menu_banner_complete);
  1743. }
  1744. break;
  1745. default: // Command not recognized
  1746. dc27_invalid_cmd();
  1747. break;
  1748. }
  1749. }
  1750. }
  1751.  
  1752. /**************************************************************/
  1753.  
  1754. // ASCII art generator
  1755. // Inspired by:
  1756. // https://twitter.com/ef1j95/status/1101865167741173760
  1757. // http://www.vintage-basic.net/bcg/love.bas
  1758. // https://www.associationforpublicart.org/artwork/love/
  1759. void DC27_ASCIIArt(uint8_t *A)
  1760. {
  1761. volatile uint32_t I, J, L, C, P, A1, ptr;
  1762. uint8_t T[120]; // crafted line of text to print
  1763.  
  1764. L = strlen((char *)A); // input text from user
  1765.  
  1766. // craft a line based on the input text from user
  1767. for (J = 0; J < (ART_WIDTH / L) + 1; J++)
  1768. {
  1769. for (I = 0; I < L; I++) // repeat the input text for the entire line
  1770. {
  1771. T[(J * L) + I] = A[I];
  1772. }
  1773. }
  1774.  
  1775. C = 0;
  1776. A1 = 0;
  1777. ptr = 0;
  1778.  
  1779. while(1)
  1780. {
  1781. if (A1 == 0 || A1 > ART_WIDTH) // print one line at a time
  1782. {
  1783. A1 = 1; // current column count into the line
  1784. P = 0; // flag to print message characters (true) or spaces (false)
  1785. C += 1;
  1786. if (C == ART_LINES) // if we've reached the end of our artwork
  1787. {
  1788. PRINTF("\n\r");
  1789. return; // done!
  1790. }
  1791. PRINTF("\n\r ");
  1792. }
  1793.  
  1794. A[0] = ART_DATA[ptr++]; // read from the data array (number of the next set of characters or spaces)
  1795. A1 += A[0];
  1796. if (P)
  1797. {
  1798. for (I = (A1 - A[0] - 1); I < A1 - 1; I++)
  1799. {
  1800. PRINTF("%c", T[I]); // print character from the crafted message array
  1801. }
  1802. P = 0;
  1803. }
  1804. else
  1805. {
  1806. for (I = 0; I < A[0]; I++)
  1807. {
  1808. PRINTF(" "); // print space
  1809. }
  1810. P = 1;
  1811. }
  1812. }
  1813. }
  1814.  
  1815. /**************************************************************/
  1816.  
  1817. int KL_Flash_Init(void)
  1818. {
  1819. ftfx_security_state_t securityStatus = kFTFx_SecurityStateNotSecure; // Memory protection status
  1820. status_t result; // Return code from each flash driver function
  1821.  
  1822. // Clear structs
  1823. memset(&s_flashDriver, 0, sizeof(flash_config_t));
  1824. memset(&s_cacheDriver, 0, sizeof(ftfx_cache_config_t));
  1825.  
  1826. // Setup flash driver
  1827. result = FLASH_Init(&s_flashDriver);
  1828. if (result != kStatus_FTFx_Success)
  1829. {
  1830. return 1;
  1831. }
  1832.  
  1833. // Setup flash cache driver
  1834. result = FTFx_CACHE_Init(&s_cacheDriver);
  1835. if (result != kStatus_FTFx_Success)
  1836. {
  1837. return 1;
  1838. }
  1839.  
  1840. // Check security status
  1841. result = FLASH_GetSecurityState(&s_flashDriver, &securityStatus);
  1842. if (result != kStatus_FTFx_Success)
  1843. {
  1844. return 1;
  1845. }
  1846.  
  1847. // Only proceed with unprotected memory (we won't be able to read/write otherwise)
  1848. if (securityStatus != kFTFx_SecurityStateNotSecure)
  1849. {
  1850. return 1;
  1851. }
  1852.  
  1853. // Get flash properties
  1854. FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0BlockBaseAddr, &pflashBlockBase);
  1855. FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0TotalSize, &pflashTotalSize);
  1856. FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0SectorSize, &pflashSectorSize);
  1857.  
  1858. // Print flash information to debug console
  1859. PRINTF("\n\r-> Memory Size = %dKB [0x%X]\n\r", (pflashTotalSize / 1024), pflashTotalSize);
  1860. PRINTF("-> Sector Size = %dKB [0x%X]\n\r", (pflashSectorSize / 1024), pflashSectorSize);
  1861.  
  1862. return 0;
  1863. }
  1864.  
  1865. /**************************************************************/
  1866.  
  1867. // Erase and write a single Flash sector
  1868. int KL_Flash_Write(uint32_t data)
  1869. {
  1870. status_t result; // Return code from each flash driver function
  1871. uint32_t destAddress; // Base address of the target memory location
  1872. uint32_t s_buffer[NVM_DATA_SIZE];
  1873. uint32_t i, failAddr, failDat;
  1874.  
  1875. __disable_irq(); // Disable all interrupts during Flash write operations
  1876.  
  1877. // Prepare flash cache/prefetch/speculation
  1878. FTFx_CACHE_ClearCachePrefetchSpeculation(&s_cacheDriver, true);
  1879.  
  1880. // In case of the protected sectors at the end of the pFlash just select
  1881. // the block from the end of pFlash to be used for operations
  1882. // SECTOR_INDEX_FROM_END = 1 means the last sector
  1883. // SECTOR_INDEX_FROM_END = 2 means (the last sector - 1)
  1884.  
  1885. // Erase a sector starting from destAddress
  1886. destAddress = pflashBlockBase + (pflashTotalSize - (SECTOR_INDEX_FROM_END * pflashSectorSize));
  1887. result = FLASH_Erase(&s_flashDriver, destAddress, pflashSectorSize, kFTFx_ApiEraseKey);
  1888. if (kStatus_FTFx_Success != result)
  1889. {
  1890. __enable_irq();
  1891. return 1;
  1892. }
  1893.  
  1894. // Prepare user buffer with data
  1895. for (i = 0; i < NVM_DATA_SIZE; i++)
  1896. {
  1897. s_buffer[i] = (data >> (24-(i*8))) & 0xFF;
  1898. }
  1899.  
  1900. // Program user buffer into flash
  1901. result = FLASH_Program(&s_flashDriver, destAddress, (uint8_t *)s_buffer, sizeof(s_buffer));
  1902. if (kStatus_FTFx_Success != result)
  1903. {
  1904. __enable_irq();
  1905. return 1;
  1906. }
  1907.  
  1908. // Verify programming
  1909. result = FLASH_VerifyProgram(&s_flashDriver, destAddress, sizeof(s_buffer), (const uint8_t *)s_buffer, kFTFx_MarginValueUser,
  1910. &failAddr, &failDat);
  1911. if (kStatus_FTFx_Success != result)
  1912. {
  1913. __enable_irq();
  1914. return 1;
  1915. }
  1916.  
  1917. // Clean-up
  1918. FTFx_CACHE_ClearCachePrefetchSpeculation(&s_cacheDriver, false);
  1919.  
  1920. __enable_irq();
  1921. return 0;
  1922. }
  1923.  
  1924. /**************************************************************/
  1925.  
  1926. void KL_Flash_Read(uint32_t *data)
  1927. {
  1928. uint32_t i;
  1929. uint32_t s_buffer_rbc[NVM_DATA_SIZE];
  1930. uint32_t destAddress; // Base address of the target memory location
  1931.  
  1932. // In case of the protected sectors at the end of the pFlash just select
  1933. // the block from the end of pFlash to be used for operations
  1934. // SECTOR_INDEX_FROM_END = 1 means the last sector
  1935. // SECTOR_INDEX_FROM_END = 2 means (the last sector - 1)
  1936.  
  1937. // calculate address
  1938. destAddress = pflashBlockBase + (pflashTotalSize - (SECTOR_INDEX_FROM_END * pflashSectorSize));
  1939.  
  1940. for (i = 0; i < NVM_DATA_SIZE; i++)
  1941. {
  1942. s_buffer_rbc[i] = *(volatile uint32_t *)(destAddress + i * 4);
  1943. }
  1944.  
  1945. for (i = 0; i < NVM_DATA_SIZE; i++)
  1946. {
  1947. *data <<= 8;
  1948. *data |= (s_buffer_rbc[i] & 0xFF);
  1949. }
  1950. }
  1951.  
  1952. /**************************************************************/
  1953.  
  1954. bool KL_Check_RX(void) // check if USB-to-Serial adapter is connected
  1955. {
  1956. bool res;
  1957.  
  1958. // re-map pin from KL_RX to GPIO E23
  1959. gpio_pin_config_t KL_RX_config = {
  1960. .pinDirection = kGPIO_DigitalInput,
  1961. .outputLogic = 0U
  1962. };
  1963. GPIO_PinInit(GPIOE, BOARD_INITPINS_KL_RX_PIN, &KL_RX_config);
  1964. PORT_SetPinMux(BOARD_INITPINS_KL_RX_PORT, BOARD_INITPINS_KL_RX_PIN, kPORT_MuxAsGpio);
  1965. PORTE->PCR[BOARD_INITPINS_KL_RX_PIN] = ((PORTE->PCR[BOARD_INITPINS_KL_RX_PIN] &
  1966. /* Mask bits to zero which are setting */
  1967. (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_ISF_MASK)))
  1968.  
  1969. /* Pull Select: Internal pulldown resistor is enabled on the corresponding pin, if the
  1970. * corresponding PE field is set. */
  1971. | (uint32_t)(kPORT_PullDown));
  1972. SysTick_DelayTicks(10);
  1973.  
  1974. res = (bool)GPIO_PinRead(GPIOE, BOARD_INITPINS_KL_RX_PIN);
  1975.  
  1976. // set KL_RX back to UART2_RX
  1977. PORT_SetPinInterruptConfig(BOARD_INITPINS_KL_RX_PORT, BOARD_INITPINS_KL_RX_PIN, kPORT_InterruptOrDMADisabled);
  1978. PORT_SetPinMux(BOARD_INITPINS_KL_RX_PORT, BOARD_INITPINS_KL_RX_PIN, kPORT_MuxAlt4);
  1979. SysTick_DelayTicks(10);
  1980.  
  1981. return res;
  1982. }
  1983.  
  1984. /**************************************************************/
  1985.  
  1986. void KL_Error(bool error_piezo, bool error_led)
  1987. {
  1988. int i;
  1989.  
  1990. if (error_piezo || error_led)
  1991. {
  1992. for (i = 0; i < 5; ++i)
  1993. {
  1994. if (error_led)
  1995. LP5569_SetLED_AllOn();
  1996.  
  1997. if (error_piezo)
  1998. KL_Piezo(2600, 250, 50);
  1999. else
  2000. SysTick_DelayTicks(250);
  2001.  
  2002. if (error_led)
  2003. LP5569_SetLED_AllOff();
  2004.  
  2005. SysTick_DelayTicks(250);
  2006. }
  2007. }
  2008. }
  2009.  
  2010. /**************************************************************/
  2011.  
  2012. void KL_Sleep(void)
  2013. {
  2014. if (badge_state == ATTRACT || badge_state == COMPLETE) // set timer for attract mode, otherwise only wake via NXH
  2015. {
  2016. LPTMR_StartTimer(LPTMR0_PERIPHERAL); // Start LPTMR for periodic interrupt (LED heartbeat)
  2017. }
  2018.  
  2019. SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; // Disable SysTick timer interrupt while we sleep
  2020.  
  2021. SMC_PreEnterStopModes();
  2022. SMC_SetPowerModeVlps(SMC); // Zzzz...
  2023. SMC_PostExitStopModes();
  2024.  
  2025. SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; // Re-enable SysTick timer interrupt
  2026. LPTMR_StopTimer(LPTMR0_PERIPHERAL); // Stop timer once we wake up
  2027. }
  2028.  
  2029. /**************************************************************/
  2030.  
  2031. // Output square wave to the piezo element using the provided parameters
  2032. // frequency (Hz), duration (ms), duty cycle (%)
  2033. void KL_Piezo(uint32_t freq_Hz, uint32_t duration_ms, uint8_t pwm_duty)
  2034. {
  2035. // Update parameters
  2036. if (freq_Hz > 0)
  2037. {
  2038. TPM_SetupPwm(TPM0_PERIPHERAL, TPM0_pwmSignalParams, 1, kTPM_EdgeAlignedPwm, freq_Hz, TPM0_CLOCK_SOURCE); // Frequency
  2039. TPM_UpdatePwmDutycycle(TPM0_PERIPHERAL,TPM0_pwmSignalParams->chnlNumber, kTPM_EdgeAlignedPwm, pwm_duty); // Duty cycle
  2040.  
  2041. TPM_StartTimer(TPM0_PERIPHERAL, kTPM_SystemClock); // Start the TPM counter
  2042. }
  2043.  
  2044. if (duration_ms > 0)
  2045. SysTick_DelayTicks(duration_ms); // Duration of note (delay for specified length in ms)
  2046.  
  2047. TPM_StopTimer(TPM0_PERIPHERAL); // Stop the TPM counter
  2048. }
  2049.  
  2050. /**************************************************************/
  2051.  
  2052. void KL_Piezo_1Up(void)
  2053. {
  2054. int i;
  2055.  
  2056. for (i = 0; i < sizeof(tune_1up) / sizeof(struct note); ++i)
  2057. {
  2058. KL_Piezo(tune_1up[i].freq, tune_1up[i].duration, tune_1up[i].duty);
  2059. SysTick_DelayTicks(10);
  2060. }
  2061. }
  2062.  
  2063. /**************************************************************/
  2064.  
  2065. void KL_Piezo_RickRoll(void)
  2066. {
  2067. int i, led_num;
  2068.  
  2069. SysTick_DelayTicks(250);
  2070. g_random = (unsigned char)SysTick->VAL; // Seed PRNG with current value of SysTick timer
  2071.  
  2072. /*for (i = 0; i < sizeof(tune_rickroll_intro) / sizeof(struct note); ++i)
  2073. {
  2074. led_num = Get_Random_Byte() % LP5569_LED_NUM;
  2075. if (tune_rickroll_intro[i].freq != NOTE_REST) LP5569_SetLED(led_num, LP5569_PWM[led_num]); // Enable LED to flash along with the music
  2076. KL_Piezo(tune_rickroll_intro[i].freq, tune_rickroll_intro[i].duration, tune_rickroll_intro[i].duty);
  2077. LP5569_SetLED(led_num, 0x00);
  2078. SysTick_DelayTicks(45);
  2079. }
  2080. for (i = 0; i < sizeof(tune_rickroll_verse) / sizeof(struct note); ++i)
  2081. {
  2082. led_num = Get_Random_Byte() % LP5569_LED_NUM;
  2083. if (tune_rickroll_verse[i].freq != NOTE_REST) LP5569_SetLED(led_num, LP5569_PWM[led_num]); // Enable LED to flash along with the music
  2084. PRINTF("%s", tune_rickroll_verse_lyrics[i]);
  2085. KL_Piezo(tune_rickroll_verse[i].freq, tune_rickroll_verse[i].duration, tune_rickroll_verse[i].duty);
  2086. LP5569_SetLED(led_num, 0x00);
  2087. SysTick_DelayTicks(30);
  2088. }*/
  2089. for (i = 0; i < sizeof(tune_rickroll_chorus) / sizeof(struct note); ++i)
  2090. {
  2091. led_num = Get_Random_Byte() % LP5569_LED_NUM;
  2092. if (tune_rickroll_chorus[i].freq != NOTE_REST) LP5569_SetLED(led_num, LP5569_PWM); // Enable LED to flash along with the music
  2093. PRINTF("%s", tune_rickroll_chorus_lyrics[i]);
  2094. KL_Piezo(tune_rickroll_chorus[i].freq, tune_rickroll_chorus[i].duration, tune_rickroll_chorus[i].duty);
  2095. LP5569_SetLED(led_num, 0x00);
  2096. SysTick_DelayTicks(30);
  2097. }
  2098. }
  2099.  
  2100. /**************************************************************/
  2101.  
  2102. int KL_Setup_NXH2261(void) // Configure NXH2261 NFMI Radio
  2103. {
  2104. // Program the NXH binary via I2C
  2105. if (KL_Program_NXH2261(NxH2281Eep_size, NxH2281Eep))
  2106. {
  2107. return 1; // Fail!
  2108. }
  2109.  
  2110. LP5569_SetLED(2, 0); // Update start-up progress via LEDs
  2111. LP5569_SetLED(3, 0);
  2112.  
  2113. PRINTF("-> Executing Program...");
  2114. KL_Reset_NXH2261();
  2115. SysTick_DelayTicks(200); // maximum delay of NXH2261 low-power state
  2116. PRINTF("Done!\n\r");
  2117.  
  2118. // Calibration process
  2119. PRINTF("-> Calibrating...");
  2120. CLOCK_SetClkOutClock(SIM_CLKOUT_SEL_OSCERCLK_CLK); // Set OSCERCLK to CLKOUT
  2121. SysTick_DelayTicks(100);
  2122.  
  2123. // Toggle NXH_UPDATE to switch NXH2261 into UART Open State (we need to be here in order to calibrate)
  2124. GPIO_PinWrite(BOARD_INITPINS_NXH_UPDATE_GPIO, BOARD_INITPINS_NXH_UPDATE_GPIO_PIN, HIGH);
  2125. SysTick_DelayTicks(500);
  2126. GPIO_PinWrite(BOARD_INITPINS_NXH_UPDATE_GPIO, BOARD_INITPINS_NXH_UPDATE_GPIO_PIN, LOW);
  2127.  
  2128. SysTick_DelayTicks(100);
  2129.  
  2130. // Toggle NXH_CAL to tell NXH2261 that we're ready to start calibration
  2131. GPIO_PinWrite(BOARD_INITPINS_NXH_CAL_GPIO, BOARD_INITPINS_NXH_CAL_GPIO_PIN, HIGH);
  2132. SysTick_DelayTicks(500);
  2133. GPIO_PinWrite(BOARD_INITPINS_NXH_CAL_GPIO, BOARD_INITPINS_NXH_CAL_GPIO_PIN, LOW);
  2134.  
  2135. SysTick_DelayTicks(500); // wait for calibration to complete (typical 50-150ms)
  2136. CLOCK_SetClkOutClock(0); // Turn off CLKOUT
  2137.  
  2138. PRINTF("Done!\n\r");
  2139.  
  2140. LP5569_SetLED(1, 0); // Update start-up progress via LEDs
  2141. LP5569_SetLED(4, 0);
  2142.  
  2143. return 0; // Success!
  2144. }
  2145.  
  2146. /**************************************************************/
  2147.  
  2148. int KL_Program_NXH2261(const uint32_t NxH2281Eep_size, const unsigned char *NxH2281Eep)
  2149. {
  2150. uint8_t i = 0;
  2151. uint32_t res;
  2152. uint8_t txbuf[12], rxbuf[12];
  2153.  
  2154. PRINTF("-> Entering Bootloader...");
  2155. KL_Reset_NXH2261();
  2156.  
  2157. // After reset, the NXH2261 waits 30ms before loading code from its internal EEPROM.
  2158. // Within this time, the host controller can send a Prevent Boot command, which forces
  2159. // the device into bootloader mode and allows us to send new firmware to its EEPROM.
  2160. do
  2161. {
  2162. res = 1;
  2163. txbuf[0] = LOW_BYTE(NXH2261_CMD_PREVENT_BOOT);
  2164. txbuf[1] = HIGH_BYTE(NXH2261_CMD_PREVENT_BOOT);
  2165. txbuf[2] = 0; // tag
  2166. I2C_WriteBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, txbuf, 3);
  2167. if (!I2C_ReadBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, rxbuf, 4))
  2168. {
  2169. // if I2C was successful, response should be all 0x00
  2170. res = rxbuf[0] | rxbuf[1] | rxbuf[2] | rxbuf[3];
  2171. }
  2172. SysTick_DelayTicks(5);
  2173. ++i;
  2174. } while (res != 0 && i < 100);
  2175.  
  2176. if (i >= 100) // Timeout
  2177. {
  2178. PRINTF("Error!\n\r");
  2179. return 1;
  2180. }
  2181.  
  2182. PRINTF("Done!\n\r");
  2183.  
  2184. // Get version information
  2185. txbuf[0] = LOW_BYTE(NXH2261_CMD_GET_VERSION);
  2186. txbuf[1] = HIGH_BYTE(NXH2261_CMD_GET_VERSION);
  2187. txbuf[2] = 0; // tag
  2188. I2C_WriteBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, txbuf, 3);
  2189. I2C_ReadBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, rxbuf, 9);
  2190. PRINTF("-> Firmware Version: 0x%02X 0x%02X\n\r", rxbuf[0], rxbuf[1]);
  2191. PRINTF("-> Hardware Version: 0x%02X%02X 0x%02X%02X\n\r", rxbuf[3], rxbuf[2], rxbuf[6], rxbuf[5]);
  2192. PRINTF("-> ROM Version: 0x%02X 0x%02X\n\r", rxbuf[7], rxbuf[8]);
  2193.  
  2194. PRINTF("-> Programming...");
  2195.  
  2196. // Enable the EEPROM in preparation to program
  2197. txbuf[0] = LOW_BYTE(NXH2261_CMD_EEPROM_ENABLE);
  2198. txbuf[1] = HIGH_BYTE(NXH2261_CMD_EEPROM_ENABLE);
  2199. txbuf[2] = 0; // tag
  2200. I2C_WriteBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, txbuf, 3);
  2201. if (!I2C_ReadBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, rxbuf, 4))
  2202. {
  2203. // if I2C was successful, response should be all 0x00
  2204. res = rxbuf[0] | rxbuf[1] | rxbuf[2] | rxbuf[3];
  2205. }
  2206. if (res != 0)
  2207. {
  2208. PRINTF("Error!\n\r");
  2209. return 1;
  2210. }
  2211.  
  2212. // Program the Cortex image at the primary boot location
  2213. // EEPROM has a write endurance of 100k cycles
  2214. if (KL_LoadImage_NXH2261(NxH2281Eep_size, NxH2281Eep, 0x0000UL))
  2215. {
  2216. PRINTF("Error!\n\r");
  2217. return 1;
  2218. }
  2219.  
  2220. // Disable the EEPROM when programming is complete
  2221. txbuf[0] = LOW_BYTE(NXH2261_CMD_EEPROM_DISABLE);
  2222. txbuf[1] = HIGH_BYTE(NXH2261_CMD_EEPROM_DISABLE);
  2223. txbuf[2] = 0; // tag
  2224. I2C_WriteBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, txbuf, 3);
  2225. if (!I2C_ReadBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, rxbuf, 4))
  2226. {
  2227. // if I2C was successful, response should be all 0x00
  2228. res = rxbuf[0] | rxbuf[1] | rxbuf[2] | rxbuf[3];
  2229. }
  2230. if (res != 0)
  2231. {
  2232. PRINTF("Error!\n\r");
  2233. return 1;
  2234. }
  2235.  
  2236. PRINTF("Done!\n\r");
  2237.  
  2238. return 0; // Success!
  2239. }
  2240.  
  2241. /**************************************************************/
  2242.  
  2243. int KL_LoadImage_NXH2261(uint32_t size, const uint8_t *data, uint32_t address)
  2244. {
  2245. uint32_t i;
  2246. uint16_t txaddr, chunkSize, cnt;
  2247. uint32_t res = 0;
  2248. uint8_t txbuf[NXH2261_MAX_CHUNK_SIZE + 8], rxbuf[NXH2261_MAX_CHUNK_SIZE + 8];
  2249.  
  2250. i = 0;
  2251. while (i < size)
  2252. {
  2253. // Setup parameters
  2254. chunkSize = ((size - i) > NXH2261_MAX_CHUNK_SIZE ? NXH2261_MAX_CHUNK_SIZE : (size - i)); // number of bytes to write
  2255. txaddr = address + (i / 4UL); // offset (word address) into the EEPROM
  2256.  
  2257. // Unlock EEPROM memory region for a single write
  2258. txbuf[0] = LOW_BYTE(NXH2261_CMD_EEPROM_UNLOCK);
  2259. txbuf[1] = HIGH_BYTE(NXH2261_CMD_EEPROM_UNLOCK);
  2260. txbuf[2] = 0; // tag
  2261. txbuf[3] = LOW_BYTE(txaddr);
  2262. txbuf[4] = HIGH_BYTE(txaddr);
  2263. txbuf[5] = LOW_BYTE(chunkSize);
  2264. txbuf[6] = HIGH_BYTE(chunkSize);
  2265. I2C_WriteBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, txbuf, 7);
  2266. if (!I2C_ReadBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, rxbuf, 4))
  2267. {
  2268. // if I2C was successful, response should be all 0x00
  2269. res = rxbuf[0] | rxbuf[1] | rxbuf[2] | rxbuf[3];
  2270. }
  2271. if (res != 0)
  2272. {
  2273. return 1;
  2274. }
  2275.  
  2276. // Write data to EEPROM
  2277. txbuf[0] = LOW_BYTE(NXH2261_CMD_EEPROM_WRITE);
  2278. txbuf[1] = HIGH_BYTE(NXH2261_CMD_EEPROM_WRITE);
  2279. txbuf[2] = 0; // tag
  2280. txbuf[3] = LOW_BYTE(txaddr);
  2281. txbuf[4] = HIGH_BYTE(txaddr);
  2282. txbuf[5] = 0;
  2283. txbuf[6] = 0;
  2284. txbuf[7] = LOW_BYTE(chunkSize);
  2285. txbuf[8] = HIGH_BYTE(chunkSize);
  2286. txbuf[9] = 0;
  2287. txbuf[10] = 0;
  2288. cnt = chunkSize; // move length into its own variable so memcpy doesn't erase it
  2289. memcpy(&txbuf[11], data + i, cnt);
  2290. I2C_WriteBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, txbuf, 11 + chunkSize);
  2291. if (!I2C_ReadBulk(I2C0_PERIPHERAL, I2C_NXH2261_ADDR, rxbuf, 4))
  2292. {
  2293. // if I2C was successful, response should be all 0x00
  2294. res = rxbuf[0] | rxbuf[1] | rxbuf[2] | rxbuf[3];
  2295. }
  2296. if (res != 0)
  2297. {
  2298. return 1;
  2299. }
  2300.  
  2301. i += chunkSize;
  2302. }
  2303.  
  2304. return 0; // Success!
  2305. }
  2306.  
  2307. /**************************************************************/
  2308.  
  2309. // retrieve the most recently received data packet from the ring buffer, if it exists
  2310. int KL_GetPacket_NXH2261(struct packet_of_infamy *rxPacket)
  2311. {
  2312. size_t i;
  2313. uint8_t ch, dataBlob[NXH2261_DATA_PACKET_SIZE], buf[NXH2261_DATA_PACKET_SIZE >> 1];
  2314.  
  2315. // increment through the buffer until we find the packet header
  2316. do
  2317. {
  2318. if (nxhRxIndex == nxhTxIndex) // we've reached the end of the buffer
  2319. return 1;
  2320.  
  2321. ch = nxhRingBuffer[nxhTxIndex];
  2322. nxhTxIndex++;
  2323. nxhTxIndex %= LPUART0_RING_BUFFER_SIZE;
  2324. } while (ch != 'B');
  2325.  
  2326. // extract the data contents from the buffer until we reach the packet footer
  2327. i = 0;
  2328. while ((ch = nxhRingBuffer[nxhTxIndex]) != 'E')
  2329. {
  2330. if (nxhRxIndex == nxhTxIndex) // we've reached the end of the buffer
  2331. return 1;
  2332.  
  2333. dataBlob[i] = ch;
  2334. i++;
  2335. nxhTxIndex++;
  2336. nxhTxIndex %= LPUART0_RING_BUFFER_SIZE;
  2337. }
  2338.  
  2339. // remove 0xD0 padding from each nibble
  2340. for (i = 0; i < (NXH2261_DATA_PACKET_SIZE >> 1) - 1; i++)
  2341. {
  2342. buf[i] = (dataBlob[i*2] & 0x0F) << 4;
  2343. buf[i] |= dataBlob[i*2 + 1] & 0x0F;
  2344. }
  2345.  
  2346. // Place data into proper structure
  2347. rxPacket->uid = (uint32_t)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); // unique ID
  2348. rxPacket->type = buf[4]; // badge type
  2349. rxPacket->magic = buf[5]; // magic token (1 = enabled)
  2350. rxPacket->flags = buf[6]; // game flags (packed, MSB unused)
  2351. rxPacket->unused = buf[7]; // unused
  2352.  
  2353. return 0;
  2354. }
  2355.  
  2356. /**************************************************************/
  2357.  
  2358. // update NXH2261 with data packet to transmit
  2359. int KL_UpdatePacket_NXH2261(struct packet_of_infamy txPacket)
  2360. {
  2361. size_t i = 0;
  2362. uint8_t ch, dataBlob[NXH2261_DATA_PACKET_SIZE];
  2363.  
  2364. dataBlob[0] = 'B'; // header
  2365. dataBlob[NXH2261_DATA_PACKET_SIZE - 1] = 'E'; // footer
  2366.  
  2367. const unsigned char *buf = (unsigned char*)&txPacket;
  2368.  
  2369. // pad each nibble of buf with 0xD0 per the custom NXH UART protocol
  2370. for (i = 0; i < ((NXH2261_DATA_PACKET_SIZE - 2) >> 1); i++)
  2371. {
  2372. dataBlob[i*2 + 1] = (0xD0 + ((buf[i] & 0xF0) >> 4));
  2373. dataBlob[i*2 + 2] = (0xD0 + ((buf[i] & 0x0F)));
  2374. }
  2375.  
  2376. // flip ordering due to endianness
  2377. uint8_t index[] = {0, 7, 8, 5, 6, 3, 4, 1, 2, 9, 10, 11, 12, 13, 14, 15, 16, 17};
  2378. Reorder_Array(dataBlob, index, NXH2261_DATA_PACKET_SIZE);
  2379.  
  2380. // display hex data from data packet struct (without header and footer)
  2381. PRINTF("[*] Loading Data: 0x");
  2382. for (i = 1; i < NXH2261_DATA_PACKET_SIZE - 1; ++i)
  2383. {
  2384. PRINTF("%02X", dataBlob[i]);
  2385. }
  2386. PRINTF("\n\r");
  2387.  
  2388. // Toggle NXH_UPDATE to tell NXH2261 that we want to update data being sent
  2389. GPIO_PinWrite(BOARD_INITPINS_NXH_UPDATE_GPIO, BOARD_INITPINS_NXH_UPDATE_GPIO_PIN, HIGH);
  2390. SysTick_DelayTicks(100);
  2391. GPIO_PinWrite(BOARD_INITPINS_NXH_UPDATE_GPIO, BOARD_INITPINS_NXH_UPDATE_GPIO_PIN, LOW);
  2392. SysTick_DelayTicks(100);
  2393.  
  2394. // Wait until we receive "RO" from NXH to indicate that it is ready to receive new data
  2395. do
  2396. {
  2397. if (nxhRxIndex == nxhTxIndex) // we've reached the end of the buffer
  2398. return 1;
  2399.  
  2400. ch = nxhRingBuffer[nxhTxIndex];
  2401. nxhTxIndex++;
  2402. nxhTxIndex %= LPUART0_RING_BUFFER_SIZE;
  2403. } while (ch != 'R');
  2404.  
  2405. // now check if 'O' is next door
  2406. if (nxhRxIndex == nxhTxIndex) // we've reached the end of the buffer
  2407. return 1;
  2408.  
  2409. ch = nxhRingBuffer[nxhTxIndex];
  2410. nxhTxIndex++;
  2411. nxhTxIndex %= LPUART0_RING_BUFFER_SIZE;
  2412. if (ch == 'O')
  2413. {
  2414. // send our updated data packet to the NXH
  2415. LPUART_WriteBlocking(LPUART0_PERIPHERAL, dataBlob, sizeof(dataBlob));
  2416. }
  2417. else
  2418. return 1;
  2419.  
  2420. return 0;
  2421. }
  2422.  
  2423. /**************************************************************/
  2424.  
  2425. void KL_Reset_NXH2261(void)
  2426. {
  2427. GPIO_PinWrite(BOARD_INITPINS_NXH_nRESET_GPIO, BOARD_INITPINS_NXH_nRESET_GPIO_PIN, LOW); // Disable NXH2261
  2428. SysTick_DelayTicks(250);
  2429.  
  2430. GPIO_PinWrite(BOARD_INITPINS_NXH_nRESET_GPIO, BOARD_INITPINS_NXH_nRESET_GPIO_PIN, HIGH); // Enable NXH2261
  2431. SysTick_DelayTicks(10);
  2432. }
  2433.  
  2434. /**************************************************************/
  2435.  
  2436. int KL_Setup_LP5569(void) // Configure LP5569 LED Driver
  2437. {
  2438. uint8_t i, err = 0;
  2439.  
  2440. GPIO_PinWrite(BOARD_INITPINS_LED_EN_GPIO, BOARD_INITPINS_LED_EN_GPIO_PIN, LOW);
  2441. SysTick_DelayTicks(10);
  2442.  
  2443. GPIO_PinWrite(BOARD_INITPINS_LED_EN_GPIO, BOARD_INITPINS_LED_EN_GPIO_PIN, HIGH); // Enable LP5569
  2444. SysTick_DelayTicks(10);
  2445.  
  2446. // Load default LED settings
  2447. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_CONFIG, 0x00); // Disable LP5569 while setting MISC register
  2448. SysTick_DelayTicks(1); // Wait for register to be updated
  2449.  
  2450. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_MISC, 0x39); // Auto-increment disabled, auto-power save, auto-charge pump, internal 32.768kHz oscillator
  2451. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_CONFIG, 0x40); // Turn on LP5569
  2452. SysTick_DelayTicks(1); // Wait for register to be updated
  2453.  
  2454. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED_ENGINE_CONTROL2, 0xFA); // Halt all engines, enable direct LED control
  2455.  
  2456. for (i = 0; i < LP5569_LED_NUM; i++) // Control Register
  2457. {
  2458. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED0_CONTROL + i, LP5569_Control);
  2459. }
  2460.  
  2461. for (i = 0; i < LP5569_LED_NUM; i++) // Current Control
  2462. {
  2463. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED0_CURRENT + i, LP5569_Current);
  2464. }
  2465.  
  2466. for (i = 0; i < LP5569_LED_NUM; i++) // PWM Duty Cycle
  2467. {
  2468. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED0_PWM + i, 0x00); // All LEDs off
  2469. }
  2470.  
  2471. // Disable unused LED channels
  2472. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED6_CONTROL, 0x00);
  2473. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED7_CONTROL, 0x00);
  2474. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED8_CONTROL, 0x00);
  2475.  
  2476. // Map LED to register control (not execution engine)
  2477. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_ENGINE1_MAPPING1, 0x00); // LED8
  2478. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_ENGINE1_MAPPING2, 0x00); // LED7..0
  2479. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_ENGINE2_MAPPING1, 0x00); // LED8
  2480. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_ENGINE2_MAPPING2, 0x00); // LED7..0
  2481. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_ENGINE3_MAPPING1, 0x00); // LED8
  2482. err += I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_ENGINE3_MAPPING2, 0x00); // LED7..0
  2483.  
  2484. return err;
  2485. }
  2486.  
  2487. /**************************************************************/
  2488.  
  2489. void LP5569_SetLED(unsigned char led_num, unsigned char led_pwm)
  2490. {
  2491. int i;
  2492.  
  2493. //PRINTF("[*] Setting LED %d @ PWM %d\n\r", led_num, led_pwm);
  2494.  
  2495. if (I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED0_PWM + led_num, led_pwm))
  2496. {
  2497. // if write fails, try to release the bus
  2498. PRINTF("[*] I2C Bus Clear...");
  2499. I2C_ReleaseBus();
  2500. SysTick_DelayTicks(100);
  2501.  
  2502. // re-initialize I2C
  2503. I2C_MasterDeinit(I2C0_PERIPHERAL);
  2504. SysTick_DelayTicks(10);
  2505. I2C_MasterInit(I2C0_PERIPHERAL, &I2C0_config, I2C0_CLK_FREQ);
  2506. SysTick_DelayTicks(10);
  2507.  
  2508. // and re-attempt the transaction
  2509. if (I2C_WriteRegister(I2C0_PERIPHERAL, I2C_LP5569_ADDR, LP5569_REG_LED0_PWM + led_num, led_pwm))
  2510. {
  2511. PRINTF("Error!\n\r");
  2512. }
  2513. else
  2514. {
  2515. PRINTF("Done!\n\r");
  2516. }
  2517. }
  2518.  
  2519. for (i = 0; i < 100; ++i){}; // poor man's delay (us)
  2520. }
  2521.  
  2522. /**************************************************************/
  2523.  
  2524. void LP5569_SetLED_AllOn(void)
  2525. {
  2526. static volatile int i;
  2527.  
  2528. for (i = 0; i < LP5569_LED_NUM; i++) // each LED
  2529. {
  2530. LP5569_SetLED(i, LP5569_PWM); // default brightness
  2531. }
  2532. }
  2533.  
  2534. /**************************************************************/
  2535.  
  2536. void LP5569_SetLED_AllOff(void)
  2537. {
  2538. static volatile int i;
  2539.  
  2540. for (i = 0; i < LP5569_LED_NUM; i++) // each LED
  2541. {
  2542. LP5569_SetLED(i, 0); // off
  2543. }
  2544. }
  2545.  
  2546. /**************************************************************/
  2547.  
  2548. void LP5569_SetLED_D(unsigned char pwm_val)
  2549. {
  2550. LP5569_SetLED(0, 0);
  2551. LP5569_SetLED(1, 0);
  2552. LP5569_SetLED(2, 0);
  2553. LP5569_SetLED(3, pwm_val);
  2554. LP5569_SetLED(4, pwm_val);
  2555. LP5569_SetLED(5, pwm_val);
  2556. }
  2557.  
  2558. /**************************************************************/
  2559.  
  2560. void LP5569_SetLED_E(unsigned char pwm_val)
  2561. {
  2562. LP5569_SetLED(0, pwm_val);
  2563. LP5569_SetLED(1, pwm_val);
  2564. LP5569_SetLED(2, pwm_val);
  2565. LP5569_SetLED(3, 0);
  2566. LP5569_SetLED(4, pwm_val);
  2567. LP5569_SetLED(5, 0);
  2568. }
  2569.  
  2570. /**************************************************************/
  2571.  
  2572. void LP5569_SetLED_F(unsigned char pwm_val)
  2573. {
  2574. LP5569_SetLED(0, pwm_val);
  2575. LP5569_SetLED(1, pwm_val);
  2576. LP5569_SetLED(2, pwm_val);
  2577. LP5569_SetLED(3, pwm_val);
  2578. LP5569_SetLED(4, 0);
  2579. LP5569_SetLED(5, 0);
  2580. }
  2581.  
  2582. /**************************************************************/
  2583.  
  2584. void LP5569_SetLED_C(unsigned char pwm_val)
  2585. {
  2586. LP5569_SetLED(0, pwm_val);
  2587. LP5569_SetLED(1, pwm_val);
  2588. LP5569_SetLED(2, pwm_val);
  2589. LP5569_SetLED(3, 0);
  2590. LP5569_SetLED(4, 0);
  2591. LP5569_SetLED(5, 0);
  2592. }
  2593.  
  2594. /**************************************************************/
  2595.  
  2596. void LP5569_SetLED_O(unsigned char pwm_val)
  2597. {
  2598. LP5569_SetLED(0, pwm_val);
  2599. LP5569_SetLED(1, pwm_val);
  2600. LP5569_SetLED(2, pwm_val);
  2601. LP5569_SetLED(3, pwm_val);
  2602. LP5569_SetLED(4, pwm_val);
  2603. LP5569_SetLED(5, pwm_val);
  2604. }
  2605.  
  2606. /**************************************************************/
  2607.  
  2608. void LP5569_SetLED_N(unsigned char pwm_val)
  2609. {
  2610. LP5569_SetLED(0, pwm_val);
  2611. LP5569_SetLED(1, pwm_val);
  2612. LP5569_SetLED(2, 0);
  2613. LP5569_SetLED(3, pwm_val);
  2614. LP5569_SetLED(4, pwm_val);
  2615. LP5569_SetLED(5, 0);
  2616. }
  2617.  
  2618. /**************************************************************/
  2619.  
  2620. void LP5569_RampLED(badge_state_t ch) // display heartbeat (ramp up/down) of specified LED pattern
  2621. {
  2622. static volatile int j;
  2623.  
  2624. for (j = 0; j <= LP5569_PWM; j += 4) // ramp up to maximum defined brightness
  2625. {
  2626. if (g_nxhDetect)
  2627. {
  2628. g_nxhDetect = false;
  2629. return; // exit the heartbeat if new badge data has just been received
  2630. }
  2631.  
  2632. switch (ch)
  2633. {
  2634. case D:
  2635. LP5569_SetLED_D(j);
  2636. break;
  2637.  
  2638. case E:
  2639. LP5569_SetLED_E(j);
  2640. break;
  2641.  
  2642. case F:
  2643. LP5569_SetLED_F(j);
  2644. break;
  2645.  
  2646. case C:
  2647. LP5569_SetLED_C(j);
  2648. break;
  2649.  
  2650. case O:
  2651. LP5569_SetLED_O(j);
  2652. break;
  2653.  
  2654. case N:
  2655. LP5569_SetLED_N(j);
  2656. break;
  2657.  
  2658. case ATTRACT:
  2659. case COMPLETE:
  2660. default:
  2661. break;
  2662. }
  2663.  
  2664. SysTick_DelayTicks(LED_HEARTBEAT_FADE_DELAY);
  2665. }
  2666.  
  2667. LPTMR_SetTimerPeriod(LPTMR0_PERIPHERAL, LED_HEARTBEAT_WAIT_DELAY); // Set time to sleep at LED maximum brightness
  2668. KL_Sleep(); // Go to sleep until our delay period is complete
  2669. if (g_nxhDetect)
  2670. {
  2671. g_nxhDetect = false;
  2672. return; // exit the heartbeat if new badge data has just been received
  2673. }
  2674.  
  2675. for (j = LP5569_PWM; j >= 0; j -= 4) // ramp down from maximum defined brightness
  2676. {
  2677. if (g_nxhDetect)
  2678. {
  2679. g_nxhDetect = false;
  2680. return; // exit the heartbeat if new badge data has just been received
  2681. }
  2682.  
  2683. switch (ch)
  2684. {
  2685. case D:
  2686. LP5569_SetLED_D(j);
  2687. break;
  2688.  
  2689. case E:
  2690. LP5569_SetLED_E(j);
  2691. break;
  2692.  
  2693. case F:
  2694. LP5569_SetLED_F(j);
  2695. break;
  2696.  
  2697. case C:
  2698. LP5569_SetLED_C(j);
  2699. break;
  2700.  
  2701. case O:
  2702. LP5569_SetLED_O(j);
  2703. break;
  2704.  
  2705. case N:
  2706. LP5569_SetLED_N(j);
  2707. break;
  2708.  
  2709. case ATTRACT:
  2710. case COMPLETE:
  2711. default:
  2712. break;
  2713. }
  2714.  
  2715. SysTick_DelayTicks(LED_HEARTBEAT_FADE_DELAY);
  2716. }
  2717. }
  2718.  
  2719. /**************************************************************/
  2720.  
  2721. // Utility function to read single byte from specified register of the I2C device
  2722. bool I2C_ReadRegister(I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t *rxBuff, uint32_t rxSize)
  2723. {
  2724. i2c_master_transfer_t masterXfer;
  2725. memset(&masterXfer, 0, sizeof(masterXfer));
  2726.  
  2727. masterXfer.slaveAddress = device_addr;
  2728. masterXfer.direction = kI2C_Read;
  2729. masterXfer.subaddress = reg_addr;
  2730. masterXfer.subaddressSize = 1;
  2731. masterXfer.data = rxBuff;
  2732. masterXfer.dataSize = rxSize;
  2733. masterXfer.flags = kI2C_TransferDefaultFlag;
  2734.  
  2735. /* direction=write : start+device_write;cmdbuff;xBuff; */
  2736. /* direction=receive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */
  2737.  
  2738. // does not return until the transfer succeeds or fails due to arbitration lost or receiving a NAK
  2739. if (I2C_MasterTransferBlocking(base, &masterXfer) == kStatus_Success)
  2740. return 0;
  2741. else
  2742. return 1;
  2743. }
  2744.  
  2745. /**************************************************************/
  2746.  
  2747. // Utility function to write single byte to specified register of the I2C device
  2748. bool I2C_WriteRegister(I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t value)
  2749. {
  2750. i2c_master_transfer_t masterXfer;
  2751. memset(&masterXfer, 0, sizeof(masterXfer));
  2752.  
  2753. masterXfer.slaveAddress = device_addr;
  2754. masterXfer.direction = kI2C_Write;
  2755. masterXfer.subaddress = reg_addr;
  2756. masterXfer.subaddressSize = 1;
  2757. masterXfer.data = &value;
  2758. masterXfer.dataSize = 1;
  2759. masterXfer.flags = kI2C_TransferDefaultFlag;
  2760.  
  2761. /* direction=write : start+device_write;cmdbuff;xBuff; */
  2762. /* direction=receive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */
  2763.  
  2764. // does not return until the transfer succeeds or fails due to arbitration lost or receiving a NAK
  2765. if (I2C_MasterTransferBlocking(base, &masterXfer) == kStatus_Success)
  2766. return 0;
  2767. else
  2768. return 1;
  2769. }
  2770.  
  2771. /**************************************************************/
  2772.  
  2773. // Utility function to read multiple bytes (rxSize) from the specified I2C device
  2774. bool I2C_ReadBulk(I2C_Type *base, uint8_t device_addr, uint8_t *rxBuff, uint32_t rxSize)
  2775. {
  2776. i2c_master_transfer_t masterXfer;
  2777. memset(&masterXfer, 0, sizeof(masterXfer));
  2778.  
  2779. masterXfer.slaveAddress = device_addr;
  2780. masterXfer.direction = kI2C_Read;
  2781. masterXfer.subaddress = 0;
  2782. masterXfer.subaddressSize = 0;
  2783. masterXfer.data = rxBuff;
  2784. masterXfer.dataSize = rxSize;
  2785. masterXfer.flags = kI2C_TransferDefaultFlag;
  2786.  
  2787. /* direction=write : start+device_write;cmdbuff;xBuff; */
  2788. /* direction=receive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */
  2789.  
  2790. // does not return until the transfer succeeds or fails due to arbitration lost or receiving a NAK
  2791. if (I2C_MasterTransferBlocking(base, &masterXfer) == kStatus_Success)
  2792. return 0;
  2793. else
  2794. return 1;
  2795. }
  2796.  
  2797. /**************************************************************/
  2798.  
  2799. // Utility function to write multiple bytes (txSize) to the specified I2C device
  2800. bool I2C_WriteBulk(I2C_Type *base, uint8_t device_addr, uint8_t *txBuff, uint32_t txSize)
  2801. {
  2802. i2c_master_transfer_t masterXfer;
  2803. memset(&masterXfer, 0, sizeof(masterXfer));
  2804.  
  2805. masterXfer.slaveAddress = device_addr;
  2806. masterXfer.direction = kI2C_Write;
  2807. masterXfer.subaddress = 0;
  2808. masterXfer.subaddressSize = 0;
  2809. masterXfer.data = txBuff;
  2810. masterXfer.dataSize = txSize;
  2811. masterXfer.flags = kI2C_TransferDefaultFlag;
  2812.  
  2813. /* direction=write : start+device_write;cmdbuff;xBuff; */
  2814. /* direction=receive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */
  2815.  
  2816. // does not return until the transfer succeeds or fails due to arbitration lost or receiving a NAK
  2817. if (I2C_MasterTransferBlocking(base, &masterXfer) == kStatus_Success)
  2818. return 0;
  2819. else
  2820. return 1;
  2821. }
  2822.  
  2823. /**************************************************************/
  2824.  
  2825. // Release/clear the bus due to an error condition of SDA stuck LOW
  2826. // From UM10204 I2C bus specification and user manual, pg. 20
  2827. // https://www.nxp.com/docs/en/user-guide/UM10204.pdf
  2828. void I2C_ReleaseBus(void)
  2829. {
  2830. uint8_t i = 0, j;
  2831.  
  2832. // set SCL pin as GPIO
  2833. gpio_pin_config_t SCL_config = {
  2834. .pinDirection = kGPIO_DigitalOutput,
  2835. .outputLogic = 1U
  2836. };
  2837. GPIO_PinInit(GPIOB, BOARD_INITPINS_SCL_PIN, &SCL_config);
  2838. PORT_SetPinMux(BOARD_INITPINS_SCL_PORT, BOARD_INITPINS_SCL_PIN, kPORT_MuxAsGpio);
  2839. SysTick_DelayTicks(10);
  2840.  
  2841. // send 9 pulses on SCL
  2842. // the slave device that is holding the bus LOW should release it sometime within these clocks
  2843. for (i = 0; i < 9; i++)
  2844. {
  2845. GPIO_PinWrite(GPIOB, BOARD_INITPINS_SCL_PIN, 0U);
  2846. for (j = 0; j < 10; ++j){}; // poor man's delay (us)
  2847.  
  2848. GPIO_PinWrite(GPIOB, BOARD_INITPINS_SCL_PIN, 1U);
  2849. for (j = 0; j < 10; ++j){}; // poor man's delay (us)
  2850. }
  2851.  
  2852. // set SCL back to I2C0_SCL
  2853. PORT_SetPinMux(BOARD_INITPINS_SCL_PORT, BOARD_INITPINS_SCL_PIN, kPORT_MuxAlt2);
  2854. SysTick_DelayTicks(10);
  2855. }
  2856.  
  2857. /**************************************************************/
  2858.  
  2859. unsigned char Get_Random_Byte(void) // PRNG
  2860. {
  2861. unsigned char sum = 0;
  2862.  
  2863. // This calculates parity on the selected bits (mask = 0xb4)
  2864. if(g_random & 0x80)
  2865. sum = 1;
  2866.  
  2867. if(g_random & 0x20)
  2868. sum ^= 1;
  2869.  
  2870. if(g_random & 0x10)
  2871. sum ^= 1;
  2872.  
  2873. if(g_random & 0x04)
  2874. sum ^= 1;
  2875.  
  2876. g_random <<= 1;
  2877. g_random |= sum;
  2878.  
  2879. return(g_random);
  2880. }
  2881.  
  2882. /**************************************************************/
  2883.  
  2884. // print all 8 bits of a byte including leading zeros
  2885. // from https://forum.arduino.cc/index.php?topic=46320.0
  2886. void Print_Bits(uint8_t myByte)
  2887. {
  2888. for (uint8_t mask = 0x80; mask; mask >>= 1)
  2889. {
  2890. if(mask & myByte)
  2891. PRINTF("1");
  2892. else
  2893. PRINTF("0");
  2894. }
  2895. }
  2896.  
  2897. /**************************************************************/
  2898.  
  2899. // Reorder elements in an array of N size based on index array
  2900. // from https://www.tutorialcup.com/array/reorder-array-indexes.htm
  2901. void Reorder_Array(uint8_t *array, uint8_t *index, uint8_t N)
  2902. {
  2903. size_t i;
  2904. uint8_t temp[N]; // temporary array
  2905.  
  2906. // array[i] should present at index[i] index
  2907. for (i = 0; i < N; i++)
  2908. {
  2909. temp[index[i]] = array[i];
  2910. }
  2911.  
  2912. for (i = 0; i < N; i++)
  2913. {
  2914. array[i] = temp[i];
  2915. index[i] = i;
  2916. }
  2917. }
  2918.  
  2919. /**************************************************************/
  2920.  
  2921. void SysTick_DelayTicks(uint32_t n)
  2922. {
  2923. g_systickCounter = n;
  2924. while(g_systickCounter != 0U){}; // wait here until counter is done
  2925. }
  2926.  
  2927.  
  2928. /****************************************************************************
  2929. ********************* Interrupt Handlers ***********************************
  2930. ***************************************************************************/
  2931.  
  2932. void SysTick_Handler(void)
  2933. {
  2934. if (g_systickCounter != 0U)
  2935. {
  2936. g_systickCounter--;
  2937. }
  2938. }
  2939.  
  2940. /**************************************************************/
  2941.  
  2942. void LPUART0_SERIAL_RX_TX_IRQHANDLER(void)
  2943. {
  2944. volatile uint8_t data;
  2945.  
  2946. // If new data has arrived from the NXH...
  2947. if (kLPUART_RxDataRegFullFlag & LPUART_GetStatusFlags(LPUART0_PERIPHERAL))
  2948. {
  2949. data = LPUART_ReadByte(LPUART0_PERIPHERAL);
  2950.  
  2951. // If ring buffer isn't full, add the data
  2952. if (((nxhRxIndex + 1) % LPUART0_RING_BUFFER_SIZE) != nxhTxIndex)
  2953. {
  2954. nxhRingBuffer[nxhRxIndex] = data;
  2955. nxhRxIndex++;
  2956. nxhRxIndex %= LPUART0_RING_BUFFER_SIZE;
  2957. }
  2958. }
  2959.  
  2960. // If the UART buffer has overrun and can't store incoming data...
  2961. if (kLPUART_RxOverrunFlag & LPUART_GetStatusFlags(LPUART0_PERIPHERAL))
  2962. {
  2963. data = LPUART_ReadByte(LPUART0_PERIPHERAL); // dummy read to clear buffer (could cause misalignment of data packet)
  2964. LPUART_ClearStatusFlags(LPUART0_PERIPHERAL, kLPUART_RxOverrunFlag);
  2965. }
  2966. }
  2967.  
  2968. /**************************************************************/
  2969.  
  2970. void LPTMR0_IRQHandler(void)
  2971. {
  2972. g_lptmrFlag = true; // Set state of global variable
  2973.  
  2974. LPTMR_ClearStatusFlags(LPTMR0_PERIPHERAL, kLPTMR_TimerCompareFlag);
  2975. }
  2976.  
  2977. /**************************************************************/
  2978.  
  2979. void PORTB_PORTC_PORTD_PORTE_IRQHandler(void)
  2980. {
  2981. if (GPIO_PortGetInterruptFlags(GPIOC_GPIO)) // If interrupt was from Port C (NXH_DETECT)
  2982. {
  2983. g_nxhDetect = true; // Set state of global variable
  2984.  
  2985. GPIO_PortClearInterruptFlags(GPIOC_GPIO, 1U << BOARD_INITPINS_NXH_DETECT_PIN); // Clear external interrupt flag
  2986. }
  2987. else // Otherwise, interrupt must have been from Port E (KL_RX) via USB-to-Serial connection
  2988. {
  2989. GPIO_PortClearInterruptFlags(GPIOE, 1U << BOARD_INITPINS_KL_RX_PIN); // Clear external interrupt flag
  2990. }
  2991. }
  2992.  
  2993. /**************************************************************/
  2994.  
  2995. // The End!
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement