Teensy 4.1 core updated for C++20
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

422 lines
11KB

  1. /* Teensyduino Core Library
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2013 PJRC.COM, LLC.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining
  6. * a copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * 1. The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * 2. If the Software is incorporated into a build system that allows
  17. * selection among a list of target devices, then similar target
  18. * devices manufactured by PJRC.COM must be included in the list of
  19. * target devices and selectable in the same manner.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  25. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  26. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  27. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  28. * SOFTWARE.
  29. */
  30. #include "core_pins.h"
  31. //#include "HardwareSerial.h"
  32. static uint8_t calibrating;
  33. static uint8_t analog_right_shift = 0;
  34. static uint8_t analog_config_bits = 10;
  35. static uint8_t analog_num_average = 4;
  36. static uint8_t analog_reference_internal = 0;
  37. // the alternate clock is connected to OSCERCLK (16 MHz).
  38. // datasheet says ADC clock should be 2 to 12 MHz for 16 bit mode
  39. // datasheet says ADC clock should be 1 to 18 MHz for 8-12 bit mode
  40. #if F_BUS == 48000000
  41. #define ADC_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1)
  42. #define ADC_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1)
  43. #define ADC_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1)
  44. #elif F_BUS == 24000000
  45. #define ADC_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(0)
  46. #define ADC_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0)
  47. #define ADC_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0)
  48. #else
  49. #error
  50. #endif
  51. void analog_init(void)
  52. {
  53. uint32_t num;
  54. VREF_TRM = 0x60;
  55. VREF_SC = 0xE1; // enable 1.2 volt ref
  56. if (analog_config_bits == 8) {
  57. ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0);
  58. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  59. #if defined(__MK20DX256__)
  60. ADC1_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0);
  61. ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  62. #endif
  63. } else if (analog_config_bits == 10) {
  64. ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
  65. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  66. #if defined(__MK20DX256__)
  67. ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
  68. ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  69. #endif
  70. } else if (analog_config_bits == 12) {
  71. ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
  72. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  73. #if defined(__MK20DX256__)
  74. ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
  75. ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  76. #endif
  77. } else {
  78. ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
  79. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  80. #if defined(__MK20DX256__)
  81. ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
  82. ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  83. #endif
  84. }
  85. if (analog_reference_internal) {
  86. ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
  87. #if defined(__MK20DX256__)
  88. ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
  89. #endif
  90. } else {
  91. ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
  92. #if defined(__MK20DX256__)
  93. ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
  94. #endif
  95. }
  96. num = analog_num_average;
  97. if (num <= 1) {
  98. ADC0_SC3 = ADC_SC3_CAL; // begin cal
  99. #if defined(__MK20DX256__)
  100. ADC1_SC3 = ADC_SC3_CAL; // begin cal
  101. #endif
  102. } else if (num <= 4) {
  103. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
  104. #if defined(__MK20DX256__)
  105. ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
  106. #endif
  107. } else if (num <= 8) {
  108. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
  109. #if defined(__MK20DX256__)
  110. ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
  111. #endif
  112. } else if (num <= 16) {
  113. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
  114. #if defined(__MK20DX256__)
  115. ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
  116. #endif
  117. } else {
  118. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
  119. #if defined(__MK20DX256__)
  120. ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
  121. #endif
  122. }
  123. calibrating = 1;
  124. }
  125. static void wait_for_cal(void)
  126. {
  127. uint16_t sum;
  128. //serial_print("wait_for_cal\n");
  129. #if defined(__MK20DX128__)
  130. while (ADC0_SC3 & ADC_SC3_CAL) {
  131. // wait
  132. }
  133. #elif defined(__MK20DX256__)
  134. while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) {
  135. // wait
  136. }
  137. #endif
  138. __disable_irq();
  139. if (calibrating) {
  140. //serial_print("\n");
  141. sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0;
  142. sum = (sum / 2) | 0x8000;
  143. ADC0_PG = sum;
  144. //serial_print("ADC0_PG = ");
  145. //serial_phex16(sum);
  146. //serial_print("\n");
  147. sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0;
  148. sum = (sum / 2) | 0x8000;
  149. ADC0_MG = sum;
  150. //serial_print("ADC0_MG = ");
  151. //serial_phex16(sum);
  152. //serial_print("\n");
  153. #if defined(__MK20DX256__)
  154. sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
  155. sum = (sum / 2) | 0x8000;
  156. ADC1_PG = sum;
  157. sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0;
  158. sum = (sum / 2) | 0x8000;
  159. ADC1_MG = sum;
  160. #endif
  161. calibrating = 0;
  162. }
  163. __enable_irq();
  164. }
  165. // ADCx_SC2[REFSEL] bit selects the voltage reference sources for ADC.
  166. // VREFH/VREFL - connected as the primary reference option
  167. // 1.2 V VREF_OUT - connected as the VALT reference option
  168. #define DEFAULT 0
  169. #define INTERNAL 2
  170. #define INTERNAL1V2 2
  171. #define INTERNAL1V1 2
  172. #define EXTERNAL 0
  173. void analogReference(uint8_t type)
  174. {
  175. if (type) {
  176. // internal reference requested
  177. if (!analog_reference_internal) {
  178. analog_reference_internal = 1;
  179. if (calibrating) {
  180. ADC0_SC3 = 0; // cancel cal
  181. #if defined(__MK20DX256__)
  182. ADC1_SC3 = 0; // cancel cal
  183. #endif
  184. }
  185. analog_init();
  186. }
  187. } else {
  188. // vcc or external reference requested
  189. if (analog_reference_internal) {
  190. analog_reference_internal = 0;
  191. if (calibrating) {
  192. ADC0_SC3 = 0; // cancel cal
  193. #if defined(__MK20DX256__)
  194. ADC1_SC3 = 0; // cancel cal
  195. #endif
  196. }
  197. analog_init();
  198. }
  199. }
  200. }
  201. void analogReadRes(unsigned int bits)
  202. {
  203. unsigned int config;
  204. if (bits >= 13) {
  205. if (bits > 16) bits = 16;
  206. config = 16;
  207. } else if (bits >= 11) {
  208. config = 12;
  209. } else if (bits >= 9) {
  210. config = 10;
  211. } else {
  212. config = 8;
  213. }
  214. analog_right_shift = config - bits;
  215. if (config != analog_config_bits) {
  216. analog_config_bits = config;
  217. if (calibrating) ADC0_SC3 = 0; // cancel cal
  218. analog_init();
  219. }
  220. }
  221. void analogReadAveraging(unsigned int num)
  222. {
  223. if (calibrating) wait_for_cal();
  224. if (num <= 1) {
  225. num = 0;
  226. ADC0_SC3 = 0;
  227. } else if (num <= 4) {
  228. num = 4;
  229. ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
  230. } else if (num <= 8) {
  231. num = 8;
  232. ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
  233. } else if (num <= 16) {
  234. num = 16;
  235. ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
  236. } else {
  237. num = 32;
  238. ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
  239. }
  240. analog_num_average = num;
  241. }
  242. // The SC1A register is used for both software and hardware trigger modes of operation.
  243. #if defined(__MK20DX128__)
  244. static const uint8_t channel2sc1a[] = {
  245. 5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
  246. 0, 19, 3, 21, 26, 22, 23
  247. };
  248. #elif defined(__MK20DX256__)
  249. static const uint8_t channel2sc1a[] = {
  250. 5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
  251. 0, 19, 3, 19+128, 26, 18+128, 23,
  252. 5+192, 5+128, 4+128, 6+128, 7+128, 4+192
  253. // A15 26 E1 ADC1_SE5a 5+64
  254. // A16 27 C9 ADC1_SE5b 5
  255. // A17 28 C8 ADC1_SE4b 4
  256. // A18 29 C10 ADC1_SE6b 6
  257. // A19 30 C11 ADC1_SE7b 7
  258. // A20 31 E0 ADC1_SE4a 4+64
  259. };
  260. #endif
  261. // TODO: perhaps this should store the NVIC priority, so it works recursively?
  262. static volatile uint8_t analogReadBusyADC0 = 0;
  263. #if defined(__MK20DX256__)
  264. static volatile uint8_t analogReadBusyADC1 = 0;
  265. #endif
  266. int analogRead(uint8_t pin)
  267. {
  268. int result;
  269. uint8_t index, channel;
  270. //serial_phex(pin);
  271. //serial_print(" ");
  272. if (pin <= 13) {
  273. index = pin; // 0-13 refer to A0-A13
  274. } else if (pin <= 23) {
  275. index = pin - 14; // 14-23 are A0-A9
  276. #if defined(__MK20DX256__)
  277. } else if (pin >= 26 && pin <= 31) {
  278. index = pin - 9; // 26-31 are A15-A20
  279. #endif
  280. } else if (pin >= 34 && pin <= 40) {
  281. index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
  282. // 39 is vref, 40 is unused (A14 on Teensy 3.1)
  283. } else {
  284. return 0; // all others are invalid
  285. }
  286. //serial_phex(index);
  287. //serial_print(" ");
  288. channel = channel2sc1a[index];
  289. //serial_phex(channel);
  290. //serial_print(" ");
  291. //serial_print("analogRead");
  292. //return 0;
  293. if (calibrating) wait_for_cal();
  294. //pin = 5; // PTD1/SE5b, pin 14, analog 0
  295. #if defined(__MK20DX256__)
  296. if (channel & 0x80) goto beginADC1;
  297. #endif
  298. __disable_irq();
  299. startADC0:
  300. //serial_print("startADC0\n");
  301. ADC0_SC1A = channel;
  302. analogReadBusyADC0 = 1;
  303. __enable_irq();
  304. while (1) {
  305. __disable_irq();
  306. if ((ADC0_SC1A & ADC_SC1_COCO)) {
  307. result = ADC0_RA;
  308. analogReadBusyADC0 = 0;
  309. __enable_irq();
  310. result >>= analog_right_shift;
  311. return result;
  312. }
  313. // detect if analogRead was used from an interrupt
  314. // if so, our analogRead got canceled, so it must
  315. // be restarted.
  316. if (!analogReadBusyADC0) goto startADC0;
  317. __enable_irq();
  318. yield();
  319. }
  320. #if defined(__MK20DX256__)
  321. beginADC1:
  322. __disable_irq();
  323. startADC1:
  324. //serial_print("startADC0\n");
  325. // ADC1_CFG2[MUXSEL] bit selects between ADCx_SEn channels a and b.
  326. if (channel & 0x40) {
  327. ADC1_CFG2 &= ~ADC_CFG2_MUXSEL;
  328. } else {
  329. ADC1_CFG2 |= ADC_CFG2_MUXSEL;
  330. }
  331. ADC1_SC1A = channel & 0x3F;
  332. analogReadBusyADC1 = 1;
  333. __enable_irq();
  334. while (1) {
  335. __disable_irq();
  336. if ((ADC1_SC1A & ADC_SC1_COCO)) {
  337. result = ADC1_RA;
  338. analogReadBusyADC1 = 0;
  339. __enable_irq();
  340. result >>= analog_right_shift;
  341. return result;
  342. }
  343. // detect if analogRead was used from an interrupt
  344. // if so, our analogRead got canceled, so it must
  345. // be restarted.
  346. if (!analogReadBusyADC1) goto startADC1;
  347. __enable_irq();
  348. yield();
  349. }
  350. #endif
  351. }
  352. void analogWriteDAC0(int val)
  353. {
  354. #if defined(__MK20DX256__)
  355. SIM_SCGC2 |= SIM_SCGC2_DAC0;
  356. if (analog_reference_internal) {
  357. DAC0_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1
  358. } else {
  359. DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
  360. }
  361. if (val < 0) val = 0; // TODO: saturate instruction?
  362. else if (val > 4095) val = 4095;
  363. *(int16_t *)&(DAC0_DAT0L) = val;
  364. #endif
  365. }