You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

avr_emulation.h 37KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  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. #ifndef _avr_emulation_h_
  31. #define _avr_emulation_h_
  32. #include "mk20dx128.h"
  33. #include "core_pins.h"
  34. #include "pins_arduino.h"
  35. #ifdef __cplusplus
  36. #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
  37. #define GPIO_BITBAND(reg, bit) (*(uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
  38. #define CONFIG_PULLUP (PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS)
  39. #define CONFIG_NOPULLUP (PORT_PCR_MUX(1))
  40. class PORTDemulation
  41. {
  42. public:
  43. inline PORTDemulation & operator = (int val) __attribute__((always_inline)) {
  44. digitalWriteFast(0, (val & (1<<0)));
  45. if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT))
  46. CORE_PIN0_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  47. digitalWriteFast(1, (val & (1<<1)));
  48. if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT))
  49. CORE_PIN1_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  50. digitalWriteFast(2, (val & (1<<2)));
  51. if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT))
  52. CORE_PIN2_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  53. digitalWriteFast(3, (val & (1<<3)));
  54. if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT))
  55. CORE_PIN3_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  56. digitalWriteFast(4, (val & (1<<4)));
  57. if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT))
  58. CORE_PIN4_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  59. digitalWriteFast(5, (val & (1<<5)));
  60. if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT))
  61. CORE_PIN5_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  62. digitalWriteFast(6, (val & (1<<6)));
  63. if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT))
  64. CORE_PIN6_CONFIG = ((val & (1<<6)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  65. digitalWriteFast(7, (val & (1<<7)));
  66. if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT))
  67. CORE_PIN7_CONFIG = ((val & (1<<7)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  68. return *this;
  69. }
  70. inline PORTDemulation & operator |= (int val) __attribute__((always_inline)) {
  71. if (val & (1<<0)) {
  72. digitalWriteFast(0, HIGH);
  73. if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) CORE_PIN0_CONFIG = CONFIG_PULLUP;
  74. }
  75. if (val & (1<<1)) {
  76. digitalWriteFast(1, HIGH);
  77. if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = CONFIG_PULLUP;
  78. }
  79. if (val & (1<<2)) {
  80. digitalWriteFast(2, HIGH);
  81. if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) CORE_PIN2_CONFIG = CONFIG_PULLUP;
  82. }
  83. if (val & (1<<3)) {
  84. digitalWriteFast(3, HIGH);
  85. if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) CORE_PIN3_CONFIG = CONFIG_PULLUP;
  86. }
  87. if (val & (1<<4)) {
  88. digitalWriteFast(4, HIGH);
  89. if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) CORE_PIN4_CONFIG = CONFIG_PULLUP;
  90. }
  91. if (val & (1<<5)) {
  92. digitalWriteFast(5, HIGH);
  93. if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) CORE_PIN5_CONFIG = CONFIG_PULLUP;
  94. }
  95. if (val & (1<<6)) {
  96. digitalWriteFast(6, HIGH);
  97. if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) CORE_PIN6_CONFIG = CONFIG_PULLUP;
  98. }
  99. if (val & (1<<7)) {
  100. digitalWriteFast(7, HIGH);
  101. if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN7_CONFIG = CONFIG_PULLUP;
  102. }
  103. return *this;
  104. }
  105. inline PORTDemulation & operator &= (int val) __attribute__((always_inline)) {
  106. if (!(val & (1<<0))) {
  107. digitalWriteFast(0, LOW);
  108. if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) CORE_PIN0_CONFIG = CONFIG_NOPULLUP;
  109. }
  110. if (!(val & (1<<1))) {
  111. digitalWriteFast(1, LOW);
  112. if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = CONFIG_NOPULLUP;
  113. }
  114. if (!(val & (1<<2))) {
  115. digitalWriteFast(2, LOW);
  116. if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) CORE_PIN2_CONFIG = CONFIG_NOPULLUP;
  117. }
  118. if (!(val & (1<<3))) {
  119. digitalWriteFast(3, LOW);
  120. if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) CORE_PIN3_CONFIG = CONFIG_NOPULLUP;
  121. }
  122. if (!(val & (1<<4))) {
  123. digitalWriteFast(4, LOW);
  124. if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) CORE_PIN4_CONFIG = CONFIG_NOPULLUP;
  125. }
  126. if (!(val & (1<<5))) {
  127. digitalWriteFast(5, LOW);
  128. if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) CORE_PIN5_CONFIG = CONFIG_NOPULLUP;
  129. }
  130. if (!(val & (1<<6))) {
  131. digitalWriteFast(6, LOW);
  132. if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) CORE_PIN6_CONFIG = CONFIG_NOPULLUP;
  133. }
  134. if (!(val & (1<<7))) {
  135. digitalWriteFast(7, LOW);
  136. if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN7_CONFIG = CONFIG_NOPULLUP;
  137. }
  138. return *this;
  139. }
  140. };
  141. extern PORTDemulation PORTD;
  142. class PINDemulation
  143. {
  144. public:
  145. inline int operator & (int val) const __attribute__((always_inline)) {
  146. int ret = 0;
  147. if ((val & (1<<0)) && digitalReadFast(0)) ret |= (1<<0);
  148. if ((val & (1<<1)) && digitalReadFast(1)) ret |= (1<<1);
  149. if ((val & (1<<2)) && digitalReadFast(2)) ret |= (1<<2);
  150. if ((val & (1<<3)) && digitalReadFast(3)) ret |= (1<<3);
  151. if ((val & (1<<4)) && digitalReadFast(4)) ret |= (1<<4);
  152. if ((val & (1<<5)) && digitalReadFast(5)) ret |= (1<<5);
  153. if ((val & (1<<6)) && digitalReadFast(6)) ret |= (1<<6);
  154. if ((val & (1<<7)) && digitalReadFast(7)) ret |= (1<<7);
  155. return ret;
  156. }
  157. operator int () const __attribute__((always_inline)) {
  158. int ret = 0;
  159. if (digitalReadFast(0)) ret |= (1<<0);
  160. if (digitalReadFast(1)) ret |= (1<<1);
  161. if (digitalReadFast(2)) ret |= (1<<2);
  162. if (digitalReadFast(3)) ret |= (1<<3);
  163. if (digitalReadFast(4)) ret |= (1<<4);
  164. if (digitalReadFast(5)) ret |= (1<<5);
  165. if (digitalReadFast(6)) ret |= (1<<6);
  166. if (digitalReadFast(7)) ret |= (1<<7);
  167. return ret;
  168. }
  169. };
  170. extern PINDemulation PIND;
  171. class DDRDemulation
  172. {
  173. public:
  174. inline DDRDemulation & operator = (int val) __attribute__((always_inline)) {
  175. if (val & (1<<0)) set0(); else clr0();
  176. if (val & (1<<1)) set1(); else clr1();
  177. if (val & (1<<2)) set2(); else clr2();
  178. if (val & (1<<3)) set3(); else clr3();
  179. if (val & (1<<4)) set4(); else clr4();
  180. if (val & (1<<5)) set5(); else clr5();
  181. if (val & (1<<6)) set6(); else clr6();
  182. if (val & (1<<7)) set7(); else clr7();
  183. return *this;
  184. }
  185. inline DDRDemulation & operator |= (int val) __attribute__((always_inline)) {
  186. if (val & (1<<0)) set0();
  187. if (val & (1<<1)) set1();
  188. if (val & (1<<2)) set2();
  189. if (val & (1<<3)) set3();
  190. if (val & (1<<4)) set4();
  191. if (val & (1<<5)) set5();
  192. if (val & (1<<6)) set6();
  193. if (val & (1<<7)) set7();
  194. return *this;
  195. }
  196. inline DDRDemulation & operator &= (int val) __attribute__((always_inline)) {
  197. if (!(val & (1<<0))) clr0();
  198. if (!(val & (1<<1))) clr1();
  199. if (!(val & (1<<2))) clr2();
  200. if (!(val & (1<<3))) clr3();
  201. if (!(val & (1<<4))) clr4();
  202. if (!(val & (1<<5))) clr5();
  203. if (!(val & (1<<6))) clr6();
  204. if (!(val & (1<<7))) clr7();
  205. return *this;
  206. }
  207. private:
  208. inline void set0() __attribute__((always_inline)) {
  209. GPIO_BITBAND(CORE_PIN0_DDRREG, CORE_PIN0_BIT) = 1;
  210. CORE_PIN0_CONFIG = CONFIG_PULLUP;
  211. }
  212. inline void set1() __attribute__((always_inline)) {
  213. GPIO_BITBAND(CORE_PIN1_DDRREG, CORE_PIN1_BIT) = 1;
  214. CORE_PIN1_CONFIG = CONFIG_PULLUP;
  215. }
  216. inline void set2() __attribute__((always_inline)) {
  217. GPIO_BITBAND(CORE_PIN2_DDRREG, CORE_PIN2_BIT) = 1;
  218. CORE_PIN2_CONFIG = CONFIG_PULLUP;
  219. }
  220. inline void set3() __attribute__((always_inline)) {
  221. GPIO_BITBAND(CORE_PIN3_DDRREG, CORE_PIN3_BIT) = 1;
  222. CORE_PIN3_CONFIG = CONFIG_PULLUP;
  223. }
  224. inline void set4() __attribute__((always_inline)) {
  225. GPIO_BITBAND(CORE_PIN4_DDRREG, CORE_PIN4_BIT) = 1;
  226. CORE_PIN4_CONFIG = CONFIG_PULLUP;
  227. }
  228. inline void set5() __attribute__((always_inline)) {
  229. GPIO_BITBAND(CORE_PIN5_DDRREG, CORE_PIN5_BIT) = 1;
  230. CORE_PIN5_CONFIG = CONFIG_PULLUP;
  231. }
  232. inline void set6() __attribute__((always_inline)) {
  233. GPIO_BITBAND(CORE_PIN6_DDRREG, CORE_PIN6_BIT) = 1;
  234. CORE_PIN6_CONFIG = CONFIG_PULLUP;
  235. }
  236. inline void set7() __attribute__((always_inline)) {
  237. GPIO_BITBAND(CORE_PIN7_DDRREG, CORE_PIN7_BIT) = 1;
  238. CORE_PIN7_CONFIG = CONFIG_PULLUP;
  239. }
  240. inline void clr0() __attribute__((always_inline)) {
  241. CORE_PIN0_CONFIG = ((CORE_PIN0_PORTREG & CORE_PIN0_BITMASK)
  242. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  243. GPIO_BITBAND(CORE_PIN0_DDRREG, CORE_PIN0_BIT) = 0;
  244. }
  245. inline void clr1() __attribute__((always_inline)) {
  246. CORE_PIN1_CONFIG = ((CORE_PIN1_PORTREG & CORE_PIN1_BITMASK)
  247. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  248. GPIO_BITBAND(CORE_PIN1_DDRREG, CORE_PIN1_BIT) = 0;
  249. }
  250. inline void clr2() __attribute__((always_inline)) {
  251. CORE_PIN2_CONFIG = ((CORE_PIN2_PORTREG & CORE_PIN2_BITMASK)
  252. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  253. GPIO_BITBAND(CORE_PIN2_DDRREG, CORE_PIN2_BIT) = 0;
  254. }
  255. inline void clr3() __attribute__((always_inline)) {
  256. CORE_PIN3_CONFIG = ((CORE_PIN3_PORTREG & CORE_PIN3_BITMASK)
  257. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  258. GPIO_BITBAND(CORE_PIN3_DDRREG, CORE_PIN3_BIT) = 0;
  259. }
  260. inline void clr4() __attribute__((always_inline)) {
  261. CORE_PIN4_CONFIG = ((CORE_PIN4_PORTREG & CORE_PIN4_BITMASK)
  262. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  263. GPIO_BITBAND(CORE_PIN4_DDRREG, CORE_PIN4_BIT) = 0;
  264. }
  265. inline void clr5() __attribute__((always_inline)) {
  266. CORE_PIN5_CONFIG = ((CORE_PIN5_PORTREG & CORE_PIN5_BITMASK)
  267. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  268. GPIO_BITBAND(CORE_PIN5_DDRREG, CORE_PIN5_BIT) = 0;
  269. }
  270. inline void clr6() __attribute__((always_inline)) {
  271. CORE_PIN6_CONFIG = ((CORE_PIN6_PORTREG & CORE_PIN6_BITMASK)
  272. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  273. GPIO_BITBAND(CORE_PIN6_DDRREG, CORE_PIN6_BIT) = 0;
  274. }
  275. inline void clr7() __attribute__((always_inline)) {
  276. CORE_PIN7_CONFIG = ((CORE_PIN7_PORTREG & CORE_PIN7_BITMASK)
  277. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  278. GPIO_BITBAND(CORE_PIN7_DDRREG, CORE_PIN7_BIT) = 0;
  279. }
  280. };
  281. extern DDRDemulation DDRD;
  282. class PORTBemulation
  283. {
  284. public:
  285. inline PORTBemulation & operator = (int val) __attribute__((always_inline)) {
  286. digitalWriteFast(8, (val & (1<<0)));
  287. if (!(CORE_PIN8_DDRREG & CORE_PIN8_BIT))
  288. CORE_PIN8_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  289. digitalWriteFast(9, (val & (1<<1)));
  290. if (!(CORE_PIN9_DDRREG & CORE_PIN9_BIT))
  291. CORE_PIN9_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  292. digitalWriteFast(10, (val & (1<<2)));
  293. if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT))
  294. CORE_PIN10_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  295. digitalWriteFast(11, (val & (1<<3)));
  296. if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT))
  297. CORE_PIN11_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  298. digitalWriteFast(12, (val & (1<<4)));
  299. if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT))
  300. CORE_PIN12_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  301. digitalWriteFast(13, (val & (1<<5)));
  302. if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT))
  303. CORE_PIN13_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  304. return *this;
  305. }
  306. inline PORTBemulation & operator |= (int val) __attribute__((always_inline)) {
  307. if (val & (1<<0)) {
  308. digitalWriteFast(8, HIGH);
  309. if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN8_CONFIG = CONFIG_PULLUP;
  310. }
  311. if (val & (1<<1)) {
  312. digitalWriteFast(9, HIGH);
  313. if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN9_CONFIG = CONFIG_PULLUP;
  314. }
  315. if (val & (1<<2)) {
  316. digitalWriteFast(10, HIGH);
  317. if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) CORE_PIN10_CONFIG = CONFIG_PULLUP;
  318. }
  319. if (val & (1<<3)) {
  320. digitalWriteFast(11, HIGH);
  321. if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) CORE_PIN11_CONFIG = CONFIG_PULLUP;
  322. }
  323. if (val & (1<<4)) {
  324. digitalWriteFast(12, HIGH);
  325. if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) CORE_PIN12_CONFIG = CONFIG_PULLUP;
  326. }
  327. if (val & (1<<5)) {
  328. digitalWriteFast(13, HIGH);
  329. if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) CORE_PIN13_CONFIG = CONFIG_PULLUP;
  330. }
  331. return *this;
  332. }
  333. inline PORTBemulation & operator &= (int val) __attribute__((always_inline)) {
  334. if (!(val & (1<<0))) {
  335. digitalWriteFast(8, LOW);
  336. if (!(CORE_PIN8_DDRREG & CORE_PIN8_BIT)) CORE_PIN8_CONFIG = CONFIG_NOPULLUP;
  337. }
  338. if (!(val & (1<<1))) {
  339. digitalWriteFast(9, LOW);
  340. if (!(CORE_PIN9_DDRREG & CORE_PIN9_BIT)) CORE_PIN9_CONFIG = CONFIG_NOPULLUP;
  341. }
  342. if (!(val & (1<<2))) {
  343. digitalWriteFast(10, LOW);
  344. if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) CORE_PIN10_CONFIG = CONFIG_NOPULLUP;
  345. }
  346. if (!(val & (1<<3))) {
  347. digitalWriteFast(11, LOW);
  348. if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) CORE_PIN11_CONFIG = CONFIG_NOPULLUP;
  349. }
  350. if (!(val & (1<<4))) {
  351. digitalWriteFast(12, LOW);
  352. if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) CORE_PIN12_CONFIG = CONFIG_NOPULLUP;
  353. }
  354. if (!(val & (1<<5))) {
  355. digitalWriteFast(13, LOW);
  356. if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) CORE_PIN13_CONFIG = CONFIG_NOPULLUP;
  357. }
  358. return *this;
  359. }
  360. };
  361. extern PORTBemulation PORTB;
  362. class PINBemulation
  363. {
  364. public:
  365. inline int operator & (int val) const __attribute__((always_inline)) {
  366. int ret = 0;
  367. if ((val & (1<<0)) && digitalReadFast(8)) ret |= (1<<0);
  368. if ((val & (1<<1)) && digitalReadFast(9)) ret |= (1<<1);
  369. if ((val & (1<<2)) && digitalReadFast(10)) ret |= (1<<2);
  370. if ((val & (1<<3)) && digitalReadFast(11)) ret |= (1<<3);
  371. if ((val & (1<<4)) && digitalReadFast(12)) ret |= (1<<4);
  372. if ((val & (1<<5)) && digitalReadFast(13)) ret |= (1<<5);
  373. return ret;
  374. }
  375. operator int () const __attribute__((always_inline)) {
  376. int ret = 0;
  377. if (digitalReadFast(8)) ret |= (1<<0);
  378. if (digitalReadFast(9)) ret |= (1<<1);
  379. if (digitalReadFast(10)) ret |= (1<<2);
  380. if (digitalReadFast(11)) ret |= (1<<3);
  381. if (digitalReadFast(12)) ret |= (1<<4);
  382. if (digitalReadFast(13)) ret |= (1<<5);
  383. return ret;
  384. }
  385. };
  386. extern PINBemulation PINB;
  387. class DDRBemulation
  388. {
  389. public:
  390. inline DDRBemulation & operator = (int val) __attribute__((always_inline)) {
  391. if (val & (1<<0)) set0(); else clr0();
  392. if (val & (1<<1)) set1(); else clr1();
  393. if (val & (1<<2)) set2(); else clr2();
  394. if (val & (1<<3)) set3(); else clr3();
  395. if (val & (1<<4)) set4(); else clr4();
  396. if (val & (1<<5)) set5(); else clr5();
  397. return *this;
  398. }
  399. inline DDRBemulation & operator |= (int val) __attribute__((always_inline)) {
  400. if (val & (1<<0)) set0();
  401. if (val & (1<<1)) set1();
  402. if (val & (1<<2)) set2();
  403. if (val & (1<<3)) set3();
  404. if (val & (1<<4)) set4();
  405. if (val & (1<<5)) set5();
  406. return *this;
  407. }
  408. inline DDRBemulation & operator &= (int val) __attribute__((always_inline)) {
  409. if (!(val & (1<<0))) clr0();
  410. if (!(val & (1<<1))) clr1();
  411. if (!(val & (1<<2))) clr2();
  412. if (!(val & (1<<3))) clr3();
  413. if (!(val & (1<<4))) clr4();
  414. if (!(val & (1<<5))) clr5();
  415. return *this;
  416. }
  417. private:
  418. inline void set0() __attribute__((always_inline)) {
  419. GPIO_BITBAND(CORE_PIN8_DDRREG, CORE_PIN8_BIT) = 1;
  420. CORE_PIN8_CONFIG = CONFIG_PULLUP;
  421. }
  422. inline void set1() __attribute__((always_inline)) {
  423. GPIO_BITBAND(CORE_PIN9_DDRREG, CORE_PIN9_BIT) = 1;
  424. CORE_PIN9_CONFIG = CONFIG_PULLUP;
  425. }
  426. inline void set2() __attribute__((always_inline)) {
  427. GPIO_BITBAND(CORE_PIN10_DDRREG, CORE_PIN10_BIT) = 1;
  428. CORE_PIN10_CONFIG = CONFIG_PULLUP;
  429. }
  430. inline void set3() __attribute__((always_inline)) {
  431. GPIO_BITBAND(CORE_PIN11_DDRREG, CORE_PIN11_BIT) = 1;
  432. CORE_PIN11_CONFIG = CONFIG_PULLUP;
  433. }
  434. inline void set4() __attribute__((always_inline)) {
  435. GPIO_BITBAND(CORE_PIN12_DDRREG, CORE_PIN12_BIT) = 1;
  436. CORE_PIN12_CONFIG = CONFIG_PULLUP;
  437. }
  438. inline void set5() __attribute__((always_inline)) {
  439. GPIO_BITBAND(CORE_PIN13_DDRREG, CORE_PIN13_BIT) = 1;
  440. CORE_PIN13_CONFIG = CONFIG_PULLUP;
  441. }
  442. inline void clr0() __attribute__((always_inline)) {
  443. CORE_PIN8_CONFIG = ((CORE_PIN8_PORTREG & CORE_PIN8_BITMASK)
  444. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  445. GPIO_BITBAND(CORE_PIN8_DDRREG, CORE_PIN8_BIT) = 0;
  446. }
  447. inline void clr1() __attribute__((always_inline)) {
  448. CORE_PIN9_CONFIG = ((CORE_PIN9_PORTREG & CORE_PIN9_BITMASK)
  449. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  450. GPIO_BITBAND(CORE_PIN9_DDRREG, CORE_PIN9_BIT) = 0;
  451. }
  452. inline void clr2() __attribute__((always_inline)) {
  453. CORE_PIN10_CONFIG = ((CORE_PIN10_PORTREG & CORE_PIN10_BITMASK)
  454. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  455. GPIO_BITBAND(CORE_PIN10_DDRREG, CORE_PIN10_BIT) = 0;
  456. }
  457. inline void clr3() __attribute__((always_inline)) {
  458. CORE_PIN11_CONFIG = ((CORE_PIN11_PORTREG & CORE_PIN11_BITMASK)
  459. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  460. GPIO_BITBAND(CORE_PIN11_DDRREG, CORE_PIN11_BIT) = 0;
  461. }
  462. inline void clr4() __attribute__((always_inline)) {
  463. CORE_PIN12_CONFIG = ((CORE_PIN12_PORTREG & CORE_PIN12_BITMASK)
  464. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  465. GPIO_BITBAND(CORE_PIN12_DDRREG, CORE_PIN12_BIT) = 0;
  466. }
  467. inline void clr5() __attribute__((always_inline)) {
  468. CORE_PIN13_CONFIG = ((CORE_PIN13_PORTREG & CORE_PIN13_BITMASK)
  469. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  470. GPIO_BITBAND(CORE_PIN13_DDRREG, CORE_PIN13_BIT) = 0;
  471. }
  472. };
  473. extern DDRBemulation DDRB;
  474. class PORTCemulation
  475. {
  476. public:
  477. inline PORTCemulation & operator = (int val) __attribute__((always_inline)) {
  478. digitalWriteFast(14, (val & (1<<0)));
  479. if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT))
  480. CORE_PIN14_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  481. digitalWriteFast(15, (val & (1<<1)));
  482. if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT))
  483. CORE_PIN15_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  484. digitalWriteFast(16, (val & (1<<2)));
  485. if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT))
  486. CORE_PIN16_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  487. digitalWriteFast(17, (val & (1<<3)));
  488. if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT))
  489. CORE_PIN17_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  490. digitalWriteFast(18, (val & (1<<4)));
  491. if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT))
  492. CORE_PIN18_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  493. digitalWriteFast(19, (val & (1<<5)));
  494. if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT))
  495. CORE_PIN19_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  496. return *this;
  497. }
  498. inline PORTCemulation & operator |= (int val) __attribute__((always_inline)) {
  499. if (val & (1<<0)) {
  500. digitalWriteFast(14, HIGH);
  501. if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) CORE_PIN14_CONFIG = CONFIG_PULLUP;
  502. }
  503. if (val & (1<<1)) {
  504. digitalWriteFast(15, HIGH);
  505. if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) CORE_PIN15_CONFIG = CONFIG_PULLUP;
  506. }
  507. if (val & (1<<2)) {
  508. digitalWriteFast(16, HIGH);
  509. if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) CORE_PIN16_CONFIG = CONFIG_PULLUP;
  510. }
  511. if (val & (1<<3)) {
  512. digitalWriteFast(17, HIGH);
  513. if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) CORE_PIN17_CONFIG = CONFIG_PULLUP;
  514. }
  515. if (val & (1<<4)) {
  516. digitalWriteFast(18, HIGH);
  517. if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) CORE_PIN18_CONFIG = CONFIG_PULLUP;
  518. }
  519. if (val & (1<<5)) {
  520. digitalWriteFast(19, HIGH);
  521. if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) CORE_PIN19_CONFIG = CONFIG_PULLUP;
  522. }
  523. return *this;
  524. }
  525. inline PORTCemulation & operator &= (int val) __attribute__((always_inline)) {
  526. if (!(val & (1<<0))) {
  527. digitalWriteFast(14, LOW);
  528. if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) CORE_PIN14_CONFIG = CONFIG_NOPULLUP;
  529. }
  530. if (!(val & (1<<1))) {
  531. digitalWriteFast(15, LOW);
  532. if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) CORE_PIN15_CONFIG = CONFIG_NOPULLUP;
  533. }
  534. if (!(val & (1<<2))) {
  535. digitalWriteFast(16, LOW);
  536. if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) CORE_PIN16_CONFIG = CONFIG_NOPULLUP;
  537. }
  538. if (!(val & (1<<3))) {
  539. digitalWriteFast(17, LOW);
  540. if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) CORE_PIN17_CONFIG = CONFIG_NOPULLUP;
  541. }
  542. if (!(val & (1<<4))) {
  543. digitalWriteFast(18, LOW);
  544. if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) CORE_PIN18_CONFIG = CONFIG_NOPULLUP;
  545. }
  546. if (!(val & (1<<5))) {
  547. digitalWriteFast(19, LOW);
  548. if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) CORE_PIN19_CONFIG = CONFIG_NOPULLUP;
  549. }
  550. return *this;
  551. }
  552. };
  553. extern PORTCemulation PORTC;
  554. class PINCemulation
  555. {
  556. public:
  557. inline int operator & (int val) const __attribute__((always_inline)) {
  558. int ret = 0;
  559. if ((val & (1<<0)) && digitalReadFast(8)) ret |= (1<<0);
  560. if ((val & (1<<1)) && digitalReadFast(9)) ret |= (1<<1);
  561. if ((val & (1<<2)) && digitalReadFast(10)) ret |= (1<<2);
  562. if ((val & (1<<3)) && digitalReadFast(11)) ret |= (1<<3);
  563. if ((val & (1<<4)) && digitalReadFast(12)) ret |= (1<<4);
  564. if ((val & (1<<5)) && digitalReadFast(13)) ret |= (1<<5);
  565. return ret;
  566. }
  567. operator int () const __attribute__((always_inline)) {
  568. int ret = 0;
  569. if (digitalReadFast(8)) ret |= (1<<0);
  570. if (digitalReadFast(9)) ret |= (1<<1);
  571. if (digitalReadFast(10)) ret |= (1<<2);
  572. if (digitalReadFast(11)) ret |= (1<<3);
  573. if (digitalReadFast(12)) ret |= (1<<4);
  574. if (digitalReadFast(13)) ret |= (1<<5);
  575. return ret;
  576. }
  577. };
  578. extern PINCemulation PINC;
  579. class DDRCemulation
  580. {
  581. public:
  582. inline DDRCemulation & operator = (int val) __attribute__((always_inline)) {
  583. if (val & (1<<0)) set0(); else clr0();
  584. if (val & (1<<1)) set1(); else clr1();
  585. if (val & (1<<2)) set2(); else clr2();
  586. if (val & (1<<3)) set3(); else clr3();
  587. if (val & (1<<4)) set4(); else clr4();
  588. if (val & (1<<5)) set5(); else clr5();
  589. return *this;
  590. }
  591. inline DDRCemulation & operator |= (int val) __attribute__((always_inline)) {
  592. if (val & (1<<0)) set0();
  593. if (val & (1<<1)) set1();
  594. if (val & (1<<2)) set2();
  595. if (val & (1<<3)) set3();
  596. if (val & (1<<4)) set4();
  597. if (val & (1<<5)) set5();
  598. return *this;
  599. }
  600. inline DDRCemulation & operator &= (int val) __attribute__((always_inline)) {
  601. if (!(val & (1<<0))) clr0();
  602. if (!(val & (1<<1))) clr1();
  603. if (!(val & (1<<2))) clr2();
  604. if (!(val & (1<<3))) clr3();
  605. if (!(val & (1<<4))) clr4();
  606. if (!(val & (1<<5))) clr5();
  607. return *this;
  608. }
  609. private:
  610. inline void set0() __attribute__((always_inline)) {
  611. GPIO_BITBAND(CORE_PIN14_DDRREG, CORE_PIN14_BIT) = 1;
  612. CORE_PIN14_CONFIG = CONFIG_PULLUP;
  613. }
  614. inline void set1() __attribute__((always_inline)) {
  615. GPIO_BITBAND(CORE_PIN15_DDRREG, CORE_PIN15_BIT) = 1;
  616. CORE_PIN15_CONFIG = CONFIG_PULLUP;
  617. }
  618. inline void set2() __attribute__((always_inline)) {
  619. GPIO_BITBAND(CORE_PIN16_DDRREG, CORE_PIN16_BIT) = 1;
  620. CORE_PIN16_CONFIG = CONFIG_PULLUP;
  621. }
  622. inline void set3() __attribute__((always_inline)) {
  623. GPIO_BITBAND(CORE_PIN17_DDRREG, CORE_PIN17_BIT) = 1;
  624. CORE_PIN17_CONFIG = CONFIG_PULLUP;
  625. }
  626. inline void set4() __attribute__((always_inline)) {
  627. GPIO_BITBAND(CORE_PIN18_DDRREG, CORE_PIN18_BIT) = 1;
  628. CORE_PIN18_CONFIG = CONFIG_PULLUP;
  629. }
  630. inline void set5() __attribute__((always_inline)) {
  631. GPIO_BITBAND(CORE_PIN19_DDRREG, CORE_PIN19_BIT) = 1;
  632. CORE_PIN19_CONFIG = CONFIG_PULLUP;
  633. }
  634. inline void clr0() __attribute__((always_inline)) {
  635. CORE_PIN14_CONFIG = ((CORE_PIN14_PORTREG & CORE_PIN14_BITMASK)
  636. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  637. GPIO_BITBAND(CORE_PIN14_DDRREG, CORE_PIN14_BIT) = 0;
  638. }
  639. inline void clr1() __attribute__((always_inline)) {
  640. CORE_PIN15_CONFIG = ((CORE_PIN15_PORTREG & CORE_PIN15_BITMASK)
  641. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  642. GPIO_BITBAND(CORE_PIN15_DDRREG, CORE_PIN15_BIT) = 0;
  643. }
  644. inline void clr2() __attribute__((always_inline)) {
  645. CORE_PIN16_CONFIG = ((CORE_PIN16_PORTREG & CORE_PIN16_BITMASK)
  646. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  647. GPIO_BITBAND(CORE_PIN16_DDRREG, CORE_PIN16_BIT) = 0;
  648. }
  649. inline void clr3() __attribute__((always_inline)) {
  650. CORE_PIN17_CONFIG = ((CORE_PIN17_PORTREG & CORE_PIN17_BITMASK)
  651. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  652. GPIO_BITBAND(CORE_PIN17_DDRREG, CORE_PIN17_BIT) = 0;
  653. }
  654. inline void clr4() __attribute__((always_inline)) {
  655. CORE_PIN18_CONFIG = ((CORE_PIN18_PORTREG & CORE_PIN18_BITMASK)
  656. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  657. GPIO_BITBAND(CORE_PIN18_DDRREG, CORE_PIN18_BIT) = 0;
  658. }
  659. inline void clr5() __attribute__((always_inline)) {
  660. CORE_PIN19_CONFIG = ((CORE_PIN19_PORTREG & CORE_PIN19_BITMASK)
  661. ? CONFIG_PULLUP : CONFIG_NOPULLUP);
  662. GPIO_BITBAND(CORE_PIN19_DDRREG, CORE_PIN19_BIT) = 0;
  663. }
  664. };
  665. extern DDRCemulation DDRC;
  666. #define PINB0 0
  667. #define PINB1 1
  668. #define PINB2 2
  669. #define PINB3 3
  670. #define PINB4 4
  671. #define PINB5 5
  672. #define PINB6 6
  673. #define PINB7 7
  674. #define DDB0 0
  675. #define DDB1 1
  676. #define DDB2 2
  677. #define DDB3 3
  678. #define DDB4 4
  679. #define DDB5 5
  680. #define DDB6 6
  681. #define DDB7 7
  682. #define PORTB0 0
  683. #define PORTB1 1
  684. #define PORTB2 2
  685. #define PORTB3 3
  686. #define PORTB4 4
  687. #define PORTB5 5
  688. #define PORTB6 6
  689. #define PORTB7 7
  690. #define PINC0 0
  691. #define PINC1 1
  692. #define PINC2 2
  693. #define PINC3 3
  694. #define PINC4 4
  695. #define PINC5 5
  696. #define PINC6 6
  697. #define DDC0 0
  698. #define DDC1 1
  699. #define DDC2 2
  700. #define DDC3 3
  701. #define DDC4 4
  702. #define DDC5 5
  703. #define DDC6 6
  704. #define PORTC0 0
  705. #define PORTC1 1
  706. #define PORTC2 2
  707. #define PORTC3 3
  708. #define PORTC4 4
  709. #define PORTC5 5
  710. #define PORTC6 6
  711. #define PIND0 0
  712. #define PIND1 1
  713. #define PIND2 2
  714. #define PIND3 3
  715. #define PIND4 4
  716. #define PIND5 5
  717. #define PIND6 6
  718. #define PIND7 7
  719. #define DDD0 0
  720. #define DDD1 1
  721. #define DDD2 2
  722. #define DDD3 3
  723. #define DDD4 4
  724. #define DDD5 5
  725. #define DDD6 6
  726. #define DDD7 7
  727. #define PORTD0 0
  728. #define PORTD1 1
  729. #define PORTD2 2
  730. #define PORTD3 3
  731. #define PORTD4 4
  732. #define PORTD5 5
  733. #define PORTD6 6
  734. #define PORTD7 7
  735. #if 0
  736. extern "C" {
  737. void serial_print(const char *p);
  738. void serial_phex(uint32_t n);
  739. void serial_phex16(uint32_t n);
  740. void serial_phex32(uint32_t n);
  741. }
  742. #endif
  743. // SPI Control Register ­ SPCR
  744. #define SPIE 7 // SPI Interrupt Enable - not supported
  745. #define SPE 6 // SPI Enable
  746. #define DORD 5 // DORD: Data Order
  747. #define MSTR 4 // MSTR: Master/Slave Select
  748. #define CPOL 3 // CPOL: Clock Polarity
  749. #define CPHA 2 // CPHA: Clock Phase
  750. #define SPR1 1 // Clock: 3 = 125 kHz, 2 = 250 kHz, 1 = 1 MHz, 0->4 MHz
  751. #define SPR0 0
  752. // SPI Status Register ­ SPSR
  753. #define SPIF 7 // SPIF: SPI Interrupt Flag
  754. #define WCOL 6 // WCOL: Write COLlision Flag - not implemented
  755. #define SPI2X 0 // SPI2X: Double SPI Speed Bit
  756. // SPI Data Register ­ SPDR
  757. class SPCRemulation;
  758. class SPSRemulation;
  759. class SPDRemulation;
  760. class SPCRemulation
  761. {
  762. public:
  763. inline SPCRemulation & operator = (int val) __attribute__((always_inline)) {
  764. uint32_t ctar, mcr, sim6;
  765. //serial_print("SPCR=");
  766. //serial_phex(val);
  767. //serial_print("\n");
  768. sim6 = SIM_SCGC6;
  769. if (!(sim6 & SIM_SCGC6_SPI0)) {
  770. //serial_print("init1\n");
  771. SIM_SCGC6 = sim6 | SIM_SCGC6_SPI0;
  772. SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  773. }
  774. if (!(val & (1<<SPE))) {
  775. SPI0_MCR |= SPI_MCR_MDIS; // TODO: use bitband for atomic access
  776. }
  777. ctar = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1);
  778. if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE;
  779. if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
  780. if (val & (1<<CPHA)) {
  781. ctar |= SPI_CTAR_CPHA;
  782. if ((val & 3) == 0) {
  783. ctar |= SPI_CTAR_BR(1) | SPI_CTAR_ASC(1);
  784. } else if ((val & 3) == 1) {
  785. ctar |= SPI_CTAR_BR(4) | SPI_CTAR_ASC(4);
  786. } else if ((val & 3) == 2) {
  787. ctar |= SPI_CTAR_BR(6) | SPI_CTAR_ASC(6);
  788. } else {
  789. ctar |= SPI_CTAR_BR(7) | SPI_CTAR_ASC(7);
  790. }
  791. } else {
  792. if ((val & 3) == 0) {
  793. ctar |= SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  794. } else if ((val & 3) == 1) {
  795. ctar |= SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4);
  796. } else if ((val & 3) == 2) {
  797. ctar |= SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6);
  798. } else {
  799. ctar |= SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(7);
  800. }
  801. }
  802. ctar |= (SPI0_CTAR0 & SPI_CTAR_DBR);
  803. update_ctar(ctar);
  804. mcr = SPI_MCR_DCONF(0) | SPI_MCR_PCSIS(0x1F);
  805. if (val & (1<<MSTR)) mcr |= SPI_MCR_MSTR;
  806. if (val & (1<<SPE)) {
  807. mcr &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
  808. SPI0_MCR = mcr;
  809. enable_pins();
  810. } else {
  811. mcr |= (SPI_MCR_MDIS | SPI_MCR_HALT);
  812. SPI0_MCR = mcr;
  813. disable_pins();
  814. }
  815. //serial_print("MCR:");
  816. //serial_phex32(SPI0_MCR);
  817. //serial_print(", CTAR0:");
  818. //serial_phex32(SPI0_CTAR0);
  819. //serial_print("\n");
  820. return *this;
  821. }
  822. inline SPCRemulation & operator |= (int val) __attribute__((always_inline)) {
  823. uint32_t sim6;
  824. //serial_print("SPCR |= ");
  825. //serial_phex(val);
  826. //serial_print("\n");
  827. sim6 = SIM_SCGC6;
  828. if (!(sim6 & SIM_SCGC6_SPI0)) {
  829. //serial_print("init2\n");
  830. SIM_SCGC6 = sim6 | SIM_SCGC6_SPI0;
  831. SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1);
  832. }
  833. if (val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
  834. uint32_t ctar = SPI0_CTAR0;
  835. if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; // TODO: use bitband
  836. if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
  837. if ((val & 3) == 1) {
  838. // TODO: implement - is this ever really needed
  839. } else if ((val & 3) == 2) {
  840. // TODO: implement - is this ever really needed
  841. } else if ((val & 3) == 3) {
  842. // TODO: implement - is this ever really needed
  843. }
  844. if (val & (1<<CPHA) && !(ctar & SPI_CTAR_CPHA)) {
  845. ctar |= SPI_CTAR_CPHA;
  846. // TODO: clear SPI_CTAR_CSSCK, set SPI_CTAR_ASC
  847. }
  848. update_ctar(ctar);
  849. }
  850. if (val & (1<<MSTR)) SPI0_MCR |= SPI_MCR_MSTR;
  851. if (val & (1<<SPE)) {
  852. SPI0_MCR &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
  853. enable_pins();
  854. }
  855. //serial_print("MCR:");
  856. //serial_phex32(SPI0_MCR);
  857. //serial_print(", CTAR0:");
  858. //serial_phex32(SPI0_CTAR0);
  859. //serial_print("\n");
  860. return *this;
  861. }
  862. inline SPCRemulation & operator &= (int val) __attribute__((always_inline)) {
  863. //serial_print("SPCR &= ");
  864. //serial_phex(val);
  865. //serial_print("\n");
  866. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  867. if (!(val & (1<<SPE))) {
  868. SPI0_MCR |= (SPI_MCR_MDIS | SPI_MCR_HALT);
  869. disable_pins();
  870. }
  871. if ((val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) != ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
  872. uint32_t ctar = SPI0_CTAR0;
  873. if (!(val & (1<<DORD))) ctar &= ~SPI_CTAR_LSBFE; // TODO: use bitband
  874. if (!(val & (1<<CPOL))) ctar &= ~SPI_CTAR_CPOL;
  875. if ((val & 3) == 0) {
  876. // TODO: implement - is this ever really needed
  877. } else if ((val & 3) == 1) {
  878. // TODO: implement - is this ever really needed
  879. } else if ((val & 3) == 2) {
  880. // TODO: implement - is this ever really needed
  881. }
  882. if (!(val & (1<<CPHA)) && (ctar & SPI_CTAR_CPHA)) {
  883. ctar &= ~SPI_CTAR_CPHA;
  884. // TODO: set SPI_CTAR_ASC, clear SPI_CTAR_CSSCK
  885. }
  886. update_ctar(ctar);
  887. }
  888. if (!(val & (1<<MSTR))) SPI0_MCR &= ~SPI_MCR_MSTR;
  889. return *this;
  890. }
  891. inline int operator & (int val) const __attribute__((always_inline)) {
  892. int ret = 0;
  893. //serial_print("SPCR & ");
  894. //serial_phex(val);
  895. //serial_print("\n");
  896. if ((val & (1<<DORD)) && (SPI0_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD);
  897. if ((val & (1<<CPOL)) && (SPI0_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL);
  898. if ((val & (1<<CPHA)) && (SPI0_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA);
  899. if ((val & 3) == 3) {
  900. uint32_t dbr = SPI0_CTAR0 & 15;
  901. if (dbr <= 1) {
  902. } else if (dbr <= 4) {
  903. ret |= (1<<SPR0);
  904. } else if (dbr <= 6) {
  905. ret |= (1<<SPR1);
  906. } else {
  907. ret |= (1<<SPR1)|(1<<SPR0);
  908. }
  909. } else if ((val & 3) == 1) {
  910. // TODO: implement - is this ever really needed
  911. } else if ((val & 3) == 2) {
  912. // TODO: implement - is this ever really needed
  913. }
  914. if (val & (1<<SPE) && (!(SPI0_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE);
  915. if (val & (1<<MSTR) && (SPI0_MCR & SPI_MCR_MSTR)) ret |= (1<<MSTR);
  916. //serial_print("ret = ");
  917. //serial_phex(ret);
  918. //serial_print("\n");
  919. return ret;
  920. }
  921. operator int () const __attribute__((always_inline)) {
  922. int ret = 0;
  923. if ((SIM_SCGC6 & SIM_SCGC6_SPI0)) {
  924. int ctar = SPI0_CTAR0;
  925. if (ctar & SPI_CTAR_LSBFE) ret |= (1<<DORD);
  926. if (ctar & SPI_CTAR_CPOL) ret |= (1<<CPOL);
  927. if (ctar & SPI_CTAR_CPHA) ret |= (1<<CPHA);
  928. ctar &= 15;
  929. if (ctar <= 1) {
  930. } else if (ctar <= 4) {
  931. ret |= (1<<SPR0);
  932. } else if (ctar <= 6) {
  933. ret |= (1<<SPR1);
  934. } else {
  935. ret |= (1<<SPR1)|(1<<SPR0);
  936. }
  937. int mcr = SPI0_MCR;
  938. if (!(mcr & SPI_MCR_MDIS)) ret |= (1<<SPE);
  939. if (mcr & SPI_MCR_MSTR) ret |= (1<<MSTR);
  940. }
  941. return ret;
  942. }
  943. inline void setMOSI(uint8_t pin) __attribute__((always_inline)) {
  944. if (pin == 11) pinout &= ~1;
  945. if (pin == 7) pinout |= 1;
  946. }
  947. inline void setMISO(uint8_t pin) __attribute__((always_inline)) {
  948. if (pin == 12) pinout &= ~2;
  949. if (pin == 8) pinout |= 2;
  950. }
  951. inline void setSCK(uint8_t pin) __attribute__((always_inline)) {
  952. if (pin == 13) pinout &= ~4;
  953. if (pin == 14) pinout |= 4;
  954. }
  955. friend class SPSRemulation;
  956. friend class SPIFIFOclass;
  957. private:
  958. static inline void update_ctar(uint32_t ctar) __attribute__((always_inline)) {
  959. if (SPI0_CTAR0 == ctar) return;
  960. uint32_t mcr = SPI0_MCR;
  961. if (mcr & SPI_MCR_MDIS) {
  962. SPI0_CTAR0 = ctar;
  963. } else {
  964. SPI0_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT;
  965. SPI0_CTAR0 = ctar;
  966. SPI0_MCR = mcr;
  967. }
  968. }
  969. static uint8_t pinout;
  970. public:
  971. inline void enable_pins(void) __attribute__((always_inline)) {
  972. //serial_print("enable_pins\n");
  973. if ((pinout & 1) == 0) {
  974. CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); // DOUT/MOSI = 11 (PTC6)
  975. } else {
  976. CORE_PIN7_CONFIG = PORT_PCR_MUX(2); // DOUT/MOSI = 7 (PTD2)
  977. }
  978. if ((pinout & 2) == 0) {
  979. CORE_PIN12_CONFIG = PORT_PCR_MUX(2); // DIN/MISO = 12 (PTC7)
  980. } else {
  981. CORE_PIN8_CONFIG = PORT_PCR_MUX(2); // DIN/MISO = 8 (PTD3)
  982. }
  983. if ((pinout & 4) == 0) {
  984. CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); // SCK = 13 (PTC5)
  985. } else {
  986. CORE_PIN14_CONFIG = PORT_PCR_MUX(2); // SCK = 14 (PTD1)
  987. }
  988. }
  989. inline void disable_pins(void) __attribute__((always_inline)) {
  990. //serial_print("disable_pins\n");
  991. CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  992. CORE_PIN12_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  993. CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  994. }
  995. };
  996. extern SPCRemulation SPCR;
  997. class SPSRemulation
  998. {
  999. public:
  1000. inline SPSRemulation & operator = (int val) __attribute__((always_inline)) {
  1001. //serial_print("SPSR=");
  1002. //serial_phex(val);
  1003. //serial_print("\n");
  1004. uint32_t ctar = SPI0_CTAR0;
  1005. if (val & (1<<SPI2X)) {
  1006. ctar |= SPI_CTAR_DBR;
  1007. } else {
  1008. ctar &= ~SPI_CTAR_DBR;
  1009. }
  1010. SPCRemulation::update_ctar(ctar);
  1011. //serial_print("MCR:");
  1012. //serial_phex32(SPI0_MCR);
  1013. //serial_print(", CTAR0:");
  1014. //serial_phex32(SPI0_CTAR0);
  1015. //serial_print("\n");
  1016. return *this;
  1017. }
  1018. inline SPSRemulation & operator |= (int val) __attribute__((always_inline)) {
  1019. //serial_print("SPSR |= ");
  1020. //serial_phex(val);
  1021. //serial_print("\n");
  1022. if (val & (1<<SPI2X)) SPCRemulation::update_ctar(SPI0_CTAR0 |= SPI_CTAR_DBR);
  1023. return *this;
  1024. }
  1025. inline SPSRemulation & operator &= (int val) __attribute__((always_inline)) {
  1026. //serial_print("SPSR &= ");
  1027. //serial_phex(val);
  1028. //serial_print("\n");
  1029. if (!(val & (1<<SPI2X))) SPCRemulation::update_ctar(SPI0_CTAR0 &= ~SPI_CTAR_DBR);
  1030. return *this;
  1031. }
  1032. inline int operator & (int val) const __attribute__((always_inline)) {
  1033. int ret = 0;
  1034. //serial_print("SPSR & ");
  1035. //serial_phex(val);
  1036. //serial_print("\n");
  1037. // TODO: using SPI_SR_TCF isn't quite right. Control returns to the
  1038. // caller after the final edge that captures data, which is 1/2 cycle
  1039. // sooner than AVR returns. At 500 kHz and slower SPI, this can make
  1040. // a difference when digitalWrite is used to manually control the CS
  1041. // pin, and perhaps it could matter at high clocks if faster register
  1042. // access is used? But does it really matter? Do any SPI chips in
  1043. // practice really perform differently if CS negates early, after the
  1044. // final bit is clocked, but before the end of the whole clock cycle?
  1045. if ((val & (1<<SPIF)) && (SPI0_SR & SPI_SR_TCF)) ret = (1<<SPIF);
  1046. if ((val & (1<<SPI2X)) && (SPI0_CTAR0 & SPI_CTAR_DBR)) ret |= (1<<SPI2X);
  1047. //delayMicroseconds(50000);
  1048. return ret;
  1049. }
  1050. operator int () const __attribute__((always_inline)) {
  1051. int ret = 0;
  1052. //serial_print("SPSR (int)\n");
  1053. if (SPI0_SR & SPI_SR_TCF) ret = (1<<SPIF);
  1054. if (SPI0_CTAR0 & SPI_CTAR_DBR) ret |= (1<<SPI2X);
  1055. return ret;
  1056. }
  1057. };
  1058. extern SPSRemulation SPSR;
  1059. class SPDRemulation
  1060. {
  1061. public:
  1062. inline SPDRemulation & operator = (int val) __attribute__((always_inline)) {
  1063. //serial_print("SPDR = ");
  1064. //serial_phex(val);
  1065. //serial_print("\n");
  1066. SPI0_MCR |= SPI_MCR_CLR_RXF; // discard any received data
  1067. SPI0_SR = SPI_SR_TCF;
  1068. //SPI0_SR = SPI_SR_EOQF;
  1069. //SPI0_PUSHR = (val & 255) | SPI0_PUSHR_EOQ;
  1070. SPI0_PUSHR = (val & 255);
  1071. return *this;
  1072. }
  1073. operator int () const __attribute__((always_inline)) {
  1074. uint32_t val;
  1075. val = SPI0_POPR & 255;
  1076. //serial_print("SPDR (int) ");
  1077. //serial_phex(val);
  1078. //serial_print("\n");
  1079. return val;
  1080. }
  1081. };
  1082. extern SPDRemulation SPDR;
  1083. class SREGemulation
  1084. {
  1085. public:
  1086. operator int () const __attribute__((always_inline)) {
  1087. uint32_t primask;
  1088. asm volatile("mrs %0, primask\n" : "=r" (primask)::);
  1089. if (primask) return 0;
  1090. return (1<<7);
  1091. }
  1092. inline SREGemulation & operator = (int val) __attribute__((always_inline)) {
  1093. if (val & (1<<7)) {
  1094. __enable_irq();
  1095. } else {
  1096. __disable_irq();
  1097. }
  1098. return *this;
  1099. }
  1100. };
  1101. extern SREGemulation SREG;
  1102. // these are not intended for public consumption...
  1103. #undef GPIO_BITBAND_ADDR
  1104. #undef GPIO_BITBAND
  1105. #undef CONFIG_PULLUP
  1106. #undef CONFIG_NOPULLUP
  1107. #endif // __cplusplus
  1108. #endif