U8x8lib.cpp 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910
  1. /*
  2. U8x8lib.cpp
  3. Arduino specific low level functions
  4. Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
  5. Copyright (c) 2016, olikraus@gmail.com
  6. All rights reserved.
  7. Redistribution and use in source and binary forms, with or without modification,
  8. are permitted provided that the following conditions are met:
  9. * Redistributions of source code must retain the above copyright notice, this list
  10. of conditions and the following disclaimer.
  11. * Redistributions in binary form must reproduce the above copyright notice, this
  12. list of conditions and the following disclaimer in the documentation and/or other
  13. materials provided with the distribution.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  15. CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  16. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  17. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  19. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  24. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  26. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "U8x8lib.h"
  29. #ifdef ARDUINO
  30. #ifdef U8X8_HAVE_HW_SPI
  31. #include <SPI.h>
  32. #endif
  33. #ifdef U8X8_HAVE_HW_I2C
  34. # ifdef U8X8_HAVE_HW_I2C_TEENSY3
  35. # include <i2c_t3.h>
  36. # else
  37. # include <Wire.h>
  38. # ifdef U8X8_HAVE_2ND_HW_I2C
  39. # if defined(MINICORE) && defined(__AVR_ATmega328PB__)
  40. # include <Wire1.h>
  41. # endif
  42. # endif
  43. # endif
  44. #endif /* U8X8_HAVE_HW_I2C */
  45. #endif /* ARDUINO */
  46. /*=============================================*/
  47. size_t U8X8::write(uint8_t v)
  48. {
  49. if ( v == '\n' )
  50. {
  51. uint8_t dy = u8x8_pgm_read(u8x8.font+3); /* new 2019 format */
  52. ty+=dy;
  53. tx=0;
  54. }
  55. else
  56. {
  57. uint8_t dx = u8x8_pgm_read(u8x8.font+2); /* new 2019 format */
  58. u8x8_DrawGlyph(&u8x8, tx, ty, v);
  59. tx+=dx;
  60. }
  61. return 1;
  62. }
  63. /*=============================================*/
  64. /*=== ARDUINO GPIO & DELAY ===*/
  65. #ifdef ARDUINO
  66. #ifdef U8X8_USE_PINS
  67. extern "C" uint8_t u8x8_gpio_and_delay_arduino(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  68. {
  69. uint8_t i;
  70. switch(msg)
  71. {
  72. case U8X8_MSG_GPIO_AND_DELAY_INIT:
  73. for( i = 0; i < U8X8_PIN_CNT; i++ )
  74. if ( u8x8->pins[i] != U8X8_PIN_NONE )
  75. {
  76. if ( i < U8X8_PIN_OUTPUT_CNT )
  77. {
  78. pinMode(u8x8->pins[i], OUTPUT);
  79. }
  80. else
  81. {
  82. #ifdef INPUT_PULLUP
  83. pinMode(u8x8->pins[i], INPUT_PULLUP);
  84. #else
  85. pinMode(u8x8->pins[i], OUTPUT);
  86. digitalWrite(u8x8->pins[i], 1);
  87. #endif
  88. }
  89. }
  90. break;
  91. #ifndef __AVR__
  92. /* this case is not compiled for any AVR, because AVR uC are so slow */
  93. /* that this delay does not matter */
  94. case U8X8_MSG_DELAY_NANO:
  95. delayMicroseconds(arg_int==0?0:1);
  96. break;
  97. #endif
  98. case U8X8_MSG_DELAY_10MICRO:
  99. /* not used at the moment */
  100. break;
  101. case U8X8_MSG_DELAY_100NANO:
  102. /* not used at the moment */
  103. break;
  104. case U8X8_MSG_DELAY_MILLI:
  105. delay(arg_int);
  106. break;
  107. case U8X8_MSG_DELAY_I2C:
  108. /* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
  109. delayMicroseconds(arg_int<=2?5:2);
  110. break;
  111. case U8X8_MSG_GPIO_I2C_CLOCK:
  112. case U8X8_MSG_GPIO_I2C_DATA:
  113. if ( arg_int == 0 )
  114. {
  115. pinMode(u8x8_GetPinValue(u8x8, msg), OUTPUT);
  116. digitalWrite(u8x8_GetPinValue(u8x8, msg), 0);
  117. }
  118. else
  119. {
  120. #ifdef INPUT_PULLUP
  121. pinMode(u8x8_GetPinValue(u8x8, msg), INPUT_PULLUP);
  122. #else
  123. pinMode(u8x8_GetPinValue(u8x8, msg), OUTPUT);
  124. digitalWrite(u8x8_GetPinValue(u8x8, msg), 1);
  125. #endif
  126. }
  127. break;
  128. default:
  129. if ( msg >= U8X8_MSG_GPIO(0) )
  130. {
  131. i = u8x8_GetPinValue(u8x8, msg);
  132. if ( i != U8X8_PIN_NONE )
  133. {
  134. if ( u8x8_GetPinIndex(u8x8, msg) < U8X8_PIN_OUTPUT_CNT )
  135. {
  136. digitalWrite(i, arg_int);
  137. }
  138. else
  139. {
  140. if ( u8x8_GetPinIndex(u8x8, msg) == U8X8_PIN_OUTPUT_CNT )
  141. {
  142. // call yield() for the first pin only, u8x8 will always request all the pins, so this should be ok
  143. yield();
  144. }
  145. u8x8_SetGPIOResult(u8x8, digitalRead(i) == 0 ? 0 : 1);
  146. }
  147. }
  148. break;
  149. }
  150. return 0;
  151. }
  152. return 1;
  153. }
  154. #endif // U8X8_USE_PINS
  155. /*=============================================*/
  156. /*=== 3 WIRE SOFTWARE SPI ===*/
  157. /*
  158. replacement for a more faster u8x8_byte_3wire_sw_spi
  159. in general u8x8_byte_3wire_sw_spi could be a fallback:
  160. uint8_t u8x8_byte_arduino_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  161. {
  162. return u8x8_byte_3wire_sw_spi(u8x8, msg,arg_int, arg_ptr);
  163. }
  164. */
  165. #ifndef __AVR_ARCH__
  166. #define __AVR_ARCH__ 0
  167. #endif
  168. #if !defined(U8X8_USE_PINS)
  169. /* no pin information (very strange), so fallback */
  170. uint8_t u8x8_byte_arduino_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  171. {
  172. return u8x8_byte_3wire_sw_spi(u8x8, msg,arg_int, arg_ptr);
  173. }
  174. #elif __AVR_ARCH__ == 4 || __AVR_ARCH__ == 5 || __AVR_ARCH__ == 51 || __AVR_ARCH__ == 6 || __AVR_ARCH__ == 103
  175. /* this function completely replaces u8x8_byte_4wire_sw_spi*/
  176. extern "C" uint8_t u8x8_byte_arduino_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  177. {
  178. uint8_t i;
  179. uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
  180. uint16_t b;
  181. uint8_t *data;
  182. /* the following static vars are recalculated in U8X8_MSG_BYTE_START_TRANSFER */
  183. /* so, it should be possible to use multiple displays with different pins */
  184. static volatile uint8_t *arduino_clock_port;
  185. static uint8_t arduino_clock_mask;
  186. static uint8_t arduino_clock_n_mask;
  187. static volatile uint8_t *arduino_data_port;
  188. static uint8_t arduino_data_mask;
  189. static uint8_t arduino_data_n_mask;
  190. static uint8_t last_dc;
  191. switch(msg)
  192. {
  193. case U8X8_MSG_BYTE_SEND:
  194. data = (uint8_t *)arg_ptr;
  195. if ( takeover_edge == 0 )
  196. {
  197. while( arg_int > 0 )
  198. {
  199. b = *data;
  200. if ( last_dc != 0 )
  201. b |= 256;
  202. data++;
  203. arg_int--;
  204. /* issue 156, check for speed */
  205. #if F_CPU <= 17000000
  206. if ( b == 0 )
  207. {
  208. *arduino_data_port &= arduino_data_n_mask;
  209. for( i = 0; i < 9; i++ )
  210. {
  211. *arduino_clock_port |= arduino_clock_mask;
  212. *arduino_clock_port &= arduino_clock_n_mask;
  213. }
  214. }
  215. else
  216. #endif
  217. {
  218. for( i = 0; i < 9; i++ )
  219. {
  220. if ( b & 256 )
  221. *arduino_data_port |= arduino_data_mask;
  222. else
  223. *arduino_data_port &= arduino_data_n_mask;
  224. *arduino_clock_port |= arduino_clock_mask;
  225. b <<= 1;
  226. *arduino_clock_port &= arduino_clock_n_mask;
  227. }
  228. }
  229. }
  230. }
  231. else
  232. {
  233. while( arg_int > 0 )
  234. {
  235. b = *data;
  236. if ( last_dc != 0 )
  237. b |= 256;
  238. data++;
  239. arg_int--;
  240. /* issue 156, check for speed */
  241. #if F_CPU <= 17000000
  242. if ( b == 0 )
  243. {
  244. *arduino_data_port &= arduino_data_n_mask;
  245. for( i = 0; i < 9; i++ )
  246. {
  247. *arduino_clock_port &= arduino_clock_n_mask;
  248. *arduino_clock_port |= arduino_clock_mask;
  249. }
  250. }
  251. else
  252. #endif
  253. {
  254. for( i = 0; i < 9; i++ )
  255. {
  256. if ( b & 256 )
  257. *arduino_data_port |= arduino_data_mask;
  258. else
  259. *arduino_data_port &= arduino_data_n_mask;
  260. *arduino_clock_port &= arduino_clock_n_mask;
  261. b <<= 1;
  262. *arduino_clock_port |= arduino_clock_mask;
  263. }
  264. }
  265. }
  266. }
  267. break;
  268. case U8X8_MSG_BYTE_INIT:
  269. /* disable chipselect */
  270. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  271. /* no wait required here */
  272. /* for SPI: setup correct level of the clock signal */
  273. u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
  274. break;
  275. case U8X8_MSG_BYTE_SET_DC:
  276. last_dc = arg_int;
  277. break;
  278. case U8X8_MSG_BYTE_START_TRANSFER:
  279. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
  280. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
  281. /* there is no consistency checking for u8x8->pins[U8X8_PIN_SPI_CLOCK] */
  282. arduino_clock_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_CLOCK]));
  283. arduino_clock_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_CLOCK]);
  284. arduino_clock_n_mask = ~arduino_clock_mask;
  285. /* there is no consistency checking for u8x8->pins[U8X8_PIN_SPI_DATA] */
  286. arduino_data_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_DATA]));
  287. arduino_data_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_DATA]);
  288. arduino_data_n_mask = ~arduino_data_mask;
  289. break;
  290. case U8X8_MSG_BYTE_END_TRANSFER:
  291. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
  292. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  293. break;
  294. default:
  295. return 0;
  296. }
  297. return 1;
  298. }
  299. #else
  300. /* fallback */
  301. uint8_t u8x8_byte_arduino_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  302. {
  303. return u8x8_byte_3wire_sw_spi(u8x8, msg,arg_int, arg_ptr);
  304. }
  305. #endif
  306. /*=============================================*/
  307. /*=== 4 WIRE SOFTWARE SPI ===*/
  308. /*
  309. replacement for a more faster u8x8_byte_4wire_sw_spi
  310. in general u8x8_byte_4wire_sw_spi could be a fallback:
  311. uint8_t u8x8_byte_arduino_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  312. {
  313. return u8x8_byte_4wire_sw_spi(u8x8, msg,arg_int, arg_ptr);
  314. }
  315. */
  316. #ifndef __AVR_ARCH__
  317. #define __AVR_ARCH__ 0
  318. #endif
  319. #if !defined(U8X8_USE_PINS)
  320. /* no pin information (very strange), so fallback */
  321. uint8_t u8x8_byte_arduino_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  322. {
  323. return u8x8_byte_4wire_sw_spi(u8x8, msg,arg_int, arg_ptr);
  324. }
  325. #elif __AVR_ARCH__ == 4 || __AVR_ARCH__ == 5 || __AVR_ARCH__ == 51 || __AVR_ARCH__ == 6 || __AVR_ARCH__ == 103
  326. /* this function completely replaces u8x8_byte_4wire_sw_spi*/
  327. extern "C" uint8_t u8x8_byte_arduino_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  328. {
  329. uint8_t SREG_backup;
  330. uint8_t i, b;
  331. uint8_t *data;
  332. uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
  333. //uint8_t not_takeover_edge = 1 - takeover_edge;
  334. /* the following static vars are recalculated in U8X8_MSG_BYTE_START_TRANSFER */
  335. /* so, it should be possible to use multiple displays with different pins */
  336. static volatile uint8_t *arduino_clock_port;
  337. static uint8_t arduino_clock_mask;
  338. static uint8_t arduino_clock_n_mask;
  339. static volatile uint8_t *arduino_data_port;
  340. static uint8_t arduino_data_mask;
  341. static uint8_t arduino_data_n_mask;
  342. switch(msg)
  343. {
  344. case U8X8_MSG_BYTE_SEND:
  345. data = (uint8_t *)arg_ptr;
  346. if ( takeover_edge == 0 )
  347. {
  348. while( arg_int > 0 )
  349. {
  350. b = *data;
  351. data++;
  352. arg_int--;
  353. SREG_backup = SREG; cli();
  354. /* issue 156, check for speed */
  355. #if F_CPU <= 17000000
  356. if ( b == 0 )
  357. {
  358. *arduino_data_port &= arduino_data_n_mask;
  359. for( i = 0; i < 8; i++ )
  360. {
  361. *arduino_clock_port |= arduino_clock_mask;
  362. *arduino_clock_port &= arduino_clock_n_mask;
  363. }
  364. }
  365. else
  366. #endif
  367. {
  368. for( i = 0; i < 8; i++ )
  369. {
  370. if ( b & 128 )
  371. *arduino_data_port |= arduino_data_mask;
  372. else
  373. *arduino_data_port &= arduino_data_n_mask;
  374. *arduino_clock_port |= arduino_clock_mask;
  375. b <<= 1;
  376. *arduino_clock_port &= arduino_clock_n_mask;
  377. }
  378. }
  379. SREG = SREG_backup;
  380. }
  381. }
  382. else
  383. {
  384. while( arg_int > 0 )
  385. {
  386. b = *data;
  387. data++;
  388. arg_int--;
  389. SREG_backup = SREG; cli();
  390. /* issue 156, check for speed */
  391. #if F_CPU <= 17000000
  392. if ( b == 0 )
  393. {
  394. *arduino_data_port &= arduino_data_n_mask;
  395. for( i = 0; i < 8; i++ )
  396. {
  397. *arduino_clock_port &= arduino_clock_n_mask;
  398. *arduino_clock_port |= arduino_clock_mask;
  399. }
  400. }
  401. else
  402. #endif
  403. {
  404. for( i = 0; i < 8; i++ )
  405. {
  406. if ( b & 128 )
  407. *arduino_data_port |= arduino_data_mask;
  408. else
  409. *arduino_data_port &= arduino_data_n_mask;
  410. *arduino_clock_port &= arduino_clock_n_mask;
  411. b <<= 1;
  412. *arduino_clock_port |= arduino_clock_mask;
  413. }
  414. }
  415. SREG = SREG_backup;
  416. }
  417. }
  418. break;
  419. case U8X8_MSG_BYTE_INIT:
  420. /* disable chipselect */
  421. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  422. /* no wait required here */
  423. /* for SPI: setup correct level of the clock signal */
  424. u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
  425. break;
  426. case U8X8_MSG_BYTE_SET_DC:
  427. u8x8_gpio_SetDC(u8x8, arg_int);
  428. break;
  429. case U8X8_MSG_BYTE_START_TRANSFER:
  430. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
  431. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
  432. /* there is no consistency checking for u8x8->pins[U8X8_PIN_SPI_CLOCK] */
  433. arduino_clock_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_CLOCK]));
  434. arduino_clock_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_CLOCK]);
  435. arduino_clock_n_mask = ~arduino_clock_mask;
  436. /* there is no consistency checking for u8x8->pins[U8X8_PIN_SPI_DATA] */
  437. arduino_data_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_DATA]));
  438. arduino_data_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_DATA]);
  439. arduino_data_n_mask = ~arduino_data_mask;
  440. break;
  441. case U8X8_MSG_BYTE_END_TRANSFER:
  442. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
  443. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  444. break;
  445. default:
  446. return 0;
  447. }
  448. return 1;
  449. }
  450. #elif defined(__SAM3X8E__) /* Arduino DUE */
  451. /* this function completely replaces u8x8_byte_4wire_sw_spi*/
  452. extern "C" uint8_t u8x8_byte_arduino_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  453. {
  454. uint8_t i, b;
  455. uint16_t us = ((u8x8->display_info->sck_pulse_width_ns + 999)/1000);
  456. uint8_t *data;
  457. uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
  458. //uint8_t not_takeover_edge = 1 - takeover_edge;
  459. /* the following static vars are recalculated in U8X8_MSG_BYTE_START_TRANSFER */
  460. /* so, it should be possible to use multiple displays with different pins */
  461. /*
  462. static volatile uint32_t *arduino_clock_port;
  463. static uint32_t arduino_clock_mask;
  464. static uint32_t arduino_clock_n_mask;
  465. static volatile uint32_t *arduino_data_port;
  466. static uint32_t arduino_data_mask;
  467. static uint32_t arduino_data_n_mask;
  468. */
  469. static WoReg *arduinoSetClockPort, *arduinoUnsetClockPort;
  470. static uint32_t arduino_clock_mask;
  471. static WoReg *arduinoSetDataPort, *arduinoUnsetDataPort;
  472. static uint32_t arduino_data_mask;
  473. switch(msg)
  474. {
  475. case U8X8_MSG_BYTE_SEND:
  476. data = (uint8_t *)arg_ptr;
  477. if ( takeover_edge == 0 )
  478. {
  479. while( arg_int > 0 )
  480. {
  481. b = *data;
  482. data++;
  483. arg_int--;
  484. {
  485. for( i = 0; i < 8; i++ )
  486. {
  487. /*
  488. if ( b & 128 )
  489. *arduino_data_port |= arduino_data_mask;
  490. else
  491. *arduino_data_port &= arduino_data_n_mask;
  492. */
  493. if (b & 128)
  494. *arduinoSetDataPort = arduino_data_mask;
  495. else
  496. *arduinoUnsetDataPort = arduino_data_mask;
  497. //delayMicroseconds(us);
  498. //*arduino_clock_port |= arduino_clock_mask;
  499. *arduinoSetClockPort = arduino_clock_mask;
  500. b <<= 1;
  501. delayMicroseconds(us);
  502. //*arduino_clock_port &= arduino_clock_n_mask;
  503. *arduinoUnsetClockPort = arduino_clock_mask;
  504. }
  505. }
  506. }
  507. }
  508. else
  509. {
  510. while( arg_int > 0 )
  511. {
  512. b = *data;
  513. data++;
  514. arg_int--;
  515. {
  516. for( i = 0; i < 8; i++ )
  517. {
  518. /*
  519. if ( b & 128 )
  520. *arduino_data_port |= arduino_data_mask;
  521. else
  522. *arduino_data_port &= arduino_data_n_mask;
  523. */
  524. if (b & 128)
  525. *arduinoSetDataPort = arduino_data_mask;
  526. else
  527. *arduinoUnsetDataPort = arduino_data_mask;
  528. //delayMicroseconds(us);
  529. //*arduino_clock_port &= arduino_clock_n_mask;
  530. *arduinoUnsetClockPort = arduino_clock_mask;
  531. b <<= 1;
  532. delayMicroseconds(us);
  533. //*arduino_clock_port |= arduino_clock_mask;
  534. *arduinoSetClockPort = arduino_clock_mask;
  535. }
  536. }
  537. }
  538. }
  539. break;
  540. case U8X8_MSG_BYTE_INIT:
  541. /* disable chipselect */
  542. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  543. /* no wait required here */
  544. /* for SPI: setup correct level of the clock signal */
  545. u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
  546. break;
  547. case U8X8_MSG_BYTE_SET_DC:
  548. u8x8_gpio_SetDC(u8x8, arg_int);
  549. break;
  550. case U8X8_MSG_BYTE_START_TRANSFER:
  551. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
  552. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
  553. /* there is no consistency checking for u8x8->pins[U8X8_PIN_SPI_CLOCK] */
  554. /*
  555. arduino_clock_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_CLOCK]));
  556. arduino_clock_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_CLOCK]);
  557. arduino_clock_n_mask = ~arduino_clock_mask;
  558. arduino_data_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_DATA]));
  559. arduino_data_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_DATA]);
  560. arduino_data_n_mask = ~arduino_data_mask;
  561. */
  562. arduinoSetClockPort = &digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_CLOCK])->PIO_SODR;
  563. arduinoUnsetClockPort = &digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_CLOCK])->PIO_CODR;
  564. arduino_clock_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_CLOCK]);
  565. arduinoSetDataPort = &digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_DATA])->PIO_SODR;
  566. arduinoUnsetDataPort = &digitalPinToPort(u8x8->pins[U8X8_PIN_SPI_DATA])->PIO_CODR;
  567. arduino_data_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_SPI_DATA]);
  568. break;
  569. case U8X8_MSG_BYTE_END_TRANSFER:
  570. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
  571. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  572. break;
  573. default:
  574. return 0;
  575. }
  576. return 1;
  577. }
  578. #else
  579. /* fallback */
  580. uint8_t u8x8_byte_arduino_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  581. {
  582. return u8x8_byte_4wire_sw_spi(u8x8, msg,arg_int, arg_ptr);
  583. }
  584. #endif
  585. /*=============================================*/
  586. /*=== 3 WIRE HARDWARE SPI with 8 bit HW SPI Subsystem ===*/
  587. /*
  588. references:
  589. https://github.com/olikraus/ucglib/blob/master/cppsrc/Ucglib.cpp#L581
  590. https://github.com/olikraus/u8g2/issues/1041
  591. */
  592. static uint8_t arduino_hw_spi_3w_buffer[9];
  593. static uint8_t arduino_hw_spi_3w_bytepos;
  594. static uint16_t arduino_hw_spi_3w_dc; // 0 = dc==0, 256 = dc==1
  595. static void arduino_hw_spi_3w_init()
  596. {
  597. memset(arduino_hw_spi_3w_buffer, 0, 9);
  598. arduino_hw_spi_3w_bytepos = 0;
  599. }
  600. static void arduino_hw_spi_3w_flush(void)
  601. {
  602. #ifdef U8X8_HAVE_HW_SPI
  603. uint8_t i;
  604. for(i = 0; i <= arduino_hw_spi_3w_bytepos; i++)
  605. {
  606. SPI.transfer(arduino_hw_spi_3w_buffer[i]);
  607. }
  608. #endif
  609. }
  610. static void arduino_hw_spi_3w_sendbyte(uint8_t data)
  611. {
  612. static union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } data16; // well well, not legal ISO 9899 code
  613. data16.val = (arduino_hw_spi_3w_dc + data) << (7 - arduino_hw_spi_3w_bytepos);
  614. #ifdef __BYTE_ORDER__
  615. #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  616. arduino_hw_spi_3w_buffer[arduino_hw_spi_3w_bytepos] |= data16.msb;
  617. ++arduino_hw_spi_3w_bytepos;
  618. arduino_hw_spi_3w_buffer[arduino_hw_spi_3w_bytepos] |= data16.lsb;
  619. #else
  620. arduino_hw_spi_3w_buffer[arduino_hw_spi_3w_bytepos] |= data16.lsb;
  621. ++arduino_hw_spi_3w_bytepos;
  622. arduino_hw_spi_3w_buffer[arduino_hw_spi_3w_bytepos] |= data16.msb;
  623. #endif
  624. #else // __BYTE_ORDER__ not defined (no gcc)
  625. // assume little endian
  626. arduino_hw_spi_3w_buffer[arduino_hw_spi_3w_bytepos] |= data16.msb;
  627. ++arduino_hw_spi_3w_bytepos;
  628. arduino_hw_spi_3w_buffer[arduino_hw_spi_3w_bytepos] |= data16.lsb;
  629. #endif
  630. if (arduino_hw_spi_3w_bytepos == 8)
  631. {
  632. arduino_hw_spi_3w_flush();
  633. arduino_hw_spi_3w_init();
  634. }
  635. }
  636. extern "C" uint8_t u8x8_byte_arduino_3wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  637. {
  638. #ifdef U8X8_HAVE_HW_SPI
  639. uint8_t *data;
  640. uint8_t internal_spi_mode;
  641. switch(msg)
  642. {
  643. case U8X8_MSG_BYTE_SEND:
  644. data = (uint8_t *)arg_ptr;
  645. while(arg_int > 0) {
  646. arduino_hw_spi_3w_sendbyte((uint8_t)*data);
  647. data++;
  648. arg_int--;
  649. }
  650. break;
  651. case U8X8_MSG_BYTE_INIT:
  652. if ( u8x8->bus_clock == 0 ) /* issue 769 */
  653. u8x8->bus_clock = u8x8->display_info->sck_clock_hz;
  654. /* disable chipselect */
  655. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  656. #if defined(ESP_PLATFORM) || defined(ARDUINO_ARCH_ESP32)
  657. /* ESP32 has the following begin: SPI.begin(int8_t sck=SCK, int8_t miso=MISO, int8_t mosi=MOSI, int8_t ss=-1); */
  658. /* not sure about ESP8266 */
  659. /* apply bugfix from PR 2123 */
  660. //if ( u8x8->pins[U8X8_PIN_I2C_CLOCK] != U8X8_PIN_NONE && u8x8->pins[U8X8_PIN_I2C_DATA] != U8X8_PIN_NONE )
  661. if ( u8x8->pins[U8X8_PIN_SPI_CLOCK] != U8X8_PIN_NONE && u8x8->pins[U8X8_PIN_SPI_DATA] != U8X8_PIN_NONE )
  662. {
  663. /* SPI.begin(int8_t sck=SCK, int8_t miso=MISO, int8_t mosi=MOSI, int8_t ss=-1); */
  664. /* actually MISO is not used, but what else could be used here??? */
  665. //SPI.begin(u8x8->pins[U8X8_PIN_I2C_CLOCK], MISO, u8x8->pins[U8X8_PIN_I2C_DATA]);
  666. SPI.begin(u8x8->pins[U8X8_PIN_SPI_CLOCK], MISO, u8x8->pins[U8X8_PIN_SPI_DATA]);
  667. }
  668. else
  669. {
  670. SPI.begin();
  671. }
  672. #else
  673. SPI.begin();
  674. #endif
  675. break;
  676. case U8X8_MSG_BYTE_SET_DC:
  677. arduino_hw_spi_3w_dc = arg_int ? 256 : 0;
  678. break;
  679. case U8X8_MSG_BYTE_START_TRANSFER:
  680. /* SPI mode has to be mapped to the mode of the current controller;
  681. at least Uno, Due, 101 have different SPI_MODEx values */
  682. internal_spi_mode = 0;
  683. switch(u8x8->display_info->spi_mode) {
  684. case 0: internal_spi_mode = SPI_MODE0; break;
  685. case 1: internal_spi_mode = SPI_MODE1; break;
  686. case 2: internal_spi_mode = SPI_MODE2; break;
  687. case 3: internal_spi_mode = SPI_MODE3; break;
  688. }
  689. #if ARDUINO >= 10600
  690. SPI.beginTransaction(
  691. SPISettings(u8x8->bus_clock, MSBFIRST, internal_spi_mode));
  692. #else
  693. SPI.begin();
  694. if (u8x8->display_info->sck_pulse_width_ns < 70)
  695. SPI.setClockDivider(SPI_CLOCK_DIV2);
  696. else if (u8x8->display_info->sck_pulse_width_ns < 140)
  697. SPI.setClockDivider(SPI_CLOCK_DIV4);
  698. else
  699. SPI.setClockDivider(SPI_CLOCK_DIV8);
  700. SPI.setDataMode(internal_spi_mode);
  701. SPI.setBitOrder(MSBFIRST);
  702. #endif
  703. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
  704. u8x8->gpio_and_delay_cb(
  705. u8x8,
  706. U8X8_MSG_DELAY_NANO,
  707. u8x8->display_info->post_chip_enable_wait_ns,
  708. NULL);
  709. arduino_hw_spi_3w_init();
  710. break;
  711. case U8X8_MSG_BYTE_END_TRANSFER:
  712. u8x8->gpio_and_delay_cb(
  713. u8x8,
  714. U8X8_MSG_DELAY_NANO,
  715. u8x8->display_info->pre_chip_disable_wait_ns,
  716. NULL);
  717. if (arduino_hw_spi_3w_bytepos)
  718. arduino_hw_spi_3w_flush();
  719. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  720. #if ARDUINO >= 10600
  721. SPI.endTransaction();
  722. #else
  723. SPI.end();
  724. #endif
  725. break;
  726. default:
  727. return 0;
  728. }
  729. #endif // U8X8_HAVE_HW_SPI
  730. return 1;
  731. }
  732. /*=============================================*/
  733. /*=== 4 WIRE HARDWARE SPI ===*/
  734. #ifdef U8X8_USE_PINS
  735. extern "C" uint8_t u8x8_byte_arduino_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  736. {
  737. #ifdef U8X8_HAVE_HW_SPI
  738. #if !defined(ESP_PLATFORM)
  739. uint8_t *data;
  740. #endif
  741. uint8_t internal_spi_mode;
  742. switch(msg)
  743. {
  744. case U8X8_MSG_BYTE_SEND:
  745. #if defined(ESP_PLATFORM)
  746. //T.M.L 2023-02-28: use the block transfer function on ESP, which does not overwrite the buffer.
  747. SPI.writeBytes((uint8_t*)arg_ptr, arg_int);
  748. #else
  749. // 1.6.5 offers a block transfer, but the problem is, that the
  750. // buffer is overwritten with the incoming data
  751. // so it can not be used...
  752. // SPI.transfer((uint8_t *)arg_ptr, arg_int);
  753. data = (uint8_t *)arg_ptr;
  754. while( arg_int > 0 )
  755. {
  756. SPI.transfer((uint8_t)*data);
  757. data++;
  758. arg_int--;
  759. }
  760. #endif
  761. break;
  762. case U8X8_MSG_BYTE_INIT:
  763. if ( u8x8->bus_clock == 0 ) /* issue 769 */
  764. u8x8->bus_clock = u8x8->display_info->sck_clock_hz;
  765. /* disable chipselect */
  766. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  767. /* no wait required here */
  768. /* for SPI: setup correct level of the clock signal */
  769. // removed, use SPI.begin() instead: pinMode(11, OUTPUT);
  770. // removed, use SPI.begin() instead: pinMode(13, OUTPUT);
  771. // removed, use SPI.begin() instead: digitalWrite(13, u8x8_GetSPIClockPhase(u8x8));
  772. /* setup hardware with SPI.begin() instead of previous digitalWrite() and pinMode() calls */
  773. /* issue #377 */
  774. /* issue #378: removed ESP8266 support, which is implemented differently */
  775. #if defined(ESP_PLATFORM) || defined(ARDUINO_ARCH_ESP32)
  776. /* ESP32 has the following begin: SPI.begin(int8_t sck=SCK, int8_t miso=MISO, int8_t mosi=MOSI, int8_t ss=-1); */
  777. /* not sure about ESP8266 */
  778. if ( u8x8->pins[U8X8_PIN_SPI_CLOCK] != U8X8_PIN_NONE && u8x8->pins[U8X8_PIN_SPI_DATA] != U8X8_PIN_NONE )
  779. {
  780. /* SPI.begin(int8_t sck=SCK, int8_t miso=MISO, int8_t mosi=MOSI, int8_t ss=-1); */
  781. /* actually MISO is not used, but what else could be used here??? */
  782. SPI.begin(u8x8->pins[U8X8_PIN_SPI_CLOCK], MISO, u8x8->pins[U8X8_PIN_SPI_DATA]);
  783. }
  784. else
  785. {
  786. SPI.begin();
  787. }
  788. #else
  789. SPI.begin();
  790. #endif
  791. break;
  792. case U8X8_MSG_BYTE_SET_DC:
  793. u8x8_gpio_SetDC(u8x8, arg_int);
  794. break;
  795. case U8X8_MSG_BYTE_START_TRANSFER:
  796. /* SPI mode has to be mapped to the mode of the current controller, at least Uno, Due, 101 have different SPI_MODEx values */
  797. internal_spi_mode = 0;
  798. switch(u8x8->display_info->spi_mode)
  799. {
  800. case 0: internal_spi_mode = SPI_MODE0; break;
  801. case 1: internal_spi_mode = SPI_MODE1; break;
  802. case 2: internal_spi_mode = SPI_MODE2; break;
  803. case 3: internal_spi_mode = SPI_MODE3; break;
  804. }
  805. #if ARDUINO >= 10600
  806. SPI.beginTransaction(SPISettings(u8x8->bus_clock, MSBFIRST, internal_spi_mode));
  807. #else
  808. SPI.begin();
  809. if ( u8x8->display_info->sck_pulse_width_ns < 70 )
  810. SPI.setClockDivider( SPI_CLOCK_DIV2 );
  811. else if ( u8x8->display_info->sck_pulse_width_ns < 140 )
  812. SPI.setClockDivider( SPI_CLOCK_DIV4 );
  813. else
  814. SPI.setClockDivider( SPI_CLOCK_DIV8 );
  815. SPI.setDataMode(internal_spi_mode);
  816. SPI.setBitOrder(MSBFIRST);
  817. #endif
  818. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
  819. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
  820. break;
  821. case U8X8_MSG_BYTE_END_TRANSFER:
  822. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
  823. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  824. #if ARDUINO >= 10600
  825. SPI.endTransaction();
  826. #else
  827. SPI.end();
  828. #endif
  829. break;
  830. default:
  831. return 0;
  832. }
  833. #else /* U8X8_HAVE_HW_SPI */
  834. #endif /* U8X8_HAVE_HW_SPI */
  835. return 1;
  836. }
  837. /* issue #244 */
  838. extern "C" uint8_t u8x8_byte_arduino_2nd_hw_spi(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  839. {
  840. #ifdef U8X8_HAVE_2ND_HW_SPI
  841. uint8_t *data;
  842. uint8_t internal_spi_mode;
  843. switch(msg)
  844. {
  845. case U8X8_MSG_BYTE_SEND:
  846. // 1.6.5 offers a block transfer, but the problem is, that the
  847. // buffer is overwritten with the incoming data
  848. // so it can not be used...
  849. // SPI.transfer((uint8_t *)arg_ptr, arg_int);
  850. data = (uint8_t *)arg_ptr;
  851. while( arg_int > 0 )
  852. {
  853. SPI1.transfer((uint8_t)*data);
  854. data++;
  855. arg_int--;
  856. }
  857. break;
  858. case U8X8_MSG_BYTE_INIT:
  859. if ( u8x8->bus_clock == 0 ) /* issue 769 */
  860. u8x8->bus_clock = u8x8->display_info->sck_clock_hz;
  861. /* disable chipselect */
  862. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  863. /* no wait required here */
  864. /* for SPI1: setup correct level of the clock signal */
  865. // removed, use SPI.begin() instead: pinMode(11, OUTPUT);
  866. // removed, use SPI.begin() instead: pinMode(13, OUTPUT);
  867. // removed, use SPI.begin() instead: digitalWrite(13, u8x8_GetSPIClockPhase(u8x8));
  868. /* setup hardware with SPI.begin() instead of previous digitalWrite() and pinMode() calls */
  869. SPI1.begin();
  870. break;
  871. case U8X8_MSG_BYTE_SET_DC:
  872. u8x8_gpio_SetDC(u8x8, arg_int);
  873. break;
  874. case U8X8_MSG_BYTE_START_TRANSFER:
  875. /* SPI1 mode has to be mapped to the mode of the current controller, at least Uno, Due, 101 have different SPI_MODEx values */
  876. internal_spi_mode = 0;
  877. switch(u8x8->display_info->spi_mode)
  878. {
  879. case 0: internal_spi_mode = SPI_MODE0; break;
  880. case 1: internal_spi_mode = SPI_MODE1; break;
  881. case 2: internal_spi_mode = SPI_MODE2; break;
  882. case 3: internal_spi_mode = SPI_MODE3; break;
  883. }
  884. #if ARDUINO >= 10600
  885. SPI1.beginTransaction(SPISettings(u8x8->bus_clock, MSBFIRST, internal_spi_mode));
  886. #else
  887. SPI1.begin();
  888. if ( u8x8->display_info->sck_pulse_width_ns < 70 )
  889. SPI1.setClockDivider( SPI_CLOCK_DIV2 );
  890. else if ( u8x8->display_info->sck_pulse_width_ns < 140 )
  891. SPI1.setClockDivider( SPI_CLOCK_DIV4 );
  892. else
  893. SPI1.setClockDivider( SPI_CLOCK_DIV8 );
  894. SPI1.setDataMode(internal_spi_mode);
  895. SPI1.setBitOrder(MSBFIRST);
  896. #endif
  897. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
  898. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
  899. break;
  900. case U8X8_MSG_BYTE_END_TRANSFER:
  901. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
  902. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  903. #if ARDUINO >= 10600
  904. SPI1.endTransaction();
  905. #else
  906. SPI1.end();
  907. #endif
  908. break;
  909. default:
  910. return 0;
  911. }
  912. #else
  913. #endif
  914. return 1;
  915. }
  916. /*=============================================*/
  917. /* fast SW I2C for AVR uC */
  918. #if !defined(U8X8_USE_PINS)
  919. /* no pin information (very strange), so fallback */
  920. extern "C" uint8_t u8x8_byte_arduino_sw_i2c(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  921. {
  922. return u8x8_byte_sw_i2c(u8x8, msg,arg_int, arg_ptr);
  923. }
  924. #elif !defined(U8X8_USE_ARDUINO_AVR_SW_I2C_OPTIMIZATION)
  925. extern "C" uint8_t u8x8_byte_arduino_sw_i2c(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  926. {
  927. return u8x8_byte_sw_i2c(u8x8, msg,arg_int, arg_ptr);
  928. }
  929. #elif __AVR_ARCH__ == 4 || __AVR_ARCH__ == 5 || __AVR_ARCH__ == 51 || __AVR_ARCH__ == 6 || __AVR_ARCH__ == 103
  930. /* the following static vars are recalculated in U8X8_MSG_BYTE_START_TRANSFER */
  931. /* so, it should be possible to use multiple displays with different pins */
  932. static volatile uint8_t *arduino_i2c_clock_port;
  933. static uint8_t arduino_i2c_clock_mask;
  934. static uint8_t arduino_i2c_clock_n_mask;
  935. static volatile uint8_t *arduino_i2c_data_port;
  936. static uint8_t arduino_i2c_data_mask;
  937. static uint8_t arduino_i2c_data_n_mask;
  938. /*
  939. software i2c,
  940. ignores ACK response (which is anyway not provided by some displays)
  941. also does not allow reading from the device
  942. */
  943. static void i2c_delay(u8x8_t *u8x8) U8X8_NOINLINE;
  944. static void i2c_delay(u8x8_t *u8x8)
  945. {
  946. //u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_10MICRO, u8x8->display_info->i2c_bus_clock_100kHz);
  947. u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_I2C, u8x8->display_info->i2c_bus_clock_100kHz);
  948. }
  949. static void i2c_init(u8x8_t *u8x8)
  950. {
  951. *arduino_i2c_clock_port |= arduino_i2c_clock_mask;
  952. *arduino_i2c_data_port |= arduino_i2c_data_mask;
  953. i2c_delay(u8x8);
  954. }
  955. /* actually, the scl line is not observed, so this procedure does not return a value */
  956. static void i2c_read_scl_and_delay(u8x8_t *u8x8)
  957. {
  958. /* set as input (line will be high) */
  959. *arduino_i2c_clock_port |= arduino_i2c_clock_mask;
  960. i2c_delay(u8x8);
  961. }
  962. static void i2c_clear_scl(u8x8_t *u8x8)
  963. {
  964. *arduino_i2c_clock_port &= arduino_i2c_clock_n_mask;
  965. }
  966. static void i2c_read_sda(u8x8_t *u8x8)
  967. {
  968. /* set as input (line will be high) */
  969. *arduino_i2c_data_port |= arduino_i2c_data_mask;
  970. }
  971. static void i2c_clear_sda(u8x8_t *u8x8)
  972. {
  973. /* set open collector and drive low */
  974. *arduino_i2c_data_port &= arduino_i2c_data_n_mask;
  975. }
  976. static void i2c_start(u8x8_t *u8x8)
  977. {
  978. if ( u8x8->i2c_started != 0 )
  979. {
  980. /* if already started: do restart */
  981. i2c_read_sda(u8x8); /* SDA = 1 */
  982. i2c_delay(u8x8);
  983. i2c_read_scl_and_delay(u8x8);
  984. }
  985. i2c_read_sda(u8x8);
  986. /* send the start condition, both lines go from 1 to 0 */
  987. i2c_clear_sda(u8x8);
  988. i2c_delay(u8x8);
  989. i2c_clear_scl(u8x8);
  990. u8x8->i2c_started = 1;
  991. }
  992. static void i2c_stop(u8x8_t *u8x8)
  993. {
  994. /* set SDA to 0 */
  995. i2c_clear_sda(u8x8);
  996. i2c_delay(u8x8);
  997. /* now release all lines */
  998. i2c_read_scl_and_delay(u8x8);
  999. /* set SDA to 1 */
  1000. i2c_read_sda(u8x8);
  1001. i2c_delay(u8x8);
  1002. u8x8->i2c_started = 0;
  1003. }
  1004. static void i2c_write_bit(u8x8_t *u8x8, uint8_t val)
  1005. {
  1006. if (val)
  1007. i2c_read_sda(u8x8);
  1008. else
  1009. i2c_clear_sda(u8x8);
  1010. i2c_delay(u8x8);
  1011. i2c_read_scl_and_delay(u8x8);
  1012. i2c_clear_scl(u8x8);
  1013. }
  1014. static void i2c_read_bit(u8x8_t *u8x8)
  1015. {
  1016. //uint8_t val;
  1017. /* do not drive SDA */
  1018. i2c_read_sda(u8x8);
  1019. i2c_delay(u8x8);
  1020. i2c_read_scl_and_delay(u8x8);
  1021. i2c_read_sda(u8x8);
  1022. i2c_delay(u8x8);
  1023. i2c_clear_scl(u8x8);
  1024. //return val;
  1025. }
  1026. static void i2c_write_byte(u8x8_t *u8x8, uint8_t b)
  1027. {
  1028. i2c_write_bit(u8x8, b & 128);
  1029. i2c_write_bit(u8x8, b & 64);
  1030. i2c_write_bit(u8x8, b & 32);
  1031. i2c_write_bit(u8x8, b & 16);
  1032. i2c_write_bit(u8x8, b & 8);
  1033. i2c_write_bit(u8x8, b & 4);
  1034. i2c_write_bit(u8x8, b & 2);
  1035. i2c_write_bit(u8x8, b & 1);
  1036. /* read ack from client */
  1037. /* 0: ack was given by client */
  1038. /* 1: nothing happend during ack cycle */
  1039. i2c_read_bit(u8x8);
  1040. }
  1041. extern "C" uint8_t u8x8_byte_arduino_sw_i2c(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  1042. {
  1043. uint8_t *data;
  1044. switch(msg)
  1045. {
  1046. case U8X8_MSG_BYTE_SEND:
  1047. data = (uint8_t *)arg_ptr;
  1048. while( arg_int > 0 )
  1049. {
  1050. i2c_write_byte(u8x8, *data);
  1051. data++;
  1052. arg_int--;
  1053. }
  1054. break;
  1055. case U8X8_MSG_BYTE_INIT:
  1056. pinMode(u8x8->pins[U8X8_PIN_I2C_CLOCK], OUTPUT);
  1057. digitalWrite(u8x8->pins[U8X8_PIN_I2C_CLOCK], 1);
  1058. pinMode(u8x8->pins[U8X8_PIN_I2C_DATA], OUTPUT);
  1059. digitalWrite(u8x8->pins[U8X8_PIN_I2C_DATA], 1);
  1060. i2c_init(u8x8);
  1061. break;
  1062. case U8X8_MSG_BYTE_SET_DC:
  1063. break;
  1064. case U8X8_MSG_BYTE_START_TRANSFER:
  1065. /* there is no consistency checking for u8x8->pins[U8X8_PIN_I2C_CLOCK] */
  1066. arduino_i2c_clock_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_I2C_CLOCK]));
  1067. arduino_i2c_clock_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_I2C_CLOCK]);
  1068. arduino_i2c_clock_n_mask = ~arduino_i2c_clock_mask;
  1069. /* there is no consistency checking for u8x8->pins[U8X8_PIN_I2C_DATA] */
  1070. arduino_i2c_data_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_I2C_DATA]));
  1071. arduino_i2c_data_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_I2C_DATA]);
  1072. arduino_i2c_data_n_mask = ~arduino_i2c_data_mask;
  1073. i2c_start(u8x8);
  1074. i2c_write_byte(u8x8, u8x8_GetI2CAddress(u8x8));
  1075. break;
  1076. case U8X8_MSG_BYTE_END_TRANSFER:
  1077. i2c_stop(u8x8);
  1078. break;
  1079. default:
  1080. return 0;
  1081. }
  1082. return 1;
  1083. }
  1084. #else
  1085. /* not AVR architecture, fallback */
  1086. extern "C" uint8_t u8x8_byte_arduino_sw_i2c(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  1087. {
  1088. return u8x8_byte_sw_i2c(u8x8, msg,arg_int, arg_ptr);
  1089. }
  1090. #endif
  1091. /*=============================================*/
  1092. /*=== HARDWARE I2C ===*/
  1093. extern "C" uint8_t u8x8_byte_arduino_hw_i2c(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  1094. {
  1095. #ifdef U8X8_HAVE_HW_I2C
  1096. switch(msg)
  1097. {
  1098. case U8X8_MSG_BYTE_SEND:
  1099. Wire.write((uint8_t *)arg_ptr, (int)arg_int);
  1100. break;
  1101. case U8X8_MSG_BYTE_INIT:
  1102. if ( u8x8->bus_clock == 0 ) /* issue 769 */
  1103. u8x8->bus_clock = u8x8->display_info->i2c_bus_clock_100kHz * 100000UL;
  1104. #if defined(ESP8266) || defined(ARDUINO_ARCH_ESP8266) || defined(ESP_PLATFORM) || defined(ARDUINO_ARCH_ESP32)
  1105. /* for ESP8266/ESP32, Wire.begin has two more arguments: clock and data */
  1106. if ( u8x8->pins[U8X8_PIN_I2C_CLOCK] != U8X8_PIN_NONE && u8x8->pins[U8X8_PIN_I2C_DATA] != U8X8_PIN_NONE )
  1107. {
  1108. // second argument for the wire lib is the clock pin. In u8g2, the first argument of the clock pin in the clock/data pair
  1109. Wire.begin((int)u8x8->pins[U8X8_PIN_I2C_DATA] , u8x8->pins[U8X8_PIN_I2C_CLOCK]);
  1110. }
  1111. else
  1112. {
  1113. Wire.begin();
  1114. }
  1115. #else
  1116. Wire.begin();
  1117. #endif
  1118. break;
  1119. case U8X8_MSG_BYTE_SET_DC:
  1120. break;
  1121. case U8X8_MSG_BYTE_START_TRANSFER:
  1122. #if ARDUINO >= 10600
  1123. /* not sure when the setClock function was introduced, but it is there since 1.6.0 */
  1124. /* if there is any error with Wire.setClock() just remove this function call by */
  1125. /* defining U8X8_DO_NOT_SET_WIRE_CLOCK */
  1126. #ifndef U8X8_DO_NOT_SET_WIRE_CLOCK
  1127. Wire.setClock(u8x8->bus_clock);
  1128. #endif
  1129. #endif
  1130. Wire.beginTransmission(u8x8_GetI2CAddress(u8x8)>>1);
  1131. break;
  1132. case U8X8_MSG_BYTE_END_TRANSFER:
  1133. Wire.endTransmission();
  1134. break;
  1135. default:
  1136. return 0;
  1137. }
  1138. #endif
  1139. return 1;
  1140. }
  1141. extern "C" uint8_t u8x8_byte_arduino_2nd_hw_i2c(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  1142. {
  1143. #ifdef U8X8_HAVE_2ND_HW_I2C
  1144. switch(msg)
  1145. {
  1146. case U8X8_MSG_BYTE_SEND:
  1147. Wire1.write((uint8_t *)arg_ptr, (int)arg_int);
  1148. break;
  1149. case U8X8_MSG_BYTE_INIT:
  1150. if ( u8x8->bus_clock == 0 ) /* issue 769 */
  1151. u8x8->bus_clock = u8x8->display_info->i2c_bus_clock_100kHz * 100000UL;
  1152. Wire1.begin();
  1153. break;
  1154. case U8X8_MSG_BYTE_SET_DC:
  1155. break;
  1156. case U8X8_MSG_BYTE_START_TRANSFER:
  1157. #if ARDUINO >= 10600
  1158. /* not sure when the setClock function was introduced, but it is there since 1.6.0 */
  1159. /* if there is any error with Wire.setClock() just remove this function call by */
  1160. /* defining U8X8_DO_NOT_SET_WIRE_CLOCK */
  1161. #ifndef U8X8_DO_NOT_SET_WIRE_CLOCK
  1162. Wire1.setClock(u8x8->bus_clock);
  1163. #endif
  1164. #endif
  1165. Wire1.beginTransmission(u8x8_GetI2CAddress(u8x8)>>1);
  1166. break;
  1167. case U8X8_MSG_BYTE_END_TRANSFER:
  1168. Wire1.endTransmission();
  1169. break;
  1170. default:
  1171. return 0;
  1172. }
  1173. #endif
  1174. return 1;
  1175. }
  1176. #endif // U8X8_USE_PINS
  1177. /*=============================================*/
  1178. /*
  1179. replacement for a more faster u8x8_byte_8bit_8080mode
  1180. in general u8x8_byte_8bit_8080mode could be a fallback:
  1181. uint8_t u8x8_byte_arduino_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1182. {
  1183. return u8x8_byte_8bit_8080mode(u8x8, msg,arg_int, arg_ptr);
  1184. }
  1185. */
  1186. #ifndef __AVR_ARCH__
  1187. #define __AVR_ARCH__ 0
  1188. #endif
  1189. #if !defined(U8X8_USE_PINS)
  1190. /* no pin information (very strange), so fallback */
  1191. extern "C" uint8_t u8x8_byte_arduino_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1192. {
  1193. return u8x8_byte_8bit_8080mode(u8x8, msg,arg_int, arg_ptr);
  1194. }
  1195. #elif __AVR_ARCH__ == 4 || __AVR_ARCH__ == 5 || __AVR_ARCH__ == 51 || __AVR_ARCH__ == 6 || __AVR_ARCH__ == 103
  1196. /* this function completly replaces u8x8_byte_8bit_8080mode*/
  1197. extern "C" uint8_t u8x8_byte_arduino_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1198. {
  1199. uint8_t i, b;
  1200. uint8_t *data;
  1201. /* the following static vars are recalculated in U8X8_MSG_BYTE_START_TRANSFER */
  1202. /* so, it should be possible to use multiple displays with different pins */
  1203. static volatile uint8_t *arduino_e_port;
  1204. static volatile uint8_t arduino_e_mask;
  1205. static volatile uint8_t arduino_e_n_mask;
  1206. static volatile uint8_t *arduino_data_port[8];
  1207. static volatile uint8_t arduino_data_mask[8];
  1208. static volatile uint8_t arduino_data_n_mask[8];
  1209. switch(msg)
  1210. {
  1211. case U8X8_MSG_BYTE_SEND:
  1212. data = (uint8_t *)arg_ptr;
  1213. while( arg_int > 0 )
  1214. {
  1215. b = *data;
  1216. data++;
  1217. arg_int--;
  1218. for( i = 0; i < 8; i++ )
  1219. {
  1220. if ( b & 1 )
  1221. *arduino_data_port[i] |= arduino_data_mask[i];
  1222. else
  1223. *arduino_data_port[i] &= arduino_data_n_mask[i];
  1224. b >>= 1;
  1225. }
  1226. *arduino_e_port &= arduino_e_n_mask;
  1227. /* AVR Architecture is very slow, extra call is not required */
  1228. //u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sda_setup_time_ns);
  1229. u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
  1230. *arduino_e_port |= arduino_e_mask;
  1231. /* AVR Architecture is very slow, extra call is not required */
  1232. //u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sck_pulse_width_ns);
  1233. u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
  1234. }
  1235. break;
  1236. case U8X8_MSG_BYTE_INIT:
  1237. /* disable chipselect */
  1238. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  1239. /* no wait required here */
  1240. /* ensure that the enable signal is high */
  1241. u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
  1242. break;
  1243. case U8X8_MSG_BYTE_SET_DC:
  1244. u8x8_gpio_SetDC(u8x8, arg_int);
  1245. break;
  1246. case U8X8_MSG_BYTE_START_TRANSFER:
  1247. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
  1248. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
  1249. /* there is no consistency checking for u8x8->pins[U8X8_PIN_E] */
  1250. arduino_e_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_E]));
  1251. arduino_e_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_E]);
  1252. arduino_e_n_mask = ~arduino_e_mask;
  1253. /* there is no consistency checking for u8x8->pins[U8X8_PIN_D0] */
  1254. for( i = 0; i < 8; i++ )
  1255. {
  1256. arduino_data_port[i] = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_D0+i]));
  1257. arduino_data_mask[i] = digitalPinToBitMask(u8x8->pins[U8X8_PIN_D0+i]);
  1258. arduino_data_n_mask[i] = ~arduino_data_mask[i];
  1259. }
  1260. break;
  1261. case U8X8_MSG_BYTE_END_TRANSFER:
  1262. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
  1263. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  1264. break;
  1265. default:
  1266. return 0;
  1267. }
  1268. return 1;
  1269. }
  1270. #else
  1271. /* fallback */
  1272. extern "C" uint8_t u8x8_byte_arduino_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1273. {
  1274. return u8x8_byte_8bit_8080mode(u8x8, msg,arg_int, arg_ptr);
  1275. }
  1276. #endif
  1277. /*=============================================*/
  1278. /*
  1279. replacement for a more faster u8x8_byte_ks0108
  1280. in general u8x8_byte_ks0108 could be a fallback:
  1281. uint8_t u8x8_byte_arduino_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1282. {
  1283. return u8x8_byte_ks0108(u8x8, msg,arg_int, arg_ptr);
  1284. }
  1285. */
  1286. #ifndef __AVR_ARCH__
  1287. #define __AVR_ARCH__ 0
  1288. #endif
  1289. #if !defined(U8X8_USE_PINS)
  1290. /* no pin information (very strange), so fallback */
  1291. extern "C" uint8_t u8x8_byte_arduino_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1292. {
  1293. return u8x8_byte_ks0108(u8x8, msg,arg_int, arg_ptr);
  1294. }
  1295. #elif __AVR_ARCH__ == 4 || __AVR_ARCH__ == 5 || __AVR_ARCH__ == 51 || __AVR_ARCH__ == 6 || __AVR_ARCH__ == 103
  1296. /* this function completly replaces u8x8_byte_ks0108*/
  1297. extern "C" uint8_t u8x8_byte_arduino_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1298. {
  1299. uint8_t i, b;
  1300. uint8_t *data;
  1301. /* the following static vars are recalculated in U8X8_MSG_BYTE_START_TRANSFER */
  1302. /* so, it should be possible to use multiple displays with different pins */
  1303. static volatile uint8_t *arduino_e_port;
  1304. static volatile uint8_t arduino_e_mask;
  1305. static volatile uint8_t arduino_e_n_mask;
  1306. static volatile uint8_t *arduino_data_port[8];
  1307. static volatile uint8_t arduino_data_mask[8];
  1308. static volatile uint8_t arduino_data_n_mask[8];
  1309. switch(msg)
  1310. {
  1311. case U8X8_MSG_BYTE_SEND:
  1312. data = (uint8_t *)arg_ptr;
  1313. while( arg_int > 0 )
  1314. {
  1315. b = *data;
  1316. data++;
  1317. arg_int--;
  1318. for( i = 0; i < 8; i++ )
  1319. {
  1320. if ( b & 1 )
  1321. *arduino_data_port[i] |= arduino_data_mask[i];
  1322. else
  1323. *arduino_data_port[i] &= arduino_data_n_mask[i];
  1324. b >>= 1;
  1325. }
  1326. *arduino_e_port |= arduino_e_mask;
  1327. /* AVR Architecture is very slow, extra call is not required */
  1328. u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
  1329. *arduino_e_port &= arduino_e_n_mask;
  1330. /* AVR Architecture is very slow, extra call is not required */
  1331. u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
  1332. }
  1333. break;
  1334. case U8X8_MSG_BYTE_INIT:
  1335. /* disable chipselect */
  1336. u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
  1337. /* no wait required here */
  1338. /* ensure that the enable signal is low */
  1339. u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
  1340. break;
  1341. case U8X8_MSG_BYTE_SET_DC:
  1342. u8x8_gpio_SetDC(u8x8, arg_int);
  1343. break;
  1344. case U8X8_MSG_BYTE_START_TRANSFER:
  1345. u8x8_byte_set_ks0108_cs(u8x8, arg_int);
  1346. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
  1347. /* there is no consistency checking for u8x8->pins[U8X8_PIN_E] */
  1348. arduino_e_port = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_E]));
  1349. arduino_e_mask = digitalPinToBitMask(u8x8->pins[U8X8_PIN_E]);
  1350. arduino_e_n_mask = ~arduino_e_mask;
  1351. /* there is no consistency checking for u8x8->pins[U8X8_PIN_D0] */
  1352. for( i = 0; i < 8; i++ )
  1353. {
  1354. arduino_data_port[i] = portOutputRegister(digitalPinToPort(u8x8->pins[U8X8_PIN_D0+i]));
  1355. arduino_data_mask[i] = digitalPinToBitMask(u8x8->pins[U8X8_PIN_D0+i]);
  1356. arduino_data_n_mask[i] = ~arduino_data_mask[i];
  1357. }
  1358. break;
  1359. case U8X8_MSG_BYTE_END_TRANSFER:
  1360. u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
  1361. u8x8_byte_set_ks0108_cs(u8x8, arg_int);
  1362. break;
  1363. default:
  1364. return 0;
  1365. }
  1366. return 1;
  1367. }
  1368. #else
  1369. /* fallback */
  1370. extern "C" uint8_t u8x8_byte_arduino_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  1371. {
  1372. return u8x8_byte_ks0108(u8x8, msg,arg_int, arg_ptr);
  1373. }
  1374. #endif
  1375. #endif /*ARDUINO*/
  1376. #ifdef U8X8_USE_PINS
  1377. /*
  1378. use U8X8_PIN_NONE as value for "reset", if there is no reset line
  1379. */
  1380. void u8x8_SetPin_4Wire_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset)
  1381. {
  1382. u8x8_SetPin(u8x8, U8X8_PIN_SPI_CLOCK, clock);
  1383. u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data);
  1384. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1385. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1386. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1387. }
  1388. #ifdef _obsolete_com_specific_setup
  1389. void u8x8_Setup_4Wire_SW_SPI(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset)
  1390. {
  1391. u8x8_Setup(u8x8, display_cb, u8x8_cad_001, u8x8_byte_4wire_sw_spi, u8x8_gpio_and_delay_arduino);
  1392. /* assign individual pin values (only for ARDUINO, if pin_list is available) */
  1393. u8x8_SetPin(u8x8, U8X8_PIN_SPI_CLOCK, clock);
  1394. u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data);
  1395. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1396. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1397. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1398. }
  1399. #endif /* obsolete com specific setup */
  1400. void u8x8_SetPin_3Wire_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset)
  1401. {
  1402. u8x8_SetPin(u8x8, U8X8_PIN_SPI_CLOCK, clock);
  1403. u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data);
  1404. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1405. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1406. }
  1407. #ifdef _obsolete_com_specific_setup
  1408. void u8x8_Setup_3Wire_SW_SPI(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset)
  1409. {
  1410. u8x8_Setup(u8x8, display_cb, u8x8_cad_001, u8x8_byte_3wire_sw_spi, u8x8_gpio_and_delay_arduino);
  1411. /* assign individual pin values (only for ARDUINO, if pin_list is available) */
  1412. u8x8_SetPin(u8x8, U8X8_PIN_SPI_CLOCK, clock);
  1413. u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data);
  1414. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1415. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1416. }
  1417. #endif /* obsolete com specific setup */
  1418. /*
  1419. use U8X8_PIN_NONE as value for "reset", if there is no reset line
  1420. */
  1421. void u8x8_SetPin_3Wire_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t reset)
  1422. {
  1423. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1424. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1425. }
  1426. /*
  1427. use U8X8_PIN_NONE as value for "reset", if there is no reset line
  1428. */
  1429. void u8x8_SetPin_4Wire_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t dc, uint8_t reset)
  1430. {
  1431. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1432. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1433. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1434. }
  1435. void u8x8_SetPin_ST7920_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t reset)
  1436. {
  1437. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1438. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1439. }
  1440. #ifdef _obsolete_com_specific_setup
  1441. void u8x8_Setup_4Wire_HW_SPI(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t cs, uint8_t dc, uint8_t reset)
  1442. {
  1443. u8x8_Setup(u8x8, display_cb, u8x8_cad_001, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino);
  1444. /* assign individual pin values (only for ARDUINO, if pin_list is available) */
  1445. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1446. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1447. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1448. }
  1449. #endif /* obsolete com specific setup */
  1450. void u8x8_SetPin_SW_I2C(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t reset)
  1451. {
  1452. u8x8_SetPin(u8x8, U8X8_PIN_I2C_CLOCK, clock);
  1453. u8x8_SetPin(u8x8, U8X8_PIN_I2C_DATA, data);
  1454. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1455. }
  1456. #ifdef _obsolete_com_specific_setup
  1457. void u8x8_Setup_SSD13xx_SW_I2C(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t clock, uint8_t data, uint8_t reset)
  1458. {
  1459. u8x8_Setup(u8x8, display_cb, u8x8_cad_001, u8x8_byte_ssd13xx_sw_i2c, u8x8_gpio_and_delay_arduino);
  1460. /* assign individual pin values (only for ARDUINO, if pin_list is available) */
  1461. u8x8_SetPin(u8x8, U8X8_PIN_I2C_CLOCK, clock);
  1462. u8x8_SetPin(u8x8, U8X8_PIN_I2C_DATA, data);
  1463. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1464. }
  1465. #endif /* obsolete com specific setup */
  1466. void u8x8_SetPin_HW_I2C(u8x8_t *u8x8, uint8_t reset, uint8_t clock, uint8_t data)
  1467. {
  1468. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1469. u8x8_SetPin(u8x8, U8X8_PIN_I2C_CLOCK, clock);
  1470. u8x8_SetPin(u8x8, U8X8_PIN_I2C_DATA, data);
  1471. }
  1472. void u8x8_SetPin_8Bit_6800(u8x8_t *u8x8, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t enable, uint8_t cs, uint8_t dc, uint8_t reset)
  1473. {
  1474. u8x8_SetPin(u8x8, U8X8_PIN_D0, d0);
  1475. u8x8_SetPin(u8x8, U8X8_PIN_D1, d1);
  1476. u8x8_SetPin(u8x8, U8X8_PIN_D2, d2);
  1477. u8x8_SetPin(u8x8, U8X8_PIN_D3, d3);
  1478. u8x8_SetPin(u8x8, U8X8_PIN_D4, d4);
  1479. u8x8_SetPin(u8x8, U8X8_PIN_D5, d5);
  1480. u8x8_SetPin(u8x8, U8X8_PIN_D6, d6);
  1481. u8x8_SetPin(u8x8, U8X8_PIN_D7, d7);
  1482. u8x8_SetPin(u8x8, U8X8_PIN_E, enable);
  1483. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1484. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1485. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1486. }
  1487. #ifdef _obsolete_com_specific_setup
  1488. void u8x8_Setup_8Bit_6800(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t enable, uint8_t cs, uint8_t dc, uint8_t reset)
  1489. {
  1490. u8x8_Setup(u8x8, display_cb, u8x8_cad_001, u8x8_byte_8bit_6800mode, u8x8_gpio_and_delay_arduino);
  1491. /* assign individual pin values (only for ARDUINO, if pin_list is available) */
  1492. u8x8_SetPin(u8x8, U8X8_PIN_D0, d0);
  1493. u8x8_SetPin(u8x8, U8X8_PIN_D1, d1);
  1494. u8x8_SetPin(u8x8, U8X8_PIN_D2, d2);
  1495. u8x8_SetPin(u8x8, U8X8_PIN_D3, d3);
  1496. u8x8_SetPin(u8x8, U8X8_PIN_D4, d4);
  1497. u8x8_SetPin(u8x8, U8X8_PIN_D5, d5);
  1498. u8x8_SetPin(u8x8, U8X8_PIN_D6, d6);
  1499. u8x8_SetPin(u8x8, U8X8_PIN_D7, d7);
  1500. u8x8_SetPin(u8x8, U8X8_PIN_E, enable);
  1501. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1502. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1503. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1504. }
  1505. #endif /* obsolete com specific setup */
  1506. void u8x8_SetPin_8Bit_8080(u8x8_t *u8x8, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t wr, uint8_t cs, uint8_t dc, uint8_t reset)
  1507. {
  1508. u8x8_SetPin(u8x8, U8X8_PIN_D0, d0);
  1509. u8x8_SetPin(u8x8, U8X8_PIN_D1, d1);
  1510. u8x8_SetPin(u8x8, U8X8_PIN_D2, d2);
  1511. u8x8_SetPin(u8x8, U8X8_PIN_D3, d3);
  1512. u8x8_SetPin(u8x8, U8X8_PIN_D4, d4);
  1513. u8x8_SetPin(u8x8, U8X8_PIN_D5, d5);
  1514. u8x8_SetPin(u8x8, U8X8_PIN_D6, d6);
  1515. u8x8_SetPin(u8x8, U8X8_PIN_D7, d7);
  1516. u8x8_SetPin(u8x8, U8X8_PIN_E, wr);
  1517. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1518. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1519. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1520. }
  1521. #ifdef _obsolete_com_specific_setup
  1522. void u8x8_Setup_8Bit_8080(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t wr, uint8_t cs, uint8_t dc, uint8_t reset)
  1523. {
  1524. u8x8_Setup(u8x8, display_cb, u8x8_cad_001, u8x8_byte_8bit_8080mode, u8x8_gpio_and_delay_arduino);
  1525. /* assign individual pin values (only for ARDUINO, if pin_list is available) */
  1526. u8x8_SetPin(u8x8, U8X8_PIN_D0, d0);
  1527. u8x8_SetPin(u8x8, U8X8_PIN_D1, d1);
  1528. u8x8_SetPin(u8x8, U8X8_PIN_D2, d2);
  1529. u8x8_SetPin(u8x8, U8X8_PIN_D3, d3);
  1530. u8x8_SetPin(u8x8, U8X8_PIN_D4, d4);
  1531. u8x8_SetPin(u8x8, U8X8_PIN_D5, d5);
  1532. u8x8_SetPin(u8x8, U8X8_PIN_D6, d6);
  1533. u8x8_SetPin(u8x8, U8X8_PIN_D7, d7);
  1534. u8x8_SetPin(u8x8, U8X8_PIN_E, wr);
  1535. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs);
  1536. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1537. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1538. }
  1539. #endif /* obsolete com specific setup */
  1540. void u8x8_SetPin_KS0108(u8x8_t *u8x8, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t enable, uint8_t dc, uint8_t cs0, uint8_t cs1, uint8_t cs2, uint8_t reset)
  1541. {
  1542. u8x8_SetPin(u8x8, U8X8_PIN_D0, d0);
  1543. u8x8_SetPin(u8x8, U8X8_PIN_D1, d1);
  1544. u8x8_SetPin(u8x8, U8X8_PIN_D2, d2);
  1545. u8x8_SetPin(u8x8, U8X8_PIN_D3, d3);
  1546. u8x8_SetPin(u8x8, U8X8_PIN_D4, d4);
  1547. u8x8_SetPin(u8x8, U8X8_PIN_D5, d5);
  1548. u8x8_SetPin(u8x8, U8X8_PIN_D6, d6);
  1549. u8x8_SetPin(u8x8, U8X8_PIN_D7, d7);
  1550. u8x8_SetPin(u8x8, U8X8_PIN_E, enable);
  1551. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1552. u8x8_SetPin(u8x8, U8X8_PIN_CS, cs0);
  1553. u8x8_SetPin(u8x8, U8X8_PIN_CS1, cs1);
  1554. u8x8_SetPin(u8x8, U8X8_PIN_CS2, cs2);
  1555. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1556. }
  1557. void u8x8_SetPin_SED1520(u8x8_t *u8x8, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t dc, uint8_t e1, uint8_t e2, uint8_t reset)
  1558. {
  1559. u8x8_SetPin(u8x8, U8X8_PIN_D0, d0);
  1560. u8x8_SetPin(u8x8, U8X8_PIN_D1, d1);
  1561. u8x8_SetPin(u8x8, U8X8_PIN_D2, d2);
  1562. u8x8_SetPin(u8x8, U8X8_PIN_D3, d3);
  1563. u8x8_SetPin(u8x8, U8X8_PIN_D4, d4);
  1564. u8x8_SetPin(u8x8, U8X8_PIN_D5, d5);
  1565. u8x8_SetPin(u8x8, U8X8_PIN_D6, d6);
  1566. u8x8_SetPin(u8x8, U8X8_PIN_D7, d7);
  1567. u8x8_SetPin(u8x8, U8X8_PIN_E, e1);
  1568. u8x8_SetPin(u8x8, U8X8_PIN_CS, e2);
  1569. u8x8_SetPin(u8x8, U8X8_PIN_DC, dc);
  1570. u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset);
  1571. }
  1572. #endif // U8X8_USE_PINS