u8g2port.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*
  2. * This code supports multiple displays since GPIO pin handles have been
  3. * moved into user_data_struct. I2C and SPI handles are global since they can be
  4. * shared by multiple devices (think I2C with different address sharing bus).
  5. *
  6. * So far I have tested this with 3 software I2C displays. See examples.
  7. */
  8. #include "u8g2port.h"
  9. // c-periphery I2C handles
  10. static i2c_t *i2c_handles[MAX_I2C_HANDLES] = { NULL };
  11. // c-periphery SPI handles
  12. static spi_t *spi_handles[MAX_SPI_HANDLES] = { NULL };
  13. /*
  14. * Sleep milliseconds.
  15. */
  16. void sleep_ms(unsigned long milliseconds) {
  17. struct timespec ts;
  18. ts.tv_sec = milliseconds / 1000;
  19. ts.tv_nsec = (milliseconds % 1000) * 1000000;
  20. nanosleep(&ts, NULL);
  21. }
  22. /*
  23. * Sleep microseconds.
  24. */
  25. void sleep_us(unsigned long microseconds) {
  26. struct timespec ts;
  27. ts.tv_sec = microseconds / 1000 / 1000;
  28. ts.tv_nsec = (microseconds % 1000000) * 1000;
  29. nanosleep(&ts, NULL);
  30. }
  31. /**
  32. * Sleep nanoseconds.
  33. */
  34. void sleep_ns(unsigned long nanoseconds) {
  35. struct timespec ts;
  36. ts.tv_sec = 0;
  37. ts.tv_nsec = nanoseconds;
  38. nanosleep(&ts, NULL);
  39. }
  40. /*
  41. * Allocate user_data_struct, set common values and set user_ptr.
  42. */
  43. user_data_t* init_user_data(u8g2_t *u8g2) {
  44. // Dynamically allocate user data_struct
  45. user_data_t *user_data = (user_data_t*) malloc(sizeof(user_data_t));
  46. // Dynamically allocate internal buffer
  47. user_data->int_buf = (uint8_t*)malloc(u8g2_GetBufferSize(u8g2));
  48. // We need a unique buffer for each display in order to be thread friendly
  49. u8g2_SetBufferPtr(u8g2, user_data->int_buf);
  50. for (int i = 0; i < U8X8_PIN_CNT; ++i) {
  51. user_data->pins[i] = NULL;
  52. }
  53. u8g2_SetUserPtr(u8g2, user_data);
  54. return user_data;
  55. }
  56. /*
  57. * Allocate user_data_struct for I2C hardware.
  58. */
  59. void init_i2c_hw(u8g2_t *u8g2, uint8_t bus) {
  60. user_data_t *user_data = init_user_data(u8g2);
  61. user_data->bus = bus;
  62. }
  63. /*
  64. * Allocate user_data_struct for I2C software.
  65. */
  66. void init_i2c_sw(u8g2_t *u8g2, uint8_t gpio_chip, uint8_t scl, uint8_t sda,
  67. uint8_t res, unsigned long delay) {
  68. user_data_t *user_data = init_user_data(u8g2);
  69. user_data->gpio_chip = gpio_chip;
  70. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_I2C_CLOCK, scl);
  71. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_I2C_DATA, sda);
  72. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_RESET, res);
  73. user_data->delay = delay;
  74. }
  75. /*
  76. * Allocate user_data_struct for hardware SPI advanced.
  77. */
  78. void init_spi_hw_advanced(u8g2_t *u8g2, uint8_t gpio_chip, uint8_t bus,
  79. uint8_t dc, uint8_t res, uint8_t cs, unsigned int spi_mode,
  80. uint32_t max_speed) {
  81. user_data_t *user_data = init_user_data(u8g2);
  82. user_data->gpio_chip = gpio_chip;
  83. user_data->bus = bus;
  84. user_data->spi_mode = spi_mode;
  85. user_data->max_speed = max_speed;
  86. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_DC, dc);
  87. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_RESET, res);
  88. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_CS, cs);
  89. }
  90. /*
  91. * Allocate user_data_struct for hardware SPI.
  92. */
  93. void init_spi_hw(u8g2_t *u8g2, uint8_t gpio_chip, uint8_t bus, uint8_t dc,
  94. uint8_t res, uint8_t cs) {
  95. init_spi_hw_advanced(u8g2, gpio_chip, bus, dc, res, cs,
  96. u8g2_GetU8x8(u8g2)->display_info->spi_mode, 500000);
  97. }
  98. /*
  99. * Allocate user_data_struct for hardware SPI.
  100. */
  101. void init_spi_sw(u8g2_t *u8g2, uint8_t gpio_chip, uint8_t dc, uint8_t res,
  102. uint8_t mosi, uint8_t sck, uint8_t cs, unsigned long delay) {
  103. user_data_t *user_data = init_user_data(u8g2);
  104. user_data->gpio_chip = gpio_chip;
  105. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_DC, dc);
  106. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_RESET, res);
  107. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_SPI_DATA, mosi);
  108. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_SPI_CLOCK, sck);
  109. u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_CS, cs);
  110. user_data->delay = delay;
  111. }
  112. /*
  113. * Close GPIO pins and free user_data_struct.
  114. */
  115. void done_user_data(u8g2_t *u8g2) {
  116. user_data_t *user_data = u8g2_GetUserPtr(u8g2);
  117. if (user_data != NULL) {
  118. // Close all GPIO pins
  119. for (int i = 0; i < U8X8_PIN_CNT; ++i) {
  120. if (user_data->pins[i] != NULL) {
  121. gpio_close(user_data->pins[i]);
  122. gpio_free(user_data->pins[i]);
  123. }
  124. }
  125. // Free internal buffer
  126. free(user_data->int_buf);
  127. // Free user data struct
  128. free(user_data);
  129. u8g2_SetUserPtr(u8g2, NULL);
  130. }
  131. }
  132. /**
  133. * Initialize pin if not set to U8X8_PIN_NONE and NULL.
  134. */
  135. #if PERIPHERY_GPIO_CDEV_SUPPORT
  136. void init_pin(u8x8_t *u8x8, uint8_t pin) {
  137. user_data_t *user_data = u8x8_GetUserPtr(u8x8);
  138. char filename[16];
  139. if (u8x8->pins[pin] != U8X8_PIN_NONE && user_data -> pins[pin] == NULL) {
  140. snprintf(filename, sizeof(filename), "/dev/gpiochip%d", user_data ->gpio_chip);
  141. user_data -> pins[pin] = gpio_new();
  142. int error = gpio_open(user_data -> pins[pin], filename, u8x8->pins[pin], GPIO_DIR_OUT_HIGH);
  143. if (error < 0) {
  144. fprintf(stderr, "gpio_open(): pin %d, %s\n", u8x8->pins[pin],
  145. gpio_errmsg(user_data -> pins[pin]));
  146. gpio_free(user_data->pins[pin]);
  147. }
  148. }
  149. }
  150. #else
  151. void init_pin(u8x8_t *u8x8, uint8_t pin) {
  152. user_data_t *user_data = u8x8_GetUserPtr(u8x8);
  153. if (u8x8->pins[pin] != U8X8_PIN_NONE && user_data->pins[pin] == NULL) {
  154. user_data->pins[pin] = gpio_new();
  155. int error = gpio_open_sysfs(user_data->pins[pin], u8x8->pins[pin],
  156. GPIO_DIR_OUT_HIGH);
  157. if (error < 0) {
  158. fprintf(stderr, "gpio_open_sysfs(): pin %d, %s\n", u8x8->pins[pin],
  159. gpio_errmsg(user_data->pins[pin]));
  160. gpio_free(user_data->pins[pin]);
  161. }
  162. }
  163. }
  164. #endif
  165. /**
  166. * Write pin if not set to U8X8_PIN_NONE.
  167. */
  168. void write_pin(u8x8_t *u8x8, uint8_t pin, uint8_t value) {
  169. user_data_t *user_data = u8x8_GetUserPtr(u8x8);
  170. if (u8x8->pins[pin] != U8X8_PIN_NONE) {
  171. gpio_write(user_data->pins[pin], value);
  172. }
  173. }
  174. /*
  175. * Initialize I2C bus.
  176. */
  177. void init_i2c(u8x8_t *u8x8) {
  178. char filename[11];
  179. user_data_t *user_data = u8x8_GetUserPtr(u8x8);
  180. // Only open bus once
  181. if (i2c_handles[user_data->bus] == NULL) {
  182. snprintf(filename, sizeof(filename), "/dev/i2c-%d", user_data->bus);
  183. i2c_handles[user_data->bus] = i2c_new();
  184. int error = i2c_open(i2c_handles[user_data->bus], filename);
  185. if (error) {
  186. fprintf(stderr, "i2c_open(): %s\n",
  187. i2c_errmsg(i2c_handles[user_data->bus]));
  188. i2c_free(i2c_handles[user_data->bus]);
  189. i2c_handles[user_data->bus] = NULL;
  190. }
  191. }
  192. }
  193. /*
  194. * Close and free all i2c_t.
  195. */
  196. void done_i2c() {
  197. for (int i = 0; i < MAX_I2C_HANDLES; ++i) {
  198. if (i2c_handles[i] != NULL) {
  199. i2c_close(i2c_handles[i]);
  200. i2c_free(i2c_handles[i]);
  201. i2c_handles[i] = NULL;
  202. }
  203. }
  204. }
  205. /*
  206. * Initialize SPI bus.
  207. */
  208. void init_spi(u8x8_t *u8x8) {
  209. char filename[15];
  210. user_data_t *user_data = u8x8_GetUserPtr(u8x8);
  211. // Only open bus once
  212. if (spi_handles[user_data->bus] == NULL) {
  213. // user_data->bus should be in the format 0x12 for /dev/spidev1.2
  214. snprintf(filename, sizeof(filename), "/dev/spidev%d.%d",
  215. user_data->bus >> 4, user_data->bus & 0x0f);
  216. spi_handles[user_data->bus] = spi_new();
  217. /* SPI mode has to be mapped to the mode of the current controller, at least Uno, Due, 101 have different SPI_MODEx values */
  218. /* 0: clock active high, data out on falling edge, clock default value is zero, takover on rising edge */
  219. /* 1: clock active high, data out on rising edge, clock default value is zero, takover on falling edge */
  220. /* 2: clock active low, data out on rising edge */
  221. /* 3: clock active low, data out on falling edge */
  222. int error = spi_open(spi_handles[user_data->bus], filename,
  223. user_data->spi_mode, user_data->max_speed);
  224. if (error < 0) {
  225. fprintf(stderr, "spi_open(): %s\n",
  226. spi_errmsg(spi_handles[user_data->bus]));
  227. spi_free(spi_handles[user_data->bus]);
  228. spi_handles[user_data->bus] = NULL;
  229. }
  230. }
  231. }
  232. /*
  233. * Close and free all spi_t.
  234. */
  235. void done_spi() {
  236. for (int i = 0; i < MAX_SPI_HANDLES; ++i) {
  237. if (spi_handles[i] != NULL) {
  238. spi_close(spi_handles[i]);
  239. spi_free(spi_handles[i]);
  240. spi_handles[i] = NULL;
  241. }
  242. }
  243. }
  244. /**
  245. * GPIO callback.
  246. */
  247. uint8_t u8x8_arm_linux_gpio_and_delay(u8x8_t *u8x8, uint8_t msg,
  248. uint8_t arg_int, void *arg_ptr) {
  249. user_data_t *user_data;
  250. (void) arg_ptr; /* suppress unused parameter warning */
  251. switch (msg) {
  252. case U8X8_MSG_DELAY_NANO:
  253. // delay arg_int * 1 nano second or 0 for none
  254. user_data = u8x8_GetUserPtr(u8x8);
  255. if (user_data->delay != 0) {
  256. sleep_ns(user_data->delay);
  257. }
  258. break;
  259. case U8X8_MSG_DELAY_100NANO:
  260. // delay arg_int * 100 nano seconds
  261. sleep_ns(arg_int * 100);
  262. break;
  263. case U8X8_MSG_DELAY_10MICRO:
  264. // delay arg_int * 10 micro seconds
  265. sleep_us(arg_int * 10);
  266. break;
  267. case U8X8_MSG_DELAY_MILLI:
  268. // delay arg_int * 1 milli second
  269. sleep_ms(arg_int);
  270. break;
  271. case U8X8_MSG_DELAY_I2C:
  272. // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz, but we ignore
  273. // that and use user_data->delay
  274. user_data = u8x8_GetUserPtr(u8x8);
  275. if (user_data->delay != 0) {
  276. sleep_ns(user_data->delay);
  277. }
  278. break;
  279. case U8X8_MSG_GPIO_AND_DELAY_INIT:
  280. // Function which implements a delay, arg_int contains the amount of ms
  281. // SPI Pins
  282. init_pin(u8x8, U8X8_PIN_SPI_CLOCK);
  283. init_pin(u8x8, U8X8_PIN_SPI_DATA);
  284. init_pin(u8x8, U8X8_PIN_CS);
  285. init_pin(u8x8, U8X8_PIN_D2);
  286. init_pin(u8x8, U8X8_PIN_D3);
  287. init_pin(u8x8, U8X8_PIN_D4);
  288. init_pin(u8x8, U8X8_PIN_D5);
  289. init_pin(u8x8, U8X8_PIN_D6);
  290. init_pin(u8x8, U8X8_PIN_D7);
  291. init_pin(u8x8, U8X8_PIN_E);
  292. init_pin(u8x8, U8X8_PIN_RESET);
  293. init_pin(u8x8, U8X8_PIN_DC);
  294. // I2c pins
  295. init_pin(u8x8, U8X8_PIN_I2C_DATA);
  296. init_pin(u8x8, U8X8_PIN_I2C_CLOCK);
  297. break;
  298. case U8X8_MSG_GPIO_D2:
  299. // D2 pin: Output level in arg_int
  300. write_pin(u8x8, U8X8_PIN_D2, arg_int);
  301. break;
  302. case U8X8_MSG_GPIO_D3:
  303. // D3 pin: Output level in arg_int
  304. write_pin(u8x8, U8X8_PIN_D3, arg_int);
  305. break;
  306. case U8X8_MSG_GPIO_D4:
  307. // D4 pin: Output level in arg_int
  308. write_pin(u8x8, U8X8_PIN_D4, arg_int);
  309. break;
  310. case U8X8_MSG_GPIO_D5:
  311. // D5 pin: Output level in arg_int
  312. write_pin(u8x8, U8X8_PIN_D5, arg_int);
  313. break;
  314. case U8X8_MSG_GPIO_D6:
  315. // D6 pin: Output level in arg_int
  316. write_pin(u8x8, U8X8_PIN_D6, arg_int);
  317. break;
  318. case U8X8_MSG_GPIO_D7:
  319. // D7 pin: Output level in arg_int
  320. write_pin(u8x8, U8X8_PIN_D7, arg_int);
  321. break;
  322. case U8X8_MSG_GPIO_E:
  323. // E/WR pin: Output level in arg_int
  324. write_pin(u8x8, U8X8_PIN_E, arg_int);
  325. break;
  326. case U8X8_MSG_GPIO_I2C_CLOCK:
  327. // arg_int=0: Output low at I2C clock pin
  328. // arg_int=1: Input dir with pullup high for I2C clock pin
  329. write_pin(u8x8, U8X8_PIN_I2C_CLOCK, arg_int);
  330. break;
  331. case U8X8_MSG_GPIO_I2C_DATA:
  332. // arg_int=0: Output low at I2C data pin
  333. // arg_int=1: Input dir with pullup high for I2C data pin
  334. write_pin(u8x8, U8X8_PIN_I2C_DATA, arg_int);
  335. break;
  336. case U8X8_MSG_GPIO_SPI_CLOCK: // Same as U8X8_MSG_GPIO_D0
  337. //Function to define the logic level of the clockline
  338. write_pin(u8x8, U8X8_PIN_SPI_CLOCK, arg_int);
  339. break;
  340. case U8X8_MSG_GPIO_SPI_DATA: // Same as U8X8_MSG_GPIO_D1
  341. //Function to define the logic level of the data line to the display
  342. write_pin(u8x8, U8X8_PIN_SPI_DATA, arg_int);
  343. break;
  344. case U8X8_MSG_GPIO_CS:
  345. // Function to define the logic level of the CS line
  346. write_pin(u8x8, U8X8_PIN_CS, arg_int);
  347. break;
  348. case U8X8_MSG_GPIO_DC:
  349. //Function to define the logic level of the Data/ Command line
  350. write_pin(u8x8, U8X8_PIN_DC, arg_int);
  351. break;
  352. case U8X8_MSG_GPIO_RESET:
  353. //Function to define the logic level of the RESET line
  354. write_pin(u8x8, U8X8_PIN_RESET, arg_int);
  355. break;
  356. default:
  357. return 0;
  358. }
  359. return 1;
  360. }
  361. /*
  362. * I2c callback.
  363. */
  364. uint8_t u8x8_byte_arm_linux_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
  365. void *arg_ptr) {
  366. user_data_t *user_data;
  367. uint8_t *data;
  368. struct i2c_msg msgs[1];
  369. switch (msg) {
  370. case U8X8_MSG_BYTE_SEND:
  371. user_data = u8x8_GetUserPtr(u8x8);
  372. data = (uint8_t*) arg_ptr;
  373. while (arg_int > 0) {
  374. user_data->buffer[user_data->index++] = *data;
  375. data++;
  376. arg_int--;
  377. }
  378. break;
  379. case U8X8_MSG_BYTE_INIT:
  380. init_i2c(u8x8);
  381. break;
  382. case U8X8_MSG_BYTE_START_TRANSFER:
  383. user_data = u8x8_GetUserPtr(u8x8);
  384. user_data->index = 0;
  385. break;
  386. case U8X8_MSG_BYTE_END_TRANSFER:
  387. user_data = u8x8_GetUserPtr(u8x8);
  388. msgs[0].addr = u8x8_GetI2CAddress(u8x8) >> 1;
  389. msgs[0].flags = 0; // Write
  390. msgs[0].len = user_data->index;
  391. msgs[0].buf = user_data->buffer;
  392. i2c_transfer(i2c_handles[user_data->bus], msgs, 1);
  393. break;
  394. default:
  395. return 0;
  396. }
  397. return 1;
  398. }
  399. /*
  400. * SPI callback.
  401. */
  402. uint8_t u8x8_byte_arm_linux_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
  403. void *arg_ptr) {
  404. user_data_t *user_data;
  405. uint8_t *data;
  406. switch (msg) {
  407. case U8X8_MSG_BYTE_SEND:
  408. user_data = u8x8_GetUserPtr(u8x8);
  409. user_data->index = 0;
  410. data = (uint8_t*) arg_ptr;
  411. while (arg_int > 0) {
  412. user_data->buffer[user_data->index++] = *data;
  413. data++;
  414. arg_int--;
  415. }
  416. spi_transfer(spi_handles[user_data->bus], user_data->buffer,
  417. user_data->buffer, user_data->index);
  418. break;
  419. case U8X8_MSG_BYTE_INIT:
  420. init_spi(u8x8);
  421. break;
  422. case U8X8_MSG_BYTE_SET_DC:
  423. u8x8_gpio_SetDC(u8x8, arg_int);
  424. break;
  425. case U8X8_MSG_BYTE_START_TRANSFER:
  426. break;
  427. case U8X8_MSG_BYTE_END_TRANSFER:
  428. break;
  429. default:
  430. return 0;
  431. }
  432. return 1;
  433. }