Compare commits
	
		
			578 Commits
		
	
	
	| Author | SHA1 | Date | 
|---|---|---|
|  Bodmer | 8c83eb84bd | |
|  Bodmer | c08763ca44 | |
|  Bodmer | 3670949658 | |
|  Dracir | 326e4a722f | |
|  Bodmer | e94a7491a3 | |
|  Bodmer | 1db5f438b3 | |
|  Bodmer | 01f217fba1 | |
|  Bodmer | 5f5fef5419 | |
|  Bodmer | 6e291a9176 | |
|  Bodmer | c133cf1523 | |
|  Bodmer | a6909486a4 | |
|  Bodmer | 21b27258f7 | |
|  Bodmer | c6bcfa9db9 | |
|  Bodmer | d6064fe141 | |
|  Bodmer | 01b8420b97 | |
|  Bodmer | c04fa09251 | |
|  Bodmer | 21ee26071c | |
|  Bodmer | f35b4366ac | |
|  Bodmer | 19c745e4f8 | |
|  Bodmer | 6545e032b0 | |
|  Bodmer | b2d20d6d39 | |
|  Bodmer | c6d600b4a1 | |
|  Bodmer | 890f6ff2b9 | |
|  Bodmer | 19eadee669 | |
|  Bodmer | e6024025c0 | |
|  Bodmer | 6414f511c5 | |
|  Bodmer | bd33fc3ff9 | |
|  Bodmer | c208a31a26 | |
|  Bodmer | 7b67abc797 | |
|  Bodmer | 90c3511913 | |
|  Bodmer | 1a50a23561 | |
|  lbuque | beaf30cc97 | |
|  Bodmer | b5edd54f6e | |
|  Bodmer | 954a3a5ed3 | |
|  Bodmer | 1549705b96 | |
|  Bodmer | 1a6aa0476b | |
|  Bodmer | 79345ca72d | |
|  Bodmer | 9f829679e7 | |
|  Bodmer | d6b868fe79 | |
|  Bodmer | f33836faac | |
|  Bodmer | d37f202b94 | |
|  Bodmer | ea82a7c15a | |
|  Bodmer | 91b8e248d3 | |
|  Bodmer | 024453fc1e | |
|  Bodmer | cc1e00d663 | |
|  Bodmer | 0b5512727e | |
|  Bodmer | 5ab29abf30 | |
|  Bodmer | b287023ac4 | |
|  Bodmer | 92f980be85 | |
|  Bodmer | 8013821ad8 | |
|  Bodmer | 31a5ccd02e | |
|  Bodmer | 0fd239c751 | |
|  Bodmer | 543c5a3b54 | |
|  Bodmer | 0490b94287 | |
|  Jacques Supcik | 6ee13641cf | |
|  Bodmer | ef7c020980 | |
|  Bodmer | 1b07eeb980 | |
|  Bodmer | 48d729c2e7 | |
|  Bodmer | 2b6833220a | |
|  Bodmer | 15cedf1e24 | |
|  goutamreddy | bdeeb131ad | |
|  Bodmer | 421377e8bc | |
|  Bodmer | c23fffe414 | |
|  Bodmer | f02b09a380 | |
|  Bodmer | 3c6dab0a52 | |
|  Bodmer | 64a31ef252 | |
|  Bodmer | d3a715da1e | |
|  Bodmer | 3d2b9ae3a2 | |
|  Paul Tsupikoff | 6c74d55292 | |
|  Bodmer | 67e41c75f2 | |
|  Bodmer | 13e62a88d0 | |
|  SimonXI | dd5f74c956 | |
|  Bodmer | c15257ad00 | |
|  Bodmer | 5a493559d0 | |
|  Bodmer | f106fb03ac | |
|  SimonXI | f0889e11f0 | |
|  Bodmer | f94fb28737 | |
|  Bodmer | 7c9e1cbbd1 | |
|  Bodmer | 49f44e41aa | |
|  Bodmer | ca024b4514 | |
|  Bodmer | a3015f0090 | |
|  Bodmer | 7b529eef06 | |
|  Bodmer | 1e8eb39135 | |
|  Bodmer | 33be3070bf | |
|  Bodmer | fc8228acae | |
|  Bodmer | f1bae721c8 | |
|  Bodmer | 8b454bc19d | |
|  Bodmer | b2e0bd855c | |
|  Bodmer | 48499856ac | |
|  Bodmer | eea916d221 | |
|  Bodmer | d1bb18bdde | |
|  Bodmer | 385cb5423e | |
|  Bodmer | f20b5ef55e | |
|  Bodmer | 4573e30d59 | |
|  Bodmer | 83b501bd9d | |
|  Bodmer | 967ccfcd3c | |
|  Bodmer | 2b6a41c53a | |
|  Bodmer | 33e6c3580d | |
|  Bodmer | b3c8287114 | |
|  Bodmer | 450941382b | |
|  Bodmer | db309cc407 | |
|  Bodmer | 7562720dc9 | |
|  Bodmer | 532efe4b02 | |
|  Bodmer | 2b576dc614 | |
|  Bodmer | de688f5ae7 | |
|  Bodmer | e446f65ff9 | |
|  Bodmer | 5592f603dd | |
|  Bodmer | c35e73a9cc | |
|  Bodmer | 7b2cb1dfbd | |
|  Bodmer | a0dd2db654 | |
|  Bodmer | f9f9a4ba63 | |
|  Bodmer | 55477b58b2 | |
|  Bodmer | afd72efb5a | |
|  Nicolas Boulicault | 2882f1d794 | |
|  Nicolas Boulicault | 0416870179 | |
|  Bodmer | 333f0f845c | |
|  Bodmer | 90fe790ff9 | |
|  Bodmer | cc9787deaf | |
|  Bodmer | ec23732c11 | |
|  Bodmer | f2d8d2f26d | |
|  Bodmer | d94408bdaa | |
|  Bodmer | a0bfb52386 | |
|  Bodmer | 345f39127c | |
|  Ivan Kravets | 5efbb617ea | |
|  Bodmer | 23df2a9628 | |
|  Bodmer | 0094ee744a | |
|  Bodmer | 483459ba9b | |
|  Bodmer | 781b0bc67c | |
|  Bodmer | 27963e00cc | |
|  Dustin Watts | 2cfc5c5a52 | |
|  Dustin Watts | ead97168ab | |
|  Dustin Watts | d6974252f3 | |
|  Bodmer | 4ced37add4 | |
|  Dracir | a9f435eced | |
|  Bodmer | ba819765af | |
|  Bodmer | bed65958e5 | |
|  Bodmer | 59d0e36d36 | |
|  Bodmer | 7bf48bb179 | |
|  Bodmer | 84238dde70 | |
|  Bodmer | 7d5fe20e43 | |
|  Bodmer | 1f7ce88dbe | |
|  Bodmer | 24b0e88852 | |
|  Bodmer | fe5609e367 | |
|  Bodmer | d883856dc0 | |
|  Bodmer | 8e0e7183c2 | |
|  Bodmer | 7b5f98a638 | |
|  Bodmer | 6b1b2006a2 | |
|  Bodmer | 59dfae94b2 | |
|  Bodmer | 073696d8c7 | |
|  Bodmer | fa1613f32e | |
|  Bodmer | d9acc229bf | |
|  Bodmer | 7d3f4f21b1 | |
|  Bodmer | 673de31fab | |
|  Bodmer | f7e9a91ead | |
|  Bodmer | 22901f5d6e | |
|  Bodmer | 79b41bc833 | |
|  Bodmer | f0ec6d22b3 | |
|  Bodmer | 18a76f1c65 | |
|  Bodmer | e09230c9ac | |
|  Bodmer | d655e1383a | |
|  Bodmer | cfb4689c85 | |
|  Bodmer | d0cc0a89d8 | |
|  Bodmer | 073b5233d4 | |
|  Bodmer | 416a84e535 | |
|  Bodmer | 4e8af767bd | |
|  Bodmer | 89a2457ca9 | |
|  Bodmer | a1b6240370 | |
|  Bodmer | 0141bf6842 | |
|  Bodmer | f8c995ca11 | |
|  Bodmer | 908b46165b | |
|  Bodmer | f624d5059c | |
|  Bodmer | 38b52a46a1 | |
|  Bodmer | 89c0028a36 | |
|  Bodmer | a815d77ec4 | |
|  Bodmer | 338d56ca42 | |
|  Bodmer | d6544c9cb4 | |
|  Bodmer | 8582ff7e3e | |
|  Dracir | 24a6a06a6b | |
|  dracir | 433b9a5342 | |
|  dracir | 8dff74503f | |
|  Bodmer | 7f5b8a9181 | |
|  Bodmer | a0fa2c31bd | |
|  Bodmer | 7fc8b99b64 | |
|  Bodmer | d0494af057 | |
|  Bodmer | f790c86818 | |
|  Dracir | 42549673dc | |
|  dracir | db15796b5d | |
|  dracir | c016ea65f0 | |
|  Bodmer | 181a85f86f | |
|  Dracir | 05d590e58c | |
|  dracir | 1ab684e40d | |
|  dracir | 83cd940200 | |
|  Bodmer | 8f0f8e517c | |
|  dracir | ff18c1b3b5 | |
|  dracir | 248c15d9e9 | |
|  Bodmer | e52a0161e6 | |
|  Bodmer | e4accc0d53 | |
|  Bodmer | 12fd90c345 | |
|  Bodmer | 652a26179e | |
|  Bodmer | 6cd087ca7c | |
|  Bodmer | 0c935de08d | |
|  Bodmer | ba67e95f7c | |
|  Bodmer | 0b7c57fe0a | |
|  Bodmer | 810aa98fc0 | |
|  Bodmer | c92c82bed5 | |
|  Bodmer | 8480f39a9c | |
|  Bodmer | 3b63aa9e63 | |
|  Bodmer | 896bbf62de | |
|  Bodmer | 25e74fe90c | |
|  Bodmer | 352d1e007c | |
|  Bodmer | 34d450dd90 | |
|  Bodmer | bc75274625 | |
|  Bodmer | 395b44dd34 | |
|  Bodmer | 1be1b4b05b | |
|  Bodmer | 31b2de56c1 | |
|  Bodmer | 39b0d6ab9a | |
|  Bodmer | e7767d1a8b | |
|  Bodmer | ee59bd0ae9 | |
|  Mingjie Li | 40306ae615 | |
|  Bodmer | cb37ae0aba | |
|  Bodmer | 6f4cf86834 | |
|  Frogomeli | 4fd8aa8bd4 | |
|  Bodmer | e83383c69a | |
|  Bodmer | 90804c33fb | |
|  Bodmer | a23a2df977 | |
|  Bodmer | 5d9b09bc2d | |
|  moion | b911c86572 | |
|  Bodmer | ec504067c1 | |
|  Bodmer | b6708b65ae | |
|  Bodmer | d50b7f6c13 | |
|  Bodmer | 284893c374 | |
|  Bodmer | d1e6637b88 | |
|  Bodmer | 6823025758 | |
|  Bodmer | 4fae4fa6cb | |
|  Bodmer | 92d51413aa | |
|  Bodmer | 97a9455e63 | |
|  Bodmer | 032e54dd10 | |
|  Bodmer | 86101770ac | |
|  Bodmer | 4f7f8f7d7e | |
|  Bodmer | 5f35a28db4 | |
|  Bodmer | f0e080165a | |
|  Bodmer | de3c7490c2 | |
|  Bodmer | f576040a32 | |
|  Bodmer | 5b1b49f8ea | |
|  Bodmer | 51a6e25151 | |
|  Bodmer | 2aa4df5133 | |
|  Bodmer | efd7cc517c | |
|  Bodmer | d5ba4a1886 | |
|  Bodmer | 25f1398564 | |
|  Bodmer | 3086fad767 | |
|  Bodmer | 78685d48b8 | |
|  Bodmer | b7b0660fb9 | |
|  Bodmer | 2ee3f36f68 | |
|  Bodmer | a4a149405f | |
|  Bodmer | 1ce36a801e | |
|  Bodmer | 9cfcf7cbfe | |
|  Bodmer | ca6c2ecd19 | |
|  gql19950701 | 8a1d91652f | |
|  Bodmer | 10fbeece04 | |
|  Bodmer | 31d845b1c5 | |
|  Bodmer | 6ca074446f | |
|  Bodmer | 29094c9c07 | |
|  Bodmer | 0dc68c45b8 | |
|  Bodmer | 4dd4cb678d | |
|  Bodmer | 3b50740a29 | |
|  Bodmer | 48da363c68 | |
|  Bodmer | 7522d6b41b | |
|  Bodmer | 8c5f269a32 | |
|  LeFauve | 64afd184dc | |
|  Bodmer | 9ff32bf501 | |
|  Bodmer | d819c2e89e | |
|  Bodmer | b6db90ada4 | |
|  Bodmer | 97ca3fdbe2 | |
|  Dr. Stefan Labich | 14ff368d5f | |
|  Bodmer | 32d9914254 | |
|  Bodmer | cb2f5be6c8 | |
|  Bodmer | 3528ac1457 | |
|  Bodmer | de1682667e | |
|  Bodmer | 2434cb515b | |
|  Bodmer | 984bd42896 | |
|  Bodmer | 0c18297d77 | |
|  LeFauve | 10d0471345 | |
|  Bodmer | a2140a4d04 | |
|  Bodmer | 80730ff9c4 | |
|  Bodmer | 47895f1e7b | |
|  Bodmer | cd9f68313a | |
|  Bodmer | 2de16b2bba | |
|  Bodmer | 4b3928cb55 | |
|  Bodmer | 7f6e256e37 | |
|  Bodmer | e742a41ce2 | |
|  Bodmer | d0ef07d7f6 | |
|  Bodmer | 3cc1e2e20a | |
|  Bodmer | 0d12646909 | |
|  Bodmer | 230463317f | |
|  Bodmer | c9997f8dc5 | |
|  Bodmer | e61fb8c78d | |
|  Bodmer | 420165904c | |
|  Bodmer | 0daee5d502 | |
|  Bodmer | 73ff86b85b | |
|  Bodmer | bb2424f168 | |
|  Bodmer | 1242ba14d1 | |
|  Bodmer | 6df79d020b | |
|  Bodmer | 3f6f0bd779 | |
|  Bodmer | 04af1d11ea | |
|  Bodmer | 1dd7b4ec6c | |
|  Bodmer | 493b1a7fe5 | |
|  Bodmer | 553307aa63 | |
|  Bodmer | c725f201ee | |
|  Bodmer | 8a2398451b | |
|  Bodmer | 681eb9dfec | |
|  Bodmer | 5e7394f485 | |
|  Bodmer | d9573fe10f | |
|  Bodmer | 77a39370a3 | |
|  Bodmer | 4b841c03e3 | |
|  Bodmer | 7060d0cd6f | |
|  Bodmer | 40cd5bfe7b | |
|  Bodmer | e66d0f4069 | |
|  Bodmer | eee56b2cec | |
|  Bodmer | 20ad7e2cc1 | |
|  Bodmer | 48ad4c98fc | |
|  Bodmer | 174414f726 | |
|  Bodmer | ebdc2dead9 | |
|  Bodmer | dd8fc20cb4 | |
|  Bodmer | 3129fbf296 | |
|  Bodmer | 61608a7ca2 | |
|  Bodmer | 2aa554f072 | |
|  Bodmer | a474f4cd23 | |
|  Bodmer | 64a45f6e07 | |
|  Bodmer | bcce0fc7ce | |
|  Bodmer | 77fc9baea7 | |
|  Bodmer | f42daecdb8 | |
|  Bodmer | 2e626b0d7e | |
|  Bodmer | 52f3186da9 | |
|  Bodmer | 289eb7a255 | |
|  Bodmer | 4dd15657bf | |
|  Bodmer | 5959550dd7 | |
|  Bodmer | 12f9ce8691 | |
|  Bodmer | 84a6945716 | |
|  Bodmer | 9bf9c0940f | |
|  Bodmer | 07e77ad051 | |
|  Bodmer | ee7955b34d | |
|  Bodmer | dff20fd77d | |
|  bonaime | e17ad53809 | |
|  Bodmer | f60425d52b | |
|  Bodmer | b955571a60 | |
|  Ivan Kravets | d73057a39c | |
|  Bodmer | a2822e6d99 | |
|  Bodmer | c8c5dd7cbb | |
|  Bodmer | 26e1f80be9 | |
|  Bodmer | 9a084839bd | |
|  Bodmer | 11b006e1d9 | |
|  Bodmer | aa7bad45d3 | |
|  Bodmer | 0ad6de9161 | |
|  Bodmer | 9d33b3eac2 | |
|  Bodmer | e23d8e083b | |
|  Dave Bennett | f3135aea29 | |
|  Bodmer | 9e64092f58 | |
|  Bodmer | e240947d08 | |
|  Dennis Heynlein | c6773cc1f7 | |
|  Bodmer | 0992770d3d | |
|  Mateusz Czarnecki | afd78101e5 | |
|  Mateusz Czarnecki | 28be85212e | |
|  Bodmer | 58f457ba97 | |
|  Bodmer | c7a3f464c3 | |
|  Bodmer | 8efb988cda | |
|  Bodmer | 5a6ef1d05d | |
|  Bodmer | 8164629397 | |
|  Bodmer | 612e76343e | |
|  Bodmer | 6b40880375 | |
|  Bodmer | 9fc8fa6956 | |
|  Bodmer | 01b99a50d9 | |
|  arduino12 | d121a84d5a | |
|  arduino12 | 25d84a977a | |
|  arduino12 | e1161c17f4 | |
|  Bodmer | fa8ff798e1 | |
|  Bodmer | 1cc39dfa2b | |
|  Bodmer | c627b6e31a | |
|  David Cheeseman | 0560cf4df3 | |
|  Bodmer | 481c7abc9c | |
|  Bodmer | 637f7f1fe3 | |
|  Bodmer | ff3a888212 | |
|  Bodmer | 079d7f6ee5 | |
|  Bodmer | a0703e7880 | |
|  Bodmer | 233b98aa05 | |
|  Bodmer | 018c884312 | |
|  Bodmer | fe580e9fe6 | |
|  Bodmer | 3b07cfa81b | |
|  Bodmer | af25b79faa | |
|  Bodmer | 83fd35a6d5 | |
|  Bodmer | 715b4de525 | |
|  Bodmer | f33674c1a2 | |
|  Bodmer | 8a8ad47521 | |
|  Bodmer | 168a73fea9 | |
|  Bodmer | add47960b1 | |
|  Bodmer | f96efe5d59 | |
|  Bodmer | 534372ef99 | |
|  Bodmer | fd99db4354 | |
|  Bodmer | 16f144ff76 | |
|  Bodmer | d0619b0527 | |
|  Bodmer | fce86c0f2e | |
|  Bodmer | d9c7d4a923 | |
|  Bodmer | 6c29d8e29b | |
|  Bodmer | c06c10edb9 | |
|  Bodmer | 71b1d090c4 | |
|  Bodmer | 356095bdf3 | |
|  Bodmer | 4e8497c159 | |
|  Bodmer | 91c34afc49 | |
|  Bodmer | dba2ef1855 | |
|  Bodmer | 135610b00d | |
|  Bodmer | f6e90349d8 | |
|  Bodmer | 1c36c2c933 | |
|  Bodmer | 4cc57699fa | |
|  Bodmer | c11ecd6932 | |
|  Bodmer | 865983e39c | |
|  Bodmer | e6df924f10 | |
|  Bodmer | 3c6ea1f594 | |
|  Bodmer | 107b2dd4ed | |
|  Bodmer | cd025dbc79 | |
|  Bodmer | c47d6e2d09 | |
|  andrew911 | c8c1af627c | |
|  andrew911 | 68e314f8f7 | |
|  andrew911 | 82b0aebded | |
|  Bodmer | 1e9dda3fb1 | |
|  lewisxhe | bd434c6a3c | |
|  Bodmer | 85539606e1 | |
|  Bodmer | a7a19be467 | |
|  Bodmer | c0054aaadf | |
|  Bodmer | 040d76f1a2 | |
|  Bodmer | fef40d9c8b | |
|  Bodmer | 2bf4d15b02 | |
|  Bodmer | 190fe54266 | |
|  unknown | 3307110b00 | |
|  Bodmer | 66bcbb2669 | |
|  Bodmer | a40e053662 | |
|  Bodmer | 602525a2ab | |
|  unknown | 4780bd2fee | |
|  unknown | f19e98c192 | |
|  Bodmer | 6f2c5f7301 | |
|  Bodmer | b1fb969e86 | |
|  Bodmer | e829dcac21 | |
|  Bodmer | 25362ee893 | |
|  Bodmer | e8843111ba | |
|  Bodmer | 9f083c0b2d | |
|  Bodmer | 0899be91df | |
|  Bodmer | 9e08131add | |
|  Bodmer | 3942471ab5 | |
|  Bodmer | 22c514cce9 | |
|  Bodmer | f6ee102619 | |
|  Maximilian Gerhardt | b3dab67178 | |
|  Bodmer | 5f171eeefd | |
|  Bodmer | 64239999e4 | |
|  Bodmer | 9fec44b6ea | |
|  Bodmer | 9a7958ed28 | |
|  Bodmer | 8e75cfa83f | |
|  Bodmer | e48059a6d6 | |
|  Bodmer | 1c4860dec3 | |
|  Bodmer | a4e94634a6 | |
|  Bodmer | 16eefd6ada | |
|  Bodmer | 95d1cd89c2 | |
|  Bodmer | acdfeb0b36 | |
|  Bodmer | 974cd7d9cb | |
|  Bodmer | 63dc212061 | |
|  Bodmer | 1b54ce87e9 | |
|  Bodmer | 53c3fcaa05 | |
|  Bodmer | 2162936b40 | |
|  Bodmer | 04b8ae9096 | |
|  Bodmer | ad0130309c | |
|  Bodmer | 42e6fc87ff | |
|  Bodmer | 27216f89cc | |
|  Bodmer | 3b39bf10c3 | |
|  Bodmer | 4bb3712a04 | |
|  Bodmer | fd16a6066d | |
|  Bodmer | 0de102f3ac | |
|  Bodmer | d6be490735 | |
|  Bodmer | d6e573c230 | |
|  Bodmer | abe5a442b6 | |
|  Bodmer | df23e14675 | |
|  Bodmer | bf5bf1852e | |
|  Bodmer | 788048155c | |
|  Bodmer | 579961bd5d | |
|  Bodmer | cd98515f1f | |
|  Bodmer | de8619027d | |
|  Bodmer | 54f6e730b5 | |
|  Bodmer | 45eb2d38e5 | |
|  Bodmer | b0edefb39d | |
|  Bodmer | 68869aa171 | |
|  Bodmer | 2c01c41c02 | |
|  Bodmer | aa4a32bc6b | |
|  Bodmer | 24b0eca084 | |
|  Bodmer | 975347d5de | |
|  Bodmer | 9cfc86839f | |
|  Bodmer | c9490f91b5 | |
|  Bodmer | 7eb365fcf5 | |
|  Bodmer | e49e546d2c | |
|  Bodmer | 5f272751f7 | |
|  Bodmer | f96c42253c | |
|  Bodmer | c8c6317241 | |
|  Bodmer | 1c1ec8cfa3 | |
|  Bodmer | ce3f0e219c | |
|  Bodmer | 0c4bedc681 | |
|  Bodmer | 35126bcc4d | |
|  Bodmer | e41e869851 | |
|  Bodmer | aaf96fa870 | |
|  Bodmer | 0d31c9f1a5 | |
|  Bodmer | 482e559b26 | |
|  Bodmer | e4e17b9af1 | |
|  Bodmer | 126aa7dff5 | |
|  Bodmer | 6a839479a7 | |
|  Bodmer | 9bd670be45 | |
|  Bodmer | d495b268c2 | |
|  Bodmer | b1f8cae069 | |
|  Bodmer | 505ca81a70 | |
|  Bodmer | ee91f723e7 | |
|  Bodmer | 39fe01afa3 | |
|  Bodmer | c0f14b2f99 | |
|  Bodmer | 27cf479e55 | |
|  Bodmer | 26ffe75a0e | |
|  Bodmer | dfba4633ad | |
|  Bodmer | 13d217dc89 | |
|  Bodmer | 22ca8193c5 | |
|  Bodmer | ef93dbe687 | |
|  Bodmer | 49cef1f35d | |
|  Bodmer | 0c49b71dd4 | |
|  Bodmer | d7fdcc0991 | |
|  Bodmer | aaebc18844 | |
|  Bodmer | 4c314c5c33 | |
|  Bodmer | 27657bcb9a | |
|  QrackEE | ddf03d43ea | |
|  Bodmer | 731228d13a | |
|  Bodmer | 1c66d306d5 | |
|  Bodmer | a8cd5c5d91 | |
|  Bodmer | 787893f949 | |
|  Bodmer | 47baa19645 | |
|  Bodmer | 52ee45b30b | |
|  Bodmer | cfcb9c6632 | |
|  Bodmer | 31125ca5ac | |
|  Bodmer | dc114db01b | |
|  Bodmer | c124688ab1 | |
|  Bodmer | 90cabab91a | |
|  Bodmer | a6d50ea5ef | |
|  Bodmer | 8fc52dc1f5 | |
|  Bodmer | a3fea4299e | |
|  Bodmer | af5aba3aae | |
|  Bodmer | c7383df1a3 | |
|  Bodmer | 61f1c5f98e | |
|  kamorris | a7be0c0ebe | |
|  Bodmer | 7861a0206e | |
|  Bodmer | 8cb59566d4 | |
|  Bodmer | 24750c605d | |
|  Bodmer | 284f52b009 | |
|  Bodmer | fb86ae4d1b | |
|  Bodmer | 21aa38b87f | |
|  Bodmer | b5826586fc | |
|  Kate Morris | 110128b055 | |
|  Kate Morris | 3a2157805e | |
|  kamorris | 5ffd4feac4 | |
|  kamorris | 0db6eed9e0 | |
|  Bodmer | 960ff6c7b9 | |
|  Bodmer | 232330d5cd | |
|  Bodmer | cd10a92f11 | |
|  Bodmer | 1314a34c3d | |
|  Bodmer | 7e4566f3f2 | |
|  Bodmer | cc3a1084fb | |
|  Bodmer | cc4f35f8c1 | |
|  Bodmer | fc8d912f52 | |
|  Bodmer | 00ac129667 | |
|  Bodmer | 489d90c935 | |
|  Bodmer | f6748bf906 | |
|  Bodmer | fb2e669d37 | |
|  Bodmer | 1f2d4b0a75 | |
|  Bodmer | cf979d40b7 | |
|  lovyan03 | c01ee2c4f7 | |
|  Bodmer | 90af737fa1 | |
|  Bodmer | 353d80a78e | |
|  Bodmer | e937a3496f | |
|  Bodmer | 875b451590 | |
|  Bodmer | 5ab0a08d1d | |
|  Bodmer | 5ff03cd2e9 | 
|  | @ -0,0 +1,36 @@ | |||
| --- | ||||
| name: Issue template | ||||
| about: Guide to content | ||||
| title: '' | ||||
| labels: '' | ||||
| assignees: '' | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| Only raise issues for problems with the library and/or provided examples. Post questions, comments and useful tips etc in the "Discussions" section. | ||||
| 
 | ||||
| To minimise effort to resolve issues the following should be provided as a minimum: | ||||
| 1. A description of the problem and the conditions that cause it to occur | ||||
| 2. IDE (e.g. Arduino or PlatformIO) | ||||
| 3. TFT_eSPI library version (try the latest, the problem may have been resolved!) from the Manage Libraries... menu | ||||
| 4. Board package version (e.g. 2.0.3) available from the Boards Manager... menu | ||||
| 5. Procesor, e.g RP2040, ESP32 S3 etc | ||||
| 6. TFT driver (e.g. ILI9341), a link to the vendors product web page is useful too. | ||||
| 7. Interface type (SPI or parallel) | ||||
| 
 | ||||
| Plus further information as appropriate to the problem: | ||||
| 1. TFT to processor connections used | ||||
| 2. A zip file containing your setup file (just drag and drop in message window - do not paste in long files!) | ||||
| 3. A zip file  containing a simple and complete example sketch that demonstrates the problem but needs no special hardware sensors or libraries. | ||||
| 4. Screen shot pictures showing the problem  (just drag and drop in message window) | ||||
| 
 | ||||
| The idea is to provide sufficient information so I can setup the exact same (or sufficiently similar) scenario to investigate and resolve the issue without having a tedious ping-pong of Q&A. | ||||
| 
 | ||||
| DO NOT paste code directly into the issue. To correctly format code put three ticks ( ` character on key next to "1" key) at the start and end of short pasted code segments to avoid format/markup anomolies. [See here:](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#quoting-code) | ||||
| 
 | ||||
| Example output: | ||||
| 
 | ||||
| ``` | ||||
|   Serial.begin(115200); | ||||
|   tft.init(); | ||||
| ``` | ||||
|  | @ -17,6 +17,11 @@ $RECYCLE.BIN/ | |||
| # Windows shortcuts | ||||
| *.lnk | ||||
| 
 | ||||
| # Arduino debug | ||||
| debug.cfg | ||||
| debug_custom.json | ||||
| *.svd | ||||
| 
 | ||||
| # ========================= | ||||
| # Operating System Files | ||||
| # ========================= | ||||
|  |  | |||
|  | @ -0,0 +1,4 @@ | |||
| 
 | ||||
| idf_component_register(SRCS "TFT_eSPI.cpp" | ||||
|                     INCLUDE_DIRS "." | ||||
|                     PRIV_REQUIRES arduino) | ||||
|  | @ -3,10 +3,13 @@ | |||
| ** Grabbed from Adafruit_GFX library and enhanced to handle any label font | ||||
| ***************************************************************************************/ | ||||
| TFT_eSPI_Button::TFT_eSPI_Button(void) { | ||||
|   _gfx       = 0; | ||||
|   _gfx       = nullptr; | ||||
|   _xd        = 0; | ||||
|   _yd        = 0; | ||||
|   _textdatum = MC_DATUM; | ||||
|   _label[9]  = '\0'; | ||||
|   currstate = false; | ||||
|   laststate = false; | ||||
| } | ||||
| 
 | ||||
| // Classic initButton() function: pass center & size
 | ||||
|  | @ -63,16 +66,30 @@ void TFT_eSPI_Button::drawButton(bool inverted, String long_name) { | |||
|   _gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill); | ||||
|   _gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline); | ||||
| 
 | ||||
|   _gfx->setTextColor(text, fill); | ||||
|   _gfx->setTextSize(_textsize); | ||||
|   if (_gfx->textfont == 255) { | ||||
|     _gfx->setCursor(_x1 + (_w / 8), | ||||
|                     _y1 + (_h / 4)); | ||||
|     _gfx->setTextColor(text); | ||||
|     _gfx->setTextSize(_textsize); | ||||
|     _gfx->print(_label); | ||||
|   } | ||||
|   else { | ||||
|     _gfx->setTextColor(text, fill); | ||||
|     _gfx->setTextSize(_textsize); | ||||
| 
 | ||||
|   uint8_t tempdatum = _gfx->getTextDatum(); | ||||
|   _gfx->setTextDatum(_textdatum); | ||||
|   if (long_name == "") | ||||
|     _gfx->drawString(_label, _x1 + (_w/2) + _xd, _y1 + (_h/2) - 4 + _yd); | ||||
|   else | ||||
|     _gfx->drawString(long_name, _x1 + (_w/2) + _xd, _y1 + (_h/2) - 4 + _yd); | ||||
|   _gfx->setTextDatum(tempdatum); | ||||
|     uint8_t tempdatum = _gfx->getTextDatum(); | ||||
|     _gfx->setTextDatum(_textdatum); | ||||
|     uint16_t tempPadding = _gfx->getTextPadding(); | ||||
|     _gfx->setTextPadding(0); | ||||
| 
 | ||||
|     if (long_name == "") | ||||
|       _gfx->drawString(_label, _x1 + (_w/2) + _xd, _y1 + (_h/2) - 4 + _yd); | ||||
|     else | ||||
|       _gfx->drawString(long_name, _x1 + (_w/2) + _xd, _y1 + (_h/2) - 4 + _yd); | ||||
| 
 | ||||
|     _gfx->setTextDatum(tempdatum); | ||||
|     _gfx->setTextPadding(tempPadding); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| bool TFT_eSPI_Button::contains(int16_t x, int16_t y) { | ||||
|  |  | |||
|  | @ -6,11 +6,11 @@ | |||
| // within button
 | ||||
| ***************************************************************************************/ | ||||
| 
 | ||||
| class TFT_eSPI_Button { | ||||
| class TFT_eSPI_Button : public TFT_eSPI { | ||||
| 
 | ||||
|  public: | ||||
|   TFT_eSPI_Button(void); | ||||
|   // "Classic" initButton() uses center & size
 | ||||
|   // "Classic" initButton() uses centre & size
 | ||||
|   void     initButton(TFT_eSPI *gfx, int16_t x, int16_t y, | ||||
|   uint16_t w, uint16_t h, uint16_t outline, uint16_t fill, | ||||
|   uint16_t textcolor, char *label, uint8_t textsize); | ||||
|  | @ -34,7 +34,7 @@ class TFT_eSPI_Button { | |||
|  private: | ||||
|   TFT_eSPI *_gfx; | ||||
|   int16_t  _x1, _y1; // Coordinates of top-left corner of button
 | ||||
|   int16_t  _xd, _yd; // Button text datum offsets (wrt center of button)
 | ||||
|   int16_t  _xd, _yd; // Button text datum offsets (wrt centre of button)
 | ||||
|   uint16_t _w, _h;   // Width and height of button
 | ||||
|   uint8_t  _textsize, _textdatum; // Text size multiplier and text datum for button
 | ||||
|   uint16_t _outlinecolor, _fillcolor, _textcolor; | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ void TFT_eSPI::loadFont(String fontName, bool flash) | |||
| 
 | ||||
|     The bitmaps start next at 24 + (28 * gCount) bytes from the start of the file. | ||||
|     Each pixel is 1 byte, an 8 bit Alpha value which represents the transparency from | ||||
|     0xFF foreground colour, 0x00 background. The sketch uses a linear interpolation | ||||
|     0xFF foreground colour, 0x00 background. The library uses a linear interpolation | ||||
|     between the foreground and background RGB component colours. e.g. | ||||
|         pixelRed = ((fgRed * alpha) + (bgRed * (255 - alpha))/255 | ||||
|     To gain a performance advantage fixed point arithmetic is used with rounding and | ||||
|  | @ -86,7 +86,7 @@ void TFT_eSPI::loadFont(String fontName, bool flash) | |||
|     // | gHeight ....@@@@@..@@  +  +    <-- baseline
 | ||||
|     // |   |     ...........@@     |
 | ||||
|     // |   |     ...........@@     |   gdY is the offset to the top edge of the bitmap
 | ||||
|     // |   |     .@@.......@@. descent plot top edge of bitmap at (cursorY + yAdvance - gdY)
 | ||||
|     // |   |     .@@.......@@. descent plot top edge of bitmap at (cursorY + ascent - gdY)
 | ||||
|     // |   +     x..@@@@@@@..x     |   x marks the corner pixels of the bitmap
 | ||||
|     // |                           |
 | ||||
|     // +---------------------------+   yAdvance is y delta for the next line, font size or (ascent + descent)
 | ||||
|  | @ -117,6 +117,10 @@ void TFT_eSPI::loadFont(String fontName, bool flash) | |||
| 
 | ||||
|     fontFile.seek(0, fs::SeekSet); | ||||
|   } | ||||
| #else | ||||
|   // Avoid unused varaible warning
 | ||||
|   fontName = fontName; | ||||
|   flash = flash; | ||||
| #endif | ||||
| 
 | ||||
|   gFont.gArray   = (const uint8_t*)fontPtr; | ||||
|  | @ -202,7 +206,7 @@ void TFT_eSPI::loadMetrics(void) | |||
| 
 | ||||
|     // Different glyph sets have different ascent values not always based on "d", so we could get
 | ||||
|     // the maximum glyph ascent by checking all characters. BUT this method can generate bad values
 | ||||
|     // for non-existant glyphs, so we will reply on processing for the value and disable this code for now...
 | ||||
|     // for non-existent glyphs, so we will reply on processing for the value and disable this code for now...
 | ||||
|     /*
 | ||||
|     if (gdY[gNum] > gFont.maxAscent) | ||||
|     { | ||||
|  | @ -312,7 +316,7 @@ uint32_t TFT_eSPI::readInt32(void) | |||
| 
 | ||||
| #ifdef FONT_FS_AVAILABLE | ||||
|   if (fs_font) { | ||||
|     val |= fontFile.read() << 24; | ||||
|     val  = fontFile.read() << 24; | ||||
|     val |= fontFile.read() << 16; | ||||
|     val |= fontFile.read() << 8; | ||||
|     val |= fontFile.read(); | ||||
|  | @ -320,7 +324,7 @@ uint32_t TFT_eSPI::readInt32(void) | |||
|   else | ||||
| #endif | ||||
|   { | ||||
|     val |= pgm_read_byte(fontPtr++) << 24; | ||||
|     val  = pgm_read_byte(fontPtr++) << 24; | ||||
|     val |= pgm_read_byte(fontPtr++) << 16; | ||||
|     val |= pgm_read_byte(fontPtr++) << 8; | ||||
|     val |= pgm_read_byte(fontPtr++); | ||||
|  | @ -355,17 +359,32 @@ bool TFT_eSPI::getUnicodeIndex(uint16_t unicode, uint16_t *index) | |||
| // Expects file to be open
 | ||||
| void TFT_eSPI::drawGlyph(uint16_t code) | ||||
| { | ||||
|   uint16_t fg = textcolor; | ||||
|   uint16_t bg = textbgcolor; | ||||
| 
 | ||||
|   // Check if cursor has moved
 | ||||
|   if (last_cursor_x != cursor_x) | ||||
|   { | ||||
|     bg_cursor_x = cursor_x; | ||||
|     last_cursor_x = cursor_x; | ||||
|   } | ||||
| 
 | ||||
|   if (code < 0x21) | ||||
|   { | ||||
|     if (code == 0x20) { | ||||
|       if (_fillbg) fillRect(bg_cursor_x, cursor_y, (cursor_x + gFont.spaceWidth) - bg_cursor_x, gFont.yAdvance, bg); | ||||
|       cursor_x += gFont.spaceWidth; | ||||
|       bg_cursor_x = cursor_x; | ||||
|       last_cursor_x = cursor_x; | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     if (code == '\n') { | ||||
|       cursor_x = 0; | ||||
|       bg_cursor_x = 0; | ||||
|       last_cursor_x = 0; | ||||
|       cursor_y += gFont.yAdvance; | ||||
|       if (cursor_y >= _height) cursor_y = 0; | ||||
|       if (textwrapY && (cursor_y >= height())) cursor_y = 0; | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
|  | @ -373,18 +392,16 @@ void TFT_eSPI::drawGlyph(uint16_t code) | |||
|   uint16_t gNum = 0; | ||||
|   bool found = getUnicodeIndex(code, &gNum); | ||||
|    | ||||
|   uint16_t fg = textcolor; | ||||
|   uint16_t bg = textbgcolor; | ||||
| 
 | ||||
|   if (found) | ||||
|   { | ||||
| 
 | ||||
|     if (textwrapX && (cursor_x + gWidth[gNum] + gdX[gNum] > _width)) | ||||
|     if (textwrapX && (cursor_x + gWidth[gNum] + gdX[gNum] > width())) | ||||
|     { | ||||
|       cursor_y += gFont.yAdvance; | ||||
|       cursor_x = 0; | ||||
|       bg_cursor_x = 0; | ||||
|     } | ||||
|     if (textwrapY && ((cursor_y + gFont.yAdvance) >= _height)) cursor_y = 0; | ||||
|     if (textwrapY && ((cursor_y + gFont.yAdvance) >= height())) cursor_y = 0; | ||||
|     if (cursor_x == 0) cursor_x -= gdX[gNum]; | ||||
| 
 | ||||
|     uint8_t* pbuffer = nullptr; | ||||
|  | @ -393,21 +410,55 @@ void TFT_eSPI::drawGlyph(uint16_t code) | |||
| #ifdef FONT_FS_AVAILABLE | ||||
|     if (fs_font) | ||||
|     { | ||||
|       fontFile.seek(gBitmap[gNum], fs::SeekSet); // This is taking >30ms for a significant position shift
 | ||||
|       fontFile.seek(gBitmap[gNum], fs::SeekSet); | ||||
|       pbuffer =  (uint8_t*)malloc(gWidth[gNum]); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     int16_t  xs = 0; | ||||
|     uint32_t dl = 0; | ||||
|     uint8_t pixel; | ||||
| 
 | ||||
|     int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum]; | ||||
|     int16_t cx = cursor_x + gdX[gNum]; | ||||
| 
 | ||||
|     //  if (cx > width() && bg_cursor_x > width()) return;
 | ||||
|     //  if (cursor_y > height()) return;
 | ||||
| 
 | ||||
|     int16_t  fxs = cx; | ||||
|     uint32_t fl = 0; | ||||
|     int16_t  bxs = cx; | ||||
|     uint32_t bl = 0; | ||||
|     int16_t  bx = 0; | ||||
|     uint8_t pixel; | ||||
| 
 | ||||
|     startWrite(); // Avoid slow ESP32 transaction overhead for every pixel
 | ||||
| 
 | ||||
|     for (int y = 0; y < gHeight[gNum]; y++) | ||||
|     int16_t fillwidth  = 0; | ||||
|     int16_t fillheight = 0; | ||||
| 
 | ||||
|     // Fill area above glyph
 | ||||
|     if (_fillbg) { | ||||
|       fillwidth  = (cursor_x + gxAdvance[gNum]) - bg_cursor_x; | ||||
|       if (fillwidth > 0) { | ||||
|         fillheight = gFont.maxAscent - gdY[gNum]; | ||||
|         // Could be negative
 | ||||
|         if (fillheight > 0) { | ||||
|           fillRect(bg_cursor_x, cursor_y, fillwidth, fillheight, textbgcolor); | ||||
|         } | ||||
|       } | ||||
|       else { | ||||
|         // Could be negative
 | ||||
|         fillwidth = 0; | ||||
|       } | ||||
| 
 | ||||
|       // Fill any area to left of glyph                              
 | ||||
|       if (bg_cursor_x < cx) fillRect(bg_cursor_x, cy, cx - bg_cursor_x, gHeight[gNum], textbgcolor); | ||||
|       // Set x position in glyph area where background starts
 | ||||
|       if (bg_cursor_x > cx) bx = bg_cursor_x - cx; | ||||
|       // Fill any area to right of glyph
 | ||||
|       if (cx + gWidth[gNum] < cursor_x + gxAdvance[gNum]) { | ||||
|         fillRect(cx + gWidth[gNum], cy, (cursor_x + gxAdvance[gNum]) - (cx + gWidth[gNum]), gHeight[gNum], textbgcolor); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     for (int32_t y = 0; y < gHeight[gNum]; y++) | ||||
|     { | ||||
| #ifdef FONT_FS_AVAILABLE | ||||
|       if (fs_font) { | ||||
|  | @ -425,7 +476,8 @@ void TFT_eSPI::drawGlyph(uint16_t code) | |||
|         } | ||||
|       } | ||||
| #endif | ||||
|       for (int x = 0; x < gWidth[gNum]; x++) | ||||
| 
 | ||||
|       for (int32_t x = 0; x < gWidth[gNum]; x++) | ||||
|       { | ||||
| #ifdef FONT_FS_AVAILABLE | ||||
|         if (fs_font) pixel = pbuffer[x]; | ||||
|  | @ -435,28 +487,44 @@ void TFT_eSPI::drawGlyph(uint16_t code) | |||
| 
 | ||||
|         if (pixel) | ||||
|         { | ||||
|           if (bl) { drawFastHLine( bxs, y + cy, bl, bg); bl = 0; } | ||||
|           if (pixel != 0xFF) | ||||
|           { | ||||
|             if (dl) { | ||||
|               if (dl==1) drawPixel(xs, y + cy, fg); | ||||
|               else drawFastHLine( xs, y + cy, dl, fg); | ||||
|               dl = 0; | ||||
|             if (fl) { | ||||
|               if (fl==1) drawPixel(fxs, y + cy, fg); | ||||
|               else drawFastHLine( fxs, y + cy, fl, fg); | ||||
|               fl = 0; | ||||
|             } | ||||
|             if (getColor) bg = getColor(x + cx, y + cy); | ||||
|             drawPixel(x + cx, y + cy, alphaBlend(pixel, fg, bg)); | ||||
|           } | ||||
|           else | ||||
|           { | ||||
|             if (dl==0) xs = x + cx; | ||||
|             dl++; | ||||
|             if (fl==0) fxs = x + cx; | ||||
|             fl++; | ||||
|           } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|           if (dl) { drawFastHLine( xs, y + cy, dl, fg); dl = 0; } | ||||
|           if (fl) { drawFastHLine( fxs, y + cy, fl, fg); fl = 0; } | ||||
|           if (_fillbg) { | ||||
|             if (x >= bx) { | ||||
|               if (bl==0) bxs = x + cx; | ||||
|               bl++; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       if (dl) { drawFastHLine( xs, y + cy, dl, fg); dl = 0; } | ||||
|       if (fl) { drawFastHLine( fxs, y + cy, fl, fg); fl = 0; } | ||||
|       if (bl) { drawFastHLine( bxs, y + cy, bl, bg); bl = 0; } | ||||
|     } | ||||
| 
 | ||||
|     // Fill area below glyph
 | ||||
|     if (fillwidth > 0) { | ||||
|       fillheight = (cursor_y + gFont.yAdvance) - (cy + gHeight[gNum]); | ||||
|       if (fillheight > 0) { | ||||
|         fillRect(bg_cursor_x, cy + gHeight[gNum], fillwidth, fillheight, textbgcolor); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (pbuffer) free(pbuffer); | ||||
|  | @ -465,10 +533,12 @@ void TFT_eSPI::drawGlyph(uint16_t code) | |||
|   } | ||||
|   else | ||||
|   { | ||||
|     // Not a Unicode in font so draw a rectangle and move on cursor
 | ||||
|     // Point code not in font so draw a rectangle and move on cursor
 | ||||
|     drawRect(cursor_x, cursor_y + gFont.maxAscent - gFont.ascent, gFont.spaceWidth, gFont.ascent, fg); | ||||
|     cursor_x += gFont.spaceWidth + 1; | ||||
|   } | ||||
|   bg_cursor_x = cursor_x; | ||||
|   last_cursor_x = cursor_x; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -504,12 +574,9 @@ void TFT_eSPI::showFont(uint32_t td) | |||
|     setCursor(cursorX, cursorY); | ||||
|     drawGlyph(gUnicode[i]); | ||||
|     cursorX += gxAdvance[i]; | ||||
|     //cursorX +=  printToSprite( cursorX, cursorY, i );
 | ||||
|     yield(); | ||||
|   } | ||||
| 
 | ||||
|   delay(timeDelay); | ||||
|   fillScreen(textbgcolor); | ||||
|   //fontFile.close();
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 
 | ||||
|  public: | ||||
| 
 | ||||
|   // These are for the new antialiased fonts
 | ||||
|   // These are for the new anti-aliased fonts
 | ||||
|   void     loadFont(const uint8_t array[]); | ||||
| #ifdef FONT_FS_AVAILABLE | ||||
|   void     loadFont(String fontName, fs::FS &ffs); | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -9,17 +9,23 @@ class TFT_eSprite : public TFT_eSPI { | |||
| 
 | ||||
|  public: | ||||
| 
 | ||||
|   TFT_eSprite(TFT_eSPI *tft); | ||||
|   explicit TFT_eSprite(TFT_eSPI *tft); | ||||
|   ~TFT_eSprite(void); | ||||
| 
 | ||||
|            // Create a sprite of width x height pixels, return a pointer to the RAM area
 | ||||
|            // Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed
 | ||||
|            // RAM required is:
 | ||||
|            //  - 1 bit per pixel for 1 bit colour depth
 | ||||
|            //  - 1 byte per pixel for 8 bit colour
 | ||||
|            //  - 2 bytes per pixel for 16 bit color depth
 | ||||
|   ~TFT_eSprite(void); | ||||
|            //  - 1 nibble per pixel for 4 bit colour (with palette table)
 | ||||
|            //  - 1 byte per pixel for 8 bit colour (332 RGB format)
 | ||||
|            //  - 2 bytes per pixel for 16 bit color depth (565 RGB format)
 | ||||
|   void*    createSprite(int16_t width, int16_t height, uint8_t frames = 1); | ||||
| 
 | ||||
|   void*    createSprite(int16_t width, int16_t height, uint8_t frames = 1);   | ||||
|            // Returns a pointer to the sprite or nullptr if not created, user must cast to pointer type
 | ||||
|   void*    getPointer(void); | ||||
| 
 | ||||
|            // Returns true if sprite has been created
 | ||||
|   bool     created(void); | ||||
| 
 | ||||
|            // Delete the sprite to free up the RAM
 | ||||
|   void     deleteSprite(void); | ||||
|  | @ -28,14 +34,14 @@ class TFT_eSprite : public TFT_eSPI { | |||
|            // Returns a pointer to the Sprite frame buffer
 | ||||
|   void*    frameBuffer(int8_t f); | ||||
|    | ||||
|            // Set or get the colour depth to 4, 8 or 16 bits. Can be used to change depth an existing
 | ||||
|            // Set or get the colour depth to 1, 4, 8 or 16 bits. Can be used to change depth an existing
 | ||||
|            // sprite, but clears it to black, returns a new pointer if sprite is re-created.
 | ||||
|   void*    setColorDepth(int8_t b); | ||||
|   int8_t   getColorDepth(void); | ||||
| 
 | ||||
|            // Set the palette for a 4 bit depth sprite.  Only the first 16 colours in the map are used.
 | ||||
|   void     createPalette(uint16_t *palette, int colors = 16);       // Palette in RAM
 | ||||
|   void     createPalette(const uint16_t *palette, int colors = 16); // Palette in FLASH
 | ||||
|   void     createPalette(uint16_t *palette = nullptr, uint8_t colors = 16);       // Palette in RAM
 | ||||
|   void     createPalette(const uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in FLASH
 | ||||
| 
 | ||||
|            // Set a single palette index to the given color
 | ||||
|   void     setPaletteColor(uint8_t index, uint16_t color); | ||||
|  | @ -46,9 +52,11 @@ class TFT_eSprite : public TFT_eSPI { | |||
|            // Set foreground and background colours for 1 bit per pixel Sprite
 | ||||
|   void     setBitmapColor(uint16_t fg, uint16_t bg); | ||||
| 
 | ||||
|            // Draw a single pixel at x,y
 | ||||
|   void     drawPixel(int32_t x, int32_t y, uint32_t color); | ||||
| 
 | ||||
|   void     drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t font), | ||||
|            // Draw a single character in the GLCD or GFXFF font
 | ||||
|   void     drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), | ||||
| 
 | ||||
|            // Fill Sprite with a colour
 | ||||
|            fillSprite(uint32_t color), | ||||
|  | @ -56,18 +64,18 @@ class TFT_eSprite : public TFT_eSPI { | |||
|            // Define a window to push 16 bit colour pixels into in a raster order
 | ||||
|            // Colours are converted to the set Sprite colour bit depth
 | ||||
|            setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1), | ||||
|            // Push a color (aka singe pixel) to the screen
 | ||||
|            pushColor(uint32_t color), | ||||
|            // Push len colors (pixels) to the screen
 | ||||
|            pushColor(uint32_t color, uint16_t len), | ||||
|            // Push a pixel preformatted as a 8 or 16 bit colour (avoids conversion overhead)
 | ||||
|            // Push a color (aka singe pixel) to the sprite's set window area
 | ||||
|            pushColor(uint16_t color), | ||||
|            // Push len colors (pixels) to the sprite's set window area
 | ||||
|            pushColor(uint16_t color, uint32_t len), | ||||
|            // Push a pixel pre-formatted as a 1, 4, 8 or 16 bit colour (avoids conversion overhead)
 | ||||
|            writeColor(uint16_t color), | ||||
| 
 | ||||
|            // Set the scroll zone, top left corner at x,y with defined width and height
 | ||||
|            // The colour (optional, black is default) is used to fill the gap after the scroll
 | ||||
|            setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color = TFT_BLACK), | ||||
|            // Scroll the defined zone dx,dy pixels. Negative values left,up, positive right,down
 | ||||
|            // dy is optional (default is then no up/down scroll).
 | ||||
|            // dy is optional (default is 0, so no up/down scroll).
 | ||||
|            // The sprite coordinate frame does not move because pixels are moved
 | ||||
|            scroll(int16_t dx, int16_t dy = 0), | ||||
| 
 | ||||
|  | @ -79,9 +87,6 @@ class TFT_eSprite : public TFT_eSPI { | |||
|            // Fill a rectangular area with a color (aka draw a filled rectangle)
 | ||||
|            fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); | ||||
| 
 | ||||
|            // Set the sprite text cursor position for print class (does not change the TFT screen cursor)
 | ||||
|            //setCursor(int16_t x, int16_t y); // Not needed, so uses TFT class function
 | ||||
| 
 | ||||
|            // Set the coordinate rotation of the Sprite (for 1bpp Sprites only)
 | ||||
|            // Note: this uses coordinate rotation and is primarily for ePaper which does not support
 | ||||
|            // CGRAM rotation (like TFT drivers do) within the displays internal hardware
 | ||||
|  | @ -89,14 +94,9 @@ class TFT_eSprite : public TFT_eSPI { | |||
|   uint8_t  getRotation(void); | ||||
| 
 | ||||
|            // Push a rotated copy of Sprite to TFT with optional transparent colour
 | ||||
|   bool     pushRotated(int16_t angle, int32_t transp = -1);   // Using fixed point maths
 | ||||
|   bool     pushRotated(int16_t angle, uint32_t transp = 0x00FFFFFF); | ||||
|            // Push a rotated copy of Sprite to another different Sprite with optional transparent colour
 | ||||
|   bool     pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp = -1);   // Using fixed point maths
 | ||||
| 
 | ||||
|           // Set and get the pivot point for this Sprite
 | ||||
|   void     setPivot(int16_t x, int16_t y); | ||||
|   int16_t  getPivotX(void), | ||||
|            getPivotY(void); | ||||
|   bool     pushRotated(TFT_eSprite *spr, int16_t angle, uint32_t transp = 0x00FFFFFF); | ||||
| 
 | ||||
|            // Get the TFT bounding box for a rotated copy of this Sprite
 | ||||
|   bool     getRotatedBounds(int16_t angle, int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y); | ||||
|  | @ -110,22 +110,27 @@ class TFT_eSprite : public TFT_eSPI { | |||
|            // Read the colour of a pixel at x,y and return value in 565 format 
 | ||||
|   uint16_t readPixel(int32_t x0, int32_t y0); | ||||
| 
 | ||||
|            // return the color map index of the pixel at x,y (used when scrolling)
 | ||||
|   uint8_t  readPixelValue(int32_t x, int32_t y); | ||||
|            // return the numerical value of the pixel at x,y (used when scrolling)
 | ||||
|            // 16bpp = colour, 8bpp = byte, 4bpp = colour index, 1bpp = 1 or 0
 | ||||
|   uint16_t readPixelValue(int32_t x, int32_t y); | ||||
| 
 | ||||
|            // Write an image (colour bitmap) to the sprite.  Not implemented for _bpp == 4.
 | ||||
|   void     pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); | ||||
|            // Write an image (colour bitmap) to the sprite.
 | ||||
|   void     pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data, uint8_t sbpp = 0); | ||||
|   void     pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); | ||||
| 
 | ||||
|            // Swap the byte order for pushImage() - corrects different image endianness
 | ||||
|   void     setSwapBytes(bool swap); | ||||
|   bool     getSwapBytes(void); | ||||
| 
 | ||||
|            // Push the sprite to the TFT screen, this fn calls pushImage() in the TFT class.
 | ||||
|            // Optionally a "transparent" colour can be defined, pixels of that colour will not be rendered
 | ||||
|   void     pushSprite(int32_t x, int32_t y); | ||||
|   void     pushSprite(int32_t x, int32_t y, uint16_t transparent); | ||||
| 
 | ||||
|            // Push a windowed area of the sprite to the TFT at tx, ty
 | ||||
|   bool     pushSprite(int32_t tx, int32_t ty, int32_t sx, int32_t sy, int32_t sw, int32_t sh); | ||||
| 
 | ||||
|            // Push the sprite to another sprite at x,y. This fn calls pushImage() in the destination sprite (dspr) class.
 | ||||
|   bool     pushToSprite(TFT_eSprite *dspr, int32_t x, int32_t y); | ||||
|   bool     pushToSprite(TFT_eSprite *dspr, int32_t x, int32_t y, uint16_t transparent); | ||||
| 
 | ||||
|            // Draw a single character in the selected font
 | ||||
|   int16_t  drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), | ||||
|            drawChar(uint16_t uniCode, int32_t x, int32_t y); | ||||
| 
 | ||||
|  | @ -133,13 +138,14 @@ class TFT_eSprite : public TFT_eSPI { | |||
|   int16_t  width(void), | ||||
|            height(void); | ||||
| 
 | ||||
|            // Used by print class to print text to cursor position
 | ||||
|   size_t   write(uint8_t); | ||||
| 
 | ||||
|            // Functions associated with anti-aliased fonts
 | ||||
|            // Draw a single unicode character using the loaded font
 | ||||
|   void     drawGlyph(uint16_t code); | ||||
|            // Print string to sprite using loaded font at cursor position
 | ||||
|   void     printToSprite(String string); | ||||
|            // Print char array to sprite using loaded font at cursor position
 | ||||
|   void     printToSprite(char *cbuffer, uint16_t len); | ||||
|            // Print indexed glyph to sprite using loaded font at x,y
 | ||||
|   int16_t  printToSprite(int16_t x, int16_t y, uint16_t index); | ||||
| 
 | ||||
|  private: | ||||
|  | @ -149,36 +155,34 @@ class TFT_eSprite : public TFT_eSPI { | |||
|            // Reserve memory for the Sprite and return a pointer
 | ||||
|   void*    callocSprite(int16_t width, int16_t height, uint8_t frames = 1); | ||||
| 
 | ||||
|            // Override the non-inlined TFT_eSPI functions
 | ||||
|   void     begin_nin_write(void) { ; } | ||||
|   void     end_nin_write(void) { ; } | ||||
| 
 | ||||
|  protected: | ||||
| 
 | ||||
|   uint8_t  _bpp;     // bits per pixel (1, 8 or 16)
 | ||||
|   uint8_t  _bpp;     // bits per pixel (1, 4, 8 or 16)
 | ||||
|   uint16_t *_img;    // pointer to 16 bit sprite
 | ||||
|   uint8_t  *_img8;   // pointer to  8 bit sprite
 | ||||
|   uint8_t  *_img4;   // pointer to 4 bit sprite (uses color map)
 | ||||
|   uint8_t  *_img8_1; // pointer to  frame 1
 | ||||
|   uint8_t  *_img8_2; // pointer to  frame 2
 | ||||
|   uint8_t  *_img8;   // pointer to  1 and 8 bit sprite frame 1 or frame 2
 | ||||
|   uint8_t  *_img4;   // pointer to  4 bit sprite (uses color map)
 | ||||
|   uint8_t  *_img8_1; // pointer to frame 1
 | ||||
|   uint8_t  *_img8_2; // pointer to frame 2
 | ||||
| 
 | ||||
|   uint16_t *_colorMap; // color map: 16 entries, used with 4 bit color map.
 | ||||
|   uint16_t *_colorMap; // color map pointer: 16 entries, used with 4 bit color map.
 | ||||
| 
 | ||||
|   int16_t  _xpivot;   // x pivot point coordinate
 | ||||
|   int16_t  _ypivot;   // y pivot point coordinate
 | ||||
|   int32_t  _sinra; | ||||
|   int32_t  _cosra; | ||||
|   int32_t  _sinra;   // Sine of rotation angle in fixed point
 | ||||
|   int32_t  _cosra;   // Cosine of rotation angle in fixed point
 | ||||
| 
 | ||||
|   bool     _created;    // A Sprite has been created and memory reserved
 | ||||
|   bool     _created; // A Sprite has been created and memory reserved
 | ||||
|   bool     _gFont = false;  | ||||
| 
 | ||||
| //  int32_t  _icursor_x, _icursor_y;
 | ||||
|   uint8_t  _rotation = 0; | ||||
|   int32_t  _xs, _ys, _xe, _ye, _xptr, _yptr; // for setWindow
 | ||||
|   int32_t  _sx, _sy; // x,y for scroll zone
 | ||||
|   uint32_t _sw, _sh; // w,h for scroll zone
 | ||||
|   uint32_t _scolor;  // gap fill colour for scroll zone
 | ||||
| 
 | ||||
|   bool     _iswapBytes; // Swap the byte order for Sprite pushImage()
 | ||||
| 
 | ||||
|   int32_t  _iwidth, _iheight; // Sprite memory image bit width and height (swapped during rotations)
 | ||||
|   int32_t  _dwidth, _dheight; // Real display width and height (for <8bpp Sprites)
 | ||||
|   int32_t  _dwidth, _dheight; // Real sprite width and height (for <8bpp Sprites)
 | ||||
|   int32_t  _bitwidth;         // Sprite image bit width for drawPixel (for <8bpp Sprites, not swapped)
 | ||||
| 
 | ||||
| }; | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ inline void TFT_eSPI::end_touch_read_write(void){ | |||
|   #else | ||||
|     spi.setFrequency(SPI_FREQUENCY); | ||||
|   #endif | ||||
|   SET_BUS_WRITE_MODE; | ||||
|   //SET_BUS_WRITE_MODE;
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -107,6 +107,8 @@ uint16_t TFT_eSPI::getTouchRawZ(void){ | |||
| 
 | ||||
|   end_touch_read_write(); | ||||
| 
 | ||||
|   if (tz == 4095) tz = 0; | ||||
| 
 | ||||
|   return (uint16_t)tz; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,9 @@ | |||
|            // Convert raw x,y values to calibrated and correctly rotated screen coordinates
 | ||||
|   void     convertRawXY(uint16_t *x, uint16_t *y); | ||||
|            // Get the screen touch coordinates, returns true if screen has been touched
 | ||||
|            // if the touch cordinates are off screen then x and y are not updated
 | ||||
|            // if the touch coordinates are off screen then x and y are not updated
 | ||||
|            // The returned value can be treated as a bool type, false or 0 means touch not detected
 | ||||
|            // In future the function may return an 8 "quality" (jitter) value.
 | ||||
|   uint8_t  getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); | ||||
| 
 | ||||
|            // Run screen calibration and test, report calibration values to the serial port
 | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ | |||
| //
 | ||||
| // This font contains 96 ASCII characters
 | ||||
| 
 | ||||
| // Use the #define below to select a GBP sign instead of a dollar sign
 | ||||
| //#define FONT_4_GBP
 | ||||
| 
 | ||||
| PROGMEM const unsigned char widtbl_f32[96] =         // character width table
 | ||||
| { | ||||
|  | @ -58,6 +60,8 @@ PROGMEM const unsigned char chr_f32_23[] = | |||
| 0x7F, 0xD | ||||
| }; | ||||
| 
 | ||||
| #ifdef FONT_4_GBP | ||||
| // GBP symbol
 | ||||
| PROGMEM const unsigned char chr_f32_24[] =  | ||||
| { | ||||
| 0x1F, 0x85, 0x05, 0x89, 0x03, 0x82, 0x03, 0x82,  | ||||
|  | @ -67,6 +71,21 @@ PROGMEM const unsigned char chr_f32_24[] = | |||
| 0x0A, 0x81, 0x0B, 0x86, 0x02, 0x80, 0x01, 0x8B,  | ||||
| 0x01, 0x81, 0x04, 0x83, 0x63 | ||||
| }; | ||||
| #else | ||||
| // Dollar symbol
 | ||||
| PROGMEM const unsigned char chr_f32_24[] =  | ||||
| { | ||||
| 0x14, 0x80, 0x0A, 0x83, 0x07, 0x87, 0x04, 0x82,  | ||||
| 0x01, 0x80, 0x00, 0x82, 0x03, 0x81, 0x02, 0x80,  | ||||
| 0x01, 0x81, 0x03, 0x81, 0x02, 0x80, 0x01, 0x82,  | ||||
| 0x02, 0x82, 0x01, 0x80, 0x08, 0x84, 0x09, 0x84,  | ||||
| 0x0B, 0x83, 0x09, 0x84, 0x08, 0x80, 0x01, 0x82,  | ||||
| 0x01, 0x82, 0x02, 0x80, 0x02, 0x81, 0x02, 0x81,  | ||||
| 0x02, 0x80, 0x02, 0x81, 0x02, 0x83, 0x00, 0x80,  | ||||
| 0x01, 0x82, 0x03, 0x88, 0x06, 0x84, 0x0A, 0x80,  | ||||
| 0x67 | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| PROGMEM const unsigned char chr_f32_25[] =  | ||||
| { | ||||
|  |  | |||
|  | @ -76,7 +76,7 @@ PROGMEM const unsigned char chr_f7s_31[] = | |||
| 0x85, 0x19, 0x85, 0x19, 0x85, 0x19, 0x85, 0x19,  | ||||
| 0x85, 0x19, 0x85, 0x19, 0x85, 0x19, 0x85, 0x19,  | ||||
| 0x85, 0x19, 0x85, 0x19, 0x85, 0x19, 0x85, 0x19,  | ||||
| 0x85, 0x1B, 0x83, 0x1D, 0x81, 0x1E, 0x80, 0x5D,  | ||||
| 0x85, 0x1A, 0x84, 0x1C, 0x82, 0x1E, 0x80, 0x5D,  | ||||
| 0x81, 0x1B, 0x83, 0x19, 0x85, 0x19, 0x85, 0x19,  | ||||
| 0x85, 0x19, 0x85, 0x19, 0x85, 0x19, 0x85, 0x19,  | ||||
| 0x85, 0x19, 0x85, 0x19, 0x85, 0x19, 0x85, 0x19,  | ||||
|  |  | |||
|  | @ -0,0 +1,390 @@ | |||
| menu "TFT_eSPI" | ||||
| 
 | ||||
|     menu "Hidden menu" | ||||
|         visible if false | ||||
| 
 | ||||
|         config TFT_eSPI_ESPIDF | ||||
|             bool "Enable Configuration" | ||||
|             default y | ||||
|     endmenu | ||||
|          | ||||
|     choice TFT_DRIVER | ||||
|         prompt "Select TFT driver" | ||||
|         default TFT_ILI9341_DRIVER | ||||
|         help | ||||
|             Driver for the TFT LCD screen | ||||
| 
 | ||||
|         config TFT_ILI9341_DRIVER | ||||
|             bool "ILI9341 - 1" | ||||
|             help | ||||
|                 Generic driver for common displays | ||||
|         config TFT_ILI9341_2_DRIVER | ||||
|             bool "ILI9341 - 2" | ||||
|             help | ||||
|                 Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172 | ||||
|         config TFT_ST7735_DRIVER | ||||
|             bool "ST7735" | ||||
|             help | ||||
|                 Define additional parameters below for this display | ||||
|         config TFT_ILI9163_DRIVER | ||||
|             bool "ILI9163" | ||||
|             help | ||||
|                 Define additional parameters below for this display | ||||
|         config TFT_S6D02A1_DRIVER | ||||
|             bool "S6D02A1" | ||||
|         config TFT_HX8357D_DRIVER | ||||
|             bool "HX8357D" | ||||
|         config TFT_ILI9481_DRIVER | ||||
|             bool "ILI9481" | ||||
|         config TFT_ILI9486_DRIVER | ||||
|             bool "ILI9486" | ||||
|         config TFT_ILI9488_DRIVER | ||||
|             bool "ILI9488" | ||||
|             help | ||||
|                 WARNING: Do not connect ILI9488 display SDO to MISO if other devices  | ||||
|                 share the SPI bus (TFT SDO does NOT tristate when CS is high) | ||||
|         config TFT_ST7789_DRIVER | ||||
|             bool "ST7789 - 1" | ||||
|             help | ||||
|                 Full configuration option, define additional parameters below for this display | ||||
|         config TFT_ST7789_2_DRIVER | ||||
|             bool "ST7789 - 2" | ||||
|             help | ||||
|                 Minimal configuration option, define additional parameters below for this display | ||||
|         config TFT_R61581_DRIVER | ||||
|             bool "R61581" | ||||
|         config TFT_RM68140_DRIVER | ||||
|             bool "RM68140" | ||||
|         config TFT_ST7796_DRIVER | ||||
|             bool "ST7796" | ||||
|         config TFT_SSD1351_DRIVER | ||||
|             bool "SSD1351" | ||||
|         config TFT_SSD1963_480_DRIVER | ||||
|             bool "SSD1963_480" | ||||
|         config TFT_SSD1963_800_DRIVER | ||||
|             bool "SSD1963_800" | ||||
|         config TFT_SSD1963_800ALT_DRIVER | ||||
|             bool "SSD1963_800ALT" | ||||
|         config TFT_ILI9225_DRIVER | ||||
|             bool "ILI9225" | ||||
|         config TFT_GC9A01_DRIVER | ||||
|             bool "GC9A01" | ||||
|     endchoice | ||||
| 
 | ||||
|     if TFT_ST7735_DRIVER || TFT_ST7789_DRIVER || TFT_ST7789_2_DRIVER || TFT_ILI9341_DRIVER || TFT_ILI9341_2_DRIVER | ||||
|         choice TFT_COLOR_ORDER | ||||
|             prompt "Define the colour order" | ||||
|             help | ||||
|                 Define the colour order IF the blue and red are swapped on your display | ||||
| 
 | ||||
|             config TFT_RGB_ORDER | ||||
|                 bool "RGB" | ||||
|             config TFT_BGR_ORDER | ||||
|                 bool "BGR" | ||||
|         endchoice | ||||
|     endif | ||||
| 
 | ||||
|     config TFT_M5STACK | ||||
|         bool "M5Stack" | ||||
|         depends on TFT_ILI9341_DRIVER || TFT_ILI9341_2_DRIVER | ||||
|         help | ||||
|             Enable if using M5Stack module with integrated ILI9341 | ||||
| 
 | ||||
|     if TFT_ST7735_DRIVER || TFT_ST7789_DRIVER || TFT_ST7789_2_DRIVER || TFT_ILI9163_DRIVER || TFT_GC9A01_DRIVER | ||||
|         config TFT_WIDTH | ||||
|             int "LCD pixel width in portrait orientation" | ||||
|             default 128 | ||||
|             range 0 1024 | ||||
| 
 | ||||
|         config TFT_HEIGHT | ||||
|             int "LCD pixel height in portrait orientation" | ||||
|             default 240 | ||||
|             range 0 1024 | ||||
|     endif | ||||
| 
 | ||||
|     if TFT_ST7735_DRIVER | ||||
|         choice TFT_ST7735_TYPE | ||||
|             prompt "Define the type of display" | ||||
|             help | ||||
|                 Try out the different options below if the screen does not display graphics | ||||
|                 correctly,e.g. colours wrong, mirror images, or stray pixels at the edges. | ||||
| 
 | ||||
|             config TFT_ST7735_INITB | ||||
|                 bool "INITB" | ||||
|             config TFT_ST7735_GREENTAB | ||||
|                 bool "GREENTAB" | ||||
|             config TFT_ST7735_GREENTAB2 | ||||
|                 bool "GREENTAB2" | ||||
|             config TFT_ST7735_GREENTAB3 | ||||
|                 bool "GREENTAB3" | ||||
|             config TFT_ST7735_GREENTAB128 | ||||
|                 bool "GREENTAB128" | ||||
|                 help | ||||
|                     For 128 x 128 display | ||||
|             config TFT_ST7735_GREENTAB160x80 | ||||
|                 bool "GREENTAB160x80" | ||||
|                 help | ||||
|                     For 160 x 80 display (BGR, inverted, 26 offset) | ||||
|             config TFT_ST7735_REDTAB | ||||
|                 bool "REDTAB" | ||||
|             config TFT_ST7735_BLACKTAB | ||||
|                 bool "BLACKTAB" | ||||
|             config TFT_ST7735_REDTAB160x80 | ||||
|                 bool "REDTAB160x80" | ||||
|                 help | ||||
|                     For 160 x 80 display with 24 pixel offset | ||||
|         endchoice | ||||
|     endif | ||||
| 
 | ||||
|     choice TFT_COLOR_INVERSION | ||||
|         prompt "Color inversion correction" | ||||
|         help  | ||||
|             If colours are inverted (white shows as black) then try changing this option." | ||||
| 
 | ||||
|         config TFT_INVERSION_DISABLE | ||||
|             bool "None" | ||||
|         config TFT_INVERSION_ON | ||||
|             bool "On" | ||||
|         config TFT_INVERSION_OFF | ||||
|             bool "Off" | ||||
|              | ||||
|     endchoice | ||||
| 
 | ||||
|     config TFT_PARALLEL_8_BIT | ||||
|         bool "Enable 8-bit parallel mode (otherwise SPI is assumed)" | ||||
|         default "n" | ||||
|         depends on IDF_TARGET_ESP32 | ||||
|         help | ||||
|             Use 8-bit parallel bus to send data to the LCD. If not set SPI will be used. | ||||
|      | ||||
|     menu "Display Data pins" | ||||
|         depends on TFT_PARALLEL_8_BIT | ||||
|         config TFT_D0 | ||||
|             int "Data 0 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_D1 | ||||
|             int "Data 1 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_D2 | ||||
|             int "Data 2 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
|          | ||||
|         config TFT_D3 | ||||
|             int "Data 3 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_D4 | ||||
|             int "Data 4 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_D5 | ||||
|             int "Data 5 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_D6 | ||||
|             int "Data 6 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_D7 | ||||
|             int "Data 7 pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_WR | ||||
|             int "Write strobe pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
| 
 | ||||
|         config TFT_RD | ||||
|             int "Read strobe pin" | ||||
|             default -1 | ||||
|             range -1 33 | ||||
|     endmenu | ||||
| 
 | ||||
|     menu "Display SPI config" | ||||
|         depends on !TFT_PARALLEL_8_BIT | ||||
|      | ||||
|         choice TFT_SPI_PORT | ||||
|             prompt "SPI port" | ||||
|             default TFT_VSPI_PORT | ||||
|             help | ||||
|                 The ESP32 has 2 free SPI ports i.e. VSPI (SPI2) and HSPI (SPI3), | ||||
|                 the VSPI is the default. If the VSPI port is in use and pins are | ||||
|                 not accessible (e.g. TTGO T-Beam) then use the HSPI port for the | ||||
|                 TFT display. | ||||
|             config TFT_VSPI_PORT | ||||
|                 bool "VSPI (SPI2)" | ||||
|             config TFT_HSPI_PORT | ||||
|                 bool "HSPI (SPI3)" | ||||
|         endchoice | ||||
| 
 | ||||
|         config TFT_MISO | ||||
|             int "TFT MISO pin" | ||||
|             default -1 | ||||
|             range -1 32 if IDF_TARGET_ESP32 | ||||
|             range -1 45 if IDF_TARGET_ESP32S2 | ||||
|             help | ||||
|                 Master In Slave Out pin. | ||||
|                 Can be labelled as SDO in some displays | ||||
| 
 | ||||
|         config TFT_MOSI | ||||
|             int "TFT MOSI pin" | ||||
|             default -1 | ||||
|             range -1 32 if IDF_TARGET_ESP32 | ||||
|             range -1 45 if IDF_TARGET_ESP32S2 | ||||
|             help | ||||
|                 Master Out Slave In pin. | ||||
|                 Can be labelled as SDA or SDI in some displays | ||||
|              | ||||
|         config TFT_SCLK | ||||
|             int "TFT Clock pin" | ||||
|             default -1 | ||||
|             range -1 32 if IDF_TARGET_ESP32 | ||||
|             range -1 45 if IDF_TARGET_ESP32S2 | ||||
|             help | ||||
|                 Labelled in some displays as WR | ||||
| 
 | ||||
|         config TFT_SDA_READ | ||||
|             bool "Use SDA line for reading" | ||||
|             default "n" | ||||
|             help | ||||
|                 Some displays support SPI reads via the MISO pin, other displays have a single | ||||
|                 bi-directional SDA pin and the library will try to read this via the MOSI line | ||||
| 
 | ||||
|         config TFT_SPI_FREQUENCY | ||||
|             int "SPI Frequency (Hz)" | ||||
|             default 27000000 | ||||
|             range 1 80000000 | ||||
|             help | ||||
|                 Define the SPI clock frequency, this affects the graphics rendering speed. Too | ||||
|                 fast and the TFT driver will not keep up and display corruption appears. | ||||
|                 With an ILI9341 display 40MHz works OK, 80MHz sometimes fails | ||||
|                 With a ST7735 display more than 27MHz may not work (spurious pixels and lines) | ||||
|                 With an ILI9163 display 27 MHz works OK. | ||||
| 
 | ||||
|         config TFT_SPI_READ_FREQ | ||||
|             int "SPI Read Frequency (Hz)" | ||||
|             default 20000000 | ||||
|             range -1 80000000 | ||||
|             help | ||||
|                 Optional reduced SPI frequency for reading TFT. | ||||
|                 Set to -1 to use the default frequency | ||||
|              | ||||
|     endmenu | ||||
| 
 | ||||
|     menu "Control Pin configuration" | ||||
|         config TFT_CS | ||||
|             int "TFT Chip Select pin" | ||||
|             default -1 | ||||
|             range -1 33 if IDF_TARGET_ESP32 | ||||
|             range -1 45 if IDF_TARGET_ESP32S2 | ||||
|      | ||||
|         config TFT_DC | ||||
|             int "TFT Data/Command pin" | ||||
|             default -1 | ||||
|             range -1 31 | ||||
|             help | ||||
|                 Labelled as DC or RS (Register Select) in some displays | ||||
|      | ||||
|         config TFT_RST | ||||
|             int "TFT Reset pin" | ||||
|             default -1 | ||||
|             range -1 33 if IDF_TARGET_ESP32 | ||||
|             range -1 45 if IDF_TARGET_ESP32S2 | ||||
| 
 | ||||
|         config ENABLE_BL | ||||
|             bool "Enable backlight control" | ||||
|             default y | ||||
|          | ||||
|         if ENABLE_BL | ||||
|             config TFT_BL | ||||
|                 int "TFT Backlight pin" | ||||
|                 default -1 | ||||
|                 range -1 33 if IDF_TARGET_ESP32 | ||||
|                 range -1 45 if IDF_TARGET_ESP32S2 | ||||
|                 help | ||||
|                     Pin for the backlight control signal | ||||
|          | ||||
|             choice TFT_BACKLIGHT_ON | ||||
|                 bool "Pin state to activate backlight" | ||||
|                 default TFT_BACKLIGHT_ON_HIGH | ||||
|                 help | ||||
|                     The backlight will be turned ON when tft.begin() is called, but the library | ||||
|                     needs to know if the LEDs are ON with the pin HIGH or LOW. | ||||
|          | ||||
|                 config TFT_BACKLIGHT_ON_HIGH | ||||
|                     bool "HIGH" | ||||
|                 config TFT_BACKLIGHT_ON_LOW | ||||
|                     bool "LOW"             | ||||
|             endchoice | ||||
|         endif | ||||
|      | ||||
|         config TFT_BACKLIGHT_ON | ||||
|             int | ||||
|             default 1 if TFT_BACKLIGHT_ON_HIGH | ||||
|             default 0 if TFT_BACKLIGHT_ON_LOW | ||||
|     endmenu | ||||
| 
 | ||||
|     menu "Fonts" | ||||
|         config TFT_LOAD_GLCD | ||||
|             bool "Font 1: Original Adafruit 8 pixel font needs ~1820 bytes in FLASH" | ||||
|             default "y" | ||||
| 
 | ||||
|         config TFT_LOAD_FONT2 | ||||
|             bool "Font 2: Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters" | ||||
|             default "y" | ||||
| 
 | ||||
|         config TFT_LOAD_FONT4 | ||||
|             bool "Font 4: Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters" | ||||
|             default "y" | ||||
| 
 | ||||
|         config TFT_LOAD_FONT6 | ||||
|             bool "Font 6: Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm" | ||||
|             default "y" | ||||
| 
 | ||||
|         config TFT_LOAD_FONT7 | ||||
|             bool "Font 7: 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:." | ||||
|             default "y" | ||||
| 
 | ||||
|         config TFT_LOAD_FONT8 | ||||
|             bool "Font 8: Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-." | ||||
|             default "y" | ||||
| 
 | ||||
|         config TFT_LOAD_GFXFF | ||||
|             bool "FreeFonts: Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts" | ||||
|             default "y" | ||||
| 
 | ||||
|         config TFT_SMOOTH_FONT | ||||
|             bool "Smooth Fonts" | ||||
|             default "y" | ||||
|     endmenu | ||||
|      | ||||
|     menu "Touch screen configuration" | ||||
|         config ENABLE_TOUCH | ||||
|             bool "Enable Touch" | ||||
|             default n | ||||
| 
 | ||||
|         if ENABLE_TOUCH | ||||
|             config TOUCH_CS | ||||
|                 int "Touch chip select pin" | ||||
|                 default -1 | ||||
|                 range -1 33 if IDF_TARGET_ESP32 | ||||
|                 range -1 45 if IDF_TARGET_ESP32S2 | ||||
| 
 | ||||
|             config SPI_TOUCH_FREQUENCY | ||||
|                 int "SPI frequency for XPT2046 chip (Hz)" | ||||
|                 default 2500000 | ||||
|                 range 1 80000000 | ||||
|         endif | ||||
|     endmenu | ||||
| 
 | ||||
| endmenu | ||||
|  | @ -8,39 +8,91 @@ | |||
| 
 | ||||
| // Select the SPI port to use, ESP32 has 2 options
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   #ifdef USE_HSPI_PORT | ||||
|     SPIClass spi = SPIClass(HSPI); | ||||
|   #else // use default VSPI port
 | ||||
|     SPIClass& spi = SPI; | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       SPIClass spi = SPIClass(HSPI); | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       SPIClass spi = SPIClass(FSPI); | ||||
|     #else // use default VSPI port
 | ||||
|       SPIClass spi = SPIClass(VSPI); | ||||
|     #endif | ||||
|   #else | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       SPIClass spi = SPIClass(HSPI); | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       SPIClass spi = SPIClass(FSPI); | ||||
|     #else // use FSPI port
 | ||||
|       SPIClass& spi = SPI; | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef ESP32_DMA | ||||
|   // DMA SPA handle
 | ||||
|   spi_device_handle_t dmaHAL; | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #define DMA_CHANNEL 1 | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       spi_host_device_t spi_host = HSPI_HOST; | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       spi_host_device_t spi_host = SPI_HOST; | ||||
|     #else // use VSPI port
 | ||||
|       spi_host_device_t spi_host = VSPI_HOST; | ||||
|     #endif | ||||
|   #else | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       #define DMA_CHANNEL 2 | ||||
|       spi_host_device_t spi_host = (spi_host_device_t) DMA_CHANNEL; // Draws once then freezes
 | ||||
|     #else // use FSPI port
 | ||||
|       #define DMA_CHANNEL 1 | ||||
|       spi_host_device_t spi_host = (spi_host_device_t) DMA_CHANNEL; // Draws once then freezes
 | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   // Volatile for register reads:
 | ||||
|   volatile uint32_t* _spi_cmd       = (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT)); | ||||
|   volatile uint32_t* _spi_user      = (volatile uint32_t*)(SPI_USER_REG(SPI_PORT)); | ||||
|   // Register writes only:
 | ||||
|   volatile uint32_t* _spi_mosi_dlen = (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT)); | ||||
|   volatile uint32_t* _spi_w         = (volatile uint32_t*)(SPI_W0_REG(SPI_PORT)); | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           beginSDA | ||||
| ** Description:             Detach SPI from pin to permit software SPI | ||||
| ** Function name:           beginSDA - VSPI port only, FPSI port only for S2 | ||||
| ** Description:             Detach MOSI and attach MISO to SDA for reads | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::begin_SDA_Read(void) | ||||
| { | ||||
|   pinMatrixOutDetach(TFT_MOSI, false, false); | ||||
|   pinMode(TFT_MOSI, INPUT); | ||||
|   pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false); | ||||
|   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_INPUT); | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false); | ||||
|   #else // S2
 | ||||
|     pinMatrixInAttach(TFT_MOSI, FSPIQ_IN_IDX, false); | ||||
|   #endif | ||||
|   SET_BUS_READ_MODE; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           endSDA | ||||
| ** Description:             Attach SPI pins after software SPI | ||||
| ** Function name:           endSDA - VSPI port only, FPSI port only for S2 | ||||
| ** Description:             Attach MOSI to SDA and detach MISO for writes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::end_SDA_Read(void) | ||||
| { | ||||
|   pinMode(TFT_MOSI, OUTPUT); | ||||
|   pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false); | ||||
|   pinMode(TFT_MISO, INPUT); | ||||
|   pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false); | ||||
|   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_OUTPUT); | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false); | ||||
|   #else // S2
 | ||||
|     pinMatrixOutAttach(TFT_MOSI, FSPID_OUT_IDX, false, false); | ||||
|   #endif | ||||
|   SET_BUS_WRITE_MODE; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // #if defined (TFT_SDA_READ)
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -87,17 +139,7 @@ uint8_t TFT_eSPI::readByte(void) | |||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) | ||||
| { | ||||
|   gpioMode(TFT_D0, mode); | ||||
|   gpioMode(TFT_D1, mode); | ||||
|   gpioMode(TFT_D2, mode); | ||||
|   gpioMode(TFT_D3, mode); | ||||
|   gpioMode(TFT_D4, mode); | ||||
|   gpioMode(TFT_D5, mode); | ||||
|   gpioMode(TFT_D6, mode); | ||||
|   gpioMode(TFT_D7, mode); | ||||
|   return; | ||||
|   /*
 | ||||
|   // Arduino generic native function, but slower
 | ||||
|   // Arduino generic native function
 | ||||
|   pinMode(TFT_D0, mode); | ||||
|   pinMode(TFT_D1, mode); | ||||
|   pinMode(TFT_D2, mode); | ||||
|  | @ -106,7 +148,6 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) | |||
|   pinMode(TFT_D5, mode); | ||||
|   pinMode(TFT_D6, mode); | ||||
|   pinMode(TFT_D7, mode); | ||||
|   return; //*/
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -115,14 +156,8 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) | |||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode) | ||||
| { | ||||
|   if(mode == INPUT) GPIO.enable_w1tc = ((uint32_t)1 << gpio); | ||||
|   else GPIO.enable_w1ts = ((uint32_t)1 << gpio); | ||||
| 
 | ||||
|   ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[gpio].reg) // Register lookup
 | ||||
|     = ((uint32_t)2 << FUN_DRV_S)                        // Set drive strength 2
 | ||||
|     | (FUN_IE)                                          // Input enable
 | ||||
|     | ((uint32_t)2 << MCU_SEL_S);                       // Function select 2
 | ||||
|   GPIO.pin[gpio].val = 1;                               // Set pin HIGH
 | ||||
|   pinMode(gpio, mode); | ||||
|   digitalWrite(gpio, HIGH); | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // #ifdef TFT_PARALLEL_8_BIT
 | ||||
|  | @ -162,54 +197,96 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) | |||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif !defined (ILI9488_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most displays
 | ||||
| #elif !defined (SPI_18BIT_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most SPI displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| /*
 | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
|    | ||||
|   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); | ||||
| 
 | ||||
|   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); | ||||
|   bool empty = true; | ||||
|   volatile uint32_t* spi_w = (volatile uint32_t*)_spi_w; | ||||
|   if (len > 31) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); | ||||
|     *_spi_mosi_dlen =  511; | ||||
|     spi_w[0]  = color32; | ||||
|     spi_w[1]  = color32; | ||||
|     spi_w[2]  = color32; | ||||
|     spi_w[3]  = color32; | ||||
|     spi_w[4]  = color32; | ||||
|     spi_w[5]  = color32; | ||||
|     spi_w[6]  = color32; | ||||
|     spi_w[7]  = color32; | ||||
|     spi_w[8]  = color32; | ||||
|     spi_w[9]  = color32; | ||||
|     spi_w[10] = color32; | ||||
|     spi_w[11] = color32; | ||||
|     spi_w[12] = color32; | ||||
|     spi_w[13] = color32; | ||||
|     spi_w[14] = color32; | ||||
|     spi_w[15] = color32; | ||||
|     while(len>31) | ||||
|     { | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color32); | ||||
|       WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color32); | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|       while ((*_spi_cmd)&SPI_USR); | ||||
|       *_spi_cmd = SPI_USR; | ||||
|       len -= 32; | ||||
|     } | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     empty = false; | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1); | ||||
|     for (uint32_t i=0; i <= (len<<1); i+=4) WRITE_PERI_REG(SPI_W0_REG(SPI_PORT) + i, color32); | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     if(empty) { | ||||
|       for (uint32_t i=0; i <= len; i+=2) *spi_w++ = color32; | ||||
|     } | ||||
|     len = (len << 4) - 1; | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
|     *_spi_mosi_dlen = len; | ||||
|     *_spi_cmd = SPI_USR; | ||||
|   } | ||||
|   while ((*_spi_cmd)&SPI_USR); // Move to later in code to use transmit time usefully?
 | ||||
| } | ||||
| //*/
 | ||||
| //*
 | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
| 
 | ||||
|   volatile uint32_t* spi_w = _spi_w; | ||||
|   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); | ||||
|   uint32_t i = 0; | ||||
|   uint32_t rem = len & 0x1F; | ||||
|   len =  len - rem; | ||||
| 
 | ||||
|   // Start with partial buffer pixels
 | ||||
|   if (rem) | ||||
|   { | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
|     for (i=0; i < rem; i+=2) *spi_w++ = color32; | ||||
|     *_spi_mosi_dlen = (rem << 4) - 1; | ||||
|     *_spi_cmd = SPI_USR; | ||||
|     if (!len) return; //{while (*_spi_cmd&SPI_USR); return; }
 | ||||
|     i = i>>1; while(i++<16) *spi_w++ = color32; | ||||
|   } | ||||
| 
 | ||||
|   while (*_spi_cmd&SPI_USR); | ||||
|   if (!rem) while (i++<16) *spi_w++ = color32; | ||||
|   *_spi_mosi_dlen =  511; | ||||
| 
 | ||||
|   // End with full buffer to maximise useful time for downstream code
 | ||||
|   while(len) | ||||
|   { | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
|     *_spi_cmd = SPI_USR; | ||||
|     len -= 32; | ||||
|   } | ||||
| 
 | ||||
|   // Do not wait here
 | ||||
|   //while (*_spi_cmd&SPI_USR);
 | ||||
| } | ||||
| //*/
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushSwapBytePixels - for ESP32 | ||||
| ** Description:             Write a sequence of pixels with swapped bytes | ||||
|  | @ -231,7 +308,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | |||
|         data+=4; | ||||
|       } | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]);  | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]); | ||||
|  | @ -262,7 +339,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | |||
|     } | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 255); | ||||
|     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]);  | ||||
|     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]); | ||||
|     WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]); | ||||
|     WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]); | ||||
|     WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]); | ||||
|  | @ -338,7 +415,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | |||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9488_DRIVER) && !defined (TFT_PARALLEL_8_BIT)// Now code for ILI9488
 | ||||
| #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -443,10 +520,22 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | |||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
|   #if defined (SSD1963_DRIVER) | ||||
|   if ( ((color & 0xF800)>> 8) == ((color & 0x07E0)>> 3) && ((color & 0xF800)>> 8)== ((color & 0x001F)<< 3) ) | ||||
|   #else | ||||
|   if ( (color >> 8) == (color & 0x00FF) ) | ||||
|   #endif | ||||
|   { if (!len) return; | ||||
|     tft_Write_16(color); | ||||
|     while (--len) {WR_L; WR_H; WR_L; WR_H;} | ||||
|   #if defined (SSD1963_DRIVER) | ||||
|     while (--len) {WR_L; WR_H; WR_L; WR_H; WR_L; WR_H;} | ||||
|   #else | ||||
|     #ifdef PSEUDO_16_BIT | ||||
|       while (--len) {WR_L; WR_H;} | ||||
|     #else | ||||
|       while (--len) {WR_L; WR_H; WR_L; WR_H;} | ||||
|     #endif | ||||
|   #endif | ||||
|   } | ||||
|   else while (len--) {tft_Write_16(color);} | ||||
| } | ||||
|  | @ -475,3 +564,270 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | |||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of display interface specific functions
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (ESP32_DMA) && !defined (TFT_PARALLEL_8_BIT) //       DMA FUNCTIONS
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaBusy | ||||
| ** Description:             Check if DMA is busy | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::dmaBusy(void) | ||||
| { | ||||
|   if (!DMA_Enabled || !spiBusyCheck) return false; | ||||
| 
 | ||||
|   spi_transaction_t *rtrans; | ||||
|   esp_err_t ret; | ||||
|   uint8_t checks = spiBusyCheck; | ||||
|   for (int i = 0; i < checks; ++i) | ||||
|   { | ||||
|     ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0); | ||||
|     if (ret == ESP_OK) spiBusyCheck--; | ||||
|   } | ||||
| 
 | ||||
|   //Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck);
 | ||||
|   if (spiBusyCheck ==0) return false; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaWait | ||||
| ** Description:             Wait until DMA is over (blocking!) | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::dmaWait(void) | ||||
| { | ||||
|   if (!DMA_Enabled || !spiBusyCheck) return; | ||||
|   spi_transaction_t *rtrans; | ||||
|   esp_err_t ret; | ||||
|   for (int i = 0; i < spiBusyCheck; ++i) | ||||
|   { | ||||
|     ret = spi_device_get_trans_result(dmaHAL, &rtrans, portMAX_DELAY); | ||||
|     assert(ret == ESP_OK); | ||||
|   } | ||||
|   spiBusyCheck = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixelsDMA | ||||
| ** Description:             Push pixels to TFT (len must be less than 32767) | ||||
| ***************************************************************************************/ | ||||
| // This will byte swap the original image if setSwapBytes(true) was called by sketch.
 | ||||
| void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) | ||||
| { | ||||
|   if ((len == 0) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   dmaWait(); | ||||
| 
 | ||||
|   if(_swapBytes) { | ||||
|     for (uint32_t i = 0; i < len; i++) (image[i] = image[i] << 8 | image[i] >> 8); | ||||
|   } | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = image;  //finally send the line data
 | ||||
|   trans.length = len * 16;        //Data length, in bits
 | ||||
|   trans.flags = 0;                //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Description:             Push image to a window (w*h must be less than 65536) | ||||
| ***************************************************************************************/ | ||||
| // Fixed const data assumed, will NOT clip or swap bytes
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* image) | ||||
| { | ||||
|   if ((w == 0) || (h == 0) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   uint32_t len = w*h; | ||||
| 
 | ||||
|   dmaWait(); | ||||
| 
 | ||||
|   setAddrWindow(x, y, w, h); | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = image;   //Data pointer
 | ||||
|   trans.length = len * 16;   //Data length, in bits
 | ||||
|   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Description:             Push image to a window (w*h must be less than 65536) | ||||
| ***************************************************************************************/ | ||||
| // This will clip and also swap bytes if setSwapBytes(true) was called by sketch
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer) | ||||
| { | ||||
|   if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   int32_t dx = 0; | ||||
|   int32_t dy = 0; | ||||
|   int32_t dw = w; | ||||
|   int32_t dh = h; | ||||
| 
 | ||||
|   if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } | ||||
|   if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } | ||||
| 
 | ||||
|   if ((x + dw) > _vpW ) dw = _vpW - x; | ||||
|   if ((y + dh) > _vpH ) dh = _vpH - y; | ||||
| 
 | ||||
|   if (dw < 1 || dh < 1) return; | ||||
| 
 | ||||
|   uint32_t len = dw*dh; | ||||
| 
 | ||||
|   if (buffer == nullptr) { | ||||
|     buffer = image; | ||||
|     dmaWait(); | ||||
|   } | ||||
| 
 | ||||
|   // If image is clipped, copy pixels into a contiguous block
 | ||||
|   if ( (dw != w) || (dh != h) ) { | ||||
|     if(_swapBytes) { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         for (int32_t xb = 0; xb < dw; xb++) { | ||||
|           uint32_t src = xb + dx + w * (yb + dy); | ||||
|           (buffer[xb + yb * dw] = image[src] << 8 | image[src] >> 8); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         memcpy((uint8_t*) (buffer + yb * dw), (uint8_t*) (image + dx + w * (yb + dy)), dw << 1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   // else, if a buffer pointer has been provided copy whole image to the buffer
 | ||||
|   else if (buffer != image || _swapBytes) { | ||||
|     if(_swapBytes) { | ||||
|       for (uint32_t i = 0; i < len; i++) (buffer[i] = image[i] << 8 | image[i] >> 8); | ||||
|     } | ||||
|     else { | ||||
|       memcpy(buffer, image, len*2); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (spiBusyCheck) dmaWait(); // In case we did not wait earlier
 | ||||
| 
 | ||||
|   setAddrWindow(x, y, dw, dh); | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = buffer;  //finally send the line data
 | ||||
|   trans.length = len * 16;   //Data length, in bits
 | ||||
|   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Processor specific DMA initialisation
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // The DMA functions here work with SPI only (not parallel)
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dc_callback | ||||
| ** Description:             Toggles DC line during transaction | ||||
| ***************************************************************************************/ | ||||
| extern "C" void dc_callback(); | ||||
| 
 | ||||
| void IRAM_ATTR dc_callback(spi_transaction_t *spi_tx) | ||||
| { | ||||
|   if ((bool)spi_tx->user) {DC_D;} | ||||
|   else {DC_C;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           initDMA | ||||
| ** Description:             Initialise the DMA engine - returns true if init OK | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::initDMA(bool ctrl_cs) | ||||
| { | ||||
|   if (DMA_Enabled) return false; | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   spi_bus_config_t buscfg = { | ||||
|     .mosi_io_num = TFT_MOSI, | ||||
|     .miso_io_num = TFT_MISO, | ||||
|     .sclk_io_num = TFT_SCLK, | ||||
|     .quadwp_io_num = -1, | ||||
|     .quadhd_io_num = -1, | ||||
|     .max_transfer_sz = TFT_WIDTH * TFT_HEIGHT * 2 + 8, // TFT screen size
 | ||||
|     .flags = 0, | ||||
|     .intr_flags = 0 | ||||
|   }; | ||||
| 
 | ||||
|   int8_t pin = -1; | ||||
|   if (ctrl_cs) pin = TFT_CS; | ||||
| 
 | ||||
|   spi_device_interface_config_t devcfg = { | ||||
|     .command_bits = 0, | ||||
|     .address_bits = 0, | ||||
|     .dummy_bits = 0, | ||||
|     .mode = TFT_SPI_MODE, | ||||
|     .duty_cycle_pos = 0, | ||||
|     .cs_ena_pretrans = 0, | ||||
|     .cs_ena_posttrans = 0, | ||||
|     .clock_speed_hz = SPI_FREQUENCY, | ||||
|     .input_delay_ns = 0, | ||||
|     .spics_io_num = pin, | ||||
|     .flags = SPI_DEVICE_NO_DUMMY, //0,
 | ||||
|     .queue_size = 1, | ||||
|     .pre_cb = 0, //dc_callback, //Callback to handle D/C line
 | ||||
|     .post_cb = 0 | ||||
|   }; | ||||
|   ret = spi_bus_initialize(spi_host, &buscfg, DMA_CHANNEL); | ||||
|   ESP_ERROR_CHECK(ret); | ||||
|   ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL); | ||||
|   ESP_ERROR_CHECK(ret); | ||||
| 
 | ||||
|   DMA_Enabled = true; | ||||
|   spiBusyCheck = 0; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           deInitDMA | ||||
| ** Description:             Disconnect the DMA engine from SPI | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::deInitDMA(void) | ||||
| { | ||||
|   if (!DMA_Enabled) return; | ||||
|   spi_bus_remove_device(dmaHAL); | ||||
|   spi_bus_free(spi_host); | ||||
|   DMA_Enabled = false; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of DMA FUNCTIONS
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  |  | |||
|  | @ -10,24 +10,71 @@ | |||
| 
 | ||||
| // Include processor specific header
 | ||||
| #include "soc/spi_reg.h" | ||||
| #include "driver/spi_master.h" | ||||
| 
 | ||||
| // Processor specific code used by SPI bus transaction startWrite and endWrite functions
 | ||||
| #define SET_BUS_WRITE_MODE // Not used
 | ||||
| #define SET_BUS_READ_MODE  // Not used
 | ||||
| #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32) | ||||
|   #define CONFIG_IDF_TARGET_ESP32 | ||||
| #endif | ||||
| 
 | ||||
| // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
 | ||||
| #define DMA_BUSY_CHECK // DMA not implemented for this processor (yet)
 | ||||
| // Fix IDF problems with ESP32C3
 | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|   // Fix ESP32C3 IDF bug for missing definition
 | ||||
|   #ifndef REG_SPI_BASE | ||||
|     #define REG_SPI_BASE(i)     (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 ))) | ||||
|   #endif | ||||
| 
 | ||||
|   // Fix ESP32C3 IDF bug for name change
 | ||||
|   #ifndef SPI_MOSI_DLEN_REG | ||||
|     #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) | ||||
|   #endif | ||||
| 
 | ||||
|   // Fix ESP32C3 specific register reference
 | ||||
|   #define out_w1tc out_w1tc.val | ||||
|   #define out_w1ts out_w1ts.val | ||||
| #endif | ||||
| 
 | ||||
| // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled
 | ||||
| #if !defined (SUPPORT_TRANSACTIONS) | ||||
|   #define SUPPORT_TRANSACTIONS | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
| ESP32: | ||||
| FSPI not defined | ||||
| HSPI = 2, uses SPI2 | ||||
| VSPI = 3, uses SPI3 | ||||
| 
 | ||||
| ESP32-S2: | ||||
| FSPI = 1, uses SPI2 | ||||
| HSPI = 2, uses SPI3 | ||||
| VSPI not defined | ||||
| 
 | ||||
| ESP32 C3: | ||||
| FSPI = 0, uses SPI2 ???? To be checked | ||||
| HSPI = 1, uses SPI3 ???? To be checked | ||||
| VSPI not defined | ||||
| 
 | ||||
| For ESP32/S2/C3: | ||||
| SPI1_HOST = 0 | ||||
| SPI2_HOST = 1 | ||||
| SPI3_HOST = 2 | ||||
| */ | ||||
| 
 | ||||
| // ESP32 specific SPI port selection
 | ||||
| #ifdef USE_HSPI_PORT | ||||
|   #define SPI_PORT HSPI | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #define SPI_PORT HSPI  //HSPI is port 2 on ESP32
 | ||||
|   #else | ||||
|     #define SPI_PORT 3     //HSPI is port 3 on ESP32 S2
 | ||||
|   #endif | ||||
| #elif defined(USE_FSPI_PORT) | ||||
|     #define SPI_PORT 2 //FSPI(ESP32 S2)
 | ||||
| #else | ||||
|   #define SPI_PORT VSPI | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #define SPI_PORT VSPI | ||||
|   #else | ||||
|     #define SPI_PORT 2 //FSPI(ESP32 S2)
 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef RPI_DISPLAY_TYPE | ||||
|  | @ -41,9 +88,47 @@ | |||
| 
 | ||||
| // Define a generic flag for 8 bit parallel
 | ||||
| #if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility
 | ||||
|   #define TFT_PARALLEL_8_BIT // Generic parallel flag
 | ||||
|   #if !defined (TFT_PARALLEL_8_BIT) | ||||
|     #define TFT_PARALLEL_8_BIT // Generic parallel flag
 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Ensure ESP32 specific flag is defined for 8 bit parallel
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
|   #if !defined (ESP32_PARALLEL) | ||||
|     #define ESP32_PARALLEL | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Processor specific code used by SPI bus transaction startWrite and endWrite functions
 | ||||
| #if !defined (ESP32_PARALLEL) | ||||
|   #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) | ||||
|     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE | ||||
|     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE | ||||
|   #else | ||||
|     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | ||||
|     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | ||||
|   #endif | ||||
| #else | ||||
|     // Not applicable to parallel bus
 | ||||
|     #define SET_BUS_WRITE_MODE | ||||
|     #define SET_BUS_READ_MODE | ||||
| #endif | ||||
| 
 | ||||
| // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
 | ||||
| #if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER) | ||||
|   #define ESP32_DMA | ||||
|   // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
 | ||||
|   #define DMA_BUSY_CHECK  dmaWait() | ||||
| #else | ||||
|   #define DMA_BUSY_CHECK | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TFT_PARALLEL_8_BIT) | ||||
|   #define SPI_BUSY_CHECK | ||||
| #else | ||||
|   #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR) | ||||
| #endif | ||||
| 
 | ||||
| // If smooth font is used then it is likely SPIFFS will be needed
 | ||||
| #ifdef SMOOTH_FONT | ||||
|  | @ -54,6 +139,7 @@ | |||
|   #define FONT_FS_AVAILABLE | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the DC (TFT Data/Command or Register Select (RS))pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -62,10 +148,19 @@ | |||
|   #define DC_D // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if defined (TFT_PARALLEL_8_BIT) | ||||
|     #define DC_C GPIO.out_w1tc = (1 << TFT_DC) | ||||
|     #define DC_D GPIO.out_w1ts = (1 << TFT_DC) | ||||
|     // TFT_DC, by design, must be in range 0-31 for single register parallel write
 | ||||
|     #if (TFT_DC >= 0) &&  (TFT_DC < 32) | ||||
|       #define DC_C GPIO.out_w1tc = (1 << TFT_DC) | ||||
|       #define DC_D GPIO.out_w1ts = (1 << TFT_DC) | ||||
|     #elif (TFT_DC >= 32) | ||||
|       #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC- 32)) | ||||
|       #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC- 32)) | ||||
|     #else | ||||
|       #define DC_C | ||||
|       #define DC_D | ||||
|     #endif | ||||
|   #else | ||||
|     #if TFT_DC >= 32 | ||||
|     #if (TFT_DC >= 32) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi displays need a slower DC change
 | ||||
|         #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ | ||||
|                      GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) | ||||
|  | @ -75,16 +170,20 @@ | |||
|         #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))
 | ||||
|         #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))
 | ||||
|       #endif | ||||
|     #elif TFT_DC >= 0 | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi ILI9486 display needs a slower DC change
 | ||||
|         #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                      GPIO.out_w1tc = (1 << TFT_DC) | ||||
|         #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                      GPIO.out_w1ts = (1 << TFT_DC) | ||||
|       #elif defined (RPI_DISPLAY_TYPE)  // Other RPi displays need a slower C->D change
 | ||||
|         #define DC_C GPIO.out_w1tc = (1 << TFT_DC) | ||||
|         #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                      GPIO.out_w1ts = (1 << TFT_DC) | ||||
|     #elif (TFT_DC >= 0) | ||||
|       #if defined (RPI_DISPLAY_TYPE) | ||||
|         #if defined (ILI9486_DRIVER) | ||||
|           // RPi ILI9486 display needs a slower DC change
 | ||||
|           #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1tc = (1 << TFT_DC) | ||||
|           #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1ts = (1 << TFT_DC) | ||||
|         #else | ||||
|           // Other RPi displays need a slower C->D change
 | ||||
|           #define DC_C GPIO.out_w1tc = (1 << TFT_DC) | ||||
|           #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1ts = (1 << TFT_DC) | ||||
|         #endif | ||||
|       #else | ||||
|         #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC)
 | ||||
|         #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC)
 | ||||
|  | @ -100,8 +199,9 @@ | |||
| // Define the CS (TFT chip select) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_CS | ||||
|   #define CS_L // No macro allocated so it generates no code
 | ||||
|   #define CS_H // No macro allocated so it generates no code
 | ||||
|   #define TFT_CS -1  // Keep DMA code happy
 | ||||
|   #define CS_L       // No macro allocated so it generates no code
 | ||||
|   #define CS_H       // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if defined (TFT_PARALLEL_8_BIT) | ||||
|     #if TFT_CS >= 32 | ||||
|  | @ -115,8 +215,8 @@ | |||
|       #define CS_H | ||||
|     #endif | ||||
|   #else | ||||
|     #if TFT_CS >= 32 | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi ILI9486 display needs a slower CS change
 | ||||
|     #if (TFT_CS >= 32) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
 | ||||
|         #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ | ||||
|                      GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ | ||||
|  | @ -125,12 +225,12 @@ | |||
|         #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))
 | ||||
|       #endif | ||||
|     #elif TFT_CS >= 0 | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi ILI9486 display needs a slower CS change
 | ||||
|     #elif (TFT_CS >= 0) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
 | ||||
|         #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) | ||||
|       #else | ||||
|         #define CS_L GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) | ||||
|         #define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS)
 | ||||
|       #endif | ||||
|     #else | ||||
|  | @ -143,9 +243,22 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the WR (TFT Write) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifdef TFT_WR | ||||
|   #define WR_L GPIO.out_w1tc = (1 << TFT_WR) | ||||
|   #define WR_H GPIO.out_w1ts = (1 << TFT_WR) | ||||
| #if defined (TFT_WR) | ||||
|   #if (TFT_WR >= 32) | ||||
|     // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32
 | ||||
|     #define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32)) | ||||
|     #define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32)) | ||||
|   #elif (TFT_WR >= 0) | ||||
|     // TFT_WR, for best performance, should be in range 0-31 for single register parallel write
 | ||||
|     #define WR_L GPIO.out_w1tc = (1 << TFT_WR) | ||||
|     #define WR_H GPIO.out_w1ts = (1 << TFT_WR) | ||||
|   #else | ||||
|     #define WR_L | ||||
|     #define WR_H | ||||
|   #endif | ||||
| #else | ||||
|   #define WR_L | ||||
|   #define WR_H | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -160,12 +273,63 @@ | |||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Make sure TFT_MISO is defined if not used to avoid an error message
 | ||||
| // Make sure SPI default pins are assigned if not specified by user or set to -1
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   #ifndef TFT_MISO | ||||
|     #define TFT_MISO -1 | ||||
| 
 | ||||
|   #ifdef USE_HSPI_PORT | ||||
| 
 | ||||
|     #ifndef TFT_MISO | ||||
|       #define TFT_MISO -1 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_MOSI | ||||
|       #define TFT_MOSI 13 | ||||
|     #endif | ||||
|     #if (TFT_MOSI == -1) | ||||
|       #undef TFT_MOSI | ||||
|       #define TFT_MOSI 13 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_SCLK | ||||
|       #define TFT_SCLK 14 | ||||
|     #endif | ||||
|     #if (TFT_SCLK == -1) | ||||
|       #undef TFT_SCLK | ||||
|       #define TFT_SCLK 14 | ||||
|     #endif | ||||
| 
 | ||||
|   #else // VSPI port
 | ||||
| 
 | ||||
|     #ifndef TFT_MISO | ||||
|       #define TFT_MISO -1 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_MOSI | ||||
|       #define TFT_MOSI 23 | ||||
|     #endif | ||||
|     #if (TFT_MOSI == -1) | ||||
|       #undef TFT_MOSI | ||||
|       #define TFT_MOSI 23 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_SCLK | ||||
|       #define TFT_SCLK 18 | ||||
|     #endif | ||||
|     #if (TFT_SCLK == -1) | ||||
|       #undef TFT_SCLK | ||||
|       #define TFT_SCLK 18 | ||||
|     #endif | ||||
| 
 | ||||
|     #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) | ||||
|       #if (TFT_MISO == -1) | ||||
|         #undef TFT_MISO | ||||
|         #define TFT_MISO TFT_MOSI | ||||
|       #endif | ||||
|     #endif | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -175,7 +339,7 @@ | |||
| 
 | ||||
|   // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically
 | ||||
|   // can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF
 | ||||
|   #define CONSTRUCTOR_INIT_TFT_DATA_BUS            \ | ||||
|   #define PARALLEL_INIT_TFT_DATA_BUS               \ | ||||
|   for (int32_t c = 0; c<256; c++)                  \ | ||||
|   {                                                \ | ||||
|     xset_mask[c] = 0;                              \ | ||||
|  | @ -190,10 +354,17 @@ | |||
|   }                                                \ | ||||
| 
 | ||||
|   // Mask for the 8 data bits to set pin directions
 | ||||
|   #define dir_mask ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) | ||||
|   #define GPIO_DIR_MASK ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) | ||||
| 
 | ||||
|   // Data bits and the write line are cleared to 0 in one step
 | ||||
|   #define clr_mask (dir_mask | (1 << TFT_WR)) | ||||
|   #if (TFT_WR >= 32) | ||||
|     // Data bits and the write line are cleared sequentially
 | ||||
|     #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L | ||||
|   #elif (TFT_WR >= 0) | ||||
|     // Data bits and the write line are cleared to 0 in one step (1.25x faster)
 | ||||
|     #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) | ||||
|   #else | ||||
|     #define GPIO_OUT_CLR_MASK | ||||
|   #endif | ||||
| 
 | ||||
|   // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM
 | ||||
|   #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time
 | ||||
|  | @ -204,46 +375,78 @@ | |||
|   //*/
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)  GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C)); WR_H | ||||
|   #define tft_Write_8(C)  GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t)(C)); WR_H | ||||
| 
 | ||||
|   // Write 16 bits to TFT
 | ||||
|   #define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); WR_H; \ | ||||
|                           GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); WR_H | ||||
|   #if defined (SSD1963_DRIVER) | ||||
| 
 | ||||
|   // 16 bit write with swapped bytes
 | ||||
|   #define tft_Write_16S(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                            GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H | ||||
|     // Write 18 bit color to TFT
 | ||||
|     #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0xF800)>> 8)); WR_H; \ | ||||
|                             GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \ | ||||
|                             GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H | ||||
| 
 | ||||
|     // 18 bit color write with swapped bytes
 | ||||
|     #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) | ||||
| 
 | ||||
|   #else | ||||
| 
 | ||||
|     #ifdef PSEUDO_16_BIT | ||||
|       // One write strobe for both bytes
 | ||||
|       #define tft_Write_16(C)  GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
|       #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H | ||||
|     #else | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                               GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                                GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H | ||||
|     #endif | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
|   // Write 32 bits to TFT
 | ||||
|   #define tft_Write_32(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 24)); WR_H; \ | ||||
|                           GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 16)); WR_H; \ | ||||
|                           GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >>  8)); WR_H; \ | ||||
|                           GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >>  0)); WR_H | ||||
|   #define tft_Write_32(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 24)); WR_H; \ | ||||
|                           GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 16)); WR_H; \ | ||||
|                           GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >>  8)); WR_H; \ | ||||
|                           GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >>  0)); WR_H | ||||
| 
 | ||||
|   // Write two concatenated 16 bit values to TFT
 | ||||
|   #define tft_Write_32C(C,D) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                              GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                              GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 8)); WR_H; \ | ||||
|                              GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 0)); WR_H | ||||
|   #define tft_Write_32C(C,D) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                              GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                              GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 8)); WR_H; \ | ||||
|                              GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 0)); WR_H | ||||
| 
 | ||||
|   // Write 16 bit value twice to TFT - used by drawPixel()
 | ||||
|   #define tft_Write_32D(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                            GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
|   #define tft_Write_32D(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                            GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
| 
 | ||||
|    // Read pin
 | ||||
|   #ifdef TFT_RD | ||||
|     #define RD_L GPIO.out_w1tc = (1 << TFT_RD) | ||||
|     //#define RD_L digitalWrite(TFT_WR, LOW)
 | ||||
|     #define RD_H GPIO.out_w1ts = (1 << TFT_RD) | ||||
|     //#define RD_H digitalWrite(TFT_WR, HIGH)
 | ||||
|     #if (TFT_RD >= 32) | ||||
|       #define RD_L GPIO.out1_w1tc.val = (1 << (TFT_RD - 32)) | ||||
|       #define RD_H GPIO.out1_w1ts.val = (1 << (TFT_RD - 32)) | ||||
|     #elif (TFT_RD >= 0) | ||||
|       #define RD_L GPIO.out_w1tc = (1 << TFT_RD) | ||||
|       //#define RD_L digitalWrite(TFT_WR, LOW)
 | ||||
|       #define RD_H GPIO.out_w1ts = (1 << TFT_RD) | ||||
|       //#define RD_H digitalWrite(TFT_WR, HIGH)
 | ||||
|     #else | ||||
|       #define RD_L | ||||
|       #define RD_H | ||||
|     #endif | ||||
|   #else | ||||
|     #define TFT_RD -1 | ||||
|     #define RD_L | ||||
|     #define RD_H | ||||
|   #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to an ILI9488 TFT
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI948x TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif  defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
 | ||||
| #elif  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)   spi.transfer(C) | ||||
|  | @ -253,6 +456,9 @@ | |||
|                            spi.transfer(((C) & 0x07E0)>>3); \ | ||||
|                            spi.transfer(((C) & 0x001F)<<3) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #define tft_Write_16N(C) tft_Write_16(C) | ||||
| 
 | ||||
|   // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|   #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ | ||||
|                            spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ | ||||
|  | @ -283,9 +489,12 @@ | |||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianess for 16 bit colours
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #define tft_Write_16N(C) tft_Write_16(C) | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|  | @ -303,7 +512,7 @@ | |||
| // Macros for all other SPI displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #else | ||||
| 
 | ||||
| /* Old macros
 | ||||
|   // ESP32 low level SPI writes for 8, 16 and 32 bit values
 | ||||
|   // to avoid the function call overhead
 | ||||
|   #define TFT_WRITE_BITS(D, B) \ | ||||
|  | @ -315,7 +524,7 @@ | |||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianess for 16 bit colours
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|  | @ -324,12 +533,46 @@ | |||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| //*/
 | ||||
| //* Replacement slimmer macros
 | ||||
|   #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;    \ | ||||
|                                *_spi_w = D;             \ | ||||
|                                *_spi_cmd = SPI_USR;      \ | ||||
|                         while (*_spi_cmd & SPI_USR); | ||||
| 
 | ||||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1;       \ | ||||
|                            *_spi_w = ((C)<<8 | (C)>>8); \ | ||||
|                            *_spi_cmd = SPI_USR; | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D)  TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
| //*/
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef tft_Write_16N | ||||
|   #define tft_Write_16N tft_Write_16 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  |  | |||
|  | @ -0,0 +1,857 @@ | |||
|         ////////////////////////////////////////////////////
 | ||||
|         // TFT_eSPI driver functions for ESP32 processors //
 | ||||
|         ////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Temporarily a separate file to TFT_eSPI_ESP32.c until board package low level API stabilises
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Global variables
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Select the SPI port to use, ESP32 has 2 options
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       SPIClass spi = SPIClass(HSPI); | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       SPIClass spi = SPIClass(FSPI); | ||||
|     #else // use default VSPI port
 | ||||
|       SPIClass spi = SPIClass(VSPI); | ||||
|     #endif | ||||
|   #else | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       SPIClass spi = SPIClass(HSPI); | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       SPIClass spi = SPIClass(FSPI); | ||||
|     #else // use FSPI port
 | ||||
|       SPIClass& spi = SPI; | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef ESP32_DMA | ||||
|   // DMA SPA handle
 | ||||
|   spi_device_handle_t dmaHAL; | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #define DMA_CHANNEL 1 | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       spi_host_device_t spi_host = HSPI_HOST; | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       spi_host_device_t spi_host = SPI_HOST; | ||||
|     #else // use VSPI port
 | ||||
|       spi_host_device_t spi_host = VSPI_HOST; | ||||
|     #endif | ||||
|   #else | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       #define DMA_CHANNEL 2 | ||||
|       spi_host_device_t spi_host = (spi_host_device_t) DMA_CHANNEL; // Draws once then freezes
 | ||||
|     #else // use FSPI port
 | ||||
|       #define DMA_CHANNEL 1 | ||||
|       spi_host_device_t spi_host = (spi_host_device_t) DMA_CHANNEL; // Draws once then freezes
 | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   // Volatile for register reads:
 | ||||
|   volatile uint32_t* _spi_cmd       = (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT)); | ||||
|   volatile uint32_t* _spi_user      = (volatile uint32_t*)(SPI_USER_REG(SPI_PORT)); | ||||
|   // Register writes only:
 | ||||
|   volatile uint32_t* _spi_mosi_dlen = (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT)); | ||||
|   volatile uint32_t* _spi_w         = (volatile uint32_t*)(SPI_W0_REG(SPI_PORT)); | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           beginSDA - FPSI port only | ||||
| ** Description:             Detach MOSI and attach MISO to SDA for reads | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::begin_SDA_Read(void) | ||||
| { | ||||
|   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_INPUT); | ||||
|   pinMatrixInAttach(TFT_MOSI, FSPIQ_IN_IDX, false); | ||||
|   SET_BUS_READ_MODE; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           endSDA - FPSI port only | ||||
| ** Description:             Attach MOSI to SDA and detach MISO for writes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::end_SDA_Read(void) | ||||
| { | ||||
|   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_OUTPUT); | ||||
|   pinMatrixOutAttach(TFT_MOSI, FSPID_OUT_IDX, false, false); | ||||
|   SET_BUS_WRITE_MODE; | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // #if defined (TFT_SDA_READ)
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           read byte  - supports class functions | ||||
| ** Description:             Read a byte from ESP32 8 bit data port | ||||
| ***************************************************************************************/ | ||||
| // Parallel bus MUST be set to input before calling this function!
 | ||||
| uint8_t TFT_eSPI::readByte(void) | ||||
| { | ||||
|   uint8_t b = 0xAA; | ||||
| 
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
|   RD_L; | ||||
|   uint32_t reg;           // Read all GPIO pins 0-31
 | ||||
|   reg = gpio_input_get(); // Read three times to allow for bus access time
 | ||||
|   reg = gpio_input_get(); | ||||
|   reg = gpio_input_get(); // Data should be stable now
 | ||||
|   RD_H; | ||||
| 
 | ||||
|   // Check GPIO bits used and build value
 | ||||
|   b  = (((reg>>TFT_D0)&1) << 0); | ||||
|   b |= (((reg>>TFT_D1)&1) << 1); | ||||
|   b |= (((reg>>TFT_D2)&1) << 2); | ||||
|   b |= (((reg>>TFT_D3)&1) << 3); | ||||
|   b |= (((reg>>TFT_D4)&1) << 4); | ||||
|   b |= (((reg>>TFT_D5)&1) << 5); | ||||
|   b |= (((reg>>TFT_D6)&1) << 6); | ||||
|   b |= (((reg>>TFT_D7)&1) << 7); | ||||
| #endif | ||||
| 
 | ||||
|   return b; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifdef TFT_PARALLEL_8_BIT | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           GPIO direction control  - supports class functions | ||||
| ** Description:             Set parallel bus to INPUT or OUTPUT | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) | ||||
| { | ||||
|   // Arduino generic native function
 | ||||
|   pinMode(TFT_D0, mode); | ||||
|   pinMode(TFT_D1, mode); | ||||
|   pinMode(TFT_D2, mode); | ||||
|   pinMode(TFT_D3, mode); | ||||
|   pinMode(TFT_D4, mode); | ||||
|   pinMode(TFT_D5, mode); | ||||
|   pinMode(TFT_D6, mode); | ||||
|   pinMode(TFT_D7, mode); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           GPIO direction control  - supports class functions | ||||
| ** Description:             Set ESP32 GPIO pin to input or output (set high) ASAP | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode) | ||||
| { | ||||
|   pinMode(gpio, mode); | ||||
|   digitalWrite(gpio, HIGH); | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // #ifdef TFT_PARALLEL_8_BIT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (RPI_WRITE_STROBE) && !defined (TFT_PARALLEL_8_BIT) // Code for RPi TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 or ESP8266 RPi TFT | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) | ||||
| { | ||||
|   uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; | ||||
|   if(len) spi.writePattern(&colorBin[0], 2, 1); len--; | ||||
|   while(len--) {WR_L; WR_H;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 or ESP8266 RPi TFT | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) | ||||
| { | ||||
|   uint8_t *data = (uint8_t*)data_in; | ||||
| 
 | ||||
|   if(_swapBytes) { | ||||
|       while ( len-- ) {tft_Write_16(*data); data++;} | ||||
|       return; | ||||
|   } | ||||
| 
 | ||||
|   while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } | ||||
|   if (len) spi.writePattern(data, len, 1); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif !defined (SPI_18BIT_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most SPI displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| /*
 | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
| 
 | ||||
|   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); | ||||
|   bool empty = true; | ||||
|   volatile uint32_t* spi_w = (volatile uint32_t*)_spi_w; | ||||
|   if (len > 31) | ||||
|   { | ||||
|     *_spi_mosi_dlen =  511; | ||||
|     spi_w[0]  = color32; | ||||
|     spi_w[1]  = color32; | ||||
|     spi_w[2]  = color32; | ||||
|     spi_w[3]  = color32; | ||||
|     spi_w[4]  = color32; | ||||
|     spi_w[5]  = color32; | ||||
|     spi_w[6]  = color32; | ||||
|     spi_w[7]  = color32; | ||||
|     spi_w[8]  = color32; | ||||
|     spi_w[9]  = color32; | ||||
|     spi_w[10] = color32; | ||||
|     spi_w[11] = color32; | ||||
|     spi_w[12] = color32; | ||||
|     spi_w[13] = color32; | ||||
|     spi_w[14] = color32; | ||||
|     spi_w[15] = color32; | ||||
|     while(len>31) | ||||
|     { | ||||
|       while ((*_spi_cmd)&SPI_USR); | ||||
|       *_spi_cmd = SPI_USR; | ||||
|       len -= 32; | ||||
|     } | ||||
|     empty = false; | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     if(empty) { | ||||
|       for (uint32_t i=0; i <= len; i+=2) *spi_w++ = color32; | ||||
|     } | ||||
|     len = (len << 4) - 1; | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
|     *_spi_mosi_dlen = len; | ||||
|     *_spi_cmd = SPI_USR; | ||||
|   } | ||||
|   while ((*_spi_cmd)&SPI_USR); // Move to later in code to use transmit time usefully?
 | ||||
| } | ||||
| //*/
 | ||||
| //*
 | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
| 
 | ||||
|   volatile uint32_t* spi_w = _spi_w; | ||||
|   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); | ||||
|   uint32_t i = 0; | ||||
|   uint32_t rem = len & 0x1F; | ||||
|   len =  len - rem; | ||||
| 
 | ||||
|   // Start with partial buffer pixels
 | ||||
|   if (rem) | ||||
|   { | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
|     for (i=0; i < rem; i+=2) *spi_w++ = color32; | ||||
|     *_spi_mosi_dlen = (rem << 4) - 1; | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|     *_spi_cmd = SPI_UPDATE; | ||||
|     while (*_spi_cmd & SPI_UPDATE); | ||||
| #endif | ||||
|     *_spi_cmd = SPI_USR; | ||||
|     if (!len) return; //{while (*_spi_cmd&SPI_USR); return; }
 | ||||
|     i = i>>1; while(i++<16) *spi_w++ = color32; | ||||
|   } | ||||
| 
 | ||||
|   while (*_spi_cmd&SPI_USR); | ||||
|   if (!rem) while (i++<16) *spi_w++ = color32; | ||||
|   *_spi_mosi_dlen =  511; | ||||
| 
 | ||||
|   // End with full buffer to maximise useful time for downstream code
 | ||||
|   while(len) | ||||
|   { | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|     *_spi_cmd = SPI_UPDATE; | ||||
|     while (*_spi_cmd & SPI_UPDATE); | ||||
| #endif | ||||
|     *_spi_cmd = SPI_USR; | ||||
|     len -= 32; | ||||
|   } | ||||
| 
 | ||||
|   // Do not wait here
 | ||||
|   //while (*_spi_cmd&SPI_USR);
 | ||||
| } | ||||
| //*/
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushSwapBytePixels - for ESP32 | ||||
| ** Description:             Write a sequence of pixels with swapped bytes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint8_t* data = (uint8_t*)data_in; | ||||
|   uint32_t color[16]; | ||||
| 
 | ||||
|   if (len > 31) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); | ||||
|     while(len>31) | ||||
|     { | ||||
|       uint32_t i = 0; | ||||
|       while(i<16) | ||||
|       { | ||||
|         color[i++] = DAT8TO32(data); | ||||
|         data+=4; | ||||
|       } | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]); | ||||
|       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  color[4]); | ||||
|       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  color[5]); | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  color[6]); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  color[7]); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT),  color[8]); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT),  color[9]); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color[10]); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color[11]); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color[12]); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color[13]); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color[14]); | ||||
|       WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color[15]); | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|       len -= 32; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (len > 15) | ||||
|   { | ||||
|     uint32_t i = 0; | ||||
|     while(i<8) | ||||
|     { | ||||
|       color[i++] = DAT8TO32(data); | ||||
|       data+=4; | ||||
|     } | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 255); | ||||
|     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]); | ||||
|     WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]); | ||||
|     WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]); | ||||
|     WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]); | ||||
|     WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  color[4]); | ||||
|     WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  color[5]); | ||||
|     WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  color[6]); | ||||
|     WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  color[7]); | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|     len -= 16; | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1); | ||||
|     for (uint32_t i=0; i <= (len<<1); i+=4) { | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT)+i, DAT8TO32(data)); data+=4; | ||||
|     } | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|   } | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   if(_swapBytes) { | ||||
|     pushSwapBytePixels(data_in, len); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   uint32_t *data = (uint32_t*)data_in; | ||||
| 
 | ||||
|   if (len > 31) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); | ||||
|     while(len>31) | ||||
|     { | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), *data++); | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|       len -= 32; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1); | ||||
|     for (uint32_t i=0; i <= (len<<1); i+=4) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + i), *data++); | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|   } | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 and 3 byte RGB display | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) | ||||
| { | ||||
|   // Split out the colours
 | ||||
|   uint32_t r = (color & 0xF800)>>8; | ||||
|   uint32_t g = (color & 0x07E0)<<5; | ||||
|   uint32_t b = (color & 0x001F)<<19; | ||||
|   // Concatenate 4 pixels into three 32 bit blocks
 | ||||
|   uint32_t r0 = r<<24 | b | g | r; | ||||
|   uint32_t r1 = r0>>8 | g<<16; | ||||
|   uint32_t r2 = r1>>8 | b<<8; | ||||
| 
 | ||||
|   if (len > 19) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 479); | ||||
| 
 | ||||
|     while(len>19) | ||||
|     { | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|       len -= 20; | ||||
|     } | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len * 24) - 1); | ||||
|     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); | ||||
|     WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); | ||||
|     WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); | ||||
|     WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); | ||||
|     WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); | ||||
|     WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); | ||||
|     if (len > 8 ) | ||||
|     { | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); | ||||
|     } | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 and 3 byte RGB display | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   // ILI9488 write macro is not endianess dependant, hence !_swapBytes
 | ||||
|   if(!_swapBytes) { while ( len-- ) {tft_Write_16S(*data); data++;} } | ||||
|   else { while ( len-- ) {tft_Write_16(*data); data++;} } | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushSwapBytePixels - for ESP32 and 3 byte RGB display | ||||
| ** Description:             Write a sequence of pixels with swapped bytes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   // ILI9488 write macro is not endianess dependant, so swap byte macro not used here
 | ||||
|   while ( len-- ) {tft_Write_16(*data); data++;} | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (TFT_PARALLEL_8_BIT) // Now the code for ESP32 8 bit parallel
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 and parallel display | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
|   if ( (color >> 8) == (color & 0x00FF) ) | ||||
|   { if (!len) return; | ||||
|     tft_Write_16(color); | ||||
|   #if defined (SSD1963_DRIVER) | ||||
|     while (--len) {WR_L; WR_H; WR_L; WR_H; WR_L; WR_H;} | ||||
|   #else | ||||
|     #ifdef PSEUDO_16_BIT | ||||
|       while (--len) {WR_L; WR_H;} | ||||
|     #else | ||||
|       while (--len) {WR_L; WR_H; WR_L; WR_H;} | ||||
|     #endif | ||||
|   #endif | ||||
|   } | ||||
|   else while (len--) {tft_Write_16(color);} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushSwapBytePixels - for ESP32 and parallel display | ||||
| ** Description:             Write a sequence of pixels with swapped bytes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   while ( len-- ) {tft_Write_16(*data); data++;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 and parallel display | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   if(_swapBytes) { while ( len-- ) {tft_Write_16(*data); data++; } } | ||||
|   else { while ( len-- ) {tft_Write_16S(*data); data++;} } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of display interface specific functions
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (ESP32_DMA) && !defined (TFT_PARALLEL_8_BIT) //       DMA FUNCTIONS
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaBusy | ||||
| ** Description:             Check if DMA is busy | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::dmaBusy(void) | ||||
| { | ||||
|   if (!DMA_Enabled || !spiBusyCheck) return false; | ||||
| 
 | ||||
|   spi_transaction_t *rtrans; | ||||
|   esp_err_t ret; | ||||
|   uint8_t checks = spiBusyCheck; | ||||
|   for (int i = 0; i < checks; ++i) | ||||
|   { | ||||
|     ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0); | ||||
|     if (ret == ESP_OK) spiBusyCheck--; | ||||
|   } | ||||
| 
 | ||||
|   //Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck);
 | ||||
|   if (spiBusyCheck ==0) return false; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaWait | ||||
| ** Description:             Wait until DMA is over (blocking!) | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::dmaWait(void) | ||||
| { | ||||
|   if (!DMA_Enabled || !spiBusyCheck) return; | ||||
|   spi_transaction_t *rtrans; | ||||
|   esp_err_t ret; | ||||
|   for (int i = 0; i < spiBusyCheck; ++i) | ||||
|   { | ||||
|     ret = spi_device_get_trans_result(dmaHAL, &rtrans, portMAX_DELAY); | ||||
|     assert(ret == ESP_OK); | ||||
|   } | ||||
|   spiBusyCheck = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixelsDMA | ||||
| ** Description:             Push pixels to TFT (len must be less than 32767) | ||||
| ***************************************************************************************/ | ||||
| // This will byte swap the original image if setSwapBytes(true) was called by sketch.
 | ||||
| void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) | ||||
| { | ||||
|   if ((len == 0) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   dmaWait(); | ||||
| 
 | ||||
|   if(_swapBytes) { | ||||
|     for (uint32_t i = 0; i < len; i++) (image[i] = image[i] << 8 | image[i] >> 8); | ||||
|   } | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = image;  //finally send the line data
 | ||||
|   trans.length = len * 16;        //Data length, in bits
 | ||||
|   trans.flags = 0;                //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Description:             Push image to a window (w*h must be less than 65536) | ||||
| ***************************************************************************************/ | ||||
| // Fixed const data assumed, will NOT clip or swap bytes
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* image) | ||||
| { | ||||
|   if ((w == 0) || (h == 0) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   uint32_t len = w*h; | ||||
| 
 | ||||
|   dmaWait(); | ||||
| 
 | ||||
|   setAddrWindow(x, y, w, h); | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = image;   //Data pointer
 | ||||
|   trans.length = len * 16;   //Data length, in bits
 | ||||
|   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Description:             Push image to a window (w*h must be less than 65536) | ||||
| ***************************************************************************************/ | ||||
| // This will clip and also swap bytes if setSwapBytes(true) was called by sketch
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer) | ||||
| { | ||||
|   if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   int32_t dx = 0; | ||||
|   int32_t dy = 0; | ||||
|   int32_t dw = w; | ||||
|   int32_t dh = h; | ||||
| 
 | ||||
|   if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } | ||||
|   if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } | ||||
| 
 | ||||
|   if ((x + dw) > _vpW ) dw = _vpW - x; | ||||
|   if ((y + dh) > _vpH ) dh = _vpH - y; | ||||
| 
 | ||||
|   if (dw < 1 || dh < 1) return; | ||||
| 
 | ||||
|   uint32_t len = dw*dh; | ||||
| 
 | ||||
|   if (buffer == nullptr) { | ||||
|     buffer = image; | ||||
|     dmaWait(); | ||||
|   } | ||||
| 
 | ||||
|   // If image is clipped, copy pixels into a contiguous block
 | ||||
|   if ( (dw != w) || (dh != h) ) { | ||||
|     if(_swapBytes) { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         for (int32_t xb = 0; xb < dw; xb++) { | ||||
|           uint32_t src = xb + dx + w * (yb + dy); | ||||
|           (buffer[xb + yb * dw] = image[src] << 8 | image[src] >> 8); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         memcpy((uint8_t*) (buffer + yb * dw), (uint8_t*) (image + dx + w * (yb + dy)), dw << 1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   // else, if a buffer pointer has been provided copy whole image to the buffer
 | ||||
|   else if (buffer != image || _swapBytes) { | ||||
|     if(_swapBytes) { | ||||
|       for (uint32_t i = 0; i < len; i++) (buffer[i] = image[i] << 8 | image[i] >> 8); | ||||
|     } | ||||
|     else { | ||||
|       memcpy(buffer, image, len*2); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (spiBusyCheck) dmaWait(); // In case we did not wait earlier
 | ||||
| 
 | ||||
|   setAddrWindow(x, y, dw, dh); | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = buffer;  //finally send the line data
 | ||||
|   trans.length = len * 16;   //Data length, in bits
 | ||||
|   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Processor specific DMA initialisation
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // The DMA functions here work with SPI only (not parallel)
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dc_callback | ||||
| ** Description:             Toggles DC line during transaction | ||||
| ***************************************************************************************/ | ||||
| extern "C" void dc_callback(); | ||||
| 
 | ||||
| void IRAM_ATTR dc_callback(spi_transaction_t *spi_tx) | ||||
| { | ||||
|   if ((bool)spi_tx->user) {DC_D;} | ||||
|   else {DC_C;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           initDMA | ||||
| ** Description:             Initialise the DMA engine - returns true if init OK | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::initDMA(bool ctrl_cs) | ||||
| { | ||||
|   if (DMA_Enabled) return false; | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   spi_bus_config_t buscfg = { | ||||
|     .mosi_io_num = TFT_MOSI, | ||||
|     .miso_io_num = TFT_MISO, | ||||
|     .sclk_io_num = TFT_SCLK, | ||||
|     .quadwp_io_num = -1, | ||||
|     .quadhd_io_num = -1, | ||||
|     .max_transfer_sz = TFT_WIDTH * TFT_HEIGHT * 2 + 8, // TFT screen size
 | ||||
|     .flags = 0, | ||||
|     .intr_flags = 0 | ||||
|   }; | ||||
| 
 | ||||
|   int8_t pin = -1; | ||||
|   if (ctrl_cs) pin = TFT_CS; | ||||
| 
 | ||||
|   spi_device_interface_config_t devcfg = { | ||||
|     .command_bits = 0, | ||||
|     .address_bits = 0, | ||||
|     .dummy_bits = 0, | ||||
|     .mode = TFT_SPI_MODE, | ||||
|     .duty_cycle_pos = 0, | ||||
|     .cs_ena_pretrans = 0, | ||||
|     .cs_ena_posttrans = 0, | ||||
|     .clock_speed_hz = SPI_FREQUENCY, | ||||
|     .input_delay_ns = 0, | ||||
|     .spics_io_num = pin, | ||||
|     .flags = SPI_DEVICE_NO_DUMMY, //0,
 | ||||
|     .queue_size = 1, | ||||
|     .pre_cb = 0, //dc_callback, //Callback to handle D/C line
 | ||||
|     .post_cb = 0 | ||||
|   }; | ||||
|   ret = spi_bus_initialize(spi_host, &buscfg, DMA_CHANNEL); | ||||
|   ESP_ERROR_CHECK(ret); | ||||
|   ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL); | ||||
|   ESP_ERROR_CHECK(ret); | ||||
| 
 | ||||
|   DMA_Enabled = true; | ||||
|   spiBusyCheck = 0; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           deInitDMA | ||||
| ** Description:             Disconnect the DMA engine from SPI | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::deInitDMA(void) | ||||
| { | ||||
|   if (!DMA_Enabled) return; | ||||
|   spi_bus_remove_device(dmaHAL); | ||||
|   spi_bus_free(spi_host); | ||||
|   DMA_Enabled = false; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of DMA FUNCTIONS
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,597 @@ | |||
|         ////////////////////////////////////////////////////
 | ||||
|         // TFT_eSPI driver functions for ESP32 processors //
 | ||||
|         ////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Temporarily a separate file to TFT_eSPI_ESP32.h until board package low level API stabilises
 | ||||
| 
 | ||||
| #ifndef _TFT_eSPI_ESP32H_ | ||||
| #define _TFT_eSPI_ESP32H_ | ||||
| 
 | ||||
| #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) | ||||
|  #warning >>>>------>> DMA is not supported on the ESP32 C3 (possible future update) | ||||
| #endif | ||||
| 
 | ||||
| // Processor ID reported by getSetup()
 | ||||
| #define PROCESSOR_ID 0x32 | ||||
| 
 | ||||
| // Include processor specific header
 | ||||
| #include "soc/spi_reg.h" | ||||
| #include "driver/spi_master.h" | ||||
| 
 | ||||
| #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32) | ||||
|   #define CONFIG_IDF_TARGET_ESP32 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef VSPI | ||||
|   #define VSPI FSPI | ||||
| #endif | ||||
| 
 | ||||
| // Fix IDF problems with ESP32C3
 | ||||
| #if CONFIG_IDF_TARGET_ESP32C3 | ||||
|   // Fix ESP32C3 IDF bug for missing definition (VSPI/FSPI only tested at the moment)
 | ||||
|   #ifndef REG_SPI_BASE | ||||
|     #define REG_SPI_BASE(i) DR_REG_SPI2_BASE | ||||
|   #endif | ||||
| 
 | ||||
|   // Fix ESP32C3 IDF bug for name change
 | ||||
|   #ifndef SPI_MOSI_DLEN_REG | ||||
|     #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled
 | ||||
| #if !defined (SUPPORT_TRANSACTIONS) | ||||
|   #define SUPPORT_TRANSACTIONS | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
| ESP32: | ||||
| FSPI not defined | ||||
| HSPI = 2, uses SPI2 | ||||
| VSPI = 3, uses SPI3 | ||||
| 
 | ||||
| ESP32-S2: | ||||
| FSPI = 1, uses SPI2 | ||||
| HSPI = 2, uses SPI3 | ||||
| VSPI not defined so have made VSPI = HSPI | ||||
| 
 | ||||
| ESP32 C3: Only 1 SPI port available | ||||
| FSPI = 1, uses SPI2 | ||||
| HSPI = 1, uses SPI2 | ||||
| VSPI not defined so have made VSPI = HSPI | ||||
| 
 | ||||
| For ESP32/S2/C3: | ||||
| SPI1_HOST = 0 | ||||
| SPI2_HOST = 1 | ||||
| SPI3_HOST = 2 | ||||
| */ | ||||
| 
 | ||||
| // ESP32 specific SPI port selection - only SPI2_HOST available on C3
 | ||||
| #define SPI_PORT SPI2_HOST | ||||
| 
 | ||||
| #ifdef RPI_DISPLAY_TYPE | ||||
|   #define CMD_BITS (16-1) | ||||
| #else | ||||
|   #define CMD_BITS (8-1) | ||||
| #endif | ||||
| 
 | ||||
| // Initialise processor specific SPI functions, used by init()
 | ||||
| #define INIT_TFT_DATA_BUS // Not used
 | ||||
| 
 | ||||
| // Define a generic flag for 8 bit parallel
 | ||||
| #if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility
 | ||||
|   #if !defined (TFT_PARALLEL_8_BIT) | ||||
|     #define TFT_PARALLEL_8_BIT // Generic parallel flag
 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Ensure ESP32 specific flag is defined for 8 bit parallel
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
|   #if !defined (ESP32_PARALLEL) | ||||
|     #define ESP32_PARALLEL | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Processor specific code used by SPI bus transaction startWrite and endWrite functions
 | ||||
| #if !defined (ESP32_PARALLEL) | ||||
|   #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) | ||||
|     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE | ||||
|     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE | ||||
|   #else | ||||
|     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | ||||
|     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | ||||
|   #endif | ||||
| #else | ||||
|     // Not applicable to parallel bus
 | ||||
|     #define SET_BUS_WRITE_MODE | ||||
|     #define SET_BUS_READ_MODE | ||||
| #endif | ||||
| 
 | ||||
| // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
 | ||||
| #if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER) | ||||
|   #define ESP32_DMA | ||||
|   // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
 | ||||
|   #define DMA_BUSY_CHECK  dmaWait() | ||||
| #else | ||||
|   #define DMA_BUSY_CHECK | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TFT_PARALLEL_8_BIT) | ||||
|   #define SPI_BUSY_CHECK | ||||
| #else | ||||
|   #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR) | ||||
| #endif | ||||
| 
 | ||||
| // If smooth font is used then it is likely SPIFFS will be needed
 | ||||
| #ifdef SMOOTH_FONT | ||||
|   // Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts
 | ||||
|   #define FS_NO_GLOBALS | ||||
|   #include <FS.h> | ||||
|   #include "SPIFFS.h" // ESP32 only | ||||
|   #define FONT_FS_AVAILABLE | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the DC (TFT Data/Command or Register Select (RS))pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_DC | ||||
|   #define DC_C // No macro allocated so it generates no code
 | ||||
|   #define DC_D // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if defined (TFT_PARALLEL_8_BIT) | ||||
|     // TFT_DC, by design, must be in range 0-31 for single register parallel write
 | ||||
|     #if (TFT_DC >= 0) &&  (TFT_DC < 32) | ||||
|       #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC) | ||||
|       #define DC_D GPIO.out_w1ts.val = (1 << TFT_DC) | ||||
|     #elif (TFT_DC >= 32) | ||||
|       #define DC_C GPIO.out_w1tc.val = (1 << (TFT_DC- 32)) | ||||
|       #define DC_D GPIO.out_w1ts.val = (1 << (TFT_DC- 32)) | ||||
|     #else | ||||
|       #define DC_C | ||||
|       #define DC_D | ||||
|     #endif | ||||
|   #else | ||||
|     #if (TFT_DC >= 32) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi displays need a slower DC change
 | ||||
|         #define DC_C GPIO.out_w1ts.val = (1 << (TFT_DC - 32)); \ | ||||
|                      GPIO.out_w1tc.val = (1 << (TFT_DC - 32)) | ||||
|         #define DC_D GPIO.out_w1tc.val = (1 << (TFT_DC - 32)); \ | ||||
|                      GPIO.out_w1ts.val = (1 << (TFT_DC - 32)) | ||||
|       #else | ||||
|         #define DC_C GPIO.out_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out_w1tc.val = (1 << (TFT_DC - 32))
 | ||||
|         #define DC_D GPIO.out_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out_w1ts.val = (1 << (TFT_DC - 32))
 | ||||
|       #endif | ||||
|     #elif (TFT_DC >= 0) | ||||
|       #if defined (RPI_DISPLAY_TYPE) | ||||
|         #if defined (ILI9486_DRIVER) | ||||
|           // RPi ILI9486 display needs a slower DC change
 | ||||
|           #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1tc.val = (1 << TFT_DC) | ||||
|           #define DC_D GPIO.out_w1tc.val = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1ts.val = (1 << TFT_DC) | ||||
|         #else | ||||
|           // Other RPi displays need a slower C->D change
 | ||||
|           #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC) | ||||
|           #define DC_D GPIO.out_w1tc.val = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1ts.val = (1 << TFT_DC) | ||||
|         #endif | ||||
|       #else | ||||
|         #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC)//;GPIO.out_w1tc.val = (1 << TFT_DC)
 | ||||
|         #define DC_D GPIO.out_w1ts.val = (1 << TFT_DC)//;GPIO.out_w1ts.val = (1 << TFT_DC)
 | ||||
|       #endif | ||||
|     #else | ||||
|       #define DC_C | ||||
|       #define DC_D | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the CS (TFT chip select) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_CS | ||||
|   #define TFT_CS -1  // Keep DMA code happy
 | ||||
|   #define CS_L       // No macro allocated so it generates no code
 | ||||
|   #define CS_H       // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if defined (TFT_PARALLEL_8_BIT) | ||||
|     #if TFT_CS >= 32 | ||||
|         #define CS_L GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) | ||||
|     #elif TFT_CS >= 0 | ||||
|         #define CS_L GPIO.out_w1tc.val = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1ts.val = (1 << TFT_CS) | ||||
|     #else | ||||
|       #define CS_L | ||||
|       #define CS_H | ||||
|     #endif | ||||
|   #else | ||||
|     #if (TFT_CS >= 32) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
 | ||||
|         #define CS_L GPIO.out_w1ts.val = (1 << (TFT_CS - 32)); \ | ||||
|                      GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out_w1tc.val = (1 << (TFT_CS - 32)); \ | ||||
|                      GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) | ||||
|       #else | ||||
|         #define CS_L GPIO.out_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out_w1ts.val = (1 << (TFT_CS - 32))
 | ||||
|       #endif | ||||
|     #elif (TFT_CS >= 0) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
 | ||||
|         #define CS_L GPIO.out_w1ts.val = (1 << TFT_CS); GPIO.out_w1tc.val = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1tc.val = (1 << TFT_CS); GPIO.out_w1ts.val = (1 << TFT_CS) | ||||
|       #else | ||||
|         #define CS_L GPIO.out_w1tc.val = (1 << TFT_CS); GPIO.out_w1tc.val = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1ts.val = (1 << TFT_CS)//;GPIO.out_w1ts.val = (1 << TFT_CS)
 | ||||
|       #endif | ||||
|     #else | ||||
|       #define CS_L | ||||
|       #define CS_H | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the WR (TFT Write) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_WR) | ||||
|   #if (TFT_WR >= 32) | ||||
|     // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32
 | ||||
|     #define WR_L GPIO.out_w1tc.val = (1 << (TFT_WR - 32)) | ||||
|     #define WR_H GPIO.out_w1ts.val = (1 << (TFT_WR - 32)) | ||||
|   #elif (TFT_WR >= 0) | ||||
|     // TFT_WR, for best performance, should be in range 0-31 for single register parallel write
 | ||||
|     #define WR_L GPIO.out_w1tc.val = (1 << TFT_WR) | ||||
|     #define WR_H GPIO.out_w1ts.val = (1 << TFT_WR) | ||||
|   #else | ||||
|     #define WR_L | ||||
|     #define WR_H | ||||
|   #endif | ||||
| #else | ||||
|   #define WR_L | ||||
|   #define WR_H | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the touch screen chip select pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TOUCH_CS | ||||
|   #define T_CS_L // No macro allocated so it generates no code
 | ||||
|   #define T_CS_H // No macro allocated so it generates no code
 | ||||
| #else // XPT2046 is slow, so use slower digitalWrite here
 | ||||
|   #define T_CS_L digitalWrite(TOUCH_CS, LOW) | ||||
|   #define T_CS_H digitalWrite(TOUCH_CS, HIGH) | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Make sure SPI default pins are assigned if not specified by user or set to -1
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
| 
 | ||||
|   #ifdef USE_HSPI_PORT | ||||
| 
 | ||||
|     #ifndef TFT_MISO | ||||
|       #define TFT_MISO -1 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_MOSI | ||||
|       #define TFT_MOSI 13 | ||||
|     #endif | ||||
|     #if (TFT_MOSI == -1) | ||||
|       #undef TFT_MOSI | ||||
|       #define TFT_MOSI 13 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_SCLK | ||||
|       #define TFT_SCLK 14 | ||||
|     #endif | ||||
|     #if (TFT_SCLK == -1) | ||||
|       #undef TFT_SCLK | ||||
|       #define TFT_SCLK 14 | ||||
|     #endif | ||||
| 
 | ||||
|   #else // VSPI port
 | ||||
| 
 | ||||
|     #ifndef TFT_MISO | ||||
|       #define TFT_MISO -1 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_MOSI | ||||
|       #define TFT_MOSI 23 | ||||
|     #endif | ||||
|     #if (TFT_MOSI == -1) | ||||
|       #undef TFT_MOSI | ||||
|       #define TFT_MOSI 23 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_SCLK | ||||
|       #define TFT_SCLK 18 | ||||
|     #endif | ||||
|     #if (TFT_SCLK == -1) | ||||
|       #undef TFT_SCLK | ||||
|       #define TFT_SCLK 18 | ||||
|     #endif | ||||
| 
 | ||||
|     #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) | ||||
|       #if (TFT_MISO == -1) | ||||
|         #undef TFT_MISO | ||||
|         #define TFT_MISO TFT_MOSI | ||||
|       #endif | ||||
|     #endif | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the parallel bus interface chip pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
| 
 | ||||
|   // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically
 | ||||
|   // can then use e.g. GPIO.out_w1ts.val = set_mask(0xFF); to set data bus to 0xFF
 | ||||
|   #define PARALLEL_INIT_TFT_DATA_BUS               \ | ||||
|   for (int32_t c = 0; c<256; c++)                  \ | ||||
|   {                                                \ | ||||
|     xset_mask[c] = 0;                              \ | ||||
|     if ( c & 0x01 ) xset_mask[c] |= (1 << TFT_D0); \ | ||||
|     if ( c & 0x02 ) xset_mask[c] |= (1 << TFT_D1); \ | ||||
|     if ( c & 0x04 ) xset_mask[c] |= (1 << TFT_D2); \ | ||||
|     if ( c & 0x08 ) xset_mask[c] |= (1 << TFT_D3); \ | ||||
|     if ( c & 0x10 ) xset_mask[c] |= (1 << TFT_D4); \ | ||||
|     if ( c & 0x20 ) xset_mask[c] |= (1 << TFT_D5); \ | ||||
|     if ( c & 0x40 ) xset_mask[c] |= (1 << TFT_D6); \ | ||||
|     if ( c & 0x80 ) xset_mask[c] |= (1 << TFT_D7); \ | ||||
|   }                                                \ | ||||
| 
 | ||||
|   // Mask for the 8 data bits to set pin directions
 | ||||
|   #define GPIO_DIR_MASK ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) | ||||
| 
 | ||||
|   #if (TFT_WR >= 32) | ||||
|     // Data bits and the write line are cleared sequentially
 | ||||
|     #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L | ||||
|   #elif (TFT_WR >= 0) | ||||
|     // Data bits and the write line are cleared to 0 in one step (1.25x faster)
 | ||||
|     #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) | ||||
|   #else | ||||
|     #define GPIO_OUT_CLR_MASK | ||||
|   #endif | ||||
| 
 | ||||
|   // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM
 | ||||
|   #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time
 | ||||
| 
 | ||||
|   // Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test
 | ||||
|   /*#define set_mask(C) (((C)&0x80)>>7)<<TFT_D7 | (((C)&0x40)>>6)<<TFT_D6 | (((C)&0x20)>>5)<<TFT_D5 | (((C)&0x10)>>4)<<TFT_D4 | \
 | ||||
|                         (((C)&0x08)>>3)<<TFT_D3 | (((C)&0x04)>>2)<<TFT_D2 | (((C)&0x02)>>1)<<TFT_D1 | (((C)&0x01)>>0)<<TFT_D0 | ||||
|   //*/
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)  GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t)(C)); WR_H | ||||
| 
 | ||||
|   #if defined (SSD1963_DRIVER) | ||||
| 
 | ||||
|     // Write 18 bit color to TFT
 | ||||
|     #define tft_Write_16(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) (((C) & 0xF800)>> 8)); WR_H; \ | ||||
|                             GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \ | ||||
|                             GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H | ||||
| 
 | ||||
|     // 18 bit color write with swapped bytes
 | ||||
|     #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) | ||||
| 
 | ||||
|   #else | ||||
| 
 | ||||
|     #ifdef PSEUDO_16_BIT | ||||
|       // One write strobe for both bytes
 | ||||
|       #define tft_Write_16(C)  GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
|       #define tft_Write_16S(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H | ||||
|     #else | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                               GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                                GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H | ||||
|     #endif | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
|   // Write 32 bits to TFT
 | ||||
|   #define tft_Write_32(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 24)); WR_H; \ | ||||
|                           GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 16)); WR_H; \ | ||||
|                           GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >>  8)); WR_H; \ | ||||
|                           GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >>  0)); WR_H | ||||
| 
 | ||||
|   // Write two concatenated 16 bit values to TFT
 | ||||
|   #define tft_Write_32C(C,D) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                              GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                              GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((D) >> 8)); WR_H; \ | ||||
|                              GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((D) >> 0)); WR_H | ||||
| 
 | ||||
|   // Write 16 bit value twice to TFT - used by drawPixel()
 | ||||
|   #define tft_Write_32D(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                            GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
| 
 | ||||
|    // Read pin
 | ||||
|   #ifdef TFT_RD | ||||
|     #if (TFT_RD >= 32) | ||||
|       #define RD_L GPIO.out_w1tc.val = (1 << (TFT_RD - 32)) | ||||
|       #define RD_H GPIO.out_w1ts.val = (1 << (TFT_RD - 32)) | ||||
|     #elif (TFT_RD >= 0) | ||||
|       #define RD_L GPIO.out_w1tc.val = (1 << TFT_RD) | ||||
|       //#define RD_L digitalWrite(TFT_WR, LOW)
 | ||||
|       #define RD_H GPIO.out_w1ts.val = (1 << TFT_RD) | ||||
|       //#define RD_H digitalWrite(TFT_WR, HIGH)
 | ||||
|     #else | ||||
|       #define RD_L | ||||
|       #define RD_H | ||||
|     #endif | ||||
|   #else | ||||
|     #define TFT_RD -1 | ||||
|     #define RD_L | ||||
|     #define RD_H | ||||
|   #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI948x TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)   spi.transfer(C) | ||||
| 
 | ||||
|   // Convert 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|   #define tft_Write_16(C)  spi.transfer(((C) & 0xF800)>>8); \ | ||||
|                            spi.transfer(((C) & 0x07E0)>>3); \ | ||||
|                            spi.transfer(((C) & 0x001F)<<3) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #define tft_Write_16N(C) tft_Write_16(C) | ||||
| 
 | ||||
|   // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|   #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ | ||||
|                            spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ | ||||
|                            spi.transfer(((C) & 0x1F00)>>5) | ||||
| 
 | ||||
|   // Write 32 bits to TFT
 | ||||
|   #define tft_Write_32(C)  spi.write32(C) | ||||
| 
 | ||||
|   // Write two concatenated 16 bit values to TFT
 | ||||
|   #define tft_Write_32C(C,D) spi.write32((C)<<16 | (D)) | ||||
| 
 | ||||
|   // Write 16 bit value twice to TFT
 | ||||
|   #define tft_Write_32D(C)  spi.write32((C)<<16 | (C)) | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to an Raspberry Pi TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif  defined (RPI_DISPLAY_TYPE) | ||||
| 
 | ||||
|   // ESP32 low level SPI writes for 8, 16 and 32 bit values
 | ||||
|   // to avoid the function call overhead
 | ||||
|   #define TFT_WRITE_BITS(D, B) \ | ||||
|   WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ | ||||
|   WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ | ||||
|   SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| 
 | ||||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #define tft_Write_16N(C) tft_Write_16(C) | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D)  TFT_WRITE_BITS((C)<<24 | (C), 32); \ | ||||
|                               TFT_WRITE_BITS((D)<<24 | (D), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) tft_Write_32C(C,C) | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros for all other SPI displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #else | ||||
| /* Old macros
 | ||||
|   // ESP32 low level SPI writes for 8, 16 and 32 bit values
 | ||||
|   // to avoid the function call overhead
 | ||||
|   #define TFT_WRITE_BITS(D, B) \ | ||||
|   WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ | ||||
|   WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ | ||||
|   SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| 
 | ||||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| //*/
 | ||||
| //* Replacement slimmer macros
 | ||||
|   #if !defined(CONFIG_IDF_TARGET_ESP32C3) | ||||
|     #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;  \ | ||||
|                                *_spi_w = D;              \ | ||||
|                                *_spi_cmd = SPI_USR;      \ | ||||
|                         while (*_spi_cmd & SPI_USR); | ||||
|   #else | ||||
|     #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;  \ | ||||
|                                *_spi_w = D;              \ | ||||
|                                *_spi_cmd = SPI_UPDATE;   \ | ||||
|                         while (*_spi_cmd & SPI_UPDATE);  \ | ||||
|                                *_spi_cmd = SPI_USR;      \ | ||||
|                         while (*_spi_cmd & SPI_USR); | ||||
|   #endif | ||||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #if !defined(CONFIG_IDF_TARGET_ESP32C3) | ||||
|     #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1;    \ | ||||
|                            *_spi_w = ((C)<<8 | (C)>>8); \ | ||||
|                            *_spi_cmd = SPI_USR; | ||||
|   #else | ||||
|     #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1;    \ | ||||
|                            *_spi_w = ((C)<<8 | (C)>>8); \ | ||||
|                            *_spi_cmd = SPI_UPDATE;      \ | ||||
|                     while (*_spi_cmd & SPI_UPDATE);     \ | ||||
|                            *_spi_cmd = SPI_USR; | ||||
|   #endif | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D)  TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
| //*/
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef tft_Write_16N | ||||
|   #define tft_Write_16N tft_Write_16 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to read from display using SPI or software SPI
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   // Read from display using SPI or software SPI
 | ||||
|   // Use a SPI read transfer
 | ||||
|   #define tft_Read_8() spi.transfer(0) | ||||
| #endif | ||||
| 
 | ||||
| // Concatenate a byte sequence A,B,C,D to CDAB, P is a uint8_t pointer
 | ||||
| #define DAT8TO32(P) ( (uint32_t)P[0]<<8 | P[1] | P[2]<<24 | P[3]<<16 ) | ||||
| 
 | ||||
| #endif // Header end
 | ||||
|  | @ -0,0 +1,885 @@ | |||
|         ////////////////////////////////////////////////////
 | ||||
|         // TFT_eSPI driver functions for ESP32 processors //
 | ||||
|         ////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Temporarily a separate file to TFT_eSPI_ESP32.c until board package low level API stabilises
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Global variables
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Select the SPI port to use, ESP32 has 2 options
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       SPIClass spi = SPIClass(HSPI); | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       SPIClass spi = SPIClass(FSPI); | ||||
|     #else // use default VSPI port
 | ||||
|       SPIClass spi = SPIClass(VSPI); | ||||
|     #endif | ||||
|   #else | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       SPIClass spi = SPIClass(HSPI); | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       SPIClass spi = SPIClass(FSPI); | ||||
|     #else // use FSPI port
 | ||||
|       SPIClass& spi = SPI; | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef ESP32_DMA | ||||
|   // DMA SPA handle
 | ||||
|   spi_device_handle_t dmaHAL; | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #define DMA_CHANNEL 1 | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       spi_host_device_t spi_host = HSPI_HOST; | ||||
|     #elif defined(USE_FSPI_PORT) | ||||
|       spi_host_device_t spi_host = SPI_HOST; | ||||
|     #else // use VSPI port
 | ||||
|       spi_host_device_t spi_host = VSPI_HOST; | ||||
|     #endif | ||||
|   #else | ||||
|     #ifdef USE_HSPI_PORT | ||||
|       #define DMA_CHANNEL SPI_DMA_CH_AUTO | ||||
|       spi_host_device_t spi_host = SPI3_HOST; | ||||
|     #else // use FSPI port
 | ||||
|       #define DMA_CHANNEL SPI_DMA_CH_AUTO | ||||
|       spi_host_device_t spi_host = SPI2_HOST; | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           beginSDA - FPSI port only | ||||
| ** Description:             Detach MOSI and attach MISO to SDA for reads | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::begin_SDA_Read(void) | ||||
| { | ||||
|   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_INPUT); | ||||
|   pinMatrixInAttach(TFT_MOSI, FSPIQ_IN_IDX, false); | ||||
|   SET_BUS_READ_MODE; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           endSDA - FPSI port only | ||||
| ** Description:             Attach MOSI to SDA and detach MISO for writes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::end_SDA_Read(void) | ||||
| { | ||||
|   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_OUTPUT); | ||||
|   pinMatrixOutAttach(TFT_MOSI, FSPID_OUT_IDX, false, false); | ||||
|   SET_BUS_WRITE_MODE; | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // #if defined (TFT_SDA_READ)
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           read byte  - supports class functions | ||||
| ** Description:             Read a byte from ESP32 8 bit data port | ||||
| ***************************************************************************************/ | ||||
| // Parallel bus MUST be set to input before calling this function!
 | ||||
| uint8_t TFT_eSPI::readByte(void) | ||||
| { | ||||
|   uint8_t b = 0xAA; | ||||
| 
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
|   RD_L; | ||||
|   b  = gpio_get_level((gpio_num_t)(TFT_D0-MASK_OFFSET)); // Read three times to allow for bus access time
 | ||||
|   b  = gpio_get_level((gpio_num_t)(TFT_D0-MASK_OFFSET)); | ||||
|   b  = gpio_get_level((gpio_num_t)(TFT_D0-MASK_OFFSET)); // Data should be stable now
 | ||||
|   RD_H; | ||||
| 
 | ||||
|   // Check GPIO bits used and build value
 | ||||
|   b  = (gpio_get_level((gpio_num_t)(TFT_D0-MASK_OFFSET)) << 0); | ||||
|   b |= (gpio_get_level((gpio_num_t)(TFT_D1-MASK_OFFSET)) << 1); | ||||
|   b |= (gpio_get_level((gpio_num_t)(TFT_D2-MASK_OFFSET)) << 2); | ||||
|   b |= (gpio_get_level((gpio_num_t)(TFT_D3-MASK_OFFSET)) << 3); | ||||
|   b |= (gpio_get_level((gpio_num_t)(TFT_D4-MASK_OFFSET)) << 4); | ||||
|   b |= (gpio_get_level((gpio_num_t)(TFT_D5-MASK_OFFSET)) << 5); | ||||
|   b |= (gpio_get_level((gpio_num_t)(TFT_D6-MASK_OFFSET)) << 6); | ||||
|   b |= (gpio_get_level((gpio_num_t)(TFT_D7-MASK_OFFSET)) << 7); | ||||
| #endif | ||||
| 
 | ||||
|   return b; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifdef TFT_PARALLEL_8_BIT | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           GPIO direction control  - supports class functions | ||||
| ** Description:             Set parallel bus to INPUT or OUTPUT | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) | ||||
| { | ||||
|   // Arduino generic native function
 | ||||
|   pinMode(TFT_D0, mode); | ||||
|   pinMode(TFT_D1, mode); | ||||
|   pinMode(TFT_D2, mode); | ||||
|   pinMode(TFT_D3, mode); | ||||
|   pinMode(TFT_D4, mode); | ||||
|   pinMode(TFT_D5, mode); | ||||
|   pinMode(TFT_D6, mode); | ||||
|   pinMode(TFT_D7, mode); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           GPIO direction control  - supports class functions | ||||
| ** Description:             Set ESP32 GPIO pin to input or output (set high) ASAP | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode) | ||||
| { | ||||
|   pinMode(gpio, mode); | ||||
|   digitalWrite(gpio, HIGH); | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // #ifdef TFT_PARALLEL_8_BIT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (RPI_WRITE_STROBE) && !defined (TFT_PARALLEL_8_BIT) // Code for RPi TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 or ESP8266 RPi TFT | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) | ||||
| { | ||||
|   uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; | ||||
|   if(len) spi.writePattern(&colorBin[0], 2, 1); len--; | ||||
|   while(len--) {WR_L; WR_H;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 or ESP8266 RPi TFT | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) | ||||
| { | ||||
|   uint8_t *data = (uint8_t*)data_in; | ||||
| 
 | ||||
|   if(_swapBytes) { | ||||
|       while ( len-- ) {tft_Write_16(*data); data++;} | ||||
|       return; | ||||
|   } | ||||
| 
 | ||||
|   while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } | ||||
|   if (len) spi.writePattern(data, len, 1); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif !defined (SPI_18BIT_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most SPI displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| /*
 | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
| 
 | ||||
|   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); | ||||
|   bool empty = true; | ||||
|   volatile uint32_t* spi_w = (volatile uint32_t*)_spi_w; | ||||
|   if (len > 31) | ||||
|   { | ||||
|     *_spi_mosi_dlen =  511; | ||||
|     spi_w[0]  = color32; | ||||
|     spi_w[1]  = color32; | ||||
|     spi_w[2]  = color32; | ||||
|     spi_w[3]  = color32; | ||||
|     spi_w[4]  = color32; | ||||
|     spi_w[5]  = color32; | ||||
|     spi_w[6]  = color32; | ||||
|     spi_w[7]  = color32; | ||||
|     spi_w[8]  = color32; | ||||
|     spi_w[9]  = color32; | ||||
|     spi_w[10] = color32; | ||||
|     spi_w[11] = color32; | ||||
|     spi_w[12] = color32; | ||||
|     spi_w[13] = color32; | ||||
|     spi_w[14] = color32; | ||||
|     spi_w[15] = color32; | ||||
|     while(len>31) | ||||
|     { | ||||
|       while ((*_spi_cmd)&SPI_USR); | ||||
|       *_spi_cmd = SPI_USR; | ||||
|       len -= 32; | ||||
|     } | ||||
|     empty = false; | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     if(empty) { | ||||
|       for (uint32_t i=0; i <= len; i+=2) *spi_w++ = color32; | ||||
|     } | ||||
|     len = (len << 4) - 1; | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
|     *_spi_mosi_dlen = len; | ||||
|     *_spi_cmd = SPI_USR; | ||||
|   } | ||||
|   while ((*_spi_cmd)&SPI_USR); // Move to later in code to use transmit time usefully?
 | ||||
| } | ||||
| //*/
 | ||||
| //*
 | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
| 
 | ||||
|   volatile uint32_t* spi_w = _spi_w; | ||||
|   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); | ||||
|   uint32_t i = 0; | ||||
|   uint32_t rem = len & 0x1F; | ||||
|   len =  len - rem; | ||||
| 
 | ||||
|   // Start with partial buffer pixels
 | ||||
|   if (rem) | ||||
|   { | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
|     for (i=0; i < rem; i+=2) *spi_w++ = color32; | ||||
|     *_spi_mosi_dlen = (rem << 4) - 1; | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|     *_spi_cmd = SPI_UPDATE; | ||||
|     while (*_spi_cmd & SPI_UPDATE); | ||||
| #endif | ||||
|     *_spi_cmd = SPI_USR; | ||||
|     if (!len) return; //{while (*_spi_cmd&SPI_USR); return; }
 | ||||
|     i = i>>1; while(i++<16) *spi_w++ = color32; | ||||
|   } | ||||
| 
 | ||||
|   while (*_spi_cmd&SPI_USR); | ||||
|   if (!rem) while (i++<16) *spi_w++ = color32; | ||||
|   *_spi_mosi_dlen =  511; | ||||
| 
 | ||||
|   // End with full buffer to maximise useful time for downstream code
 | ||||
|   while(len) | ||||
|   { | ||||
|     while (*_spi_cmd&SPI_USR); | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|     *_spi_cmd = SPI_UPDATE; | ||||
|     while (*_spi_cmd & SPI_UPDATE); | ||||
| #endif | ||||
|     *_spi_cmd = SPI_USR; | ||||
|     len -= 32; | ||||
|   } | ||||
| 
 | ||||
|   // Do not wait here
 | ||||
|   //while (*_spi_cmd&SPI_USR);
 | ||||
| } | ||||
| //*/
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushSwapBytePixels - for ESP32 | ||||
| ** Description:             Write a sequence of pixels with swapped bytes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint8_t* data = (uint8_t*)data_in; | ||||
|   uint32_t color[16]; | ||||
| 
 | ||||
|   if (len > 31) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); | ||||
|     while(len>31) | ||||
|     { | ||||
|       uint32_t i = 0; | ||||
|       while(i<16) | ||||
|       { | ||||
|         color[i++] = DAT8TO32(data); | ||||
|         data+=4; | ||||
|       } | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]); | ||||
|       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  color[4]); | ||||
|       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  color[5]); | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  color[6]); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  color[7]); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT),  color[8]); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT),  color[9]); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color[10]); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color[11]); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color[12]); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color[13]); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color[14]); | ||||
|       WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color[15]); | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|       len -= 32; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (len > 15) | ||||
|   { | ||||
|     uint32_t i = 0; | ||||
|     while(i<8) | ||||
|     { | ||||
|       color[i++] = DAT8TO32(data); | ||||
|       data+=4; | ||||
|     } | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 255); | ||||
|     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]); | ||||
|     WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]); | ||||
|     WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]); | ||||
|     WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]); | ||||
|     WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  color[4]); | ||||
|     WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  color[5]); | ||||
|     WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  color[6]); | ||||
|     WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  color[7]); | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|     len -= 16; | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1); | ||||
|     for (uint32_t i=0; i <= (len<<1); i+=4) { | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT)+i, DAT8TO32(data)); data+=4; | ||||
|     } | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|   } | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   if(_swapBytes) { | ||||
|     pushSwapBytePixels(data_in, len); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   uint32_t *data = (uint32_t*)data_in; | ||||
| 
 | ||||
|   if (len > 31) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); | ||||
|     while(len>31) | ||||
|     { | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT),  *data++); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), *data++); | ||||
|       WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), *data++); | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|       len -= 32; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1); | ||||
|     for (uint32_t i=0; i <= (len<<1); i+=4) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + i), *data++); | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|   } | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 and 3 byte RGB display | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) | ||||
| { | ||||
|   // Split out the colours
 | ||||
|   uint32_t r = (color & 0xF800)>>8; | ||||
|   uint32_t g = (color & 0x07E0)<<5; | ||||
|   uint32_t b = (color & 0x001F)<<19; | ||||
|   // Concatenate 4 pixels into three 32 bit blocks
 | ||||
|   uint32_t r0 = r<<24 | b | g | r; | ||||
|   uint32_t r1 = r0>>8 | g<<16; | ||||
|   uint32_t r2 = r1>>8 | b<<8; | ||||
| 
 | ||||
|   if (len > 19) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 479); | ||||
| 
 | ||||
|     while(len>19) | ||||
|     { | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|       len -= 20; | ||||
|     } | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|   } | ||||
| 
 | ||||
|   if (len) | ||||
|   { | ||||
|     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len * 24) - 1); | ||||
|     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); | ||||
|     WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); | ||||
|     WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); | ||||
|     WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); | ||||
|     WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); | ||||
|     WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); | ||||
|     if (len > 8 ) | ||||
|     { | ||||
|       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); | ||||
|       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); | ||||
|       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); | ||||
|       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); | ||||
|     } | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE); | ||||
| #endif | ||||
|     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); | ||||
|     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 and 3 byte RGB display | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   // ILI9488 write macro is not endianess dependant, hence !_swapBytes
 | ||||
|   if(!_swapBytes) { while ( len-- ) {tft_Write_16S(*data); data++;} } | ||||
|   else { while ( len-- ) {tft_Write_16(*data); data++;} } | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushSwapBytePixels - for ESP32 and 3 byte RGB display | ||||
| ** Description:             Write a sequence of pixels with swapped bytes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   // ILI9488 write macro is not endianess dependant, so swap byte macro not used here
 | ||||
|   while ( len-- ) {tft_Write_16(*data); data++;} | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (TFT_PARALLEL_8_BIT) // Now the code for ESP32 8 bit parallel
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 and parallel display | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
|   if ( (color >> 8) == (color & 0x00FF) ) | ||||
|   { if (!len) return; | ||||
|     tft_Write_16(color); | ||||
|   #if defined (SSD1963_DRIVER) | ||||
|     while (--len) {WR_L; WR_H; WR_L; WR_H; WR_L; WR_H;} | ||||
|   #else | ||||
|     #ifdef PSEUDO_16_BIT | ||||
|       while (--len) {WR_L; WR_H;} | ||||
|     #else | ||||
|       while (--len) {WR_L; WR_H; WR_L; WR_H;} | ||||
|     #endif | ||||
|   #endif | ||||
|   } | ||||
|   else while (len--) {tft_Write_16(color);} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushSwapBytePixels - for ESP32 and parallel display | ||||
| ** Description:             Write a sequence of pixels with swapped bytes | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   while ( len-- ) {tft_Write_16(*data); data++;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 and parallel display | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   if(_swapBytes) { while ( len-- ) {tft_Write_16(*data); data++; } } | ||||
|   else { while ( len-- ) {tft_Write_16S(*data); data++;} } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of display interface specific functions
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (ESP32_DMA) && !defined (TFT_PARALLEL_8_BIT) //       DMA FUNCTIONS
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaBusy | ||||
| ** Description:             Check if DMA is busy | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::dmaBusy(void) | ||||
| { | ||||
|   if (!DMA_Enabled || !spiBusyCheck) return false; | ||||
| 
 | ||||
|   spi_transaction_t *rtrans; | ||||
|   esp_err_t ret; | ||||
|   uint8_t checks = spiBusyCheck; | ||||
|   for (int i = 0; i < checks; ++i) | ||||
|   { | ||||
|     ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0); | ||||
|     if (ret == ESP_OK) spiBusyCheck--; | ||||
|   } | ||||
| 
 | ||||
|   //Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck);
 | ||||
|   if (spiBusyCheck ==0) return false; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaWait | ||||
| ** Description:             Wait until DMA is over (blocking!) | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::dmaWait(void) | ||||
| { | ||||
|   if (!DMA_Enabled || !spiBusyCheck) return; | ||||
|   spi_transaction_t *rtrans; | ||||
|   esp_err_t ret; | ||||
|   for (int i = 0; i < spiBusyCheck; ++i) | ||||
|   { | ||||
|     ret = spi_device_get_trans_result(dmaHAL, &rtrans, portMAX_DELAY); | ||||
|     assert(ret == ESP_OK); | ||||
|   } | ||||
|   spiBusyCheck = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixelsDMA | ||||
| ** Description:             Push pixels to TFT (len must be less than 32767) | ||||
| ***************************************************************************************/ | ||||
| // This will byte swap the original image if setSwapBytes(true) was called by sketch.
 | ||||
| void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) | ||||
| { | ||||
|   if ((len == 0) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   dmaWait(); | ||||
| 
 | ||||
|   if(_swapBytes) { | ||||
|     for (uint32_t i = 0; i < len; i++) (image[i] = image[i] << 8 | image[i] >> 8); | ||||
|   } | ||||
| 
 | ||||
|   // DMA byte count for transmit is 64Kbytes maximum, so to avoid this constraint
 | ||||
|   // small transfers are performed using a blocking call until DMA capacity is reached.
 | ||||
|   // User sketch can prevent blocking by managing pixel count and splitting into blocks
 | ||||
|   // of 32768 pixels maximum. (equivalent to an area of ~320 x 100 pixels)
 | ||||
|   while(len>0x4000) { // Transfer 16 bit pixels in blocks if len*2 over 65536 bytes
 | ||||
|     pushPixels(image, 0x400); | ||||
|     len -= 0x400; image+= 0x400; // Arbitrarily send 1K pixel blocks (2Kbytes)
 | ||||
|   } | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = image;  //finally send the line data
 | ||||
|   trans.length = len * 16;        //Data length, in bits
 | ||||
|   trans.flags = 0;                //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Description:             Push image to a window (w*h must be less than 65536) | ||||
| ***************************************************************************************/ | ||||
| // Fixed const data assumed, will NOT clip or swap bytes
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* image) | ||||
| { | ||||
|   if ((w == 0) || (h == 0) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   uint16_t *buffer = (uint16_t*)image; | ||||
|   uint32_t len = w*h; | ||||
| 
 | ||||
|   dmaWait(); | ||||
| 
 | ||||
|   setAddrWindow(x, y, w, h); | ||||
|   // DMA byte count for transmit is 64Kbytes maximum, so to avoid this constraint
 | ||||
|   // small transfers are performed using a blocking call until DMA capacity is reached.
 | ||||
|   // User sketch can prevent blocking by managing pixel count and splitting into blocks
 | ||||
|   // of 32768 pixels maximum. (equivalent to an area of ~320 x 100 pixels)
 | ||||
|   while(len>0x4000) { // Transfer 16 bit pixels in blocks if len*2 over 65536 bytes
 | ||||
|     pushPixels(buffer, 0x400); | ||||
|     len -= 0x400; buffer+= 0x400; // Arbitrarily send 1K pixel blocks (2Kbytes)
 | ||||
|   } | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = buffer;   //Data pointer
 | ||||
|   trans.length = len * 16;   //Data length, in bits
 | ||||
|   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Description:             Push image to a window (w*h must be less than 65536) | ||||
| ***************************************************************************************/ | ||||
| // This will clip and also swap bytes if setSwapBytes(true) was called by sketch
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer) | ||||
| { | ||||
|   if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   int32_t dx = 0; | ||||
|   int32_t dy = 0; | ||||
|   int32_t dw = w; | ||||
|   int32_t dh = h; | ||||
| 
 | ||||
|   if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } | ||||
|   if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } | ||||
| 
 | ||||
|   if ((x + dw) > _vpW ) dw = _vpW - x; | ||||
|   if ((y + dh) > _vpH ) dh = _vpH - y; | ||||
| 
 | ||||
|   if (dw < 1 || dh < 1) return; | ||||
| 
 | ||||
|   uint32_t len = dw*dh; | ||||
| 
 | ||||
|   if (buffer == nullptr) { | ||||
|     buffer = image; | ||||
|     dmaWait(); | ||||
|   } | ||||
| 
 | ||||
|   // If image is clipped, copy pixels into a contiguous block
 | ||||
|   if ( (dw != w) || (dh != h) ) { | ||||
|     if(_swapBytes) { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         for (int32_t xb = 0; xb < dw; xb++) { | ||||
|           uint32_t src = xb + dx + w * (yb + dy); | ||||
|           (buffer[xb + yb * dw] = image[src] << 8 | image[src] >> 8); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         memcpy((uint8_t*) (buffer + yb * dw), (uint8_t*) (image + dx + w * (yb + dy)), dw << 1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   // else, if a buffer pointer has been provided copy whole image to the buffer
 | ||||
|   else if (buffer != image || _swapBytes) { | ||||
|     if(_swapBytes) { | ||||
|       for (uint32_t i = 0; i < len; i++) (buffer[i] = image[i] << 8 | image[i] >> 8); | ||||
|     } | ||||
|     else { | ||||
|       memcpy(buffer, image, len*2); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (spiBusyCheck) dmaWait(); // In case we did not wait earlier
 | ||||
| 
 | ||||
|   setAddrWindow(x, y, dw, dh); | ||||
| 
 | ||||
|   // DMA byte count for transmit is 64Kbytes maximum, so to avoid this constraint
 | ||||
|   // small transfers are performed using a blocking call until DMA capacity is reached.
 | ||||
|   // User sketch can prevent blocking by managing pixel count and splitting into blocks
 | ||||
|   // of 32768 pixels maximum. (equivalent to an area of ~320 x 100 pixels)
 | ||||
|   while(len>0x4000) { // Transfer 16 bit pixels in blocks if len*2 over 65536 bytes
 | ||||
|     pushPixels(buffer, 0x400); | ||||
|     len -= 0x400; buffer+= 0x400; // Arbitrarily send 1K pixel blocks (2Kbytes)
 | ||||
|   } | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   static spi_transaction_t trans; | ||||
| 
 | ||||
|   memset(&trans, 0, sizeof(spi_transaction_t)); | ||||
| 
 | ||||
|   trans.user = (void *)1; | ||||
|   trans.tx_buffer = buffer;  //finally send the line data
 | ||||
|   trans.length = len * 16;   //Data length, in bits
 | ||||
|   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
 | ||||
| 
 | ||||
|   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); | ||||
|   assert(ret == ESP_OK); | ||||
| 
 | ||||
|   spiBusyCheck++; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Processor specific DMA initialisation
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // The DMA functions here work with SPI only (not parallel)
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dc_callback | ||||
| ** Description:             Toggles DC line during transaction (not used) | ||||
| ***************************************************************************************/ | ||||
| extern "C" void dc_callback(); | ||||
| 
 | ||||
| void IRAM_ATTR dc_callback(spi_transaction_t *spi_tx) | ||||
| { | ||||
|   if ((bool)spi_tx->user) {DC_D;} | ||||
|   else {DC_C;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dma_end_callback | ||||
| ** Description:             Clear DMA run flag to stop retransmission loop | ||||
| ***************************************************************************************/ | ||||
| extern "C" void dma_end_callback(); | ||||
| 
 | ||||
| void IRAM_ATTR dma_end_callback(spi_transaction_t *spi_tx) | ||||
| { | ||||
|   WRITE_PERI_REG(SPI_DMA_CONF_REG(spi_host), 0); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           initDMA | ||||
| ** Description:             Initialise the DMA engine - returns true if init OK | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::initDMA(bool ctrl_cs) | ||||
| { | ||||
|   if (DMA_Enabled) return false; | ||||
| 
 | ||||
|   esp_err_t ret; | ||||
|   spi_bus_config_t buscfg = { | ||||
|     .mosi_io_num = TFT_MOSI, | ||||
|     .miso_io_num = TFT_MISO, | ||||
|     .sclk_io_num = TFT_SCLK, | ||||
|     .quadwp_io_num = -1, | ||||
|     .quadhd_io_num = -1, | ||||
|     .max_transfer_sz = 65536, // ESP32 S3 max size is 64Kbytes
 | ||||
|     .flags = 0, | ||||
|     .intr_flags = 0 | ||||
|   }; | ||||
| 
 | ||||
|   int8_t pin = -1; | ||||
|   if (ctrl_cs) pin = TFT_CS; | ||||
| 
 | ||||
|   spi_device_interface_config_t devcfg = { | ||||
|     .command_bits = 0, | ||||
|     .address_bits = 0, | ||||
|     .dummy_bits = 0, | ||||
|     .mode = TFT_SPI_MODE, | ||||
|     .duty_cycle_pos = 0, | ||||
|     .cs_ena_pretrans = 0, | ||||
|     .cs_ena_posttrans = 0, | ||||
|     .clock_speed_hz = SPI_FREQUENCY, | ||||
|     .input_delay_ns = 0, | ||||
|     .spics_io_num = pin, | ||||
|     .flags = SPI_DEVICE_NO_DUMMY, //0,
 | ||||
|     .queue_size = 1,            // Not using queues
 | ||||
|     .pre_cb = 0, //dc_callback, //Callback to handle D/C line (not used)
 | ||||
|     .post_cb = dma_end_callback //Callback to end transmission
 | ||||
|   }; | ||||
|   ret = spi_bus_initialize(spi_host, &buscfg, DMA_CHANNEL); | ||||
|   ESP_ERROR_CHECK(ret); | ||||
|   ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL); | ||||
|   ESP_ERROR_CHECK(ret); | ||||
| 
 | ||||
|   DMA_Enabled = true; | ||||
|   spiBusyCheck = 0; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           deInitDMA | ||||
| ** Description:             Disconnect the DMA engine from SPI | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::deInitDMA(void) | ||||
| { | ||||
|   if (!DMA_Enabled) return; | ||||
|   spi_bus_remove_device(dmaHAL); | ||||
|   spi_bus_free(spi_host); | ||||
|   DMA_Enabled = false; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of DMA FUNCTIONS
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,640 @@ | |||
|         ////////////////////////////////////////////////////
 | ||||
|         // TFT_eSPI driver functions for ESP32 processors //
 | ||||
|         ////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Temporarily a separate file to TFT_eSPI_ESP32.h until board package low level API stabilises
 | ||||
| 
 | ||||
| #ifndef _TFT_eSPI_ESP32H_ | ||||
| #define _TFT_eSPI_ESP32H_ | ||||
| 
 | ||||
| // Processor ID reported by getSetup()
 | ||||
| #define PROCESSOR_ID 0x32 | ||||
| 
 | ||||
| // Include processor specific header
 | ||||
| #include "soc/spi_reg.h" | ||||
| #include "driver/spi_master.h" | ||||
| 
 | ||||
| #if !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32) | ||||
|   #define CONFIG_IDF_TARGET_ESP32 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef VSPI | ||||
|   #define VSPI FSPI | ||||
| #endif | ||||
| 
 | ||||
| // Fix IDF problems with ESP32S3
 | ||||
| // Note illogical enumerations: FSPI_HOST=SPI2_HOST=1   HSPI_HOST=SPI3_HOST=2
 | ||||
| #if CONFIG_IDF_TARGET_ESP32S3 | ||||
|   // Fix ESP32C3 IDF bug for missing definition (FSPI only tested at the moment)
 | ||||
|   #ifndef REG_SPI_BASE //                      HSPI                 FSPI/VSPI
 | ||||
|     #define REG_SPI_BASE(i) (((i)>1) ? (DR_REG_SPI3_BASE) : (DR_REG_SPI2_BASE)) | ||||
|   #endif | ||||
| 
 | ||||
|   // Fix ESP32S3 IDF bug for name change
 | ||||
|   #ifndef SPI_MOSI_DLEN_REG | ||||
|     #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) | ||||
|   #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled
 | ||||
| #if !defined (SUPPORT_TRANSACTIONS) | ||||
|   #define SUPPORT_TRANSACTIONS | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
| ESP32: | ||||
| FSPI not defined | ||||
| HSPI = 2, uses SPI2 | ||||
| VSPI = 3, uses SPI3 | ||||
| 
 | ||||
| ESP32-S2: | ||||
| FSPI = 1, uses SPI2 | ||||
| HSPI = 2, uses SPI3 | ||||
| VSPI not defined | ||||
| 
 | ||||
| ESP32 C3: | ||||
| FSPI = 0, uses SPI2 ???? To be checked | ||||
| HSPI = 1, uses SPI3 ???? To be checked | ||||
| VSPI not defined | ||||
| 
 | ||||
| For ESP32/S2/C3/S3: | ||||
| SPI1_HOST = 0 | ||||
| SPI2_HOST = 1 | ||||
| SPI3_HOST = 2 | ||||
| */ | ||||
| 
 | ||||
| // ESP32 specific SPI port selection
 | ||||
| #ifdef USE_HSPI_PORT | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #define SPI_PORT HSPI  //HSPI is port 2 on ESP32
 | ||||
|   #else | ||||
|     #define SPI_PORT 3     //HSPI is port 3 on ESP32 S2
 | ||||
|   #endif | ||||
| #elif defined(USE_FSPI_PORT) | ||||
|     #define SPI_PORT 2 //FSPI(ESP32 S2)
 | ||||
| #else | ||||
|   #ifdef CONFIG_IDF_TARGET_ESP32 | ||||
|     #define SPI_PORT VSPI | ||||
|   #elif CONFIG_IDF_TARGET_ESP32S2 | ||||
|     #define SPI_PORT 2 //FSPI(ESP32 S2)
 | ||||
|   #elif CONFIG_IDF_TARGET_ESP32S3 | ||||
|     #define SPI_PORT FSPI | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef RPI_DISPLAY_TYPE | ||||
|   #define CMD_BITS (16-1) | ||||
| #else | ||||
|   #define CMD_BITS (8-1) | ||||
| #endif | ||||
| 
 | ||||
| // Initialise processor specific SPI functions, used by init()
 | ||||
| #define INIT_TFT_DATA_BUS // Not used
 | ||||
| 
 | ||||
| // Define a generic flag for 8 bit parallel
 | ||||
| #if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility
 | ||||
|   #if !defined (TFT_PARALLEL_8_BIT) | ||||
|     #define TFT_PARALLEL_8_BIT // Generic parallel flag
 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Ensure ESP32 specific flag is defined for 8 bit parallel
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
|   #if !defined (ESP32_PARALLEL) | ||||
|     #define ESP32_PARALLEL | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) && defined (ESP32_PARALLEL) | ||||
|  #warning >>>>------>> DMA is not supported in parallel mode | ||||
| #endif | ||||
| 
 | ||||
| // Processor specific code used by SPI bus transaction startWrite and endWrite functions
 | ||||
| #if !defined (ESP32_PARALLEL) | ||||
|   #define _spi_cmd       (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT)) | ||||
|   #define _spi_user      (volatile uint32_t*)(SPI_USER_REG(SPI_PORT)) | ||||
|   #define _spi_mosi_dlen (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT)) | ||||
|   #define _spi_w         (volatile uint32_t*)(SPI_W0_REG(SPI_PORT)) | ||||
| 
 | ||||
|   #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) | ||||
|     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE | ||||
|     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE | ||||
|   #else | ||||
|     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | ||||
|     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | ||||
|   #endif | ||||
| #else | ||||
|     // Not applicable to parallel bus
 | ||||
|     #define SET_BUS_WRITE_MODE | ||||
|     #define SET_BUS_READ_MODE | ||||
| #endif | ||||
| 
 | ||||
| // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
 | ||||
| #if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER) | ||||
|   #define ESP32_DMA | ||||
|   // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
 | ||||
|   #define DMA_BUSY_CHECK  dmaWait() | ||||
| #else | ||||
|   #define DMA_BUSY_CHECK | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TFT_PARALLEL_8_BIT) | ||||
|   #define SPI_BUSY_CHECK | ||||
| #else | ||||
|   #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR) | ||||
| #endif | ||||
| 
 | ||||
| // If smooth font is used then it is likely SPIFFS will be needed
 | ||||
| #ifdef SMOOTH_FONT | ||||
|   // Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts
 | ||||
|   #define FS_NO_GLOBALS | ||||
|   #include <FS.h> | ||||
|   #include "SPIFFS.h" // ESP32 only | ||||
|   #define FONT_FS_AVAILABLE | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the DC (TFT Data/Command or Register Select (RS))pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_DC | ||||
|   #define DC_C // No macro allocated so it generates no code
 | ||||
|   #define DC_D // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if defined (TFT_PARALLEL_8_BIT) | ||||
|     // TFT_DC, by design, must be in range 0-31 for single register parallel write
 | ||||
|     #if (TFT_DC >= 0) &&  (TFT_DC < 32) | ||||
|       #define DC_C GPIO.out_w1tc = (1 << TFT_DC) | ||||
|       #define DC_D GPIO.out_w1ts = (1 << TFT_DC) | ||||
|     #elif (TFT_DC >= 32) | ||||
|       #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC- 32)) | ||||
|       #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC- 32)) | ||||
|     #else | ||||
|       #define DC_C | ||||
|       #define DC_D | ||||
|     #endif | ||||
|   #else | ||||
|     #if (TFT_DC >= 32) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi displays need a slower DC change
 | ||||
|         #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ | ||||
|                      GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) | ||||
|         #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ | ||||
|                      GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) | ||||
|       #else | ||||
|         #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))
 | ||||
|         #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))
 | ||||
|       #endif | ||||
|     #elif (TFT_DC >= 0) | ||||
|       #if defined (RPI_DISPLAY_TYPE) | ||||
|         #if defined (ILI9486_DRIVER) | ||||
|           // RPi ILI9486 display needs a slower DC change
 | ||||
|           #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1tc = (1 << TFT_DC) | ||||
|           #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1ts = (1 << TFT_DC) | ||||
|         #else | ||||
|           // Other RPi displays need a slower C->D change
 | ||||
|           #define DC_C GPIO.out_w1tc = (1 << TFT_DC) | ||||
|           #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ | ||||
|                        GPIO.out_w1ts = (1 << TFT_DC) | ||||
|         #endif | ||||
|       #else | ||||
|         #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC)
 | ||||
|         #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC)
 | ||||
|       #endif | ||||
|     #else | ||||
|       #define DC_C | ||||
|       #define DC_D | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the CS (TFT chip select) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_CS | ||||
|   #define TFT_CS -1  // Keep DMA code happy
 | ||||
|   #define CS_L       // No macro allocated so it generates no code
 | ||||
|   #define CS_H       // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if defined (TFT_PARALLEL_8_BIT) | ||||
|     #if TFT_CS >= 32 | ||||
|         #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) | ||||
|     #elif TFT_CS >= 0 | ||||
|         #define CS_L GPIO.out_w1tc = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1ts = (1 << TFT_CS) | ||||
|     #else | ||||
|       #define CS_L | ||||
|       #define CS_H | ||||
|     #endif | ||||
|   #else | ||||
|     #if (TFT_CS >= 32) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
 | ||||
|         #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ | ||||
|                      GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ | ||||
|                      GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) | ||||
|       #else | ||||
|         #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) | ||||
|         #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))
 | ||||
|       #endif | ||||
|     #elif (TFT_CS >= 0) | ||||
|       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
 | ||||
|         #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) | ||||
|       #else | ||||
|         #define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) | ||||
|         #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS)
 | ||||
|       #endif | ||||
|     #else | ||||
|       #define CS_L | ||||
|       #define CS_H | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the WR (TFT Write) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_WR) | ||||
|   #if (TFT_WR >= 32) | ||||
|     // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32
 | ||||
|     #define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32)) | ||||
|     #define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32)) | ||||
|   #elif (TFT_WR >= 0) | ||||
|     // TFT_WR, for best performance, should be in range 0-31 for single register parallel write
 | ||||
|     #define WR_L GPIO.out_w1tc = (1 << TFT_WR) | ||||
|     #define WR_H GPIO.out_w1ts = (1 << TFT_WR) | ||||
|   #else | ||||
|     #define WR_L | ||||
|     #define WR_H | ||||
|   #endif | ||||
| #else | ||||
|   #define WR_L | ||||
|   #define WR_H | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the touch screen chip select pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TOUCH_CS | ||||
|   #define T_CS_L // No macro allocated so it generates no code
 | ||||
|   #define T_CS_H // No macro allocated so it generates no code
 | ||||
| #else // XPT2046 is slow, so use slower digitalWrite here
 | ||||
|   #define T_CS_L digitalWrite(TOUCH_CS, LOW) | ||||
|   #define T_CS_H digitalWrite(TOUCH_CS, HIGH) | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Make sure SPI default pins are assigned if not specified by user or set to -1
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
| 
 | ||||
|   #ifdef USE_HSPI_PORT | ||||
| 
 | ||||
|     #ifndef TFT_MISO | ||||
|       #define TFT_MISO -1 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_MOSI | ||||
|       #define TFT_MOSI 13 | ||||
|     #endif | ||||
|     #if (TFT_MOSI == -1) | ||||
|       #undef TFT_MOSI | ||||
|       #define TFT_MOSI 13 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_SCLK | ||||
|       #define TFT_SCLK 14 | ||||
|     #endif | ||||
|     #if (TFT_SCLK == -1) | ||||
|       #undef TFT_SCLK | ||||
|       #define TFT_SCLK 14 | ||||
|     #endif | ||||
| 
 | ||||
|   #else // VSPI port
 | ||||
| 
 | ||||
|     #ifndef TFT_MISO | ||||
|       #define TFT_MISO -1 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_MOSI | ||||
|       #define TFT_MOSI 23 | ||||
|     #endif | ||||
|     #if (TFT_MOSI == -1) | ||||
|       #undef TFT_MOSI | ||||
|       #define TFT_MOSI 23 | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef TFT_SCLK | ||||
|       #define TFT_SCLK 18 | ||||
|     #endif | ||||
|     #if (TFT_SCLK == -1) | ||||
|       #undef TFT_SCLK | ||||
|       #define TFT_SCLK 18 | ||||
|     #endif | ||||
| 
 | ||||
|     #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2) | ||||
|       #if (TFT_MISO == -1) | ||||
|         #undef TFT_MISO | ||||
|         #define TFT_MISO TFT_MOSI | ||||
|       #endif | ||||
|     #endif | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the parallel bus interface chip pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
| 
 | ||||
|   #if (TFT_D0 >= 32) // If D0 is a high GPIO assume all other data bits are high GPIO
 | ||||
|     #define MASK_OFFSET 32 | ||||
|     #define GPIO_CLR_REG GPIO.out1_w1tc.val | ||||
|     #define GPIO_SET_REG GPIO.out1_w1ts.val | ||||
|   #else | ||||
|     #define MASK_OFFSET 0 | ||||
|     #define GPIO_CLR_REG GPIO.out_w1tc | ||||
|     #define GPIO_SET_REG GPIO.out_w1ts | ||||
|   #endif | ||||
| 
 | ||||
|   // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically
 | ||||
|   // can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF
 | ||||
|   #define PARALLEL_INIT_TFT_DATA_BUS               \ | ||||
|   for (int32_t c = 0; c<256; c++)                  \ | ||||
|   {                                                \ | ||||
|     xset_mask[c] = 0;                              \ | ||||
|     if ( c & 0x01 ) xset_mask[c] |= (1 << (TFT_D0-MASK_OFFSET)); \ | ||||
|     if ( c & 0x02 ) xset_mask[c] |= (1 << (TFT_D1-MASK_OFFSET)); \ | ||||
|     if ( c & 0x04 ) xset_mask[c] |= (1 << (TFT_D2-MASK_OFFSET)); \ | ||||
|     if ( c & 0x08 ) xset_mask[c] |= (1 << (TFT_D3-MASK_OFFSET)); \ | ||||
|     if ( c & 0x10 ) xset_mask[c] |= (1 << (TFT_D4-MASK_OFFSET)); \ | ||||
|     if ( c & 0x20 ) xset_mask[c] |= (1 << (TFT_D5-MASK_OFFSET)); \ | ||||
|     if ( c & 0x40 ) xset_mask[c] |= (1 << (TFT_D6-MASK_OFFSET)); \ | ||||
|     if ( c & 0x80 ) xset_mask[c] |= (1 << (TFT_D7-MASK_OFFSET)); \ | ||||
|   }                                                              \ | ||||
| 
 | ||||
|   // Mask for the 8 data bits to set pin directions
 | ||||
|   #define GPIO_DIR_MASK ((1 << (TFT_D0-MASK_OFFSET)) | (1 << (TFT_D1-MASK_OFFSET)) | (1 << (TFT_D2-MASK_OFFSET)) | (1 << (TFT_D3-MASK_OFFSET)) | (1 << (TFT_D4-MASK_OFFSET)) | (1 << (TFT_D5-MASK_OFFSET)) | (1 << (TFT_D6-MASK_OFFSET)) | (1 << (TFT_D7-MASK_OFFSET))) | ||||
| 
 | ||||
|   #if (TFT_WR >= 32) | ||||
|     #if (TFT_D0 >= 32) | ||||
|       // Data bits and the write line are cleared to 0 in one step (1.25x faster)
 | ||||
|       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << (TFT_WR-32))) | ||||
|     #elif (TFT_D0 >= 0) | ||||
|       // Data bits and the write line are cleared sequentially
 | ||||
|       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L | ||||
|     #endif | ||||
|   #elif (TFT_WR >= 0) | ||||
|     #if (TFT_D0 >= 32) | ||||
|       // Data bits and the write line are cleared sequentially
 | ||||
|       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L | ||||
|     #elif (TFT_D0 >= 0) | ||||
|       // Data bits and the write line are cleared to 0 in one step (1.25x faster)
 | ||||
|       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) | ||||
|     #endif | ||||
|   #else | ||||
|     #define GPIO_OUT_CLR_MASK | ||||
|   #endif | ||||
| 
 | ||||
|   // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM
 | ||||
|   #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time
 | ||||
| 
 | ||||
|   // Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test
 | ||||
|   /*#define set_mask(C) (((C)&0x80)>>7)<<TFT_D7 | (((C)&0x40)>>6)<<TFT_D6 | (((C)&0x20)>>5)<<TFT_D5 | (((C)&0x10)>>4)<<TFT_D4 | \
 | ||||
|                         (((C)&0x08)>>3)<<TFT_D3 | (((C)&0x04)>>2)<<TFT_D2 | (((C)&0x02)>>1)<<TFT_D1 | (((C)&0x01)>>0)<<TFT_D0 | ||||
|   //*/
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)  GPIO_CLR_REG =  GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t)(C)); WR_H | ||||
| 
 | ||||
|   #if defined (SSD1963_DRIVER) | ||||
| 
 | ||||
|     // Write 18 bit color to TFT
 | ||||
|     #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0xF800)>> 8)); WR_H; \ | ||||
|                             GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \ | ||||
|                             GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H | ||||
| 
 | ||||
|     // 18 bit color write with swapped bytes
 | ||||
|     #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) | ||||
| 
 | ||||
|   #else | ||||
| 
 | ||||
|     #ifdef PSEUDO_16_BIT | ||||
|       // One write strobe for both bytes
 | ||||
|       #define tft_Write_16(C)  GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
|       #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H | ||||
|     #else | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                               GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                                GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H | ||||
|     #endif | ||||
| 
 | ||||
|   #endif | ||||
| 
 | ||||
|   // Write 32 bits to TFT
 | ||||
|   #define tft_Write_32(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 24)); WR_H; \ | ||||
|                           GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 16)); WR_H; \ | ||||
|                           GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >>  8)); WR_H; \ | ||||
|                           GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >>  0)); WR_H | ||||
| 
 | ||||
|   // Write two concatenated 16 bit values to TFT
 | ||||
|   #define tft_Write_32C(C,D) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                              GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                              GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((D) >> 8)); WR_H; \ | ||||
|                              GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((D) >> 0)); WR_H | ||||
| 
 | ||||
|   // Write 16 bit value twice to TFT - used by drawPixel()
 | ||||
|   #define tft_Write_32D(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \ | ||||
|                            GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ | ||||
|                            GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H | ||||
| 
 | ||||
|    // Read pin
 | ||||
|   #ifdef TFT_RD | ||||
|     #if (TFT_RD >= 32) | ||||
|       #define RD_L GPIO.out1_w1tc.val = (1 << (TFT_RD - 32)) | ||||
|       #define RD_H GPIO.out1_w1ts.val = (1 << (TFT_RD - 32)) | ||||
|     #elif (TFT_RD >= 0) | ||||
|       #define RD_L GPIO.out_w1tc = (1 << TFT_RD) | ||||
|       //#define RD_L digitalWrite(TFT_WR, LOW)
 | ||||
|       #define RD_H GPIO.out_w1ts = (1 << TFT_RD) | ||||
|       //#define RD_H digitalWrite(TFT_WR, HIGH)
 | ||||
|     #else | ||||
|       #define RD_L | ||||
|       #define RD_H | ||||
|     #endif | ||||
|   #else | ||||
|     #define TFT_RD -1 | ||||
|     #define RD_L | ||||
|     #define RD_H | ||||
|   #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI948x TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)   spi.transfer(C) | ||||
| 
 | ||||
|   // Convert 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|   #define tft_Write_16(C)  spi.transfer(((C) & 0xF800)>>8); \ | ||||
|                            spi.transfer(((C) & 0x07E0)>>3); \ | ||||
|                            spi.transfer(((C) & 0x001F)<<3) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #define tft_Write_16N(C) tft_Write_16(C) | ||||
| 
 | ||||
|   // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|   #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ | ||||
|                            spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ | ||||
|                            spi.transfer(((C) & 0x1F00)>>5) | ||||
| 
 | ||||
|   // Write 32 bits to TFT
 | ||||
|   #define tft_Write_32(C)  spi.write32(C) | ||||
| 
 | ||||
|   // Write two concatenated 16 bit values to TFT
 | ||||
|   #define tft_Write_32C(C,D) spi.write32((C)<<16 | (D)) | ||||
| 
 | ||||
|   // Write 16 bit value twice to TFT
 | ||||
|   #define tft_Write_32D(C)  spi.write32((C)<<16 | (C)) | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to an Raspberry Pi TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif  defined (RPI_DISPLAY_TYPE) | ||||
| 
 | ||||
|   // ESP32 low level SPI writes for 8, 16 and 32 bit values
 | ||||
|   // to avoid the function call overhead
 | ||||
|   #define TFT_WRITE_BITS(D, B) \ | ||||
|   WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ | ||||
|   WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ | ||||
|   SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| 
 | ||||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #define tft_Write_16N(C) tft_Write_16(C) | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D)  TFT_WRITE_BITS((C)<<24 | (C), 32); \ | ||||
|                               TFT_WRITE_BITS((D)<<24 | (D), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) tft_Write_32C(C,C) | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros for all other SPI displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #else | ||||
| /* Old macros
 | ||||
|   // ESP32 low level SPI writes for 8, 16 and 32 bit values
 | ||||
|   // to avoid the function call overhead
 | ||||
|   #define TFT_WRITE_BITS(D, B) \ | ||||
|   WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ | ||||
|   WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ | ||||
|   SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ | ||||
|   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); | ||||
| 
 | ||||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| //*/
 | ||||
| //* Replacement slimmer macros
 | ||||
|   #if !defined(CONFIG_IDF_TARGET_ESP32S3) | ||||
|     #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;  \ | ||||
|                                *_spi_w = D;              \ | ||||
|                                *_spi_cmd = SPI_USR;      \ | ||||
|                         while (*_spi_cmd & SPI_USR); | ||||
|   #else | ||||
|     #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;  \ | ||||
|                                *_spi_w = D;              \ | ||||
|                                *_spi_cmd = SPI_UPDATE;   \ | ||||
|                         while (*_spi_cmd & SPI_UPDATE);  \ | ||||
|                                *_spi_cmd = SPI_USR;      \ | ||||
|                         while (*_spi_cmd & SPI_USR); | ||||
|   #endif | ||||
|   // Write 8 bits
 | ||||
|   #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) | ||||
| 
 | ||||
|   // Write 16 bits with corrected endianness for 16 bit colours
 | ||||
|   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) | ||||
| 
 | ||||
|   // Future option for transfer without wait
 | ||||
|   #if !defined(CONFIG_IDF_TARGET_ESP32S3) | ||||
|     #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1;    \ | ||||
|                            *_spi_w = ((C)<<8 | (C)>>8); \ | ||||
|                            *_spi_cmd = SPI_USR; | ||||
| #else | ||||
|     #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1;    \ | ||||
|                            *_spi_w = ((C)<<8 | (C)>>8); \ | ||||
|                            *_spi_cmd = SPI_UPDATE;      \ | ||||
|                     while (*_spi_cmd & SPI_UPDATE);     \ | ||||
|                            *_spi_cmd = SPI_USR; | ||||
| #endif | ||||
| 
 | ||||
|   // Write 16 bits
 | ||||
|   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) | ||||
| 
 | ||||
|   // Write 32 bits
 | ||||
|   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) | ||||
| 
 | ||||
|   // Write two address coordinates
 | ||||
|   #define tft_Write_32C(C,D)  TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
|   // Write same value twice
 | ||||
|   #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) | ||||
| 
 | ||||
| //*/
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef tft_Write_16N | ||||
|   #define tft_Write_16N tft_Write_16 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to read from display using SPI or software SPI
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) | ||||
|   // Read from display using SPI or software SPI
 | ||||
|   // Use a SPI read transfer
 | ||||
|   #define tft_Read_8() spi.transfer(0) | ||||
| #endif | ||||
| 
 | ||||
| // Concatenate a byte sequence A,B,C,D to CDAB, P is a uint8_t pointer
 | ||||
| #define DAT8TO32(P) ( (uint32_t)P[0]<<8 | P[1] | P[2]<<24 | P[3]<<16 ) | ||||
| 
 | ||||
| #endif // Header end
 | ||||
|  | @ -109,7 +109,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ | |||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9488_DRIVER) | ||||
| #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -304,7 +304,7 @@ return; | |||
|     SPI1U1 = (511 << SPILMOSI); | ||||
|     while(len>31) | ||||
|     { | ||||
| #if defined SPI_FREQUENCY && (SPI_FREQUENCY == 80000000) | ||||
| #if (defined (SPI_FREQUENCY) && (SPI_FREQUENCY == 80000000)) | ||||
|       if(SPI1CMD & SPIBUSY) // added to sync with flag change
 | ||||
| #endif | ||||
|       while(SPI1CMD & SPIBUSY) {} | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ | |||
| #define DMA_BUSY_CHECK // DMA not available, leave blank
 | ||||
| 
 | ||||
| // Initialise processor specific SPI functions, used by init()
 | ||||
| #if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266) | ||||
| #if (!defined (SUPPORT_TRANSACTIONS) && defined (ARDUINO_ARCH_ESP8266)) | ||||
|   #define INIT_TFT_DATA_BUS \ | ||||
|     spi.setBitOrder(MSBFIRST); \ | ||||
|     spi.setDataMode(TFT_SPI_MODE); \ | ||||
|  | @ -115,9 +115,9 @@ | |||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to an ILI9488 TFT
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI948x TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if  defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
 | ||||
| #if  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)   spi.transfer(C) | ||||
|  | @ -191,6 +191,11 @@ | |||
|   SPI1CMD |= SPIBUSY; \ | ||||
|   while(SPI1CMD & SPIBUSY) {;} | ||||
| 
 | ||||
|   #define tft_Write_16N(C) \ | ||||
|   SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \ | ||||
|   SPI1W0 = ((C)<<8 | (C)>>8); \ | ||||
|   SPI1CMD |= SPIBUSY | ||||
| 
 | ||||
|   #define tft_Write_16S(C) \ | ||||
|   SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \ | ||||
|   SPI1W0 = C; \ | ||||
|  | @ -217,6 +222,10 @@ | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef tft_Write_16N | ||||
|   #define tft_Write_16N tft_Write_16 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to read from display using SPI or software SPI
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  |  | |||
|  | @ -7,7 +7,11 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Select the SPI port to use
 | ||||
| SPIClass& spi = SPI; | ||||
| #ifdef TFT_SPI_PORT | ||||
|   SPIClass& spi = TFT_SPI_PORT; | ||||
| #else | ||||
|   SPIClass& spi = SPI; | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) | ||||
|  | @ -142,7 +146,7 @@ uint8_t TFT_eSPI::readByte(void) | |||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (RPI_WRITE_STROBE)  // For RPi TFT with write strobe                      ############# UNTESTED ###################
 | ||||
| #elif defined (RPI_WRITE_STROBE)  // For RPi TFT with write strobe                      
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -168,7 +172,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) | |||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9488_DRIVER) // For 24 bit SPI colour TFT                             ############# UNTESTED ###################
 | ||||
| #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour                         
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -212,7 +216,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | |||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #else //                   Standard SPI 16 bit colour TFT                                                 All Tested
 | ||||
| #else //                   Standard SPI 16 bit colour TFT                               
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -242,7 +246,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | |||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| //                                DMA FUNCTIONS                                                   All tested on STM32F767
 | ||||
| //                                DMA FUNCTIONS                                         
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| //                Placeholder for DMA functions
 | ||||
|  |  | |||
|  | @ -2,6 +2,9 @@ | |||
|         //       TFT_eSPI generic driver functions        //
 | ||||
|         ////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // This is a generic driver for Arduino boards, it supports SPI interface displays
 | ||||
| // 8 bit parallel interface to TFT is not supported for generic processors
 | ||||
| 
 | ||||
| #ifndef _TFT_eSPI_GENERICH_ | ||||
| #define _TFT_eSPI_GENERICH_ | ||||
| 
 | ||||
|  | @ -55,6 +58,13 @@ | |||
|   #define CS_H digitalWrite(TFT_CS, HIGH) | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Make sure TFT_RD is defined if not used to avoid an error message
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_RD | ||||
|   #define TFT_RD -1 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the WR (TFT Write) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -82,9 +92,9 @@ | |||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to an ILI9488 TFT
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI948x TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if  defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
 | ||||
| #if  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C)   spi.transfer(C) | ||||
|  | @ -112,7 +122,26 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #else | ||||
|   #if  defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers
 | ||||
|     #define tft_Write_8(C)     spi.transfer(0); spi.transfer(C) | ||||
|     #define tft_Write_8(C)   spi.transfer(C); spi.transfer(C) | ||||
|     #define tft_Write_16(C)  spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0)) | ||||
|     #define tft_Write_16S(C) spi.transfer((uint8_t)((C)>>0));spi.transfer((uint8_t)((C)>>8)) | ||||
| 
 | ||||
|     #define tft_Write_32(C) \ | ||||
|       tft_Write_16((uint16_t) ((C)>>16)); \ | ||||
|       tft_Write_16((uint16_t) ((C)>>0)) | ||||
| 
 | ||||
|     #define tft_Write_32C(C,D) \ | ||||
|       spi.transfer(0); spi.transfer((C)>>8); \ | ||||
|       spi.transfer(0); spi.transfer((C)>>0); \ | ||||
|       spi.transfer(0); spi.transfer((D)>>8); \ | ||||
|       spi.transfer(0); spi.transfer((D)>>0) | ||||
| 
 | ||||
|     #define tft_Write_32D(C) \ | ||||
|       spi.transfer(0); spi.transfer((C)>>8); \ | ||||
|       spi.transfer(0); spi.transfer((C)>>0); \ | ||||
|       spi.transfer(0); spi.transfer((C)>>8); \ | ||||
|       spi.transfer(0); spi.transfer((C)>>0) | ||||
| 
 | ||||
|   #else | ||||
|     #ifdef __AVR__ // AVR processors do not have 16 bit transfer
 | ||||
|       #define tft_Write_8(C)   {SPDR=(C); while (!(SPSR&_BV(SPIF)));} | ||||
|  | @ -123,19 +152,23 @@ | |||
|       #define tft_Write_16(C)  spi.transfer16(C) | ||||
|       #define tft_Write_16S(C) spi.transfer16(((C)>>8) | ((C)<<8)) | ||||
|     #endif // AVR    
 | ||||
| 
 | ||||
|     #define tft_Write_32(C) \ | ||||
|     tft_Write_16((uint16_t) ((C)>>16)); \ | ||||
|     tft_Write_16((uint16_t) ((C)>>0)) | ||||
| 
 | ||||
|     #define tft_Write_32C(C,D) \ | ||||
|     tft_Write_16((uint16_t) (C)); \ | ||||
|     tft_Write_16((uint16_t) (D)) | ||||
| 
 | ||||
|     #define tft_Write_32D(C) \ | ||||
|     tft_Write_16((uint16_t) (C)); \ | ||||
|     tft_Write_16((uint16_t) (C)) | ||||
|   #endif // RPI_DISPLAY_TYPE
 | ||||
| #endif | ||||
| 
 | ||||
|   #define tft_Write_32(C) \ | ||||
|   tft_Write_16((uint16_t) ((C)>>16)); \ | ||||
|   tft_Write_16((uint16_t) ((C)>>0)) | ||||
| 
 | ||||
|   #define tft_Write_32C(C,D) \ | ||||
|   tft_Write_16((uint16_t) (C)); \ | ||||
|   tft_Write_16((uint16_t) (D)) | ||||
| 
 | ||||
|   #define tft_Write_32D(C) \ | ||||
|   tft_Write_16((uint16_t) (C)); \ | ||||
|   tft_Write_16((uint16_t) (C)) | ||||
| #ifndef tft_Write_16N | ||||
|   #define tft_Write_16N tft_Write_16 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  |  | |||
|  | @ -0,0 +1,738 @@ | |||
|         ////////////////////////////////////////////////////
 | ||||
|         //       TFT_eSPI generic driver functions        //
 | ||||
|         ////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Global variables
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #if !defined (RP2040_PIO_INTERFACE) // SPI
 | ||||
| 
 | ||||
|   // Select the SPI port and board package to use
 | ||||
|   #ifdef ARDUINO_ARCH_MBED | ||||
|     // Arduino RP2040 board package
 | ||||
|     MbedSPI spi = MbedSPI(TFT_MISO, TFT_MOSI, TFT_SCLK); | ||||
|   #else | ||||
|     // Community RP2040 board package by Earle Philhower
 | ||||
|     //SPIClass& spi = SPI; // will use board package default pins
 | ||||
|     SPIClassRP2040 spi = SPIClassRP2040(SPI_X, TFT_MISO, -1, TFT_SCLK, TFT_MOSI); | ||||
|   #endif | ||||
| 
 | ||||
| #else // PIO interface used (8 bit parallel or SPI)
 | ||||
| 
 | ||||
|   #ifdef RP2040_PIO_SPI | ||||
|     #if  defined (SPI_18BIT_DRIVER) | ||||
|       // SPI PIO code for 18 bit colour transmit
 | ||||
|       #include "pio_SPI_18bit.pio.h" | ||||
|     #else | ||||
|       // SPI PIO code for 16 bit colour transmit
 | ||||
|       #include "pio_SPI.pio.h" | ||||
|     #endif | ||||
|   #elif defined (TFT_PARALLEL_8_BIT) | ||||
|     #if defined (SSD1963_DRIVER) | ||||
|       // PIO code for 8 bit parallel interface (18 bit colour)
 | ||||
|       #include "pio_8bit_parallel_18bpp.pio.h" | ||||
|     #else | ||||
|       // PIO code for 8 bit parallel interface (16 bit colour)
 | ||||
|       #include "pio_8bit_parallel.pio.h" | ||||
|     #endif | ||||
|   #else // must be TFT_PARALLEL_16_BIT
 | ||||
|     // PIO code for 16 bit parallel interface (16 bit colour)
 | ||||
|     #include "pio_16bit_parallel.pio.h" | ||||
|   #endif | ||||
| 
 | ||||
|   // Board package specific differences
 | ||||
|   #ifdef ARDUINO_ARCH_MBED | ||||
|     // Not supported at the moment
 | ||||
|     #error The Arduino RP2040 MBED board package is not supported when PIO is used. Use the community package by Earle Philhower. | ||||
|   #endif | ||||
| 
 | ||||
|   // Community RP2040 board package by Earle Philhower
 | ||||
|   PIO tft_pio = pio0;     // Code will try both pio's to find a free SM
 | ||||
|   int8_t pio_sm = 0;  // pioinit will claim a free one
 | ||||
|   // Updated later with the loading offset of the PIO program.
 | ||||
|   uint32_t program_offset  = 0; | ||||
| 
 | ||||
|   // SM stalled mask
 | ||||
|   uint32_t pull_stall_mask = 0; | ||||
| 
 | ||||
|   // SM jump instructions to change SM behaviour
 | ||||
|   uint32_t pio_instr_jmp8  = 0; | ||||
|   uint32_t pio_instr_fill  = 0; | ||||
|   uint32_t pio_instr_addr  = 0; | ||||
| 
 | ||||
|   // SM "set" instructions to control DC control signal
 | ||||
|   uint32_t pio_instr_set_dc = 0; | ||||
|   uint32_t pio_instr_clr_dc = 0; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef RP2040_DMA | ||||
|   int32_t            dma_tx_channel; | ||||
|   dma_channel_config dma_tx_config; | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (TFT_SDA_READ) && !defined (RP2040_PIO_INTERFACE) | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           tft_Read_8 | ||||
| ** Description:             Bit bashed SPI to read bidirectional SDA line | ||||
| ***************************************************************************************/ | ||||
| uint8_t TFT_eSPI::tft_Read_8(void) | ||||
| { | ||||
|   uint8_t  ret = 0; | ||||
| 
 | ||||
|   /*
 | ||||
|   for (uint8_t i = 0; i < 8; i++) {  // read results
 | ||||
|     ret <<= 1; | ||||
|     SCLK_L; | ||||
|     if (digitalRead(TFT_MOSI)) ret |= 1; | ||||
|     SCLK_H; | ||||
|   } | ||||
|   */ | ||||
|    | ||||
|   ret = spi.transfer(0x00); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           beginSDA | ||||
| ** Description:             Detach SPI from pin to permit software SPI | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::begin_SDA_Read(void) | ||||
| { | ||||
|   // Release configured SPI port for SDA read
 | ||||
|   spi.end(); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           endSDA | ||||
| ** Description:             Attach SPI pins after software SPI | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::end_SDA_Read(void) | ||||
| { | ||||
|   // Configure SPI port ready for next TFT access
 | ||||
|   spi.begin(); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // #if defined (TFT_SDA_READ)
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined (RP2040_PIO_INTERFACE) | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifdef RP2040_PIO_SPI | ||||
| void pioinit(uint32_t clock_freq) { | ||||
| 
 | ||||
|   // Find a free SM on one of the PIO's
 | ||||
|   tft_pio = pio0; | ||||
|    | ||||
|   /*
 | ||||
|   pio_sm = pio_claim_unused_sm(tft_pio, false); // false means don't panic
 | ||||
|   // Try pio1 if SM not found
 | ||||
|   if (pio_sm < 0) { | ||||
|     tft_pio = pio1; | ||||
|     pio_sm = pio_claim_unused_sm(tft_pio, true); // panic this time if no SM is free
 | ||||
|   } | ||||
|   */ | ||||
| 
 | ||||
|   // Find enough free space on one of the PIO's
 | ||||
|   tft_pio = pio0; | ||||
|   if (!pio_can_add_program(tft_pio, &tft_io_program)) { | ||||
|     tft_pio = pio1; | ||||
|     if (!pio_can_add_program(tft_pio, &tft_io_program)) { | ||||
|       Serial.println("No room for PIO program!"); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   pio_sm = pio_claim_unused_sm(tft_pio, false); | ||||
| 
 | ||||
|   // Load the PIO program
 | ||||
|   program_offset = pio_add_program(tft_pio, &tft_io_program); | ||||
| 
 | ||||
|   // Associate pins with the PIO
 | ||||
|   pio_gpio_init(tft_pio, TFT_DC); | ||||
|   pio_gpio_init(tft_pio, TFT_SCLK); | ||||
|   pio_gpio_init(tft_pio, TFT_MOSI); | ||||
| 
 | ||||
|   // Configure the pins to be outputs
 | ||||
|   pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_DC, 1, true); | ||||
|   pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_SCLK, 1, true); | ||||
|   pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_MOSI, 1, true); | ||||
| 
 | ||||
|   // Configure the state machine
 | ||||
|   pio_sm_config c = tft_io_program_get_default_config(program_offset); | ||||
| 
 | ||||
|   sm_config_set_set_pins(&c, TFT_DC, 1); | ||||
|   // Define the single side-set pin
 | ||||
|   sm_config_set_sideset_pins(&c, TFT_SCLK); | ||||
|   // Define the pin used for data output
 | ||||
|   sm_config_set_out_pins(&c, TFT_MOSI, 1); | ||||
|   // Set clock divider, frequency is set up to 2% faster than specified, or next division down
 | ||||
|   uint16_t clock_div = 0.98 + clock_get_hz(clk_sys) / (clock_freq * 2.0); // 2 cycles per bit
 | ||||
|   sm_config_set_clkdiv(&c, clock_div); | ||||
|   // Make a single 8 words FIFO from the 4 words TX and RX FIFOs
 | ||||
|   sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); | ||||
|   // The OSR register shifts to the left, sm designed to send MS byte of a colour first, autopull off
 | ||||
|   sm_config_set_out_shift(&c, false, false, 0); | ||||
|   // Now load the configuration
 | ||||
|   pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_tx, &c); | ||||
| 
 | ||||
|   // Start the state machine.
 | ||||
|   pio_sm_set_enabled(tft_pio, pio_sm, true); | ||||
| 
 | ||||
|   // Create the pull stall bit mask
 | ||||
|   pull_stall_mask = 1u << (PIO_FDEBUG_TXSTALL_LSB + pio_sm); | ||||
| 
 | ||||
|   // Create the assembler instruction for the jump to byte send routine
 | ||||
|   pio_instr_jmp8  = pio_encode_jmp(program_offset + tft_io_offset_start_8); | ||||
|   pio_instr_fill  = pio_encode_jmp(program_offset + tft_io_offset_block_fill); | ||||
|   pio_instr_addr  = pio_encode_jmp(program_offset + tft_io_offset_set_addr_window); | ||||
| 
 | ||||
|   pio_instr_set_dc = pio_encode_set((pio_src_dest)0, 1); | ||||
|   pio_instr_clr_dc = pio_encode_set((pio_src_dest)0, 0); | ||||
| } | ||||
| #else // 8 or 16 bit parallel
 | ||||
| void pioinit(uint16_t clock_div, uint16_t fract_div) { | ||||
| 
 | ||||
|   // Find a free SM on one of the PIO's
 | ||||
|   tft_pio = pio0; | ||||
|   pio_sm = pio_claim_unused_sm(tft_pio, false); // false means don't panic
 | ||||
|   // Try pio1 if SM not found
 | ||||
|   if (pio_sm < 0) { | ||||
|     tft_pio = pio1; | ||||
|     pio_sm = pio_claim_unused_sm(tft_pio, true); // panic this time if no SM is free
 | ||||
|   } | ||||
| /*
 | ||||
|   // Find enough free space on one of the PIO's
 | ||||
|   tft_pio = pio0; | ||||
|   if (!pio_can_add_program(tft_pio, &tft_io_program) { | ||||
|     tft_pio = pio1; | ||||
|     if (!pio_can_add_program(tft_pio, &tft_io_program) { | ||||
|       Serial.println("No room for PIO program!"); | ||||
|       while(1) delay(100); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
| */ | ||||
|   #if defined (TFT_PARALLEL_8_BIT) | ||||
|     uint8_t bits = 8; | ||||
|   #else // must be TFT_PARALLEL_16_BIT
 | ||||
|     uint8_t bits = 16; | ||||
|   #endif | ||||
|    | ||||
|   // Load the PIO program
 | ||||
|   program_offset = pio_add_program(tft_pio, &tft_io_program); | ||||
| 
 | ||||
|   // Associate pins with the PIO
 | ||||
|   pio_gpio_init(tft_pio, TFT_DC); | ||||
|   pio_gpio_init(tft_pio, TFT_WR); | ||||
| 
 | ||||
|   for (int i = 0; i < bits; i++) { | ||||
|     pio_gpio_init(tft_pio, TFT_D0 + i); | ||||
|   } | ||||
| 
 | ||||
|   // Configure the pins to be outputs
 | ||||
|   pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_DC, 1, true); | ||||
|   pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_WR, 1, true); | ||||
|   pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_D0, bits, true); | ||||
| 
 | ||||
|   // Configure the state machine
 | ||||
|   pio_sm_config c = tft_io_program_get_default_config(program_offset); | ||||
|   // Define the set pin
 | ||||
|   sm_config_set_set_pins(&c, TFT_DC, 1); | ||||
|   // Define the single side-set pin
 | ||||
|   sm_config_set_sideset_pins(&c, TFT_WR); | ||||
|   // Define the consecutive pins that are used for data output
 | ||||
|   sm_config_set_out_pins(&c, TFT_D0, bits); | ||||
|   // Set clock divider and fractional divider
 | ||||
|   sm_config_set_clkdiv_int_frac(&c, clock_div, fract_div); | ||||
|   // Make a single 8 words FIFO from the 4 words TX and RX FIFOs
 | ||||
|   sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); | ||||
|   // The OSR register shifts to the left, sm designed to send MS byte of a colour first
 | ||||
|   sm_config_set_out_shift(&c, false, false, 0); | ||||
|   // Now load the configuration
 | ||||
|   pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_tx, &c); | ||||
| 
 | ||||
|   // Start the state machine.
 | ||||
|   pio_sm_set_enabled(tft_pio, pio_sm, true); | ||||
| 
 | ||||
|   // Create the pull stall bit mask
 | ||||
|   pull_stall_mask = 1u << (PIO_FDEBUG_TXSTALL_LSB + pio_sm); | ||||
| 
 | ||||
|   // Create the instructions for the jumps to send routines
 | ||||
|   pio_instr_jmp8  = pio_encode_jmp(program_offset + tft_io_offset_start_8); | ||||
|   pio_instr_fill  = pio_encode_jmp(program_offset + tft_io_offset_block_fill); | ||||
|   pio_instr_addr  = pio_encode_jmp(program_offset + tft_io_offset_set_addr_window); | ||||
| 
 | ||||
|   // Create the instructions to set and clear the DC signal
 | ||||
|   pio_instr_set_dc = pio_encode_set((pio_src_dest)0, 1); | ||||
|   pio_instr_clr_dc = pio_encode_set((pio_src_dest)0, 0); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for generic processor and parallel display | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| #ifdef RP2040_PIO_PUSHBLOCK | ||||
| // PIO handles pixel block fill writes
 | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) | ||||
| { | ||||
| #if  defined (SPI_18BIT_DRIVER) || (defined (SSD1963_DRIVER) && defined (TFT_PARALLEL_8_BIT)) | ||||
|   uint32_t col = ((color & 0xF800)<<8) | ((color & 0x07E0)<<5) | ((color & 0x001F)<<3); | ||||
|   if (len) { | ||||
|     WAIT_FOR_STALL; | ||||
|     tft_pio->sm[pio_sm].instr = pio_instr_fill; | ||||
| 
 | ||||
|     TX_FIFO = col; | ||||
|     TX_FIFO = --len; // Decrement first as PIO sends n+1
 | ||||
|   } | ||||
| #else | ||||
|   if (len) { | ||||
|     WAIT_FOR_STALL; | ||||
|     tft_pio->sm[pio_sm].instr = pio_instr_fill; | ||||
| 
 | ||||
|     TX_FIFO = color; | ||||
|     TX_FIFO = --len; // Decrement first as PIO sends n+1
 | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
| 
 | ||||
|   while (len > 4) { | ||||
|     // 5 seems to be the optimum for maximum transfer rate
 | ||||
|     WAIT_FOR_FIFO_FREE(5); | ||||
|     TX_FIFO = color; | ||||
|     TX_FIFO = color; | ||||
|     TX_FIFO = color; | ||||
|     TX_FIFO = color; | ||||
|     TX_FIFO = color; | ||||
| 
 | ||||
|     len -= 5; | ||||
|   } | ||||
| 
 | ||||
|   if (len) { | ||||
|     // There could be a maximum of 4 words left  to send
 | ||||
|     WAIT_FOR_FIFO_FREE(4); | ||||
|     while (len--) TX_FIFO = color; | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for generic processor and parallel display | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| #if  defined (SPI_18BIT_DRIVER) || (defined (SSD1963_DRIVER) && defined (TFT_PARALLEL_8_BIT)) | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   if (_swapBytes) { | ||||
|     while ( len-- ) { | ||||
|       uint32_t col = *data++; | ||||
|       tft_Write_16(col); | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     while ( len-- ) { | ||||
|       uint32_t col = *data++; | ||||
|       tft_Write_16S(col); | ||||
|     } | ||||
|   } | ||||
| #else | ||||
|   const uint16_t *data = (uint16_t*)data_in; | ||||
| 
 | ||||
|   // PIO sends MS byte first, so bytes are already swapped on transmit
 | ||||
|   if(_swapBytes) { | ||||
|     while (len > 4) { | ||||
|       WAIT_FOR_FIFO_FREE(5); | ||||
|       TX_FIFO = data[0]; | ||||
|       TX_FIFO = data[1]; | ||||
|       TX_FIFO = data[2]; | ||||
|       TX_FIFO = data[3]; | ||||
|       TX_FIFO = data[4]; | ||||
|       data += 5; | ||||
|       len  -= 5; | ||||
|     } | ||||
| 
 | ||||
|     if (len) { | ||||
|       WAIT_FOR_FIFO_FREE(4); | ||||
|       while(len--) TX_FIFO = *data++; | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     while (len > 4) { | ||||
|       WAIT_FOR_FIFO_FREE(5); | ||||
|       TX_FIFO = data[0] << 8 | data[0] >> 8; | ||||
|       TX_FIFO = data[1] << 8 | data[1] >> 8; | ||||
|       TX_FIFO = data[2] << 8 | data[2] >> 8; | ||||
|       TX_FIFO = data[3] << 8 | data[3] >> 8; | ||||
|       TX_FIFO = data[4] << 8 | data[4] >> 8; | ||||
|       data += 5; | ||||
|       len  -= 5; | ||||
|     } | ||||
| 
 | ||||
|     if (len) { | ||||
|       WAIT_FOR_FIFO_FREE(4); | ||||
|       while(len--) { | ||||
|         TX_FIFO = *data << 8 | *data >> 8; | ||||
|         data++; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           GPIO direction control  - supports class functions | ||||
| ** Description:             Set parallel bus to INPUT or OUTPUT | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) | ||||
| { | ||||
|   // Avoid warnings
 | ||||
|   mask = mask; | ||||
|   mode = mode; | ||||
| /*
 | ||||
|   // mask is unused for generic processor
 | ||||
|   // Arduino native functions suited well to a generic driver
 | ||||
|   pinMode(TFT_D0, mode); | ||||
|   pinMode(TFT_D1, mode); | ||||
|   pinMode(TFT_D2, mode); | ||||
|   pinMode(TFT_D3, mode); | ||||
|   pinMode(TFT_D4, mode); | ||||
|   pinMode(TFT_D5, mode); | ||||
|   pinMode(TFT_D6, mode); | ||||
|   pinMode(TFT_D7, mode); | ||||
| */ | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           GPIO direction control  - supports class functions | ||||
| ** Description:             Faster GPIO pin input/output switch | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode) | ||||
| { | ||||
|   // Avoid warnings
 | ||||
|   gpio = gpio; | ||||
|   mode = mode; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           read byte  - supports class functions | ||||
| ** Description:             Read a byte - parallel bus only - not supported yet | ||||
| ***************************************************************************************/ | ||||
| uint8_t TFT_eSPI::readByte(void) | ||||
| { | ||||
|   uint8_t b = 0; | ||||
| /*
 | ||||
|   busDir(0, INPUT); | ||||
|   digitalWrite(TFT_RD, LOW); | ||||
| 
 | ||||
|   b |= digitalRead(TFT_D0) << 0; | ||||
|   b |= digitalRead(TFT_D1) << 1; | ||||
|   b |= digitalRead(TFT_D2) << 2; | ||||
|   b |= digitalRead(TFT_D3) << 3; | ||||
|   b |= digitalRead(TFT_D4) << 4; | ||||
|   b |= digitalRead(TFT_D5) << 5; | ||||
|   b |= digitalRead(TFT_D6) << 6; | ||||
|   b |= digitalRead(TFT_D7) << 7; | ||||
| 
 | ||||
|   digitalWrite(TFT_RD, HIGH); | ||||
|   busDir(0, OUTPUT); | ||||
| */ | ||||
|   return b; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (RPI_WRITE_STROBE)  // For RPi TFT with write strobe
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for ESP32 or RP2040 RPi TFT | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
| 
 | ||||
|   if(len) { tft_Write_16(color); len--; } | ||||
|   while(len--) {WR_L; WR_H;} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for ESP32 or RP2040 RPi TFT | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) | ||||
| { | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
| 
 | ||||
|   if (_swapBytes) while ( len-- ) {tft_Write_16S(*data); data++;} | ||||
|   else while ( len-- ) {tft_Write_16(*data); data++;} | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for RP2040 and 3 byte RGB display | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) | ||||
| { | ||||
|   uint16_t r = (color & 0xF800)>>8; | ||||
|   uint16_t g = (color & 0x07E0)>>3; | ||||
|   uint16_t b = (color & 0x001F)<<3; | ||||
| 
 | ||||
|   // If more than 32 pixels then change to 16 bit transfers with concatenated pixels
 | ||||
|   if (len > 32) { | ||||
|     uint32_t rg = r<<8 | g; | ||||
|     uint32_t br = b<<8 | r; | ||||
|     uint32_t gb = g<<8 | b; | ||||
|     // Must wait before changing to 16 bit
 | ||||
|     while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; | ||||
|     hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); | ||||
|     while ( len > 1 ) { | ||||
|       while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = rg; | ||||
|       while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = br; | ||||
|       while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = gb; | ||||
|       len -= 2; | ||||
|     } | ||||
|     // Must wait before changing back to 8 bit
 | ||||
|     while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; | ||||
|     hw_write_masked(&spi_get_hw(SPI_X)->cr0, (8 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); | ||||
|   } | ||||
| 
 | ||||
|   // Mop up the remaining pixels
 | ||||
|   while ( len-- ) {tft_Write_8N(r);tft_Write_8N(g);tft_Write_8N(b);} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for RP2040 and 3 byte RGB display | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
| 
 | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   if (_swapBytes) { | ||||
|     while ( len-- ) { | ||||
|       uint32_t col = *data++; | ||||
|       tft_Write_16(col); | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     while ( len-- ) { | ||||
|       uint32_t col = *data++; | ||||
|       tft_Write_16S(col); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #else //                   Standard SPI 16 bit colour TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushBlock - for RP2040 | ||||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
|   while(len--) | ||||
|   { | ||||
|     while (!spi_is_writable(SPI_X)){}; | ||||
|     spi_get_hw(SPI_X)->dr = (uint32_t)color; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixels - for RP2040 | ||||
| ** Description:             Write a sequence of pixels | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | ||||
|   uint16_t *data = (uint16_t*)data_in; | ||||
|   if (_swapBytes) { | ||||
|     while(len--) | ||||
|     { | ||||
|       while (!spi_is_writable(SPI_X)){}; | ||||
|       spi_get_hw(SPI_X)->dr = (uint32_t)(*data++); | ||||
|     } | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     while(len--) | ||||
|     { | ||||
|       uint16_t color = *data++; | ||||
|       color = color >> 8 | color << 8; | ||||
|       while (!spi_is_writable(SPI_X)){}; | ||||
|       spi_get_hw(SPI_X)->dr = (uint32_t)color; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of display interface specific functions
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifdef RP2040_DMA // DMA functions for 16 bit SPI and 8/16 bit parallel displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| /*
 | ||||
| These are created in header file: | ||||
|   uint32_t           dma_tx_channel; | ||||
|   dma_channel_config dma_tx_config; | ||||
| */ | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaBusy | ||||
| ** Description:             Check if DMA is busy | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::dmaBusy(void) { | ||||
|   if (!DMA_Enabled) return false; | ||||
| 
 | ||||
|   if (dma_channel_is_busy(dma_tx_channel)) return true; | ||||
| 
 | ||||
| #if !defined (RP2040_PIO_INTERFACE) | ||||
|   // For SPI must also wait for FIFO to flush and reset format
 | ||||
|   while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; | ||||
|   hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); | ||||
| #endif | ||||
| 
 | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           dmaWait | ||||
| ** Description:             Wait until DMA is over (blocking!) | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::dmaWait(void) | ||||
| { | ||||
|   while (dma_channel_is_busy(dma_tx_channel)); | ||||
| 
 | ||||
| #if !defined (RP2040_PIO_INTERFACE) | ||||
|   // For SPI must also wait for FIFO to flush and reset format
 | ||||
|   while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; | ||||
|   hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixelsDMA | ||||
| ** Description:             Push pixels to TFT | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) | ||||
| { | ||||
|   if ((len == 0) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   dmaWait(); | ||||
| 
 | ||||
|   channel_config_set_bswap(&dma_tx_config, !_swapBytes); | ||||
| 
 | ||||
| #if !defined (RP2040_PIO_INTERFACE) | ||||
|   dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint16_t*)image, len, true); | ||||
| #else | ||||
|   dma_channel_configure(dma_tx_channel, &dma_tx_config, &tft_pio->txf[pio_sm], (uint16_t*)image, len, true); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Description:             Push image to a window | ||||
| ***************************************************************************************/ | ||||
| // This will clip to the viewport
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer) | ||||
| { | ||||
|   if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return; | ||||
| 
 | ||||
|   int32_t dx = 0; | ||||
|   int32_t dy = 0; | ||||
|   int32_t dw = w; | ||||
|   int32_t dh = h; | ||||
| 
 | ||||
|   if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } | ||||
|   if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } | ||||
| 
 | ||||
|   if ((x + dw) > _vpW ) dw = _vpW - x; | ||||
|   if ((y + dh) > _vpH ) dh = _vpH - y; | ||||
| 
 | ||||
|   if (dw < 1 || dh < 1) return; | ||||
| 
 | ||||
|   uint32_t len = dw*dh; | ||||
| 
 | ||||
|   if (buffer == nullptr) { | ||||
|     buffer = image; | ||||
|     dmaWait(); | ||||
|   } | ||||
| 
 | ||||
|   // If image is clipped, copy pixels into a contiguous block
 | ||||
|   if ( (dw != w) || (dh != h) ) { | ||||
|     for (int32_t yb = 0; yb < dh; yb++) { | ||||
|       memmove((uint8_t*) (buffer + yb * dw), (uint8_t*) (image + dx + w * (yb + dy)), dw << 1); | ||||
|     } | ||||
|   } | ||||
|   // else, if a buffer pointer has been provided copy whole image to the buffer
 | ||||
|   else if (buffer != image || _swapBytes) { | ||||
|     memcpy(buffer, image, len*2); | ||||
|   } | ||||
| 
 | ||||
|   dmaWait(); // In case we did not wait earlier
 | ||||
| 
 | ||||
|   setAddrWindow(x, y, dw, dh); | ||||
| 
 | ||||
|   channel_config_set_bswap(&dma_tx_config, !_swapBytes); | ||||
| 
 | ||||
| #if !defined (RP2040_PIO_INTERFACE) | ||||
|   dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint16_t*)buffer, len, true); | ||||
| #else | ||||
|   dma_channel_configure(dma_tx_channel, &dma_tx_config, &tft_pio->txf[pio_sm], (uint16_t*)buffer, len, true); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           initDMA | ||||
| ** Description:             Initialise the DMA engine - returns true if init OK | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::initDMA(bool ctrl_cs) | ||||
| { | ||||
|   if (DMA_Enabled) return false; | ||||
| 
 | ||||
|   ctrl_cs = ctrl_cs; // stop unused parameter warning
 | ||||
| 
 | ||||
|   dma_tx_channel = dma_claim_unused_channel(false); | ||||
|    | ||||
|   if (dma_tx_channel < 0) return false; | ||||
| 
 | ||||
|   dma_tx_config = dma_channel_get_default_config(dma_tx_channel); | ||||
| 
 | ||||
|   channel_config_set_transfer_data_size(&dma_tx_config, DMA_SIZE_16); | ||||
| #if !defined (RP2040_PIO_INTERFACE) | ||||
|   channel_config_set_dreq(&dma_tx_config, spi_get_index(SPI_X) ? DREQ_SPI1_TX : DREQ_SPI0_TX); | ||||
| #else | ||||
|   channel_config_set_dreq(&dma_tx_config, pio_get_dreq(tft_pio, pio_sm, true)); | ||||
| #endif | ||||
| 
 | ||||
|   DMA_Enabled = true; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           deInitDMA | ||||
| ** Description:             Disconnect the DMA engine from SPI | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::deInitDMA(void) | ||||
| { | ||||
|   if (!DMA_Enabled) return; | ||||
|   dma_channel_unclaim(dma_tx_channel); | ||||
|   DMA_Enabled = false; | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #endif // End of DMA FUNCTIONS
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,494 @@ | |||
|         ////////////////////////////////////////////////////
 | ||||
|         //       TFT_eSPI generic driver functions        //
 | ||||
|         ////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // This is a generic driver for Arduino boards, it supports SPI interface displays
 | ||||
| // 8 bit parallel interface to TFT is not supported for generic processors
 | ||||
| 
 | ||||
| #ifndef _TFT_eSPI_RP2040H_ | ||||
| #define _TFT_eSPI_RP2040H_ | ||||
| 
 | ||||
| #ifndef ARDUINO_ARCH_MBED | ||||
|   #include <LittleFS.h> | ||||
|   #define FONT_FS_AVAILABLE | ||||
|   #define SPIFFS LittleFS | ||||
| #endif | ||||
| 
 | ||||
| // Required for both the official and community board packages
 | ||||
| #include "hardware/dma.h" | ||||
| #include "hardware/pio.h" | ||||
| #include "hardware/clocks.h" | ||||
| 
 | ||||
| // Processor ID reported by getSetup()
 | ||||
| #define PROCESSOR_ID 0x2040 | ||||
| 
 | ||||
| // Transactions always supported
 | ||||
| #ifndef SUPPORT_TRANSACTIONS | ||||
|   #define SUPPORT_TRANSACTIONS | ||||
| #endif | ||||
| 
 | ||||
| // Include processor specific header
 | ||||
| // None
 | ||||
| 
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RP2040_PIO_SPI) | ||||
|   #define RP2040_PIO_INTERFACE | ||||
|   #define RP2040_PIO_PUSHBLOCK | ||||
| #endif | ||||
| 
 | ||||
| #if !defined (RP2040_PIO_INTERFACE)// SPI
 | ||||
|   // Use SPI0 as default if not defined
 | ||||
|   #ifndef TFT_SPI_PORT | ||||
|     #define TFT_SPI_PORT 0 | ||||
|   #endif | ||||
| 
 | ||||
|   #if (TFT_SPI_PORT == 0) | ||||
|     #define SPI_X spi0 | ||||
|   #else | ||||
|     #define SPI_X spi1 | ||||
|   #endif | ||||
| 
 | ||||
|   // Processor specific code used by SPI bus transaction begin/end_tft_write functions
 | ||||
|   #define SET_BUS_WRITE_MODE spi_set_format(SPI_X,  8, (spi_cpol_t)(TFT_SPI_MODE >> 1), (spi_cpha_t)(TFT_SPI_MODE & 0x1), SPI_MSB_FIRST) | ||||
|   #define SET_BUS_READ_MODE  // spi_set_format(SPI_X,  8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
 | ||||
| #else | ||||
|   // Processor specific code used by SPI bus transaction begin/end_tft_write functions
 | ||||
|   #define SET_BUS_WRITE_MODE | ||||
|   #define SET_BUS_READ_MODE | ||||
| #endif | ||||
| 
 | ||||
| // Code to check if SPI or DMA is busy, used by SPI bus transaction startWrite and/or endWrite functions
 | ||||
| #if !defined(SPI_18BIT_DRIVER) | ||||
|   #define RP2040_DMA | ||||
|   // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
 | ||||
|   #define DMA_BUSY_CHECK dmaWait() | ||||
| #else | ||||
|   #define DMA_BUSY_CHECK | ||||
| #endif | ||||
| 
 | ||||
| // Handle high performance MHS RPi display type
 | ||||
| #if  defined (MHS_DISPLAY_TYPE)  && !defined (RPI_DISPLAY_TYPE) | ||||
|   #define RPI_DISPLAY_TYPE | ||||
| #endif | ||||
| 
 | ||||
| #if !defined (RP2040_PIO_INTERFACE) // SPI
 | ||||
| 
 | ||||
|   #if  defined (MHS_DISPLAY_TYPE) // High speed RPi TFT type always needs 16 bit transfers
 | ||||
|     // This swaps to 16 bit mode, used for commands so wait avoids clash with DC timing
 | ||||
|     #define INIT_TFT_DATA_BUS hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS) | ||||
|   #else | ||||
|     // Initialise processor specific SPI functions, used by init()
 | ||||
|     #define INIT_TFT_DATA_BUS  // Not used
 | ||||
|   #endif | ||||
| 
 | ||||
|   // Wait for tx to end, flush rx FIFO, clear rx overrun
 | ||||
|   #define SPI_BUSY_CHECK while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {};     \ | ||||
|                          while (spi_is_readable(SPI_X)) (void)spi_get_hw(SPI_X)->dr; \ | ||||
|                          spi_get_hw(SPI_X)->icr = SPI_SSPICR_RORIC_BITS | ||||
| 
 | ||||
|   // To be safe, SUPPORT_TRANSACTIONS is assumed mandatory
 | ||||
|   #if !defined (SUPPORT_TRANSACTIONS) | ||||
|     #define SUPPORT_TRANSACTIONS | ||||
|   #endif | ||||
| #else | ||||
| 
 | ||||
|   // Different controllers have different minimum write cycle periods, so the PIO clock is changed accordingly
 | ||||
|   // The PIO clock is a division of the CPU clock so scales when the processor is overclocked
 | ||||
|   // PIO write frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
 | ||||
|   // The write cycle periods below assume a 125MHz CPU clock speed
 | ||||
|   #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) | ||||
|     #if defined (RP2040_PIO_CLK_DIV) | ||||
|       #if (RP2040_PIO_CLK_DIV > 0) | ||||
|         #define DIV_UNITS RP2040_PIO_CLK_DIV | ||||
|         #define DIV_FRACT 0 | ||||
|       #else | ||||
|         #define DIV_UNITS 3 | ||||
|         #define DIV_FRACT 0 | ||||
|       #endif | ||||
|     #elif defined (TFT_PARALLEL_16_BIT) | ||||
|       // Different display drivers have different minimum write cycle times
 | ||||
|       #if defined (HX8357C_DRIVER) || defined (SSD1963_DRIVER) | ||||
|         #define DIV_UNITS 1 // 32ns write cycle time SSD1963, HX8357C (maybe HX8357D?)
 | ||||
|       #elif defined (ILI9486_DRIVER) || defined (HX8357B_DRIVER) || defined (HX8357D_DRIVER) | ||||
|         #define DIV_UNITS 2 // 64ns write cycle time ILI9486, HX8357D, HX8357B
 | ||||
|       #else // ILI9481 needs a slower cycle time
 | ||||
|         #define DIV_UNITS 3 // 96ns write cycle time
 | ||||
|       #endif | ||||
|       #define DIV_FRACT 0 | ||||
|     #else // 8 bit parallel mode default 64ns write cycle time
 | ||||
|       #define DIV_UNITS 2 | ||||
|       #define DIV_FRACT 0 // Note: Fractional values done with clock period dithering
 | ||||
|     #endif | ||||
|   #endif | ||||
| 
 | ||||
|   // Initialise TFT data bus
 | ||||
|   #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) | ||||
|     #define INIT_TFT_DATA_BUS pioinit(DIV_UNITS, DIV_FRACT); | ||||
|   #elif defined (RP2040_PIO_SPI) | ||||
|     #define INIT_TFT_DATA_BUS pioinit(SPI_FREQUENCY); | ||||
|   #endif | ||||
| 
 | ||||
|   #define SPI_BUSY_CHECK | ||||
| 
 | ||||
|   // Set the state machine clock divider (from integer and fractional parts - 16:8) 
 | ||||
|   #define PARALLEL_INIT_TFT_DATA_BUS // Not used
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| // If smooth fonts are enabled the filing system may need to be loaded
 | ||||
| #if defined (SMOOTH_FONT) && !defined (ARDUINO_ARCH_MBED) | ||||
|   // Call up the filing system for the anti-aliased fonts
 | ||||
|   //#define FS_NO_GLOBALS
 | ||||
|   #include <FS.h> | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the DC (TFT Data/Command or Register Select (RS))pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_DC | ||||
|   #define DC_C // No macro allocated so it generates no code
 | ||||
|   #define DC_D // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if !defined (RP2040_PIO_INTERFACE)// SPI
 | ||||
|     //#define DC_C sio_hw->gpio_clr = (1ul << TFT_DC)
 | ||||
|     //#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
 | ||||
|     #if  defined (RPI_DISPLAY_TYPE) && !defined (MHS_DISPLAY_TYPE) | ||||
|       #define DC_C digitalWrite(TFT_DC, LOW); | ||||
|       #define DC_D digitalWrite(TFT_DC, HIGH); | ||||
|     #else | ||||
|       #define DC_C sio_hw->gpio_clr = (1ul << TFT_DC) | ||||
|       #define DC_D sio_hw->gpio_set = (1ul << TFT_DC) | ||||
|     #endif | ||||
|   #else | ||||
|     // PIO takes control of TFT_DC
 | ||||
|     // Must wait for data to flush through before changing DC line
 | ||||
|     #define DC_C  WAIT_FOR_STALL; \ | ||||
|                   tft_pio->sm[pio_sm].instr = pio_instr_clr_dc | ||||
| 
 | ||||
|     // Flush has happened before this and mode changed back to 16 bit
 | ||||
|     #define DC_D  tft_pio->sm[pio_sm].instr = pio_instr_set_dc | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the CS (TFT chip select) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_CS | ||||
|   #define CS_L // No macro allocated so it generates no code
 | ||||
|   #define CS_H // No macro allocated so it generates no code
 | ||||
| #else | ||||
|   #if !defined (RP2040_PIO_INTERFACE) // SPI
 | ||||
|     #if  defined (RPI_DISPLAY_TYPE) && !defined (MHS_DISPLAY_TYPE) | ||||
|       #define CS_L digitalWrite(TFT_CS, LOW); | ||||
|       #define CS_H digitalWrite(TFT_CS, HIGH); | ||||
|     #else | ||||
|       #define CS_L sio_hw->gpio_clr = (1ul << TFT_CS) | ||||
|       #define CS_H sio_hw->gpio_set = (1ul << TFT_CS) | ||||
|     #endif | ||||
|   #else // PIO interface display
 | ||||
|     #define CS_L sio_hw->gpio_clr = (1ul << TFT_CS) | ||||
|     #define CS_H WAIT_FOR_STALL; sio_hw->gpio_set = (1ul << TFT_CS) | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Make sure TFT_RD is defined if not used to avoid an error message
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // At the moment read is not supported for parallel mode, tie TFT signal high
 | ||||
| #ifdef TFT_RD | ||||
|   #if (TFT_RD >= 0) | ||||
|     #define RD_L sio_hw->gpio_clr = (1ul << TFT_RD) | ||||
|     //#define RD_L digitalWrite(TFT_WR, LOW)
 | ||||
|     #define RD_H sio_hw->gpio_set = (1ul << TFT_RD) | ||||
|     //#define RD_H digitalWrite(TFT_WR, HIGH)
 | ||||
|   #else | ||||
|     #define RD_L | ||||
|     #define RD_H | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_RD -1 | ||||
|   #define RD_L | ||||
|   #define RD_H | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the WR (TFT Write) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) // SPI
 | ||||
|   #ifdef TFT_WR | ||||
|     #define WR_L digitalWrite(TFT_WR, LOW) | ||||
|     #define WR_H digitalWrite(TFT_WR, HIGH) | ||||
|   #endif | ||||
| #else | ||||
|   // The PIO manages the write line
 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Define the touch screen chip select pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (RP2040_PIO_INTERFACE)// SPI
 | ||||
|   #if !defined TOUCH_CS || (TOUCH_CS < 0) | ||||
|     #define T_CS_L // No macro allocated so it generates no code
 | ||||
|     #define T_CS_H // No macro allocated so it generates no code
 | ||||
|   #else | ||||
|     #define T_CS_L digitalWrite(TOUCH_CS, LOW) | ||||
|     #define T_CS_H digitalWrite(TOUCH_CS, HIGH) | ||||
|   #endif | ||||
| #else | ||||
|   #ifdef TOUCH_CS | ||||
|     #error Touch screen not supported in parallel or SPI PIO mode, use a separate library. | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Make sure TFT_MISO is defined if not used to avoid an error message
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifndef TFT_MISO | ||||
|   #define TFT_MISO -1 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI948x TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (RP2040_PIO_INTERFACE) // SPI
 | ||||
| 
 | ||||
|   #if  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| 
 | ||||
|     // Write 8 bits to TFT
 | ||||
|     #define tft_Write_8(C)      spi_get_hw(SPI_X)->dr = (uint32_t)(C); \ | ||||
|                                 while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \ | ||||
| 
 | ||||
|     //#define tft_Write_8(C)   spi.transfer(C);
 | ||||
|     #define tft_Write_8N(B)   while (!spi_is_writable(SPI_X)){}; \ | ||||
|                              spi_get_hw(SPI_X)->dr = (uint8_t)(B) | ||||
| 
 | ||||
|     // Convert 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|     #define tft_Write_16(C)  tft_Write_8N(((C) & 0xF800)>>8); \ | ||||
|                              tft_Write_8N(((C) & 0x07E0)>>3); \ | ||||
|                              tft_Write_8N(((C) & 0x001F)<<3) | ||||
| 
 | ||||
|     // Convert 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|     #define tft_Write_16N(C)  tft_Write_8N(((C) & 0xF800)>>8); \ | ||||
|                               tft_Write_8N(((C) & 0x07E0)>>3); \ | ||||
|                               tft_Write_8N(((C) & 0x001F)<<3) | ||||
| 
 | ||||
|     // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
 | ||||
|     #define tft_Write_16S(C) tft_Write_8N((C) & 0xF8); \ | ||||
|                              tft_Write_8N(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ | ||||
|                              tft_Write_8N(((C) & 0x1F00)>>5) | ||||
|     // Write 32 bits to TFT
 | ||||
|     #define tft_Write_32(C)  tft_Write_8N(C>>24); \ | ||||
|                              tft_Write_8N(C>>16); \ | ||||
|                              tft_Write_8N(C>>8);  \ | ||||
|                              tft_Write_8N(C) | ||||
| 
 | ||||
|     // Write two address coordinates
 | ||||
|     #define tft_Write_32C(C,D) tft_Write_8N(C>>8); \ | ||||
|                                tft_Write_8N(C);    \ | ||||
|                                tft_Write_8N(D>>8); \ | ||||
|                                tft_Write_8N(D) | ||||
| 
 | ||||
|     // Write same value twice
 | ||||
|     #define tft_Write_32D(C) tft_Write_8N(C>>8); \ | ||||
|                              tft_Write_8N(C);    \ | ||||
|                              tft_Write_8N(C>>8); \ | ||||
|                              tft_Write_8N(C) | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   // Macros to write commands/pixel colour data to other displays
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   #else | ||||
|     #if  defined (MHS_DISPLAY_TYPE) // High speed RPi TFT type always needs 16 bit transfers
 | ||||
|       // This swaps to 16 bit mode, used for commands so wait avoids clash with DC timing
 | ||||
|       #define tft_Write_8(C)      while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \ | ||||
|                                   hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); \ | ||||
|                                   spi_get_hw(SPI_X)->dr = (uint32_t)((C) | ((C)<<8)); \ | ||||
|                                   while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \ | ||||
| 
 | ||||
|       // Note: the following macros do not wait for the end of transmission
 | ||||
| 
 | ||||
|       #define tft_Write_16(C)     while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|       #define tft_Write_16N(C)    while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|       #define tft_Write_16S(C)    while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)<<8 | (C)>>8 | ||||
| 
 | ||||
|       #define tft_Write_32(C)     spi_get_hw(SPI_X)->dr = (uint32_t)((C)>>16); spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|       #define tft_Write_32C(C,D)  spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(D) | ||||
| 
 | ||||
|       #define tft_Write_32D(C)    spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|     #elif  defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers
 | ||||
|       #define tft_Write_8(C)   spi.transfer(C); spi.transfer(C) | ||||
|       #define tft_Write_16(C)  spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0)) | ||||
|       #define tft_Write_16N(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0)) | ||||
|       #define tft_Write_16S(C) spi.transfer((uint8_t)((C)>>0));spi.transfer((uint8_t)((C)>>8)) | ||||
| 
 | ||||
|       #define tft_Write_32(C) \ | ||||
|         tft_Write_16((uint16_t) ((C)>>16)); \ | ||||
|         tft_Write_16((uint16_t) ((C)>>0)) | ||||
| 
 | ||||
|       #define tft_Write_32C(C,D) \ | ||||
|         spi.transfer(0); spi.transfer((C)>>8); \ | ||||
|         spi.transfer(0); spi.transfer((C)>>0); \ | ||||
|         spi.transfer(0); spi.transfer((D)>>8); \ | ||||
|         spi.transfer(0); spi.transfer((D)>>0) | ||||
| 
 | ||||
|       #define tft_Write_32D(C) \ | ||||
|         spi.transfer(0); spi.transfer((C)>>8); \ | ||||
|         spi.transfer(0); spi.transfer((C)>>0); \ | ||||
|         spi.transfer(0); spi.transfer((C)>>8); \ | ||||
|         spi.transfer(0); spi.transfer((C)>>0) | ||||
| 
 | ||||
|     #elif  defined (ILI9225_DRIVER) // Needs gaps between commands + data bytes, so use slower transfer functions
 | ||||
| 
 | ||||
|       // Warning: these all end in 8 bit SPI mode!
 | ||||
|       #define tft_Write_8(C)      spi.transfer(C); | ||||
| 
 | ||||
|       #define tft_Write_16(C)     spi.transfer16(C) | ||||
| 
 | ||||
|       #define tft_Write_16N(C)    spi.transfer16(C) | ||||
| 
 | ||||
|       #define tft_Write_16S(C)    spi.transfer16((C)<<8 | (C)>>8) | ||||
| 
 | ||||
|       #define tft_Write_32(C)     spi.transfer16((C)>>16); spi.transfer16(C) | ||||
| 
 | ||||
|       #define tft_Write_32C(C,D)  spi.transfer16(C); spi.transfer16(D) | ||||
| 
 | ||||
|       #define tft_Write_32D(C)    spi.transfer16(C); spi.transfer16(C) | ||||
| 
 | ||||
|     #else | ||||
| 
 | ||||
|       // This swaps to 8 bit mode, then back to 16 bit mode
 | ||||
|       #define tft_Write_8(C)      while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \ | ||||
|                                   hw_write_masked(&spi_get_hw(SPI_X)->cr0, (8 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); \ | ||||
|                                   spi_get_hw(SPI_X)->dr = (uint32_t)(C); \ | ||||
|                                   while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \ | ||||
|                                   hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS) | ||||
| 
 | ||||
|       // Note: the following macros do not wait for the end of transmission
 | ||||
| 
 | ||||
|       #define tft_Write_16(C)     while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|       #define tft_Write_16N(C)    while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|       #define tft_Write_16S(C)    while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)<<8 | (C)>>8 | ||||
| 
 | ||||
|       #define tft_Write_32(C)     spi_get_hw(SPI_X)->dr = (uint32_t)((C)>>16); spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|       #define tft_Write_32C(C,D)  spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(D) | ||||
| 
 | ||||
|       #define tft_Write_32D(C)    spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(C) | ||||
| 
 | ||||
|     #endif // RPI_DISPLAY_TYPE
 | ||||
|   #endif | ||||
| 
 | ||||
| #else // Parallel 8 bit or PIO SPI
 | ||||
| 
 | ||||
|   // Wait for the PIO to stall (SM pull request finds no data in TX FIFO)
 | ||||
|   // This is used to detect when the SM is idle and hence ready for a jump instruction
 | ||||
|   #define WAIT_FOR_STALL  tft_pio->fdebug = pull_stall_mask; while (!(tft_pio->fdebug & pull_stall_mask)) | ||||
| 
 | ||||
|   // Wait until at least "S" locations free
 | ||||
|   #define WAIT_FOR_FIFO_FREE(S) while (((tft_pio->flevel >> (pio_sm * 8)) & 0x000F) > (8-S)){} | ||||
| 
 | ||||
|   // Wait until at least 5 locations free
 | ||||
|   #define WAIT_FOR_FIFO_5_FREE while ((tft_pio->flevel) & (0x000c << (pio_sm * 8))){} | ||||
| 
 | ||||
|   // Wait until at least 1 location free
 | ||||
|   #define WAIT_FOR_FIFO_1_FREE while ((tft_pio->flevel) & (0x0008 << (pio_sm * 8))){} | ||||
| 
 | ||||
|   // Wait for FIFO to empty (use before swapping to 8 bits)
 | ||||
|   #define WAIT_FOR_FIFO_EMPTY  while(!(tft_pio->fstat & (1u << (PIO_FSTAT_TXEMPTY_LSB + pio_sm)))) | ||||
| 
 | ||||
|   // The write register of the TX FIFO.
 | ||||
|   #define TX_FIFO  tft_pio->txf[pio_sm] | ||||
| 
 | ||||
|   // Temporary - to be deleted
 | ||||
|   #define GPIO_DIR_MASK 0 | ||||
| 
 | ||||
|   #if  defined (SPI_18BIT_DRIVER)  || defined (SSD1963_DRIVER) // 18 bit colour (3 bytes)
 | ||||
|       // This writes 8 bits, then switches back to 16 bit mode automatically
 | ||||
|       // Have already waited for pio stalled (last data write complete) when DC switched to command mode
 | ||||
|       // The wait for stall allows DC to be changed immediately afterwards
 | ||||
|       #define tft_Write_8(C)      tft_pio->sm[pio_sm].instr = pio_instr_jmp8; \ | ||||
|                                   TX_FIFO = (C); \ | ||||
|                                   WAIT_FOR_STALL | ||||
| 
 | ||||
|       // Used to send last byte for 32 bit macros below since PIO sends 24 bits
 | ||||
|       #define tft_Write_8L(C)     WAIT_FOR_STALL; \ | ||||
|                                   tft_pio->sm[pio_sm].instr = pio_instr_jmp8; \ | ||||
|                                   TX_FIFO = (C) | ||||
| 
 | ||||
|       // Note: the following macros do not wait for the end of transmission
 | ||||
| 
 | ||||
|       #define tft_Write_16(C)     WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((((uint32_t)(C) & 0xF800)<<8) | (((C) & 0x07E0)<<5) | (((C) & 0x001F)<<3)) | ||||
| 
 | ||||
|       #define tft_Write_16N(C)    WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((((uint32_t)(C) & 0xF800)<<8) | (((C) & 0x07E0)<<5) | (((C) & 0x001F)<<3)) | ||||
| 
 | ||||
|       #define tft_Write_16S(C)    WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((((uint32_t)(C) & 0xF8) << 16) | (((C) & 0xE000)>>3) | (((C) & 0x07)<<13) | (((C) & 0x1F00)>>5)) | ||||
| 
 | ||||
|       #define tft_Write_32(C)     WAIT_FOR_FIFO_FREE(2); TX_FIFO = ((C)>>8); WAIT_FOR_STALL; tft_Write_8(C) | ||||
| 
 | ||||
|       #define tft_Write_32C(C,D)  WAIT_FOR_FIFO_FREE(2); TX_FIFO = (((C)<<8) | ((D)>>8)); tft_Write_8L(D) | ||||
| 
 | ||||
|       #define tft_Write_32D(C)    WAIT_FOR_FIFO_FREE(2); TX_FIFO = (((C)<<8) | ((C)>>8)); tft_Write_8L(C) | ||||
| 
 | ||||
|   #else // PIO interface, SPI or parallel
 | ||||
|     // This writes 8 bits, then switches back to 16 bit mode automatically
 | ||||
|     // Have already waited for pio stalled (last data write complete) when DC switched to command mode
 | ||||
|     // The wait for stall allows DC to be changed immediately afterwards
 | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (RP2040_PIO_SPI) | ||||
|       #define tft_Write_8(C)      tft_pio->sm[pio_sm].instr = pio_instr_jmp8; \ | ||||
|                                   TX_FIFO = (C); \ | ||||
|                                   WAIT_FOR_STALL | ||||
|     #else // For 16 bit parallel 16 bits are always sent
 | ||||
|       #define tft_Write_8(C)      TX_FIFO = (C); \ | ||||
|                                   WAIT_FOR_STALL | ||||
|     #endif | ||||
| 
 | ||||
|       // Note: the following macros do not wait for the end of transmission
 | ||||
| 
 | ||||
|       #define tft_Write_16(C)     WAIT_FOR_FIFO_FREE(1); TX_FIFO = (C) | ||||
| 
 | ||||
|       #define tft_Write_16N(C)    WAIT_FOR_FIFO_FREE(1); TX_FIFO = (C) | ||||
| 
 | ||||
|       #define tft_Write_16S(C)    WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((C)<<8) | ((C)>>8) | ||||
| 
 | ||||
|       #define tft_Write_32(C)     WAIT_FOR_FIFO_FREE(2); TX_FIFO = ((C)>>16); TX_FIFO = (C) | ||||
| 
 | ||||
|       #define tft_Write_32C(C,D)  WAIT_FOR_FIFO_FREE(2); TX_FIFO = (C); TX_FIFO = (D) | ||||
| 
 | ||||
|       #define tft_Write_32D(C)    WAIT_FOR_FIFO_FREE(2); TX_FIFO = (C); TX_FIFO = (C) | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef tft_Write_16N | ||||
|   #define tft_Write_16N tft_Write_16 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to read from display using SPI or software SPI
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if !defined (RP2040_PIO_INTERFACE)// SPI
 | ||||
|   #if defined (TFT_SDA_READ) | ||||
|     // Use a bit banged function call for STM32 and bi-directional SDA pin
 | ||||
|     #define TFT_eSPI_ENABLE_8_BIT_READ // Enable tft_Read_8(void);
 | ||||
|     #define SCLK_L digitalWrite(TFT_SCLK, LOW) | ||||
|     #define SCLK_H digitalWrite(TFT_SCLK, LOW) | ||||
|   #else | ||||
|     // Use a SPI read transfer
 | ||||
|     #define tft_Read_8() spi.transfer(0) | ||||
|   #endif | ||||
| #endif | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Temporary to keep the "Arduino Mbed OS RP2040 Boards" support package happy
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #if defined(ARDUINO_ARCH_RP2040) | ||||
| 
 | ||||
|   #define ltoa itoa | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif // Header end
 | ||||
|  | @ -10,8 +10,11 @@ | |||
|   // No globals
 | ||||
| #else | ||||
|   // Use STM32 default SPI port
 | ||||
|   SPIClass& spi = SPI; | ||||
| 
 | ||||
|   #if !defined (TFT_MOSI) || !defined (TFT_MISO) || !defined (TFT_SCLK) | ||||
|     SPIClass& spi = SPI; | ||||
|   #else | ||||
|     SPIClass spi(TFT_MOSI, TFT_MISO, TFT_SCLK); | ||||
|   #endif | ||||
|   // SPI HAL peripheral handle
 | ||||
|   SPI_HandleTypeDef spiHal; | ||||
| #endif | ||||
|  | @ -81,24 +84,42 @@ void TFT_eSPI::end_SDA_Read(void) | |||
| ** Description:             Write a block of pixels of the same colour | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ | ||||
|   // Loop unrolling improves speed dramtically graphics test  0.634s => 0.374s
 | ||||
|   while (len>31) { | ||||
|     // 32D macro writes 16 bits twice
 | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     len-=32; | ||||
|   } | ||||
|   while (len>7) { | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     tft_Write_32D(color); tft_Write_32D(color); | ||||
|     len-=8; | ||||
|   } | ||||
|     // Loop unrolling improves speed dramatically graphics test  0.634s => 0.374s
 | ||||
|     while (len>31) { | ||||
|     #if !defined (SSD1963_DRIVER) | ||||
|       // 32D macro writes 16 bits twice
 | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|     #else | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|     #endif | ||||
|       len-=32; | ||||
|     } | ||||
| 
 | ||||
|     while (len>7) { | ||||
|     #if !defined (SSD1963_DRIVER) | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|       tft_Write_32D(color); tft_Write_32D(color); | ||||
|     #else | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|       tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); | ||||
|     #endif | ||||
|       len-=8; | ||||
|     } | ||||
| 
 | ||||
|   while (len--) {tft_Write_16(color);} | ||||
| } | ||||
| 
 | ||||
|  | @ -128,14 +149,38 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ | |||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) | ||||
| { | ||||
| #ifdef STM_PORTA_DATA_BUS | ||||
|   if (mode == OUTPUT) GPIOA->MODER = (GPIOA->MODER & 0xFFFF0000) | 0x00005555; | ||||
|   else GPIOA->MODER &= 0xFFFF0000; | ||||
| 
 | ||||
| #elif STM_PORTB_DATA_BUS | ||||
|   if (mode == OUTPUT) GPIOB->MODER = (GPIOB->MODER & 0xFFFF0000) | 0x00005555; | ||||
|   else GPIOB->MODER &= 0xFFFF0000; | ||||
| 
 | ||||
| #if defined (STM_PORTA_DATA_BUS) | ||||
|   #if defined (STM32F1xx) | ||||
|     if (mode == OUTPUT) GPIOA->CRL = 0x33333333; | ||||
|     else GPIOA->CRL = 0x88888888; | ||||
|   #else | ||||
|     if (mode == OUTPUT) GPIOA->MODER = (GPIOA->MODER & 0xFFFF0000) | 0x00005555; | ||||
|     else GPIOA->MODER &= 0xFFFF0000; | ||||
|   #endif | ||||
| #elif defined (STM_PORTB_DATA_BUS) | ||||
|   #if defined (STM32F1xx) | ||||
|     if (mode == OUTPUT) GPIOB->CRL = 0x33333333; | ||||
|     else GPIOB->CRL = 0x88888888; | ||||
|   #else | ||||
|     if (mode == OUTPUT) GPIOB->MODER = (GPIOB->MODER & 0xFFFF0000) | 0x00005555; | ||||
|     else GPIOB->MODER &= 0xFFFF0000; | ||||
|   #endif | ||||
| #elif defined (STM_PORTC_DATA_BUS) | ||||
|   #if defined (STM32F1xx) | ||||
|     if (mode == OUTPUT) GPIOC->CRL = 0x33333333; | ||||
|     else GPIOC->CRL = 0x88888888; | ||||
|   #else | ||||
|     if (mode == OUTPUT) GPIOC->MODER = (GPIOC->MODER & 0xFFFF0000) | 0x00005555; | ||||
|     else GPIOC->MODER &= 0xFFFF0000; | ||||
|   #endif | ||||
| #elif defined (STM_PORTD_DATA_BUS) | ||||
|   #if defined (STM32F1xx) | ||||
|     if (mode == OUTPUT) GPIOD->CRL = 0x33333333; | ||||
|     else GPIOD->CRL = 0x88888888; | ||||
|   #else | ||||
|     if (mode == OUTPUT) GPIOD->MODER = (GPIOD->MODER & 0xFFFF0000) | 0x00005555; | ||||
|     else GPIOD->MODER &= 0xFFFF0000; | ||||
|   #endif | ||||
| #else | ||||
|   if (mode == OUTPUT) { | ||||
|     LL_GPIO_SetPinMode(D0_PIN_PORT, D0_PIN_MASK, LL_GPIO_MODE_OUTPUT); | ||||
|  | @ -183,16 +228,26 @@ uint8_t TFT_eSPI::readByte(void) | |||
|   uint8_t b = 0; | ||||
| 
 | ||||
|   RD_L; | ||||
| #ifdef STM_PORTA_DATA_BUS | ||||
| #if defined (STM_PORTA_DATA_BUS) | ||||
|   b = GPIOA->IDR; | ||||
|   b = GPIOA->IDR; | ||||
|   b = GPIOA->IDR; | ||||
|   b = (GPIOA->IDR) & 0xFF; | ||||
| #elif STM_PORTB_DATA_BUS | ||||
| #elif defined (STM_PORTB_DATA_BUS) | ||||
|   b = GPIOB->IDR; | ||||
|   b = GPIOB->IDR; | ||||
|   b = GPIOB->IDR; | ||||
|   b = (GPIOB->IDR) & 0xFF; | ||||
| #elif defined (STM_PORTC_DATA_BUS) | ||||
|   b = GPIOC->IDR; | ||||
|   b = GPIOC->IDR; | ||||
|   b = GPIOC->IDR; | ||||
|   b = (GPIOC->IDR) & 0xFF; | ||||
| #elif defined (STM_PORTD_DATA_BUS) | ||||
|   b = GPIOD->IDR; | ||||
|   b = GPIOD->IDR; | ||||
|   b = GPIOD->IDR; | ||||
|   b = (GPIOD->IDR) & 0xFF; | ||||
| #else | ||||
|   b  = RD_TFT_D0 | RD_TFT_D0 | RD_TFT_D0 | RD_TFT_D0; //Delay for bits to settle
 | ||||
| 
 | ||||
|  | @ -231,7 +286,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) | |||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9488_DRIVER) // For 24 bit colour TFT                                 ############# UNTESTED ###################
 | ||||
| #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
|  | @ -372,8 +427,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) | |||
| ** Function name:           dmaBusy | ||||
| ** Description:             Check if DMA is busy (usefully non-blocking!) | ||||
| ***************************************************************************************/ | ||||
| // Use "while(tft.dmaBusy());" in sketch for a blocking wait for DMA to complete
 | ||||
| // or  "while( tft.dmaBusy() ) {Do-something-useful;}"
 | ||||
| // Use while( tft.dmaBusy() ) {Do-something-useful;}"
 | ||||
| bool TFT_eSPI::dmaBusy(void) | ||||
| { | ||||
|   //return (dmaHal.State == HAL_DMA_STATE_BUSY);  // Do not use, SPI may still be busy
 | ||||
|  | @ -382,7 +436,18 @@ bool TFT_eSPI::dmaBusy(void) | |||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushImageDMA | ||||
| ** Function name:           dmaWait | ||||
| ** Description:             Wait until DMA is over (blocking!) | ||||
| ***************************************************************************************/ | ||||
| void TFT_eSPI::dmaWait(void) | ||||
| { | ||||
|   //return (dmaHal.State == HAL_DMA_STATE_BUSY);  // Do not use, SPI may still be busy
 | ||||
|   while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           pushPixelsDMA | ||||
| ** Description:             Push pixels to TFT (len must be less than 32767) | ||||
| ***************************************************************************************/ | ||||
| // This will byte swap the original image if setSwapBytes(true) was called by sketch.
 | ||||
|  | @ -408,39 +473,40 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) | |||
| // This will clip and also swap bytes if setSwapBytes(true) was called by sketch
 | ||||
| void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer) | ||||
| { | ||||
|   if ((x >= _width) || (y >= _height)) return; | ||||
|   if ((x >= _vpW) || (y >= _vpH)) return; | ||||
| 
 | ||||
|   int32_t dx = 0; | ||||
|   int32_t dy = 0; | ||||
|   int32_t dw = w; | ||||
|   int32_t dh = h; | ||||
| 
 | ||||
|   if (x < 0) { dw += x; dx = -x; x = 0; } | ||||
|   if (y < 0) { dh += y; dy = -y; y = 0; } | ||||
|   if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } | ||||
|   if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } | ||||
| 
 | ||||
|   if ((x + dw) > _width ) dw = _width  - x; | ||||
|   if ((y + dh) > _height) dh = _height - y; | ||||
|   if ((x + dw) > _vpW ) dw = _vpW - x; | ||||
|   if ((y + dh) > _vpH ) dh = _vpH - y; | ||||
| 
 | ||||
|   if (dw < 1 || dh < 1) return; | ||||
| 
 | ||||
|   if (buffer == nullptr) buffer = image; | ||||
| 
 | ||||
|   uint32_t len = dw*dh; | ||||
| 
 | ||||
|   while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy
 | ||||
|   if (buffer == nullptr) { | ||||
|     buffer = image; | ||||
|     while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy
 | ||||
|   } | ||||
| 
 | ||||
|   // If image is clipped, copy pixels into a contiguous block
 | ||||
|   if ( (dw != w) || (dh != h) ) { | ||||
|     if(_swapBytes) { | ||||
|       for (uint32_t yb = 0; yb < dh; yb++) { | ||||
|         for (uint32_t xb = 0; xb < dw; xb++) { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         for (int32_t xb = 0; xb < dw; xb++) { | ||||
|           uint32_t src = xb + dx + w * (yb + dy); | ||||
|           (buffer[xb + yb * dw] = image[src] << 8 | image[src] >> 8); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       for (uint32_t yb = 0; yb < dh; yb++) { | ||||
|       for (int32_t yb = 0; yb < dh; yb++) { | ||||
|         memcpy((uint8_t*) (buffer + yb * dw), (uint8_t*) (image + dx + w * (yb + dy)), dw << 1); | ||||
|       } | ||||
|     } | ||||
|  | @ -476,15 +542,23 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t | |||
| // The DMA functions here work with SPI only (not parallel)
 | ||||
| #if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           DMA2_StreamX_IRQHandler | ||||
| ** Description:             Override the default HAL stream 3 interrupt handler | ||||
| ** Function name:           DMAX_StreamX_IRQHandler | ||||
| ** Description:             Override the default HAL stream X interrupt handler | ||||
| ***************************************************************************************/ | ||||
| extern "C" void DMA2_Stream3_IRQHandler(); | ||||
| void DMA2_Stream3_IRQHandler(void) | ||||
| { | ||||
|   // Call the default end of buffer handler
 | ||||
|   HAL_DMA_IRQHandler(&dmaHal); | ||||
| } | ||||
|   #if (TFT_SPI_PORT == 1) | ||||
|     extern "C" void DMA2_Stream3_IRQHandler(); | ||||
|     void DMA2_Stream3_IRQHandler(void) | ||||
|   #elif (TFT_SPI_PORT == 2) | ||||
|     extern "C" void DMA1_Stream4_IRQHandler(); | ||||
|     void DMA1_Stream4_IRQHandler(void) | ||||
|   #elif (TFT_SPI_PORT == 3) | ||||
|     extern "C" void DMA1_Stream5_IRQHandler(); | ||||
|     void DMA1_Stream5_IRQHandler(void) | ||||
|   #endif | ||||
|   { | ||||
|     // Call the default end of buffer handler
 | ||||
|     HAL_DMA_IRQHandler(&dmaHal); | ||||
|   } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           initDMA | ||||
|  | @ -493,11 +567,22 @@ void DMA2_Stream3_IRQHandler(void) | |||
| // This initialisation is for STM32F2xx/4xx/7xx processors and may not work on others
 | ||||
| // Dual core H7xx series not supported yet, they are different and have a DMA MUX: 
 | ||||
| // https://electronics.stackexchange.com/questions/379813/configuring-the-dma-request-multiplexer-on-a-stm32h7-mcu
 | ||||
| bool TFT_eSPI::initDMA(void) | ||||
| bool TFT_eSPI::initDMA(bool ctrl_cs) | ||||
| { | ||||
|   __HAL_RCC_DMA2_CLK_ENABLE();                           // Enable DMA2 clock
 | ||||
|   ctrl_cs = ctrl_cs; // Not used for STM32, so stop compiler warning
 | ||||
| 
 | ||||
|   #if (TFT_SPI_PORT == 1) | ||||
|     __HAL_RCC_DMA2_CLK_ENABLE();                           // Enable DMA2 clock
 | ||||
|     dmaHal.Init.Channel = DMA_CHANNEL_3;                   // DMA channel 3 is for SPI1 TX
 | ||||
|   #elif (TFT_SPI_PORT == 2) | ||||
|     __HAL_RCC_DMA1_CLK_ENABLE();                           // Enable DMA1 clock
 | ||||
|     dmaHal.Init.Channel = DMA_CHANNEL_0;                   // DMA channel 0 is for SPI2 TX
 | ||||
|   #elif (TFT_SPI_PORT == 3) | ||||
|     __HAL_RCC_DMA1_CLK_ENABLE();                           // Enable DMA1 clock
 | ||||
|     dmaHal.Init.Channel = DMA_CHANNEL_0;                   // DMA channel 0 is for SPI3 TX
 | ||||
|    | ||||
|   #endif | ||||
| 
 | ||||
|   dmaHal.Init.Channel = DMA_CHANNEL_3;                   // DMA channel 3 is for SPI1 TX
 | ||||
|   dmaHal.Init.Mode =  DMA_NORMAL; //DMA_CIRCULAR;   //   // Normal = send buffer once
 | ||||
|   dmaHal.Init.Direction = DMA_MEMORY_TO_PERIPH;          // Copy memory to the peripheral
 | ||||
|   dmaHal.Init.PeriphInc = DMA_PINC_DISABLE;              // Don't increment peripheral address
 | ||||
|  | @ -509,10 +594,13 @@ bool TFT_eSPI::initDMA(void) | |||
|     // Insert error message here?
 | ||||
|     return DMA_Enabled = false; | ||||
|   }; | ||||
|   #if (TFT_SPI_PORT == 1) | ||||
|     HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);  // Enable DMA end interrupt handler
 | ||||
|   #elif (TFT_SPI_PORT == 2) | ||||
|     HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);  // Enable DMA end interrupt handler
 | ||||
|   #endif | ||||
| 
 | ||||
|   HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);  // Enable DMA end interrupt handler
 | ||||
| 
 | ||||
|   __HAL_LINKDMA(&spiHal, hdmatx, dmaHal); // Attach DMA engine to SPI peripheral
 | ||||
|   __HAL_LINKDMA(&spiHal, hdmatx, dmaHal);   // Attach DMA engine to SPI peripheral
 | ||||
| 
 | ||||
|   return DMA_Enabled = true; | ||||
| } | ||||
|  | @ -522,21 +610,28 @@ bool TFT_eSPI::initDMA(void) | |||
| ** Function name:           DMA1_ChannelX_IRQHandler | ||||
| ** Description:             Override the default HAL stream 3 interrupt handler | ||||
| ***************************************************************************************/ | ||||
| extern "C" void DMA1_Channel3_IRQHandler(); | ||||
|   #if (TFT_SPI_PORT == 1) | ||||
|     extern "C" void DMA1_Channel3_IRQHandler(); | ||||
|     void DMA1_Channel3_IRQHandler(void) | ||||
|   #elif (TFT_SPI_PORT == 2) | ||||
|     extern "C" void DMA1_Channel5_IRQHandler(); | ||||
|     void DMA1_Channel5_IRQHandler(void) | ||||
|   #endif | ||||
|   { | ||||
|     // Call the default end of buffer handler
 | ||||
|     HAL_DMA_IRQHandler(&dmaHal); | ||||
|   } | ||||
| 
 | ||||
| void DMA1_Channel3_IRQHandler(void) | ||||
| { | ||||
|   // Call the default end of buffer handler
 | ||||
|   HAL_DMA_IRQHandler(&dmaHal); | ||||
| } | ||||
| //*/
 | ||||
| /***************************************************************************************
 | ||||
| ** Function name:           initDMA | ||||
| ** Description:             Initialise the DMA engine - returns true if init OK | ||||
| ***************************************************************************************/ | ||||
| bool TFT_eSPI::initDMA(void) | ||||
| bool TFT_eSPI::initDMA(bool ctrl_cs) | ||||
| { | ||||
|   __HAL_RCC_DMA1_CLK_ENABLE();                           // Enable DMA2 clock
 | ||||
|   ctrl_cs = ctrl_cs; // Not used for STM32, so stop compiler warning
 | ||||
| 
 | ||||
|   __HAL_RCC_DMA1_CLK_ENABLE();                           // Enable DMA1 clock
 | ||||
| 
 | ||||
|   dmaHal.Init.Mode =  DMA_NORMAL; //DMA_CIRCULAR;   //   // Normal = send buffer once
 | ||||
|   dmaHal.Init.Direction = DMA_MEMORY_TO_PERIPH;          // Copy memory to the peripheral
 | ||||
|  | @ -553,9 +648,13 @@ bool TFT_eSPI::initDMA(void) | |||
|     return DMA_Enabled = false; | ||||
|   }; | ||||
| 
 | ||||
|   HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0); | ||||
|   HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);  // Enable DMA end interrupt handler
 | ||||
| 
 | ||||
|   #if (TFT_SPI_PORT == 1) | ||||
|     HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0); | ||||
|     HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);  // Enable DMA end interrupt handler
 | ||||
|   #elif (TFT_SPI_PORT == 2) | ||||
|     HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 1, 0); | ||||
|     HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);  // Enable DMA end interrupt handler
 | ||||
|   #endif | ||||
| 
 | ||||
|   return DMA_Enabled = true; | ||||
| } | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Write strobe timing setup
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   #if defined (ILI9341_DRIVER) || defined (ST7796_DRIVER) // WRX twc spec is 66ns = 15.15MHz
 | ||||
|   #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ST7796_DRIVER)   || defined (ILI9486_DRIVER) // WRX twc spec is <=66ns = 15.15MHz
 | ||||
| 
 | ||||
|     // Extra write pulse low time (delay for data setup)
 | ||||
|     #if defined (STM32F1xx) | ||||
|  | @ -63,7 +63,7 @@ | |||
|     #if defined (STM32F1xx) | ||||
|       #define WR_TWRH_0 | ||||
|     #elif defined (STM32F2xx) || defined (STM32F4xx) | ||||
|       #define WR_TWRH_1       // Tested with STM32F446
 | ||||
|       #define WR_TWRH_0       // Tested with STM32F446
 | ||||
|       //#define WR_TWRL_3
 | ||||
|     #elif defined (STM32F7xx) | ||||
|       #define WR_TWRH_1       //Tested with STM32F767
 | ||||
|  | @ -146,23 +146,56 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #else | ||||
| 
 | ||||
|   // Use SPI1 as default if not defined
 | ||||
|   #ifndef TFT_SPI_PORT | ||||
|     #define TFT_SPI_PORT 1 | ||||
|   #endif | ||||
| 
 | ||||
|   // Global define is _VARIANT_ARDUINO_STM32_, see board package stm32_def.h for specific variants
 | ||||
|   #if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) | ||||
| 
 | ||||
|     #define STM32_DMA // DMA is available with these processors
 | ||||
|     // Initialise processor specific SPI and DMA instances - used by init()
 | ||||
|     #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ | ||||
|                               dmaHal.Instance = DMA2_Stream3 | ||||
|     // The DMA hard-coding for SPI1 is in TFT_eSPI_STM32.c as follows:
 | ||||
|     //     DMA_CHANNEL_3 
 | ||||
|     //     DMA2_Stream3_IRQn and DMA2_Stream3_IRQHandler()
 | ||||
| 
 | ||||
|     #if (TFT_SPI_PORT == 1) | ||||
|       // Initialise processor specific SPI and DMA instances - used by init()
 | ||||
|       #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ | ||||
|                                 dmaHal.Instance = DMA2_Stream3 | ||||
|       // The DMA hard-coding for SPI1 is in TFT_eSPI_STM32.c as follows:
 | ||||
|       //     DMA_CHANNEL_3
 | ||||
|       //     DMA2_Stream3_IRQn and DMA2_Stream3_IRQHandler()
 | ||||
|     #elif (TFT_SPI_PORT == 2) | ||||
|       // Initialise processor specific SPI and DMA instances - used by init()
 | ||||
|       #define INIT_TFT_DATA_BUS spiHal.Instance = SPI2; \ | ||||
|                                 dmaHal.Instance = DMA1_Stream4 | ||||
|       // The DMA hard-coding for SPI2 is in TFT_eSPI_STM32.c as follows:
 | ||||
|       //     DMA_CHANNEL_4
 | ||||
|       //     DMA1_Stream4_IRQn and DMA1_Stream4_IRQHandler()
 | ||||
|     #elif (TFT_SPI_PORT == 3) | ||||
|       // Initialise processor specific SPI and DMA instances - used by init()
 | ||||
|       #define INIT_TFT_DATA_BUS spiHal.Instance = SPI3; \ | ||||
|                                 dmaHal.Instance = DMA1_Stream5 | ||||
|       // The DMA hard-coding for SPI3 is in TFT_eSPI_STM32.c as follows:
 | ||||
|       //     DMA_CHANNEL_4
 | ||||
|       //     DMA1_Stream5_IRQn and DMA1_Stream5_IRQHandler()
 | ||||
|     #endif | ||||
| 
 | ||||
|   #elif defined (STM32F1xx) | ||||
|     // For Blue Pill and STM32F1xx processors with DMA support
 | ||||
|     #define STM32_DMA // DMA is available with these processors
 | ||||
|     #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ | ||||
|                               dmaHal.Instance = DMA1_Channel3 | ||||
|     #if (TFT_SPI_PORT == 1) | ||||
|       #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ | ||||
|                                 dmaHal.Instance = DMA1_Channel3 | ||||
|     #elif (TFT_SPI_PORT == 2) | ||||
|       #define INIT_TFT_DATA_BUS spiHal.Instance = SPI2; \ | ||||
|                                 dmaHal.Instance = DMA1_Channel5 | ||||
|     #endif | ||||
|   #else | ||||
|     // For STM32 processor with no implemented DMA support (yet)
 | ||||
|     #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1 | ||||
|     #if (TFT_SPI_PORT == 1) | ||||
|       #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1 | ||||
|     #elif (TFT_SPI_PORT == 2) | ||||
|       #define INIT_TFT_DATA_BUS spiHal.Instance = SPI2 | ||||
|     #endif | ||||
|   #endif | ||||
| 
 | ||||
| #endif | ||||
|  | @ -187,6 +220,7 @@ | |||
| #if !defined (TFT_DC) || (TFT_DC < 0) | ||||
|   #define DC_C // No macro allocated so it generates no code
 | ||||
|   #define DC_D // No macro allocated so it generates no code
 | ||||
|   #undef  TFT_DC | ||||
| #else | ||||
|   // Convert Arduino pin reference Dn or STM pin reference PXn to port and mask
 | ||||
|   #define DC_PORT     digitalPinToPort(TFT_DC) | ||||
|  | @ -202,6 +236,7 @@ | |||
| #if !defined (TFT_CS) || (TFT_CS < 0) | ||||
|   #define CS_L // No macro allocated so it generates no code
 | ||||
|   #define CS_H // No macro allocated so it generates no code
 | ||||
|   #undef  TFT_CS | ||||
| #else | ||||
|   // Convert Arduino pin reference Dx or STM pin reference PXn to port and mask
 | ||||
|   #define CS_PORT      digitalPinToPort(TFT_CS) | ||||
|  | @ -215,12 +250,21 @@ | |||
| // Define the RD (TFT Read) pin drive code
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifdef TFT_RD | ||||
|   // Convert Arduino pin reference Dx or STM pin reference PXn to port and mask
 | ||||
|   #define RD_PORT      digitalPinToPort(TFT_RD) | ||||
|   #define RD_PIN_MASK  digitalPinToBitMask(TFT_RD) | ||||
|   // Use bit set reset register
 | ||||
|   #define RD_L RD_PORT->BSRR = RD_PIN_MASK<<16 | ||||
|   #define RD_H RD_PORT->BSRR = RD_PIN_MASK | ||||
|   #if (TFT_RD >= 0) | ||||
|     // Convert Arduino pin reference Dx or STM pin reference PXn to port and mask
 | ||||
|     #define RD_PORT      digitalPinToPort(TFT_RD) | ||||
|     #define RD_PIN_MASK  digitalPinToBitMask(TFT_RD) | ||||
|     // Use bit set reset register
 | ||||
|     #define RD_L RD_PORT->BSRR = RD_PIN_MASK<<16 | ||||
|     #define RD_H RD_PORT->BSRR = RD_PIN_MASK | ||||
|   #else | ||||
|     #define RD_L | ||||
|     #define RD_H | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_RD -1 | ||||
|   #define RD_L | ||||
|   #define RD_H | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -262,9 +306,9 @@ | |||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
| 
 | ||||
|   // Mask for the 8 data bits to set pin directions (not used)
 | ||||
|   #define dir_mask 0 | ||||
|   #define GPIO_DIR_MASK 0 | ||||
| 
 | ||||
|   #define CONSTRUCTOR_INIT_TFT_DATA_BUS // None
 | ||||
|   #define PARALLEL_INIT_TFT_DATA_BUS // None
 | ||||
| 
 | ||||
|   #define INIT_TFT_DATA_BUS // Setup built into TFT_eSPI.cpp
 | ||||
| 
 | ||||
|  | @ -374,29 +418,54 @@ | |||
|                              GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                              WR_STB // Need to slow down strobe
 | ||||
| 
 | ||||
|     // Write 16 bits to TFT
 | ||||
|     #define tft_Write_16(C)  GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                              WR_L; \ | ||||
|                              GPIOC->BSRR = D9_BSR_MASK(C); \ | ||||
|                              GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                              WR_STB; \ | ||||
|                              GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                              WR_L; \ | ||||
|                              GPIOC->BSRR = D1_BSR_MASK(C); \ | ||||
|                              GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                              WR_STB // Need to slow down strobe
 | ||||
|     #if defined (SSD1963_DRIVER) | ||||
| 
 | ||||
|     // 16 bit write with swapped bytes
 | ||||
|     #define tft_Write_16S(C) GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                              WR_L; \ | ||||
|                              GPIOC->BSRR = D1_BSR_MASK(C); \ | ||||
|                              GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                              WR_STB; \ | ||||
|                              GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                              WR_L; \ | ||||
|                              GPIOC->BSRR = D9_BSR_MASK(C); \ | ||||
|                              GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                              WR_STB | ||||
|       // Write 18 bit color to TFT (untested)
 | ||||
|       #define tft_Write_16(C)  r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ | ||||
|                                GPIOA->BSRR = D0_BSR_MASK(r6) | D2_BSR_MASK(r6) | D7_BSR_MASK(r6); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOC->BSRR = D1_BSR_MASK(r6); \ | ||||
|                                GPIOB->BSRR = D3_BSR_MASK(r6) | D4_BSR_MASK(r6) | D5_BSR_MASK(r6) | D6_BSR_MASK(r6); \ | ||||
|                                WR_STB; \ | ||||
|                                GPIOA->BSRR = D0_BSR_MASK(g6) | D2_BSR_MASK(g6) | D7_BSR_MASK(g6); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOC->BSRR = D1_BSR_MASK(g6); \ | ||||
|                                GPIOB->BSRR = D3_BSR_MASK(g6) | D4_BSR_MASK(g6) | D5_BSR_MASK(g6) | D6_BSR_MASK(g6); \ | ||||
|                                WR_STB; \ | ||||
|                                GPIOA->BSRR = D0_BSR_MASK(b6) | D2_BSR_MASK(b6) | D7_BSR_MASK(b6); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOC->BSRR = D1_BSR_MASK(b6); \ | ||||
|                                GPIOB->BSRR = D3_BSR_MASK(b6) | D4_BSR_MASK(b6) | D5_BSR_MASK(b6) | D6_BSR_MASK(b6); \ | ||||
|                                WR_STB // Need to slow down strobe
 | ||||
| 
 | ||||
|       // 18 bit color write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) | ||||
| 
 | ||||
|     #else | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C)  GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOC->BSRR = D9_BSR_MASK(C); \ | ||||
|                                GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                                WR_STB; \ | ||||
|                                GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOC->BSRR = D1_BSR_MASK(C); \ | ||||
|                                GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                                WR_STB // Need to slow down strobe
 | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOC->BSRR = D1_BSR_MASK(C); \ | ||||
|                                GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                                WR_STB; \ | ||||
|                                GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOC->BSRR = D9_BSR_MASK(C); \ | ||||
|                                GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                                WR_STB | ||||
|     #endif | ||||
| 
 | ||||
|     #define tft_Write_32(C)    tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) | ||||
| 
 | ||||
|  | @ -490,29 +559,56 @@ | |||
|                                GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                                WR_STB | ||||
| 
 | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C)  GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOD->BSRR = D9_BSR_MASK(C); \ | ||||
|                                GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                                WR_STB;\ | ||||
|                                GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOD->BSRR = D1_BSR_MASK(C); \ | ||||
|                                GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                                WR_STB | ||||
|       #if defined (SSD1963_DRIVER) | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOD->BSRR = D1_BSR_MASK(C); \ | ||||
|                                GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                                WR_STB; \ | ||||
|                                GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                GPIOD->BSRR = D9_BSR_MASK(C); \ | ||||
|                                GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                                WR_STB | ||||
|         // Write 18 bit color to TFT (untested)
 | ||||
|         #define tft_Write_16(C)  r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ | ||||
|                                  GPIOF->BSRR = D0_BSR_MASK(r6) | D2_BSR_MASK(r6) | D4_BSR_MASK(r6) | D7_BSR_MASK(r6); \ | ||||
|                                  WR_L; \ | ||||
|                                  GPIOD->BSRR = D1_BSR_MASK(r6); \ | ||||
|                                  GPIOE->BSRR = D3_BSR_MASK(r6) | D5_BSR_MASK(r6) | D6_BSR_MASK(r6); \ | ||||
|                                  WR_STB; \ | ||||
|                                  GPIOF->BSRR = D0_BSR_MASK(g6) | D2_BSR_MASK(g6) | D4_BSR_MASK(g6) | D7_BSR_MASK(g6); \ | ||||
|                                  WR_L; \ | ||||
|                                  GPIOD->BSRR = D1_BSR_MASK(g6); \ | ||||
|                                  GPIOE->BSRR = D3_BSR_MASK(g6) | D5_BSR_MASK(g6) | D6_BSR_MASK(g6); \ | ||||
|                                  WR_STB; \ | ||||
|                                  GPIOF->BSRR = D0_BSR_MASK(b6) | D2_BSR_MASK(b6) | D4_BSR_MASK(b6) | D7_BSR_MASK(b6); \ | ||||
|                                  WR_L; \ | ||||
|                                  GPIOD->BSRR = D1_BSR_MASK(b6); \ | ||||
|                                  GPIOE->BSRR = D3_BSR_MASK(b6) | D5_BSR_MASK(b6) | D6_BSR_MASK(b6); \ | ||||
|                                  WR_STB // Need to slow down strobe
 | ||||
| 
 | ||||
|         // 18 bit color write with swapped bytes
 | ||||
|         #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) | ||||
| 
 | ||||
|       #else | ||||
| 
 | ||||
|         // Write 16 bits to TFT
 | ||||
|         #define tft_Write_16(C)  GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  GPIOD->BSRR = D9_BSR_MASK(C); \ | ||||
|                                  GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                                  WR_STB;\ | ||||
|                                  GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  GPIOD->BSRR = D1_BSR_MASK(C); \ | ||||
|                                  GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                                  WR_STB | ||||
| 
 | ||||
|         // 16 bit write with swapped bytes
 | ||||
|         #define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  GPIOD->BSRR = D1_BSR_MASK(C); \ | ||||
|                                  GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ | ||||
|                                  WR_STB; \ | ||||
|                                  GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  GPIOD->BSRR = D9_BSR_MASK(C); \ | ||||
|                                  GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ | ||||
|                                  WR_STB | ||||
| 
 | ||||
|       #endif | ||||
| 
 | ||||
|       #define tft_Write_32(C)    tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) | ||||
| 
 | ||||
|  | @ -631,18 +727,42 @@ | |||
| // Support for other STM32 boards (not optimised!)
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   #else | ||||
|     #if defined (STM_PORTA_DATA_BUS) | ||||
|        | ||||
|       // Write 8 bits to TFT
 | ||||
|       #define tft_Write_8(C)   GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB | ||||
|        | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C)  GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \ | ||||
|                                GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB | ||||
|     #if defined (STM_PORTA_DATA_BUS) || defined (STM_PORTB_DATA_BUS) || defined (STM_PORTC_DATA_BUS) || defined (STM_PORTD_DATA_BUS) | ||||
|       #if defined (STM_PORTA_DATA_BUS) | ||||
|         #define GPIOX GPIOA | ||||
|       #elif defined (STM_PORTB_DATA_BUS) | ||||
|         #define GPIOX GPIOB | ||||
|       #elif defined (STM_PORTC_DATA_BUS) | ||||
|         #define GPIOX GPIOC | ||||
|       #elif defined (STM_PORTD_DATA_BUS) | ||||
|         #define GPIOX GPIOD | ||||
|       #endif | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \ | ||||
|                                GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB | ||||
|       // Write 8 bits to TFT
 | ||||
|       #define tft_Write_8(C)   GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB | ||||
| 
 | ||||
|       #if defined (SSD1963_DRIVER) | ||||
| 
 | ||||
|         // Write 18 bit color to TFT (untested)
 | ||||
| 
 | ||||
|         #define tft_Write_16(C)  r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ | ||||
|                              GPIOX->BSRR = (0x00FF0000 | (uint8_t)(r6)); WR_L; WR_STB; \ | ||||
|                              GPIOX->BSRR = (0x00FF0000 | (uint8_t)(g6)); WR_L; WR_STB; \ | ||||
|                              GPIOX->BSRR = (0x00FF0000 | (uint8_t)(b6)); WR_L; WR_STB | ||||
| 
 | ||||
|         // 18 bit color write with swapped bytes
 | ||||
|         #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) | ||||
| 
 | ||||
|       #else | ||||
| 
 | ||||
|           // Write 16 bits to TFT
 | ||||
|           #define tft_Write_16(C)  GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \ | ||||
|                                    GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB | ||||
| 
 | ||||
|           // 16 bit write with swapped bytes
 | ||||
|           #define tft_Write_16S(C) GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \ | ||||
|                                    GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB | ||||
|       #endif | ||||
| 
 | ||||
|       #define tft_Write_32(C)    tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) | ||||
| 
 | ||||
|  | @ -651,43 +771,14 @@ | |||
|       #define tft_Write_32D(C)   tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(C)) | ||||
| 
 | ||||
|       // Read a data bit
 | ||||
|       #define RD_TFT_D0 ((GPIOA->IDR) & 0x01) // Read pin TFT_D0
 | ||||
|       #define RD_TFT_D1 ((GPIOA->IDR) & 0x02) // Read pin TFT_D1
 | ||||
|       #define RD_TFT_D2 ((GPIOA->IDR) & 0x04) // Read pin TFT_D2
 | ||||
|       #define RD_TFT_D3 ((GPIOA->IDR) & 0x08) // Read pin TFT_D3
 | ||||
|       #define RD_TFT_D4 ((GPIOA->IDR) & 0x10) // Read pin TFT_D4
 | ||||
|       #define RD_TFT_D5 ((GPIOA->IDR) & 0x20) // Read pin TFT_D5
 | ||||
|       #define RD_TFT_D6 ((GPIOA->IDR) & 0x40) // Read pin TFT_D6
 | ||||
|       #define RD_TFT_D7 ((GPIOA->IDR) & 0x80) // Read pin TFT_D7
 | ||||
| 
 | ||||
|     #elif defined (STM_PORTB_DATA_BUS) | ||||
|        | ||||
|       // Write 8 bits to TFT
 | ||||
|       #define tft_Write_8(C)   GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB | ||||
|        | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C)  GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \ | ||||
|                                GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \ | ||||
|                                GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB | ||||
| 
 | ||||
|       #define tft_Write_32(C)    tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) | ||||
| 
 | ||||
|       #define tft_Write_32C(C,D) tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(D)) | ||||
| 
 | ||||
|       #define tft_Write_32D(C)   tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(C)) | ||||
| 
 | ||||
|       // Read a data bit
 | ||||
|       #define RD_TFT_D0 ((GPIOB->IDR) & 0x80) // Read pin TFT_D0
 | ||||
|       #define RD_TFT_D1 ((GPIOB->IDR) & 0x40) // Read pin TFT_D1
 | ||||
|       #define RD_TFT_D2 ((GPIOB->IDR) & 0x20) // Read pin TFT_D2
 | ||||
|       #define RD_TFT_D3 ((GPIOB->IDR) & 0x10) // Read pin TFT_D3
 | ||||
|       #define RD_TFT_D4 ((GPIOB->IDR) & 0x08) // Read pin TFT_D4
 | ||||
|       #define RD_TFT_D5 ((GPIOB->IDR) & 0x04) // Read pin TFT_D5
 | ||||
|       #define RD_TFT_D6 ((GPIOB->IDR) & 0x02) // Read pin TFT_D6
 | ||||
|       #define RD_TFT_D7 ((GPIOB->IDR) & 0x01) // Read pin TFT_D7
 | ||||
|       #define RD_TFT_D0 ((GPIOX->IDR) & 0x01) // Read pin TFT_D0
 | ||||
|       #define RD_TFT_D1 ((GPIOX->IDR) & 0x02) // Read pin TFT_D1
 | ||||
|       #define RD_TFT_D2 ((GPIOX->IDR) & 0x04) // Read pin TFT_D2
 | ||||
|       #define RD_TFT_D3 ((GPIOX->IDR) & 0x08) // Read pin TFT_D3
 | ||||
|       #define RD_TFT_D4 ((GPIOX->IDR) & 0x10) // Read pin TFT_D4
 | ||||
|       #define RD_TFT_D5 ((GPIOX->IDR) & 0x20) // Read pin TFT_D5
 | ||||
|       #define RD_TFT_D6 ((GPIOX->IDR) & 0x40) // Read pin TFT_D6
 | ||||
|       #define RD_TFT_D7 ((GPIOX->IDR) & 0x80) // Read pin TFT_D7
 | ||||
| 
 | ||||
|     #else | ||||
|       // This will work with any STM32 to parallel TFT pin mapping but will be slower
 | ||||
|  | @ -764,49 +855,90 @@ | |||
|                                D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ | ||||
|                                WR_STB | ||||
| 
 | ||||
|       // Write 16 bits to TFT
 | ||||
|       #define tft_Write_16(C)  D0_PIN_PORT->BSRR = D8_BSR_MASK(C);  \ | ||||
|                                D1_PIN_PORT->BSRR = D9_BSR_MASK(C);  \ | ||||
|                                D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ | ||||
|                                D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ | ||||
|                                D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ | ||||
|                                D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ | ||||
|                                D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ | ||||
|                                WR_STB;\ | ||||
|                                D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ | ||||
|                                D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ | ||||
|                                D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ | ||||
|                                D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ | ||||
|                                D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ | ||||
|                                D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ | ||||
|                                D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ | ||||
|                                WR_STB | ||||
|       #if defined (SSD1963_DRIVER) | ||||
| 
 | ||||
|       // 16 bit write with swapped bytes
 | ||||
|       #define tft_Write_16S(C) D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ | ||||
|                                D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ | ||||
|                                D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ | ||||
|                                D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ | ||||
|                                D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ | ||||
|                                D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ | ||||
|                                D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ | ||||
|                                WR_STB; \ | ||||
|                                D0_PIN_PORT->BSRR = D8_BSR_MASK(C);  \ | ||||
|                                D1_PIN_PORT->BSRR = D9_BSR_MASK(C);  \ | ||||
|                                D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ | ||||
|                                D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ | ||||
|                                WR_L; \ | ||||
|                                D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ | ||||
|                                D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ | ||||
|                                D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ | ||||
|                                D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ | ||||
|                                WR_STB | ||||
|         // Write 18 bit color to TFT (untested)
 | ||||
|         #define tft_Write_16(C)  r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ | ||||
|                                  D0_PIN_PORT->BSRR = D8_BSR_MASK(r6);  \ | ||||
|                                  D1_PIN_PORT->BSRR = D9_BSR_MASK(r6);  \ | ||||
|                                  D2_PIN_PORT->BSRR = D10_BSR_MASK(r6); \ | ||||
|                                  D3_PIN_PORT->BSRR = D11_BSR_MASK(r6); \ | ||||
|                                  WR_L; \ | ||||
|                                  D4_PIN_PORT->BSRR = D12_BSR_MASK(r6); \ | ||||
|                                  D5_PIN_PORT->BSRR = D13_BSR_MASK(r6); \ | ||||
|                                  D6_PIN_PORT->BSRR = D14_BSR_MASK(r6); \ | ||||
|                                  D7_PIN_PORT->BSRR = D15_BSR_MASK(r6); \ | ||||
|                                  WR_STB;\ | ||||
|                                  D0_PIN_PORT->BSRR = D8_BSR_MASK(g6);  \ | ||||
|                                  D1_PIN_PORT->BSRR = D9_BSR_MASK(g6);  \ | ||||
|                                  D2_PIN_PORT->BSRR = D10_BSR_MASK(g6); \ | ||||
|                                  D3_PIN_PORT->BSRR = D11_BSR_MASK(g6); \ | ||||
|                                  WR_L; \ | ||||
|                                  D4_PIN_PORT->BSRR = D12_BSR_MASK(g6); \ | ||||
|                                  D5_PIN_PORT->BSRR = D13_BSR_MASK(g6); \ | ||||
|                                  D6_PIN_PORT->BSRR = D14_BSR_MASK(g6); \ | ||||
|                                  D7_PIN_PORT->BSRR = D15_BSR_MASK(g6); \ | ||||
|                                  WR_STB;\ | ||||
|                                  D0_PIN_PORT->BSRR = D0_BSR_MASK(b6); \ | ||||
|                                  D1_PIN_PORT->BSRR = D1_BSR_MASK(b6); \ | ||||
|                                  D2_PIN_PORT->BSRR = D2_BSR_MASK(b6); \ | ||||
|                                  D3_PIN_PORT->BSRR = D3_BSR_MASK(b6); \ | ||||
|                                  WR_L; \ | ||||
|                                  D4_PIN_PORT->BSRR = D4_BSR_MASK(b6); \ | ||||
|                                  D5_PIN_PORT->BSRR = D5_BSR_MASK(b6); \ | ||||
|                                  D6_PIN_PORT->BSRR = D6_BSR_MASK(b6); \ | ||||
|                                  D7_PIN_PORT->BSRR = D7_BSR_MASK(b6); \ | ||||
|                                  WR_STB | ||||
| 
 | ||||
|         // 18 bit color write with swapped bytes
 | ||||
|         #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) | ||||
| 
 | ||||
|       #else | ||||
| 
 | ||||
|         // Write 16 bits to TFT
 | ||||
|         #define tft_Write_16(C)  D0_PIN_PORT->BSRR = D8_BSR_MASK(C);  \ | ||||
|                                  D1_PIN_PORT->BSRR = D9_BSR_MASK(C);  \ | ||||
|                                  D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ | ||||
|                                  D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ | ||||
|                                  D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ | ||||
|                                  D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ | ||||
|                                  D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ | ||||
|                                  WR_STB;\ | ||||
|                                  D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ | ||||
|                                  D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ | ||||
|                                  D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ | ||||
|                                  D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ | ||||
|                                  D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ | ||||
|                                  D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ | ||||
|                                  D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ | ||||
|                                  WR_STB | ||||
| 
 | ||||
|         // 16 bit write with swapped bytes
 | ||||
|         #define tft_Write_16S(C) D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ | ||||
|                                  D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ | ||||
|                                  D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ | ||||
|                                  D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ | ||||
|                                  D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ | ||||
|                                  D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ | ||||
|                                  D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ | ||||
|                                  WR_STB; \ | ||||
|                                  D0_PIN_PORT->BSRR = D8_BSR_MASK(C);  \ | ||||
|                                  D1_PIN_PORT->BSRR = D9_BSR_MASK(C);  \ | ||||
|                                  D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ | ||||
|                                  D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ | ||||
|                                  WR_L; \ | ||||
|                                  D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ | ||||
|                                  D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ | ||||
|                                  D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ | ||||
|                                  D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ | ||||
|                                  WR_STB | ||||
|       #endif | ||||
| 
 | ||||
|       #define tft_Write_32(C)    tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) | ||||
| 
 | ||||
|  | @ -826,9 +958,9 @@ | |||
|     #endif | ||||
|   #endif | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI9488 TFT
 | ||||
| // Macros to write commands/pixel colour data to a SPI ILI948x TFT
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif  defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
 | ||||
| #elif  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
 | ||||
| 
 | ||||
|   // Write 8 bits to TFT
 | ||||
|   #define tft_Write_8(C) \ | ||||
|  | @ -878,8 +1010,8 @@ | |||
|   HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } | ||||
| 
 | ||||
|   #define tft_Write_32(C) \ | ||||
|   { spiBuffer[1] = ((C)>>24); spiBuffer[3] = ((C)>>16); spiBuffer[5] = ((C)>>8); spiBuffer[7] = C; \ | ||||
|   HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); } | ||||
|   { spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \ | ||||
|   HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } | ||||
| 
 | ||||
|   #define tft_Write_32C(C,D) \ | ||||
|   { spiBuffer[1] = ((C)>>8); spiBuffer[3] = (C); spiBuffer[5] = ((D)>>8); spiBuffer[7] = D; \ | ||||
|  | @ -892,11 +1024,17 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros for all other SPI displays
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
|   #define tft_Write_8(C) \ | ||||
|   { spiBuffer[0] = C; \ | ||||
|   HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); } | ||||
|   #if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) | ||||
|     // Temporary workaround for issue #510 part 2
 | ||||
|     #define tft_Write_8(C)   spi.transfer(C) | ||||
|   #else | ||||
|     #define tft_Write_8(C) \ | ||||
|     { spiBuffer[0] = C; \ | ||||
|     HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); delayMicroseconds(1);} | ||||
|   #endif | ||||
| 
 | ||||
|   #define tft_Write_16(C) \ | ||||
|   { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \ | ||||
|  | @ -920,6 +1058,10 @@ | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef tft_Write_16N | ||||
|   #define tft_Write_16N tft_Write_16 | ||||
| #endif | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Macros to read from display using SPI or software SPI
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  |  | |||
|  | @ -0,0 +1,62 @@ | |||
| // -------------------------------------------------- //
 | ||||
| // This file is autogenerated by pioasm; do not edit! //
 | ||||
| // 16 bit parallel                                    //
 | ||||
| // -------------------------------------------------- //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| #include "hardware/pio.h" | ||||
| #endif | ||||
| 
 | ||||
| // ------ //
 | ||||
| // tft_io //
 | ||||
| // ------ //
 | ||||
| 
 | ||||
| #define tft_io_wrap_target 7 | ||||
| #define tft_io_wrap 20 | ||||
| #define tft_io_offset_block_fill 0u | ||||
| #define tft_io_offset_start_8 7u | ||||
| #define tft_io_offset_start_tx 7u | ||||
| #define tft_io_offset_set_addr_window 10u | ||||
| 
 | ||||
| static const uint16_t tft_io_program_instructions[] = { | ||||
|     0x98a0, //  0: pull   block           side 1     
 | ||||
|     0xa027, //  1: mov    x, osr                     
 | ||||
|     0x80a0, //  2: pull   block                      
 | ||||
|     0xa047, //  3: mov    y, osr                     
 | ||||
|     0xb8e1, //  4: mov    osr, x          side 1     
 | ||||
|     0x7100, //  5: out    pins, 32        side 0 [1] 
 | ||||
|     0x1884, //  6: jmp    y--, 4          side 1     
 | ||||
|             //     .wrap_target
 | ||||
|     0x98a0, //  7: pull   block           side 1     
 | ||||
|     0x7100, //  8: out    pins, 32        side 0 [1] 
 | ||||
|     0x1807, //  9: jmp    7               side 1     
 | ||||
|     0xf822, // 10: set    x, 2            side 1     
 | ||||
|     0xe000, // 11: set    pins, 0                    
 | ||||
|     0x80a0, // 12: pull   block                      
 | ||||
|     0x7000, // 13: out    pins, 32        side 0     
 | ||||
|     0x0033, // 14: jmp    !x, 19                     
 | ||||
|     0x98a0, // 15: pull   block           side 1     
 | ||||
|     0xe001, // 16: set    pins, 1                    
 | ||||
|     0x7108, // 17: out    pins, 8         side 0 [1] 
 | ||||
|     0x19f1, // 18: jmp    !osre, 17       side 1 [1] 
 | ||||
|     0x184b, // 19: jmp    x--, 11         side 1     
 | ||||
|     0xe001, // 20: set    pins, 1                    
 | ||||
|             //     .wrap
 | ||||
| }; | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| static const struct pio_program tft_io_program = { | ||||
|     .instructions = tft_io_program_instructions, | ||||
|     .length = 21, | ||||
|     .origin = -1, | ||||
| }; | ||||
| 
 | ||||
| static inline pio_sm_config tft_io_program_get_default_config(uint offset) { | ||||
|     pio_sm_config c = pio_get_default_sm_config(); | ||||
|     sm_config_set_wrap(&c, offset + tft_io_wrap_target, offset + tft_io_wrap); | ||||
|     sm_config_set_sideset(&c, 2, true, false); | ||||
|     return c; | ||||
| } | ||||
| #endif | ||||
|  | @ -0,0 +1,70 @@ | |||
| // -------------------------------------------------- //
 | ||||
| // This file is autogenerated by pioasm; do not edit! //
 | ||||
| // 8 bit parallel                                     //
 | ||||
| // -------------------------------------------------- //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| #include "hardware/pio.h" | ||||
| #endif | ||||
| 
 | ||||
| // ------ //
 | ||||
| // tft_io //
 | ||||
| // ------ //
 | ||||
| 
 | ||||
| #define tft_io_wrap_target 9 | ||||
| #define tft_io_wrap 27 | ||||
| 
 | ||||
| #define tft_io_offset_block_fill 0u | ||||
| #define tft_io_offset_start_tx 9u | ||||
| #define tft_io_offset_start_8 14u | ||||
| #define tft_io_offset_set_addr_window 17u | ||||
| 
 | ||||
| static const uint16_t tft_io_program_instructions[] = { | ||||
|     0x98a0, //  0: pull   block           side 1     
 | ||||
|     0xa027, //  1: mov    x, osr                     
 | ||||
|     0x80a0, //  2: pull   block                      
 | ||||
|     0xa047, //  3: mov    y, osr                     
 | ||||
|     0xb8e1, //  4: mov    osr, x          side 1     
 | ||||
|     0x7118, //  5: out    pins, 24        side 0 [1] 
 | ||||
|     0xb942, //  6: nop                    side 1 [1] 
 | ||||
|     0x7108, //  7: out    pins, 8         side 0 [1] 
 | ||||
|     0x1884, //  8: jmp    y--, 4          side 1     
 | ||||
|             //     .wrap_target
 | ||||
|     0x98a0, //  9: pull   block           side 1     
 | ||||
|     0x7118, // 10: out    pins, 24        side 0 [1] 
 | ||||
|     0xb942, // 11: nop                    side 1 [1] 
 | ||||
|     0x7108, // 12: out    pins, 8         side 0 [1] 
 | ||||
|     0x1809, // 13: jmp    9               side 1     
 | ||||
|     0x98a0, // 14: pull   block           side 1     
 | ||||
|     0x7100, // 15: out    pins, 32        side 0 [1] 
 | ||||
|     0x1809, // 16: jmp    9               side 1     
 | ||||
|     0xf822, // 17: set    x, 2            side 1     
 | ||||
|     0xe000, // 18: set    pins, 0                    
 | ||||
|     0x80a0, // 19: pull   block                      
 | ||||
|     0x7000, // 20: out    pins, 32        side 0     
 | ||||
|     0x003a, // 21: jmp    !x, 26                     
 | ||||
|     0x98a0, // 22: pull   block           side 1     
 | ||||
|     0xe001, // 23: set    pins, 1                    
 | ||||
|     0x7108, // 24: out    pins, 8         side 0 [1] 
 | ||||
|     0x19f8, // 25: jmp    !osre, 24       side 1 [1] 
 | ||||
|     0x1852, // 26: jmp    x--, 18         side 1     
 | ||||
|     0xe001, // 27: set    pins, 1                    
 | ||||
|             //     .wrap
 | ||||
| }; | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| static const struct pio_program tft_io_program = { | ||||
|     .instructions = tft_io_program_instructions, | ||||
|     .length = 28, | ||||
|     .origin = -1, | ||||
| }; | ||||
| 
 | ||||
| static inline pio_sm_config tft_io_program_get_default_config(uint offset) { | ||||
|     pio_sm_config c = pio_get_default_sm_config(); | ||||
|     sm_config_set_wrap(&c, offset + tft_io_wrap_target, offset + tft_io_wrap); | ||||
|     sm_config_set_sideset(&c, 2, true, false); | ||||
|     return c; | ||||
| } | ||||
| #endif | ||||
|  | @ -0,0 +1,73 @@ | |||
| // -------------------------------------------------- //
 | ||||
| // This file is autogenerated by pioasm; do not edit! //
 | ||||
| // -------------------------------------------------- //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| #include "hardware/pio.h" | ||||
| #endif | ||||
| 
 | ||||
| // ------ //
 | ||||
| // tft_io //
 | ||||
| // ------ //
 | ||||
| 
 | ||||
| #define tft_io_wrap_target 11 | ||||
| #define tft_io_wrap 31 | ||||
| 
 | ||||
| #define tft_io_offset_block_fill 0u | ||||
| #define tft_io_offset_start_tx 11u | ||||
| #define tft_io_offset_start_8 18u | ||||
| #define tft_io_offset_set_addr_window 21u | ||||
| 
 | ||||
| static const uint16_t tft_io_program_instructions[] = { | ||||
|     0x98a0, //  0: pull   block           side 1     
 | ||||
|     0xa027, //  1: mov    x, osr                     
 | ||||
|     0x80a0, //  2: pull   block                      
 | ||||
|     0xa047, //  3: mov    y, osr                     
 | ||||
|     0xb8e1, //  4: mov    osr, x          side 1     
 | ||||
|     0x7110, //  5: out    pins, 16        side 0 [1] 
 | ||||
|     0xb942, //  6: nop                    side 1 [1] 
 | ||||
|     0x7108, //  7: out    pins, 8         side 0 [1] 
 | ||||
|     0xb942, //  8: nop                    side 1 [1] 
 | ||||
|     0x7108, //  9: out    pins, 8         side 0 [1] 
 | ||||
|     0x1884, // 10: jmp    y--, 4          side 1     
 | ||||
|             //     .wrap_target
 | ||||
|     0x98a0, // 11: pull   block           side 1     
 | ||||
|     0x7110, // 12: out    pins, 16        side 0 [1] 
 | ||||
|     0xb942, // 13: nop                    side 1 [1] 
 | ||||
|     0x7108, // 14: out    pins, 8         side 0 [1] 
 | ||||
|     0xb942, // 15: nop                    side 1 [1] 
 | ||||
|     0x7108, // 16: out    pins, 8         side 0 [1] 
 | ||||
|     0x180b, // 17: jmp    11              side 1     
 | ||||
|     0x98a0, // 18: pull   block           side 1     
 | ||||
|     0x7100, // 19: out    pins, 32        side 0 [1] 
 | ||||
|     0x180b, // 20: jmp    11              side 1     
 | ||||
|     0xf822, // 21: set    x, 2            side 1     
 | ||||
|     0xe000, // 22: set    pins, 0                    
 | ||||
|     0x80a0, // 23: pull   block                      
 | ||||
|     0x7000, // 24: out    pins, 32        side 0     
 | ||||
|     0x003e, // 25: jmp    !x, 30                     
 | ||||
|     0x98a0, // 26: pull   block           side 1     
 | ||||
|     0xe001, // 27: set    pins, 1                    
 | ||||
|     0x7108, // 28: out    pins, 8         side 0 [1] 
 | ||||
|     0x19fc, // 29: jmp    !osre, 28       side 1 [1] 
 | ||||
|     0x1856, // 30: jmp    x--, 22         side 1     
 | ||||
|     0xe001, // 31: set    pins, 1                    
 | ||||
|             //     .wrap
 | ||||
| }; | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| static const struct pio_program tft_io_program = { | ||||
|     .instructions = tft_io_program_instructions, | ||||
|     .length = 32, | ||||
|     .origin = -1, | ||||
| }; | ||||
| 
 | ||||
| static inline pio_sm_config tft_io_program_get_default_config(uint offset) { | ||||
|     pio_sm_config c = pio_get_default_sm_config(); | ||||
|     sm_config_set_wrap(&c, offset + tft_io_wrap_target, offset + tft_io_wrap); | ||||
|     sm_config_set_sideset(&c, 2, true, false); | ||||
|     return c; | ||||
| } | ||||
| #endif | ||||
|  | @ -0,0 +1,74 @@ | |||
| // -------------------------------------------------- //
 | ||||
| // This file is autogenerated by pioasm; do not edit! //
 | ||||
| // 8 + 16 bit SPI - no auto colour conversion         //
 | ||||
| // -------------------------------------------------- //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| #include "hardware/pio.h" | ||||
| #endif | ||||
| 
 | ||||
| // ------ //
 | ||||
| // tft_io //
 | ||||
| // ------ //
 | ||||
| 
 | ||||
| #define tft_io_wrap_target 27 | ||||
| #define tft_io_wrap 31 | ||||
| 
 | ||||
| #define tft_io_offset_start_8 0u | ||||
| #define tft_io_offset_set_addr_window 3u | ||||
| #define tft_io_offset_block_fill 17u | ||||
| #define tft_io_offset_start_tx 27u | ||||
| 
 | ||||
| static const uint16_t tft_io_program_instructions[] = { | ||||
|     0x90a0, //  0: pull   block           side 0     
 | ||||
|     0x6019, //  1: out    pins, 25                   
 | ||||
|     0x181e, //  2: jmp    30              side 1     
 | ||||
|     0xf022, //  3: set    x, 2            side 0     
 | ||||
|     0xe000, //  4: set    pins, 0                    
 | ||||
|     0x90a0, //  5: pull   block           side 0     
 | ||||
|     0x6019, //  6: out    pins, 25                   
 | ||||
|     0xb842, //  7: nop                    side 1     
 | ||||
|     0x7001, //  8: out    pins, 1         side 0     
 | ||||
|     0x18e8, //  9: jmp    !osre, 8        side 1     
 | ||||
|     0xf001, // 10: set    pins, 1         side 0     
 | ||||
|     0x003b, // 11: jmp    !x, 27                     
 | ||||
|     0x80a0, // 12: pull   block                      
 | ||||
|     0x7001, // 13: out    pins, 1         side 0     
 | ||||
|     0x18ed, // 14: jmp    !osre, 13       side 1     
 | ||||
|     0x1044, // 15: jmp    x--, 4          side 0     
 | ||||
|     0x001b, // 16: jmp    27                         
 | ||||
|     0x90a0, // 17: pull   block           side 0     
 | ||||
|     0xa027, // 18: mov    x, osr                     
 | ||||
|     0x80a0, // 19: pull   block                      
 | ||||
|     0xa047, // 20: mov    y, osr                     
 | ||||
|     0xb0e1, // 21: mov    osr, x          side 0     
 | ||||
|     0x7011, // 22: out    pins, 17        side 0     
 | ||||
|     0xb842, // 23: nop                    side 1     
 | ||||
|     0x7001, // 24: out    pins, 1         side 0     
 | ||||
|     0x18f8, // 25: jmp    !osre, 24       side 1     
 | ||||
|     0x1095, // 26: jmp    y--, 21         side 0     
 | ||||
|             //     .wrap_target
 | ||||
|     0x90a0, // 27: pull   block           side 0     
 | ||||
|     0x7011, // 28: out    pins, 17        side 0     
 | ||||
|     0xb842, // 29: nop                    side 1     
 | ||||
|     0x7001, // 30: out    pins, 1         side 0     
 | ||||
|     0x18fe, // 31: jmp    !osre, 30       side 1     
 | ||||
|             //     .wrap
 | ||||
| }; | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| static const struct pio_program tft_io_program = { | ||||
|     .instructions = tft_io_program_instructions, | ||||
|     .length = 32, | ||||
|     .origin = -1, | ||||
| }; | ||||
| 
 | ||||
| static inline pio_sm_config tft_io_program_get_default_config(uint offset) { | ||||
|     pio_sm_config c = pio_get_default_sm_config(); | ||||
|     sm_config_set_wrap(&c, offset + tft_io_wrap_target, offset + tft_io_wrap); | ||||
|     sm_config_set_sideset(&c, 2, true, false); | ||||
|     return c; | ||||
| } | ||||
| #endif | ||||
|  | @ -0,0 +1,74 @@ | |||
| // -------------------------------------------------- //
 | ||||
| // This file is autogenerated by pioasm; do not edit! //
 | ||||
| // 8 + 18 bit SPI - no auto colour conversion         //
 | ||||
| // -------------------------------------------------- //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| #include "hardware/pio.h" | ||||
| #endif | ||||
| 
 | ||||
| // ------ //
 | ||||
| // tft_io //
 | ||||
| // ------ //
 | ||||
| 
 | ||||
| #define tft_io_wrap_target 27 | ||||
| #define tft_io_wrap 31 | ||||
| 
 | ||||
| #define tft_io_offset_start_8 0u | ||||
| #define tft_io_offset_set_addr_window 3u | ||||
| #define tft_io_offset_block_fill 17u | ||||
| #define tft_io_offset_start_tx 27u | ||||
| 
 | ||||
| static const uint16_t tft_io_program_instructions[] = { | ||||
|     0x90a0, //  0: pull   block           side 0     
 | ||||
|     0x6019, //  1: out    pins, 25                   
 | ||||
|     0x181e, //  2: jmp    30              side 1     
 | ||||
|     0xf022, //  3: set    x, 2            side 0     
 | ||||
|     0xe000, //  4: set    pins, 0                    
 | ||||
|     0x90a0, //  5: pull   block           side 0     
 | ||||
|     0x6019, //  6: out    pins, 25                   
 | ||||
|     0xb842, //  7: nop                    side 1     
 | ||||
|     0x7001, //  8: out    pins, 1         side 0     
 | ||||
|     0x18e8, //  9: jmp    !osre, 8        side 1     
 | ||||
|     0xf001, // 10: set    pins, 1         side 0     
 | ||||
|     0x003b, // 11: jmp    !x, 27                     
 | ||||
|     0x80a0, // 12: pull   block                      
 | ||||
|     0x7001, // 13: out    pins, 1         side 0     
 | ||||
|     0x18ed, // 14: jmp    !osre, 13       side 1     
 | ||||
|     0x1044, // 15: jmp    x--, 4          side 0     
 | ||||
|     0x001b, // 16: jmp    27                         
 | ||||
|     0x90a0, // 17: pull   block           side 0     
 | ||||
|     0xa027, // 18: mov    x, osr                     
 | ||||
|     0x80a0, // 19: pull   block                      
 | ||||
|     0xa047, // 20: mov    y, osr                     
 | ||||
|     0xb0e1, // 21: mov    osr, x          side 0     
 | ||||
|     0x7009, // 22: out    pins, 9         side 0     
 | ||||
|     0xb842, // 23: nop                    side 1     
 | ||||
|     0x7001, // 24: out    pins, 1         side 0     
 | ||||
|     0x18f8, // 25: jmp    !osre, 24       side 1     
 | ||||
|     0x1095, // 26: jmp    y--, 21         side 0     
 | ||||
|             //     .wrap_target
 | ||||
|     0x90a0, // 27: pull   block           side 0     
 | ||||
|     0x7009, // 28: out    pins, 9         side 0     
 | ||||
|     0xb842, // 29: nop                    side 1     
 | ||||
|     0x7001, // 30: out    pins, 1         side 0     
 | ||||
|     0x18fe, // 31: jmp    !osre, 30       side 1     
 | ||||
|             //     .wrap
 | ||||
| }; | ||||
| 
 | ||||
| #if !PICO_NO_HARDWARE | ||||
| static const struct pio_program tft_io_program = { | ||||
|     .instructions = tft_io_program_instructions, | ||||
|     .length = 32, | ||||
|     .origin = -1, | ||||
| }; | ||||
| 
 | ||||
| static inline pio_sm_config tft_io_program_get_default_config(uint offset) { | ||||
|     pio_sm_config c = pio_get_default_sm_config(); | ||||
|     sm_config_set_wrap(&c, offset + tft_io_wrap_target, offset + tft_io_wrap); | ||||
|     sm_config_set_sideset(&c, 2, true, false); | ||||
|     return c; | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										169
									
								
								README.md
								
								
								
								
							
							
						
						
									
										169
									
								
								README.md
								
								
								
								
							|  | @ -1,57 +1,117 @@ | |||
| # Tips | ||||
| If you load a new copy of TFT_eSPI then it will over-write your setups if they are kept within the TFT_eSPI folder. One way around this is to create a new folder in your Arduino library folder called "TFT_eSPI_Setups". You then place your custom setup.h files in there. After an upgrade simply edit the User_Setup_Select.h file to point to your custom setup file e.g.: | ||||
| ``` | ||||
| #include <../TFT_eSPI_Setups/my_custom_setup.h> | ||||
| ``` | ||||
| You must make sure only one setup file is called. In the the custom setup file I add the file path as a commented out first line that can be cut and pasted back into the upgraded User_Setup_Select.h file.  The ../ at the start of the path means go up one directory level. Clearly you could use different file paths or directory names as long as it does not clash with another library or folder name. | ||||
| 
 | ||||
| You can take this one step further and have your own setup select file and then you only need to replace the Setup.h line reference in User_Setup_Select.h to, for example: | ||||
| ``` | ||||
| #include <../TFT_eSPI_Setups/my_setup_select.h> | ||||
| ``` | ||||
| To select a new setup you then edit your own my_setup_select.h file (which will not get over-written during an upgrade). | ||||
| 
 | ||||
| A ["Discussions"](https://github.com/Bodmer/TFT_eSPI/discussions) facility has been added for Q&A etc. Use the ["Issues"](https://github.com/Bodmer/TFT_eSPI/issues) tab only for problems with the library. Thanks! | ||||
| # News | ||||
| 1. A new option has been added for STM32 processors to optimise performance where Port A (or B) pins 0-7 are used for the 8 bit parallel interface data pins 0-7 to the TFT. This gives a dramatic 8 times better rendering performance for the lower clock rate STM32 processors such as the STM32F103 "Blue Pill" or STM411 "Black Pill" since no time consuming data bit manipulation is required. See setup file "User_Setups/Setup35_ILI9341_STM32_Port_Bus.h". | ||||
| 1. New functions have been added to draw smooth (antialiased) arcs, circles, and rounded rectangle outlines. New sketches are provided in the "Smooth Graphics" examples folder. Arcs can be drawn with or without anti-aliasing (which will then render faster). The arc ends can be straight or rounded. The arc drawing algorithm uses an optimised fixed point sqrt() function to improve performance on processors that do not have a hardware Floating Point Unit (e.g. RP2040). Here are two demo images, on the left smooth (anti-aliased) arcs with rounded ends, the image to the right is the same resolution (grabbed from the same 240x240 TFT) with the smoothing diasbled (no anti-aliasing): | ||||
| 
 | ||||
| 2. A new "Animated_dial" example has been added to show how dials can be created using a rotated Sprite for the needle. To run this example the TFT must support reading from the screen RAM. The dial rim and scale is a jpeg image, created using a paint program. | ||||
|          | ||||
| 
 | ||||
|        | ||||
|       Here the smooth arcs have been used to create anti-aliased meter gauges on a 320x240 TFT: | ||||
|   | ||||
|        | ||||
| 
 | ||||
| 3. Anti-aliased (smooth) fonts can now be stored as arrays in FLASH (program) memory. This means that processors such as STM32 that do not have SPIFFS support can use the fonts. The processor must have sufficient FLASH memory to store the fonts used. | ||||
| 2. An excellent new compatible library is available which can render TrueType fonts on a TFT screen (or into a sprite). This has been developed by [takkaO](https://github.com/takkaO/OpenFontRender), I have created a branch with some bug fixes [here](https://github.com/Bodmer/OpenFontRender). The library provides access to compact font files, with fully scaleable anti-aliased glyphs. Left, middle and right justified text can also be printed to the screen. I have added TFT_eSPI specific examples to the OpenFontRender library and tested on RP2040 and ESP32 processors, the ESP8266 does not have sufficient RAM due to the glyph render complexity. Here is a demo screen where a single 12kbyte font file binary was used to render fully anti-aliased glyphs of gradually increasing size on a 320x480 TFT screen: | ||||
| 
 | ||||
| 4. The Sprite class now supports 4 bits per pixel with a 16 color palette. Three new examples have been added. | ||||
|        | ||||
| 
 | ||||
| 5. The library has been upgraded to support STM32 processors when used with SPI or 8 bit parallel displays. DMA capability for SPI displays has been added for STM32F103 (e.g. "Blue Pill") and STM32F2xx/4xx/7xx (e.g. 32/64/144 Nucleo boards). New DMA demo examples have been added (for STM32 only). | ||||
| 3. New GUI examples have been added for sliders, buttons, graphs and meters. These examples require a new support library here: | ||||
| 
 | ||||
| 6. The ST7796 display controller has been added. The ST7796 RPi MHS-4.0 inch Display-B type display is supported (this is fast for a SPI display as an ESP32 can clock it at 80MHz (ESP8266 at 40MHz)), see setups 27 and 28. | ||||
|    [TFT_eWidget](https://github.com/Bodmer/TFT_eWidget) | ||||
| 
 | ||||
| 7. A callback function has been added, this allows antialiased fonts to be rendered over colour gradients or images. Two new examples have been added to illustrate this new capability: | ||||
| 4. Support has been added in v2.4.70 for the RP2040 with 16 bit parallel displays. This has been tested and the screen update performance is very good (4ms to clear 320 x 480 screen with HC8357C). The use of the RP2040 PIO makes it easy to change the write cycle timing for different displays. DMA with 16 bit transfers is also supported. | ||||
| 
 | ||||
|            "Smooth_font_reading_TFT" | ||||
|      | ||||
|            "Smooth_font_gradient" | ||||
|             | ||||
|        | ||||
| 5. Support for the ESP32-S2, ESP32-S3 and ESP32-C3 has been added (DMA only on ESP32 S3 at the moment). Tested with v2.0.3 RC1 of the ESP32 board package. Example setups: | ||||
| 
 | ||||
|       [Setup70_ESP32_S2_ILI9341.h](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup70_ESP32_S2_ILI9341.h) | ||||
|        | ||||
|       [Setup70b_ESP32_S3_ILI9341.h](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup70b_ESP32_S3_ILI9341.h) | ||||
|        | ||||
|       [Setup70c_ESP32_C3_ILI9341.h](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup70c_ESP32_C3_ILI9341.h) | ||||
| 
 | ||||
|       [Setup70d_ILI9488_S3_Parallel.h](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup70d_ILI9488_S3_Parallel.h) | ||||
| 
 | ||||
| 6. Smooth fonts can now be rendered direct to the TFT with very little flicker for quickly changing values. This is achieved by a line-by-line and block-by-block update of the glyph area without drawing pixels twice. This is a "breaking" change for some sketches because a new true/false parameter is needed to render the background. The default is false if the parameter is missing, Examples: | ||||
| 
 | ||||
|       tft.setTextColor(TFT_WHITE, TFT_BLUE, true); | ||||
|       spr.setTextColor(TFT_BLUE, TFT_BLACK, true); | ||||
| 
 | ||||
| Note: background rendering for Smooth fonts is also now available when using the print stream e.g. with: tft.println("Hello World"); | ||||
| 
 | ||||
| 7. New anti-aliased graphics functions to draw lines, wedge shaped lines, circles and rounded rectangles. [Examples are included](https://github.com/Bodmer/TFT_eSPI/tree/master/examples/Smooth%20Graphics). Examples have also been added to [display PNG compressed images](https://github.com/Bodmer/TFT_eSPI/tree/master/examples/PNG%20Images) (note: requires ~40kbytes RAM). | ||||
| 
 | ||||
| 8. Frank Boesing has created an extension library for TFT_eSPI that allows a large range of ready-built fonts to be used. Frank's library (adapted to permit rendering in sprites as well as TFT) can be [downloaded here](https://github.com/Bodmer/TFT_eSPI_ext). More than 3300 additional Fonts are [available here](https://github.com/FrankBoesing/fonts/tree/master/ofl). The TFT_eSPI_ext library contains examples that demonstrate the use of the fonts. | ||||
| 
 | ||||
| 9. Users of PowerPoint experienced with running macros may be interested in the [pptm sketch generator here](https://github.com/Bodmer/PowerPoint_to_sketch), this converts graphics and tables drawn in PowerPoint slides into an Arduino sketch that renders the graphics on a 480x320 TFT. This is based on VB macros [created by Kris Kasprzak here](https://github.com/KrisKasprzak/Powerpoint-ILI9341_t3). | ||||
| 
 | ||||
| 10. The library contains two new functions for rectangles filled with a horizontal or vertical coloured gradient: | ||||
| 
 | ||||
|       tft.fillRectHGradient(x, y, w, h, color1, color2); | ||||
|    | ||||
|       tft.fillRectVGradient(x, y, w, h, color1, color2); | ||||
|        | ||||
|        | ||||
| 
 | ||||
| 11. The RP2040 8 bit parallel interface uses the PIO. The PIO now manages the "setWindow" and "block fill" actions, releasing the processor for other tasks when areas of the screen are being filled with a colour. The PIO can optionally be used for SPI interface displays if #define RP2040_PIO_SPI is put in the setup file. Touch screens and pixel read operations are not supported when the PIO interface is used. | ||||
| The RP2040 PIO features only work with [Earle Philhower's board package](https://github.com/earlephilhower/arduino-pico), NOT the Arduino Mbed version. | ||||
| 
 | ||||
| The use of PIO for SPI allows the RP2040 to be over-clocked (up to 250MHz works on my boards) in Earle's board package whilst still maintaining high SPI clock rates. | ||||
| 
 | ||||
| 12. DMA can now be used with the Raspberry Pi Pico (RP2040) when used with 8/16 bit parallel and 16 bit colour SPI displays. See "Bouncy_Circles" sketch. | ||||
| 
 | ||||
|       ["Bouncing circles"](https://www.youtube.com/watch?v=njFXIzCTQ_Q&lc=UgymaUIwOIuihvYh-Qt4AaABAg) | ||||
| 
 | ||||
| 
 | ||||
| # TFT_eSPI | ||||
| 
 | ||||
| An Arduino IDE compatible graphics and fonts library for 32 bit processors. The library is targetted at 32 bit processors, it  has been performance optimised for STM32, ESP8266 and ESP32 types.  The library includes drivers for ILI9341, ILI9163, ST7735, S6D02A1, ILI9481, ILI9486, ILI9488, HX8357D, ST7789 and ST7796 based TFT displays that support SPI or 8 bit parallel (parallel not supported on ESP8266). The library can be loaded using the Arduino IDE's Library Manager. | ||||
| An Arduino IDE compatible graphics and fonts library for 32 bit processors. The library is targeted at 32 bit processors, it  has been performance optimised for RP2040, STM32, ESP8266 and ESP32 types, other processors may be used but will use the slower generic Arduino interface calls. The library can be loaded using the Arduino IDE's Library Manager. Direct Memory Access (DMA) can be used with the ESP32, RP2040 and STM32 processors with SPI interface displays to improve rendering performance. DMA with a parallel interface (8 and 16 bit parallel) is only supported with the RP2040. | ||||
| 
 | ||||
| 8 bit parallel interface TFTs  (e.g. UNO format mcufriend shields) can used with the STM32 Nucleo 64/144 range or the UNO format ESP32 (see below for ESP32). | ||||
| Optimised drivers have been tested with the following processors: | ||||
| 
 | ||||
| The library supports TFT displays designed for the Raspberry Pi (RPi) that are based on a ILI9486 or ST7796 driver chip with a 480 x 320 pixel screen. The ILI9486 RPi display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. A modification to these displays is possible (see mod image in Tools folder) to make many graphics functions much faster (e.g. 23ms to clear the screen, 1.2ms to draw a 72 pixel high numeral). The RPi ST7796 display is supported and is superior to the Waveshare design, it must be of the MHS-4.0 inch Display-B type. | ||||
| * RP2040, e.g. Raspberry Pi Pico | ||||
| * ESP32 and ESP32-S2, ESP32-C3, ESP32-S3 | ||||
| * ESP8266 | ||||
| * STM32F1xx, STM32F2xx, STM32F4xx, STM32F767 (higher RAM processors recommended) | ||||
| 
 | ||||
| Some displays permit the internal TFT screen RAM to be read. The library supports reading from ILI9341, ST7789 and ILI9488 SPI and other supported 8 bit parallel displays. The TFT_Screen_Capture example allows full screens to be captured and sent to a PC, this is handy to create program documentation. | ||||
| For other processors only SPI interface displays are supported and the slower Arduino SPI library functions are used by the library. Higher clock speed processors such as used for the Teensy 3.x and 4.x boards will still provide a very good performance with the generic Arduino SPI functions. | ||||
| 
 | ||||
| Support has been added recently for Waveshare 2 and 3 colour ePaper displays using full frame buffers. This addition is currently relatively immature and thus only one example has been provided. | ||||
| "Four wire" SPI and 8 bit parallel interfaces are supported. Due to lack of GPIO pins the 8 bit parallel interface is NOT supported on the ESP8266. 8 bit parallel interface TFTs  (e.g. UNO format mcufriend shields) can used with the STM32 Nucleo 64/144 range or the UNO format ESP32 (see below for ESP32). | ||||
| 
 | ||||
| Displays using the following controllers are supported: | ||||
| 
 | ||||
| * GC9A01 | ||||
| * ILI9163 | ||||
| * ILI9225 | ||||
| * ILI9341 | ||||
| * ILI9342 | ||||
| * ILI9481 (DMA not supported with SPI) | ||||
| * ILI9486 (DMA not supported with SPI) | ||||
| * ILI9488 (DMA not supported with SPI) | ||||
| * HX8357B (16 bit parallel tested with RP2040) | ||||
| * HX8357C (16 bit parallel tested with RP2040) | ||||
| * HX8357D | ||||
| * R61581 | ||||
| * RM68120 (support files added but untested) | ||||
| * RM68140 | ||||
| * S6D02A1 | ||||
| * SSD1351 | ||||
| * SSD1963 | ||||
| * ST7735 | ||||
| * ST7789 | ||||
| * ST7796 | ||||
| 
 | ||||
| ILI9341 and ST7796 SPI based displays are recommended as starting point for experimenting with this library. | ||||
| 
 | ||||
| The library supports some TFT displays designed for the Raspberry Pi (RPi) that are based on a ILI9486 or ST7796 driver chip with a 480 x 320 pixel screen. The ILI9486 RPi display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. Note that due to design variations between these displays not all RPi displays will work with this library, so purchasing a RPi display of these types solely for use with this library is NOT recommended. | ||||
| 
 | ||||
| A "good" RPi display is the [MHS-4.0 inch Display-B type ST7796](http://www.lcdwiki.com/MHS-4.0inch_Display-B) which provides good performance. This has a dedicated controller and can be clocked at up to 80MHz with the ESP32 (125MHz with overclocked RP2040, 55MHz with STM32 and 40MHz with ESP8266). The [MHS-3.5 inch RPi ILI9486](http://www.lcdwiki.com/MHS-3.5inch_RPi_Display) based display is also supported, however the MHS ILI9341 based display of the same type does NOT work with this library. | ||||
| 
 | ||||
| Some displays permit the internal TFT screen RAM to be read, a few of the examples use this feature. The TFT_Screen_Capture example allows full screens to be captured and sent to a PC, this is handy to create program documentation. | ||||
| 
 | ||||
| The library supports Waveshare 2 and 3 colour ePaper displays using full frame buffers. This addition is relatively immature and thus only one example has been provided. | ||||
| 
 | ||||
| The library includes a "Sprite" class, this enables flicker free updates of complex graphics. Direct writes to the TFT with graphics functions are still available, so existing sketches do not need to be changed. | ||||
| 
 | ||||
| # Sprites | ||||
| 
 | ||||
| A Sprite is notionally an invisible graphics screen that is kept in the processors RAM. Graphics can be drawn into the Sprite just as they can be drawn directly to the screen. Once the Sprite is completed it can be plotted onto the screen in any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. Sprites by default use 16 bit colours, the bit depth can be set to 8 bits (256 colours) , or 1 bit (any 2 colours) to reduce the RAM needed. On an ESP8266 the largest 16 bit colour Sprite that can be created is about 160x128 pixels, this consumes 40Kbytes of RAM. On an ESP32 the workspace RAM is more limited than the datsheet implies so a 16 bit colour Sprite is limited to about 200x200 pixels (~80Kbytes), an 8 bit sprite to 320x240 pixels (~76kbytes). A 1 bit per pixel Sprite requires only 9600 bytes for a full 320 x 240 screen buffer, this is ideal for supporting use with 2 colour bitmap fonts. | ||||
| A Sprite is notionally an invisible graphics screen that is kept in the processors RAM. Graphics can be drawn into the Sprite just as they can be drawn directly to the screen. Once the Sprite is completed it can be plotted onto the screen in any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. Sprites by default use 16 bit colours, the bit depth can be set to 8 bits (256 colours) , or 1 bit (any 2 colours) to reduce the RAM needed. On an ESP8266 the largest 16 bit colour Sprite that can be created is about 160x128 pixels, this consumes 40Kbytes of RAM. On an ESP32 the workspace RAM is more limited than the datasheet implies so a 16 bit colour Sprite is limited to about 200x200 pixels (~80Kbytes), an 8 bit sprite to 320x240 pixels (~76kbytes). A 1 bit per pixel Sprite requires only 9600 bytes for a full 320 x 240 screen buffer, this is ideal for supporting use with 2 colour bitmap fonts. | ||||
| 
 | ||||
| One or more sprites can be created, a sprite can be any pixel width and height, limited only by available RAM. The RAM needed for a 16 bit colour depth Sprite is (2 x width x height) bytes, for a Sprite with 8 bit colour depth the RAM needed is (width x height) bytes. Sprites can be created and deleted dynamically as needed in the sketch, this means RAM can be freed up after the Sprite has been plotted on the screen, more RAM intensive WiFi based code can then be run and normal graphics operations still work. | ||||
| 
 | ||||
|  | @ -61,30 +121,37 @@ Sprites can be plotted to the TFT with one colour being specified as "transparen | |||
| 
 | ||||
| If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind. | ||||
| 
 | ||||
| The "Animated_dial" example shows how dials can be created using a rotated Sprite for the needle. To run this example the TFT interface must support reading from the screen RAM (not all do). The dial rim and scale is a jpeg image, created using a paint program. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| 
 | ||||
| # Touch controller support | ||||
| 
 | ||||
| The XPT2046 touch screen controller is supported for SPI based displays only. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. This support will eventually be deprecated when a suitable touch screen library is avaiable. | ||||
| The XPT2046 touch screen controller is supported for SPI based displays only. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. This support will eventually be deprecated when a suitable touch screen library is available. | ||||
| 
 | ||||
| The Button class from Adafruit_GFX is incorporated, with the enhancement that the button labels can be in any font. | ||||
| 
 | ||||
| # ESP8266 overlay mode | ||||
| # ESP8266 overlap mode | ||||
| 
 | ||||
| The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH, this frees up GPIO pins for other uses. | ||||
| The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH, this frees up GPIO pins for other uses. Only one SPI device can be connected to the FLASH pins and the chips select for the TFT must be on pin D3 (GPIO0). | ||||
| 
 | ||||
| 
 | ||||
| # Fonts | ||||
| 
 | ||||
| The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-alased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. | ||||
| The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-aliased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. | ||||
| 
 | ||||
| The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for ESP8266/ESP32 processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions. | ||||
| The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for the different processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions. | ||||
| 
 | ||||
| Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder, or by selecting your own configuration in the "User_Setup_Selet,h" file.  Fonts and features can easily be enabled/disabled by commenting out lines. | ||||
| Configuration of the library font selections, pins used to interface with the TFT and other features is made by editing the User_Setup.h file in the library folder, or by selecting your own configuration in the "User_Setup_Selet,h" file.  Fonts and features can easily be enabled/disabled by commenting out lines. | ||||
| 
 | ||||
| 
 | ||||
| # Anti-aliased Fonts | ||||
| 
 | ||||
| Anti-aliased (smooth) font files in "vlw" format are generated by the free [Processing IDE](https://processing.org/) using a sketch included in the library Tools folder. This sketch with the Processing IDE can be used to generate font files from your computer's font set or any TrueType (.ttf) font, the font file can include **any** combination of 16 bit Unicode characters. This means Greek, Japanese and any other UCS-2 glyphs can be used. Character arrays and Strings in UTF-8 format are supported. | ||||
| 
 | ||||
| The .vlw files must be uploaded to the processors FLASH filing system (SPIFFS, LittleFS or SD card) for use. Alternatively the .vlw files can be converted to C arrays (see "Smooth Font -> FLASH_Array" examples) and stored directly in FLASH as part of the compile process.  The array based approach is convenient, provides performance improvements and is suitable where: either use of a filing system is undesirable, or the processor type (e.g. STM32) does not support a FLASH based filing system. | ||||
| 
 | ||||
| Here is the Adafruit_GFX "FreeSans12pt" bitmap font compared to the same font drawn as anti-aliased: | ||||
| 
 | ||||
|  | ||||
|  | @ -93,13 +160,15 @@ The smooth font example displays the following screen: | |||
| 
 | ||||
|  | ||||
| 
 | ||||
| It would be possible to compress the vlw font files but the rendering performance to a TFT is still good when storing the font file(s) in SPIFFS. | ||||
| It would be possible to compress the vlw font files but the rendering performance to a TFT is still good when storing the font file(s) in SPIFFS, LittleFS or FLASH arrays. | ||||
| 
 | ||||
| Here is an example screenshot showing the anti-aliased Hiragana character Unicode block (0x3041 to 0x309F) in 24pt from the Microsoft Yahei font: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| Antialiased fonts can also be drawn over a gradient background with a callback to fetch the background colour of each pixel. This pixel colour can be set by the gradient algorithm or by reading back the TFT screen memory (if reading the display is supported). | ||||
| Anti-aliased fonts can also be drawn over a gradient background with a callback to fetch the background colour of each pixel. This pixel colour can be set by the gradient algorithm or by reading back the TFT screen memory (if reading the display is supported). | ||||
| 
 | ||||
| Anti-aliased fonts cannot be scaled with setTextSize so you need to create a font for each size you need. See examples. | ||||
| 
 | ||||
| # 8 bit parallel support | ||||
| 
 | ||||
|  | @ -109,7 +178,7 @@ The ESP32 board I have been using for testing has the following pinout: | |||
| 
 | ||||
|  | ||||
| 
 | ||||
| UNO style boards with a Wemos R32(ESP32) label are also available at low cost with the same pin-out. | ||||
| UNO style boards with a Wemos R32(ESP32) label are also available at low cost with the same pinout. | ||||
| 
 | ||||
| Unfortunately the typical UNO/mcufriend TFT display board maps LCD_RD, LCD_CS and LCD_RST signals to the ESP32 analogue pins 35, 34 and 36 which are input only.  To solve this I linked in the 3 spare pins IO15, IO33 and IO32 by adding wires to the bottom of the board as follows: | ||||
| 
 | ||||
|  | @ -119,14 +188,22 @@ IO33 wired to IO34 | |||
| 
 | ||||
| IO32 wired to IO36 | ||||
| 
 | ||||
| This is an [example setup file](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup14_ILI9341_Parallel.h) with the correct GPIO for this UNO board. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| If the display board is fitted with a resistance based touch screen then this can be used by performing the modifications described here and the fork of the Adafruit library: | ||||
| https://github.com/s60sc/Adafruit_TouchScreen | ||||
| 
 | ||||
| # ePaper displays | ||||
| 
 | ||||
| The library was intended to support only TFT displays but using a Sprite as a 1 bit per pixel screen buffer permits support for the Waveshare 2 and 3 colour SPI ePaper displays. This addition to the library is experimental and only one example is provided. Further examples will be added. | ||||
| 
 | ||||
|  | ||||
| # Tips | ||||
| If you load a new copy of TFT_eSPI then it will overwrite your setups if they are kept within the TFT_eSPI folder. One way around this is to create a new folder in your Arduino library folder called "TFT_eSPI_Setups". You then place your custom setup.h files in there. After an upgrade simply edit the User_Setup_Select.h file to point to your custom setup file e.g.: | ||||
| ``` | ||||
| #include <../TFT_eSPI_Setups/my_custom_setup.h> | ||||
| ``` | ||||
| You must make sure only one setup file is called. In the custom setup file I add the file path as a commented out first line that can be cut and pasted back into the upgraded User_Setup_Select.h file.  The ../ at the start of the path means go up one directory level. Clearly you could use different file paths or directory names as long as it does not clash with another library or folder name. | ||||
| 
 | ||||
| You can take this one step further and have your own setup select file and then you only need to replace the Setup.h line reference in User_Setup_Select.h to, for example: | ||||
| ``` | ||||
| #include <../TFT_eSPI_Setups/my_setup_select.h> | ||||
| ``` | ||||
| To select a new setup you then edit your own my_setup_select.h file (which will not get overwritten during an upgrade). | ||||
|  |  | |||
							
								
								
									
										14
									
								
								README.txt
								
								
								
								
							
							
						
						
									
										14
									
								
								README.txt
								
								
								
								
							|  | @ -1,7 +1,7 @@ | |||
| This is a standalone library that contains both graphics functions | ||||
| and the TFT chip driver library. It supports the ESP8266, ESP32 and | ||||
| STM32 processors with performance optimised code. Other Arduino IDE | ||||
| compatible boards are also supported but the library then uses | ||||
| generic functions which will be slower. The library uses 32 bit | ||||
| variables extensively so this will affect performance on 8 and 16 | ||||
| bit processors. | ||||
| This is a stand-alone library that contains both graphics functions | ||||
| and the TFT chip driver library. It supports the ESP8266, ESP32, | ||||
| STM32 and RP2040 processors with performance optimised code. Other | ||||
| Arduino IDE compatible boards are also supported but the library | ||||
| then uses generic functions which will be slower. The library uses | ||||
| 32 bit variables extensively so this will affect performance on 8 | ||||
| and 16 bit processors. | ||||
|  |  | |||
|  | @ -0,0 +1,34 @@ | |||
| // Change the width and height if required (defined in portrait mode)
 | ||||
| // or use the constructor to over-ride defaults
 | ||||
| #ifndef TFT_WIDTH | ||||
|   #define TFT_WIDTH  240 | ||||
| #endif | ||||
| #ifndef TFT_HEIGHT | ||||
|   #define TFT_HEIGHT 320 | ||||
| #endif | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
| #define TFT_INIT_DELAY 0x80 | ||||
| 
 | ||||
| // Generic commands used by TFT_eSPI.cpp
 | ||||
| #define TFT_NOP     0x00 | ||||
| #define TFT_SWRST   0x01 | ||||
| 
 | ||||
| #define TFT_CASET   0x2A | ||||
| #define TFT_PASET   0x2B | ||||
| #define TFT_RAMWR   0x2C | ||||
| 
 | ||||
| #define TFT_RAMRD   0x2E | ||||
| #define TFT_IDXRD   0x00 //0xDD // ILI9341 only, indexed control register read
 | ||||
| 
 | ||||
| #define TFT_MADCTL  0x36 | ||||
| #define TFT_MAD_MY  0x80 | ||||
| #define TFT_MAD_MX  0x40 | ||||
| #define TFT_MAD_MV  0x20 | ||||
| #define TFT_MAD_ML  0x10 | ||||
| #define TFT_MAD_BGR 0x08 | ||||
| #define TFT_MAD_MH  0x04 | ||||
| #define TFT_MAD_RGB 0x00 | ||||
| 
 | ||||
| #define TFT_INVOFF  0x20 | ||||
| #define TFT_INVON   0x21 | ||||
|  | @ -0,0 +1,232 @@ | |||
| 
 | ||||
| // This is the command sequence that initialises the GC9A01 driver
 | ||||
| 
 | ||||
| { | ||||
|   writecommand(0xEF); | ||||
|   writecommand(0xEB); | ||||
|   writedata(0x14); | ||||
| 
 | ||||
|   writecommand(0xFE); | ||||
|   writecommand(0xEF); | ||||
| 
 | ||||
|   writecommand(0xEB); | ||||
|   writedata(0x14); | ||||
| 
 | ||||
|   writecommand(0x84); | ||||
|   writedata(0x40); | ||||
| 
 | ||||
|   writecommand(0x85); | ||||
|   writedata(0xFF); | ||||
| 
 | ||||
|   writecommand(0x86); | ||||
|   writedata(0xFF); | ||||
| 
 | ||||
|   writecommand(0x87); | ||||
|   writedata(0xFF); | ||||
| 
 | ||||
|   writecommand(0x88); | ||||
|   writedata(0x0A); | ||||
| 
 | ||||
|   writecommand(0x89); | ||||
|   writedata(0x21); | ||||
| 
 | ||||
|   writecommand(0x8A); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0x8B); | ||||
|   writedata(0x80); | ||||
| 
 | ||||
|   writecommand(0x8C); | ||||
|   writedata(0x01); | ||||
| 
 | ||||
|   writecommand(0x8D); | ||||
|   writedata(0x01); | ||||
| 
 | ||||
|   writecommand(0x8E); | ||||
|   writedata(0xFF); | ||||
| 
 | ||||
|   writecommand(0x8F); | ||||
|   writedata(0xFF); | ||||
| 
 | ||||
|   writecommand(0xB6); | ||||
|   writedata(0x00); | ||||
|   writedata(0x20); | ||||
| 
 | ||||
|   writecommand(0x3A); | ||||
|   writedata(0x05); | ||||
| 
 | ||||
|   writecommand(0x90); | ||||
|   writedata(0x08); | ||||
|   writedata(0x08); | ||||
|   writedata(0x08); | ||||
|   writedata(0x08); | ||||
| 
 | ||||
|   writecommand(0xBD); | ||||
|   writedata(0x06); | ||||
| 
 | ||||
|   writecommand(0xBC); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xFF); | ||||
|   writedata(0x60); | ||||
|   writedata(0x01); | ||||
|   writedata(0x04); | ||||
| 
 | ||||
|   writecommand(0xC3); | ||||
|   writedata(0x13); | ||||
|   writecommand(0xC4); | ||||
|   writedata(0x13); | ||||
| 
 | ||||
|   writecommand(0xC9); | ||||
|   writedata(0x22); | ||||
| 
 | ||||
|   writecommand(0xBE); | ||||
|   writedata(0x11); | ||||
| 
 | ||||
|   writecommand(0xE1); | ||||
|   writedata(0x10); | ||||
|   writedata(0x0E); | ||||
| 
 | ||||
|   writecommand(0xDF); | ||||
|   writedata(0x21); | ||||
|   writedata(0x0c); | ||||
|   writedata(0x02); | ||||
| 
 | ||||
|   writecommand(0xF0); | ||||
|   writedata(0x45); | ||||
|   writedata(0x09); | ||||
|   writedata(0x08); | ||||
|   writedata(0x08); | ||||
|   writedata(0x26); | ||||
|   writedata(0x2A); | ||||
| 
 | ||||
|   writecommand(0xF1); | ||||
|   writedata(0x43); | ||||
|   writedata(0x70); | ||||
|   writedata(0x72); | ||||
|   writedata(0x36); | ||||
|   writedata(0x37); | ||||
|   writedata(0x6F); | ||||
| 
 | ||||
|   writecommand(0xF2); | ||||
|   writedata(0x45); | ||||
|   writedata(0x09); | ||||
|   writedata(0x08); | ||||
|   writedata(0x08); | ||||
|   writedata(0x26); | ||||
|   writedata(0x2A); | ||||
| 
 | ||||
|   writecommand(0xF3); | ||||
|   writedata(0x43); | ||||
|   writedata(0x70); | ||||
|   writedata(0x72); | ||||
|   writedata(0x36); | ||||
|   writedata(0x37); | ||||
|   writedata(0x6F); | ||||
| 
 | ||||
|   writecommand(0xED); | ||||
|   writedata(0x1B); | ||||
|   writedata(0x0B); | ||||
| 
 | ||||
|   writecommand(0xAE); | ||||
|   writedata(0x77); | ||||
| 
 | ||||
|   writecommand(0xCD); | ||||
|   writedata(0x63); | ||||
| 
 | ||||
|   writecommand(0x70); | ||||
|   writedata(0x07); | ||||
|   writedata(0x07); | ||||
|   writedata(0x04); | ||||
|   writedata(0x0E); | ||||
|   writedata(0x0F); | ||||
|   writedata(0x09); | ||||
|   writedata(0x07); | ||||
|   writedata(0x08); | ||||
|   writedata(0x03); | ||||
| 
 | ||||
|   writecommand(0xE8); | ||||
|   writedata(0x34); | ||||
| 
 | ||||
|   writecommand(0x62); | ||||
|   writedata(0x18); | ||||
|   writedata(0x0D); | ||||
|   writedata(0x71); | ||||
|   writedata(0xED); | ||||
|   writedata(0x70); | ||||
|   writedata(0x70); | ||||
|   writedata(0x18); | ||||
|   writedata(0x0F); | ||||
|   writedata(0x71); | ||||
|   writedata(0xEF); | ||||
|   writedata(0x70); | ||||
|   writedata(0x70); | ||||
| 
 | ||||
|   writecommand(0x63); | ||||
|   writedata(0x18); | ||||
|   writedata(0x11); | ||||
|   writedata(0x71); | ||||
|   writedata(0xF1); | ||||
|   writedata(0x70); | ||||
|   writedata(0x70); | ||||
|   writedata(0x18); | ||||
|   writedata(0x13); | ||||
|   writedata(0x71); | ||||
|   writedata(0xF3); | ||||
|   writedata(0x70); | ||||
|   writedata(0x70); | ||||
| 
 | ||||
|   writecommand(0x64); | ||||
|   writedata(0x28); | ||||
|   writedata(0x29); | ||||
|   writedata(0xF1); | ||||
|   writedata(0x01); | ||||
|   writedata(0xF1); | ||||
|   writedata(0x00); | ||||
|   writedata(0x07); | ||||
| 
 | ||||
|   writecommand(0x66); | ||||
|   writedata(0x3C); | ||||
|   writedata(0x00); | ||||
|   writedata(0xCD); | ||||
|   writedata(0x67); | ||||
|   writedata(0x45); | ||||
|   writedata(0x45); | ||||
|   writedata(0x10); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0x67); | ||||
|   writedata(0x00); | ||||
|   writedata(0x3C); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
|   writedata(0x01); | ||||
|   writedata(0x54); | ||||
|   writedata(0x10); | ||||
|   writedata(0x32); | ||||
|   writedata(0x98); | ||||
| 
 | ||||
|   writecommand(0x74); | ||||
|   writedata(0x10); | ||||
|   writedata(0x85); | ||||
|   writedata(0x80); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
|   writedata(0x4E); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0x98); | ||||
|   writedata(0x3e); | ||||
|   writedata(0x07); | ||||
| 
 | ||||
|   writecommand(0x35); | ||||
|   writecommand(0x21); | ||||
| 
 | ||||
|   writecommand(0x11); | ||||
|   delay(120); | ||||
|   writecommand(0x29); | ||||
|   delay(20); | ||||
| } | ||||
|  | @ -0,0 +1,28 @@ | |||
| 
 | ||||
| // This is the command sequence that rotates the GC9A01 driver coordinate frame
 | ||||
| 
 | ||||
|   rotation = m % 4; | ||||
| 
 | ||||
|   writecommand(TFT_MADCTL); | ||||
|   switch (rotation) { | ||||
|     case 0: // Portrait
 | ||||
|       writedata(TFT_MAD_BGR); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 1: // Landscape (Portrait + 90)
 | ||||
|       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|     case 2: // Inverter portrait
 | ||||
|       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 3: // Inverted landscape
 | ||||
|       writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|   } | ||||
|  | @ -0,0 +1,52 @@ | |||
| // Change the width and height if required (defined in portrait mode)
 | ||||
| // or use the constructor to over-ride defaults
 | ||||
| #define TFT_WIDTH  320 | ||||
| #define TFT_HEIGHT 480 | ||||
| 
 | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
| #define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked
 | ||||
| 
 | ||||
| 
 | ||||
| // Generic commands used by TFT_eSPar.cpp
 | ||||
| #define TFT_NOP     0x00 | ||||
| #define TFT_SWRST   0x01 | ||||
| 
 | ||||
| #define TFT_SLPIN   0x10 | ||||
| #define TFT_SLPOUT  0x11 | ||||
| 
 | ||||
| #define TFT_INVOFF  0x20 | ||||
| #define TFT_INVON   0x21 | ||||
| 
 | ||||
| #define TFT_DISPOFF 0x28 | ||||
| #define TFT_DISPON  0x29 | ||||
| 
 | ||||
| #define TFT_CASET   0x2A | ||||
| #define TFT_PASET   0x2B | ||||
| #define TFT_RAMWR   0x2C | ||||
| 
 | ||||
| #define TFT_RAMRD   0x2E | ||||
| 
 | ||||
| #define TFT_MADCTL  0x36 | ||||
| 
 | ||||
| #define TFT_MAD_MY  0x80 | ||||
| #define TFT_MAD_MX  0x40 | ||||
| #define TFT_MAD_MV  0x20 | ||||
| #define TFT_MAD_ML  0x10 | ||||
| #define TFT_MAD_RGB 0x00 | ||||
| #define TFT_MAD_BGR 0x08 | ||||
| #define TFT_MAD_MH  0x04 | ||||
| #define TFT_MAD_SS  0x02 | ||||
| #define TFT_MAD_GS  0x01 | ||||
| 
 | ||||
| #ifdef TFT_RGB_ORDER | ||||
|   #if (TFT_RGB_ORDER == 1) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
| #endif | ||||
| 
 | ||||
| #define TFT_IDXRD   0x00 // ILI9341 only, indexed control register read
 | ||||
|  | @ -0,0 +1,76 @@ | |||
| 
 | ||||
| // This is the command sequence that initialises the HX8357B driver
 | ||||
| //
 | ||||
| // This setup information uses simple 8 bit SPI writecommand() and writedata() functions
 | ||||
| //
 | ||||
| // See ST7735_Setup.h file for an alternative format
 | ||||
| 
 | ||||
| 
 | ||||
| // Configure HX8357-B display
 | ||||
|     writecommand(0x11); | ||||
|     delay(20); | ||||
|     writecommand(0xD0); | ||||
|     writedata(0x07); | ||||
|     writedata(0x42); | ||||
|     writedata(0x18); | ||||
| 
 | ||||
|     writecommand(0xD1); | ||||
|     writedata(0x00); | ||||
|     writedata(0x07); | ||||
|     writedata(0x10); | ||||
| 
 | ||||
|     writecommand(0xD2); | ||||
|     writedata(0x01); | ||||
|     writedata(0x02); | ||||
| 
 | ||||
|     writecommand(0xC0); | ||||
|     writedata(0x10); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x00); | ||||
|     writedata(0x02); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC5); | ||||
|     writedata(0x08); | ||||
| 
 | ||||
|     writecommand(0xC8); | ||||
|     writedata(0x00); | ||||
|     writedata(0x32); | ||||
|     writedata(0x36); | ||||
|     writedata(0x45); | ||||
|     writedata(0x06); | ||||
|     writedata(0x16); | ||||
|     writedata(0x37); | ||||
|     writedata(0x75); | ||||
|     writedata(0x77); | ||||
|     writedata(0x54); | ||||
|     writedata(0x0C); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0x36); | ||||
|     writedata(0x0a); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     writedata(0x55); | ||||
| 
 | ||||
|     writecommand(0x2A); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0x3F); | ||||
| 
 | ||||
|     writecommand(0x2B); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0xDF); | ||||
| 
 | ||||
|     delay(120); | ||||
|     writecommand(0x29); | ||||
| 
 | ||||
|     delay(25); | ||||
| 
 | ||||
| // End of HX8357B display configuration
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,47 @@ | |||
|   // This is the command sequence that rotates the HX8357C driver coordinate frame
 | ||||
| 
 | ||||
|   writecommand(TFT_MADCTL); | ||||
|   rotation = m % 8; | ||||
|   switch (rotation) { | ||||
|    case 0: // Portrait
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|      break; | ||||
|    case 1: // Landscape (Portrait + 90)
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|    case 2: // Inverter portrait
 | ||||
|      writedata( TFT_MAD_COLOR_ORDER | TFT_MAD_MY); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|     break; | ||||
|    case 3: // Inverted landscape
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|    case 4: // Portrait
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX | TFT_MAD_MY); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|      break; | ||||
|    case 5: // Landscape (Portrait + 90)
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|    case 6: // Inverter portrait
 | ||||
|      writedata( TFT_MAD_COLOR_ORDER); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|      break; | ||||
|    case 7: // Inverted landscape
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MY); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|   } | ||||
|    | ||||
|  | @ -0,0 +1,52 @@ | |||
| // Change the width and height if required (defined in portrait mode)
 | ||||
| // or use the constructor to over-ride defaults
 | ||||
| #define TFT_WIDTH  320 | ||||
| #define TFT_HEIGHT 480 | ||||
| 
 | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
| #define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked
 | ||||
| 
 | ||||
| 
 | ||||
| // Generic commands used by TFT_eSPar.cpp
 | ||||
| #define TFT_NOP     0x00 | ||||
| #define TFT_SWRST   0x01 | ||||
| 
 | ||||
| #define TFT_SLPIN   0x10 | ||||
| #define TFT_SLPOUT  0x11 | ||||
| 
 | ||||
| #define TFT_INVOFF  0x20 | ||||
| #define TFT_INVON   0x21 | ||||
| 
 | ||||
| #define TFT_DISPOFF 0x28 | ||||
| #define TFT_DISPON  0x29 | ||||
| 
 | ||||
| #define TFT_CASET   0x2A | ||||
| #define TFT_PASET   0x2B | ||||
| #define TFT_RAMWR   0x2C | ||||
| 
 | ||||
| #define TFT_RAMRD   0x2E | ||||
| 
 | ||||
| #define TFT_MADCTL  0x36 | ||||
| 
 | ||||
| #define TFT_MAD_MY  0x80 | ||||
| #define TFT_MAD_MX  0x40 | ||||
| #define TFT_MAD_MV  0x20 | ||||
| #define TFT_MAD_ML  0x10 | ||||
| #define TFT_MAD_RGB 0x00 | ||||
| #define TFT_MAD_BGR 0x08 | ||||
| #define TFT_MAD_MH  0x04 | ||||
| #define TFT_MAD_SS  0x02 | ||||
| #define TFT_MAD_GS  0x01 | ||||
| 
 | ||||
| #ifdef TFT_RGB_ORDER | ||||
|   #if (TFT_RGB_ORDER == 1) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
| #endif | ||||
| 
 | ||||
| #define TFT_IDXRD   0x00 // ILI9341 only, indexed control register read
 | ||||
|  | @ -0,0 +1,116 @@ | |||
| 
 | ||||
| // This is the command sequence that initialises the HX8357C driver
 | ||||
| //
 | ||||
| // This setup information uses simple 8 bit SPI writecommand() and writedata() functions
 | ||||
| //
 | ||||
| // See ST7735_Setup.h file for an alternative format
 | ||||
| 
 | ||||
| 
 | ||||
| // Configure HX8357C display
 | ||||
| 
 | ||||
|     writecommand(0xB9); // Enable extension command
 | ||||
|     writedata(0xFF); | ||||
|     writedata(0x83); | ||||
|     writedata(0x57); | ||||
|     delay(50); | ||||
|      | ||||
|     writecommand(0xB6); //Set VCOM voltage
 | ||||
|     writedata(0x2C);    //0x52 for HSD 3.0"
 | ||||
|      | ||||
|     writecommand(0x11); // Sleep off
 | ||||
|     delay(200); | ||||
|      | ||||
|     writecommand(0x35); // Tearing effect on
 | ||||
|     writedata(0x00);    // Added parameter
 | ||||
| 
 | ||||
|     writecommand(0x3A); // Interface pixel format
 | ||||
|     writedata(0x55);    // 16 bits per pixel
 | ||||
| 
 | ||||
|     //writecommand(0xCC); // Set panel characteristic
 | ||||
|     //writedata(0x09);    // S960>S1, G1>G480, R-G-B, normally black
 | ||||
| 
 | ||||
|     //writecommand(0xB3); // RGB interface
 | ||||
|     //writedata(0x43);
 | ||||
|     //writedata(0x00);
 | ||||
|     //writedata(0x06);
 | ||||
|     //writedata(0x06);
 | ||||
| 
 | ||||
|     writecommand(0xB1); // Power control
 | ||||
|     writedata(0x00); | ||||
|     writedata(0x15); | ||||
|     writedata(0x0D); | ||||
|     writedata(0x0D); | ||||
|     writedata(0x83); | ||||
|     writedata(0x48); | ||||
|      | ||||
|      | ||||
|     writecommand(0xC0); // Does this do anything?
 | ||||
|     writedata(0x24); | ||||
|     writedata(0x24); | ||||
|     writedata(0x01); | ||||
|     writedata(0x3C); | ||||
|     writedata(0xC8); | ||||
|     writedata(0x08); | ||||
|      | ||||
|     writecommand(0xB4); // Display cycle
 | ||||
|     writedata(0x02); | ||||
|     writedata(0x40); | ||||
|     writedata(0x00); | ||||
|     writedata(0x2A); | ||||
|     writedata(0x2A); | ||||
|     writedata(0x0D); | ||||
|     writedata(0x4F); | ||||
|      | ||||
|     writecommand(0xE0); // Gamma curve
 | ||||
|     writedata(0x00); | ||||
|     writedata(0x15); | ||||
|     writedata(0x1D); | ||||
|     writedata(0x2A); | ||||
|     writedata(0x31); | ||||
|     writedata(0x42); | ||||
|     writedata(0x4C); | ||||
|     writedata(0x53); | ||||
|     writedata(0x45); | ||||
|     writedata(0x40); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x32); | ||||
|     writedata(0x2E); | ||||
|     writedata(0x28); | ||||
|      | ||||
|     writedata(0x24); | ||||
|     writedata(0x03); | ||||
|     writedata(0x00); | ||||
|     writedata(0x15); | ||||
|     writedata(0x1D); | ||||
|     writedata(0x2A); | ||||
|     writedata(0x31); | ||||
|     writedata(0x42); | ||||
|     writedata(0x4C); | ||||
|     writedata(0x53); | ||||
|     writedata(0x45); | ||||
|     writedata(0x40); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x32); | ||||
|      | ||||
|     writedata(0x2E); | ||||
|     writedata(0x28); | ||||
|     writedata(0x24); | ||||
|     writedata(0x03); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
| 
 | ||||
|     writecommand(0x36); // MADCTL Memory access control
 | ||||
|     writedata(0x48); | ||||
|     delay(20); | ||||
| 
 | ||||
|     writecommand(0x21); //Display inversion on
 | ||||
|     delay(20); | ||||
| 
 | ||||
|     writecommand(0x29); // Display on
 | ||||
|      | ||||
|     delay(120); | ||||
| 
 | ||||
| // End of HX8357C display configuration
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,47 @@ | |||
|   // This is the command sequence that rotates the HX8357C driver coordinate frame
 | ||||
| 
 | ||||
|   writecommand(TFT_MADCTL); | ||||
|   rotation = m % 8; | ||||
|   switch (rotation) { | ||||
|    case 0: // Portrait
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|      break; | ||||
|    case 1: // Landscape (Portrait + 90)
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|    case 2: // Inverter portrait
 | ||||
|      writedata( TFT_MAD_COLOR_ORDER | TFT_MAD_MY); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|     break; | ||||
|    case 3: // Inverted landscape
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|    case 4: // Portrait
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX | TFT_MAD_MY); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|      break; | ||||
|    case 5: // Landscape (Portrait + 90)
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|    case 6: // Inverter portrait
 | ||||
|      writedata( TFT_MAD_COLOR_ORDER); | ||||
|      _width  = _init_width; | ||||
|      _height = _init_height; | ||||
|      break; | ||||
|    case 7: // Inverted landscape
 | ||||
|      writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MY); | ||||
|      _width  = _init_height; | ||||
|      _height = _init_width; | ||||
|      break; | ||||
|   } | ||||
|    | ||||
|  | @ -39,6 +39,16 @@ | |||
| #define TFT_MAD_SS  0x02 | ||||
| #define TFT_MAD_GS  0x01 | ||||
| 
 | ||||
| #ifdef TFT_RGB_ORDER | ||||
|   #if (TFT_RGB_ORDER == 1) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
| #endif | ||||
| 
 | ||||
| #define TFT_IDXRD   0x00 // ILI9341 only, indexed control register read
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -97,7 +97,7 @@ | |||
|     writedata(0x55);  // 16 bit
 | ||||
|      | ||||
|     writecommand(HX8357_MADCTL);   | ||||
|     writedata(0xC0);  | ||||
|     writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);  | ||||
|      | ||||
|     writecommand(HX8357_TEON);  // TE off
 | ||||
|     writedata(0x00);  | ||||
|  |  | |||
|  | @ -1,26 +1,26 @@ | |||
|   // This is the command sequence that rotates the ILI9481 driver coordinate frame
 | ||||
|   // This is the command sequence that rotates the HX8357D driver coordinate frame
 | ||||
| 
 | ||||
|   writecommand(TFT_MADCTL); | ||||
|   rotation = m % 4; | ||||
|   switch (rotation) { | ||||
|    case 0: // Portrait
 | ||||
|      writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); | ||||
|       _width  = TFT_WIDTH; | ||||
|       _height = TFT_HEIGHT; | ||||
|      writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|      break; | ||||
|    case 1: // Landscape (Portrait + 90)
 | ||||
|      writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); | ||||
|       _width  = TFT_HEIGHT; | ||||
|       _height = TFT_WIDTH; | ||||
|      writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|      break; | ||||
|    case 2: // Inverter portrait
 | ||||
|      writedata(TFT_MAD_RGB); | ||||
|       _width  = TFT_WIDTH; | ||||
|       _height = TFT_HEIGHT; | ||||
|      writedata(TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|      break; | ||||
|    case 3: // Inverted landscape
 | ||||
|      writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); | ||||
|       _width  = TFT_HEIGHT; | ||||
|       _height = TFT_WIDTH; | ||||
|      writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|      break; | ||||
|   } | ||||
|  |  | |||
|  | @ -0,0 +1,84 @@ | |||
| // Change the width and height if required (defined in portrait mode)
 | ||||
| // or use the constructor to over-ride defaults
 | ||||
| #define TFT_WIDTH  176 | ||||
| #define TFT_HEIGHT 220 | ||||
| 
 | ||||
| // Generic commands used by TFT_eSPI.cpp
 | ||||
| #define TFT_NOP     0x00 | ||||
| #define TFT_SWRST   0x28 | ||||
| 
 | ||||
| #define TFT_CASET 0 | ||||
| #define TFT_PASET 0 | ||||
| 
 | ||||
| #define TFT_CASET1     ILI9225_HORIZONTAL_WINDOW_ADDR2 | ||||
| #define TFT_CASET2     ILI9225_HORIZONTAL_WINDOW_ADDR1 | ||||
| 
 | ||||
| #define TFT_PASET1     ILI9225_VERTICAL_WINDOW_ADDR2 | ||||
| #define TFT_PASET2     ILI9225_VERTICAL_WINDOW_ADDR1 | ||||
| 
 | ||||
| #define TFT_RAM_ADDR1  ILI9225_RAM_ADDR_SET1 | ||||
| #define TFT_RAM_ADDR2  ILI9225_RAM_ADDR_SET2 | ||||
| 
 | ||||
| #define TFT_RAMWR      ILI9225_GRAM_DATA_REG | ||||
| 
 | ||||
| #define TFT_MAD_BGR 0x10 | ||||
| #define TFT_MAD_RGB 0x00 | ||||
| 
 | ||||
| #ifdef TFT_RGB_ORDER | ||||
|   #if (TFT_RGB_ORDER == 1) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
| #endif | ||||
| 
 | ||||
| // Not used
 | ||||
| #define TFT_INVOFF  0x00 | ||||
| #define TFT_INVON   0x00 | ||||
| #define TFT_RAMRD   0x00 | ||||
| #define TFT_IDXRD   0x00 | ||||
| 
 | ||||
| /* ILI9225 Registers */ | ||||
| #define ILI9225_DRIVER_OUTPUT_CTRL      0x01  // Driver Output Control
 | ||||
| #define ILI9225_LCD_AC_DRIVING_CTRL     0x02  // LCD AC Driving Control
 | ||||
| #define ILI9225_ENTRY_MODE              0x03  // Entry Mode
 | ||||
| #define ILI9225_DISP_CTRL1              0x07  // Display Control 1
 | ||||
| #define ILI9225_BLANK_PERIOD_CTRL1      0x08  // Blank Period Control
 | ||||
| #define ILI9225_FRAME_CYCLE_CTRL        0x0B  // Frame Cycle Control
 | ||||
| #define ILI9225_INTERFACE_CTRL          0x0C  // Interface Control
 | ||||
| #define ILI9225_OSC_CTRL                0x0F  // Osc Control
 | ||||
| #define ILI9225_POWER_CTRL1             0x10  // Power Control 1
 | ||||
| #define ILI9225_POWER_CTRL2             0x11  // Power Control 2
 | ||||
| #define ILI9225_POWER_CTRL3             0x12  // Power Control 3
 | ||||
| #define ILI9225_POWER_CTRL4             0x13  // Power Control 4
 | ||||
| #define ILI9225_POWER_CTRL5             0x14  // Power Control 5
 | ||||
| #define ILI9225_VCI_RECYCLING           0x15  // VCI Recycling
 | ||||
| #define ILI9225_RAM_ADDR_SET1           0x20  // Horizontal GRAM Address Set
 | ||||
| #define ILI9225_RAM_ADDR_SET2           0x21  // Vertical GRAM Address Set
 | ||||
| #define ILI9225_GRAM_DATA_REG           0x22  // GRAM Data Register
 | ||||
| #define ILI9225_GATE_SCAN_CTRL          0x30  // Gate Scan Control Register
 | ||||
| #define ILI9225_VERTICAL_SCROLL_CTRL1   0x31  // Vertical Scroll Control 1 Register
 | ||||
| #define ILI9225_VERTICAL_SCROLL_CTRL2   0x32  // Vertical Scroll Control 2 Register
 | ||||
| #define ILI9225_VERTICAL_SCROLL_CTRL3   0x33  // Vertical Scroll Control 3 Register
 | ||||
| #define ILI9225_PARTIAL_DRIVING_POS1    0x34  // Partial Driving Position 1 Register
 | ||||
| #define ILI9225_PARTIAL_DRIVING_POS2    0x35  // Partial Driving Position 2 Register
 | ||||
| #define ILI9225_HORIZONTAL_WINDOW_ADDR1 0x36  // Horizontal Address Start Position
 | ||||
| #define ILI9225_HORIZONTAL_WINDOW_ADDR2 0x37  // Horizontal Address End Position
 | ||||
| #define ILI9225_VERTICAL_WINDOW_ADDR1   0x38  // Vertical Address Start Position
 | ||||
| #define ILI9225_VERTICAL_WINDOW_ADDR2   0x39  // Vertical Address End Position
 | ||||
| #define ILI9225_GAMMA_CTRL1             0x50  // Gamma Control 1
 | ||||
| #define ILI9225_GAMMA_CTRL2             0x51  // Gamma Control 2
 | ||||
| #define ILI9225_GAMMA_CTRL3             0x52  // Gamma Control 3
 | ||||
| #define ILI9225_GAMMA_CTRL4             0x53  // Gamma Control 4
 | ||||
| #define ILI9225_GAMMA_CTRL5             0x54  // Gamma Control 5
 | ||||
| #define ILI9225_GAMMA_CTRL6             0x55  // Gamma Control 6
 | ||||
| #define ILI9225_GAMMA_CTRL7             0x56  // Gamma Control 7
 | ||||
| #define ILI9225_GAMMA_CTRL8             0x57  // Gamma Control 8
 | ||||
| #define ILI9225_GAMMA_CTRL9             0x58  // Gamma Control 9
 | ||||
| #define ILI9225_GAMMA_CTRL10            0x59  // Gamma Control 10
 | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
| #define TFT_INIT_DELAY 0x00 // Not used unless commandlist invoked
 | ||||
| 
 | ||||
|  | @ -0,0 +1,105 @@ | |||
| // This is the command sequence that initialises the ILI9225 driver
 | ||||
| 
 | ||||
| { | ||||
| 	writecommand(ILI9225_POWER_CTRL1); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_POWER_CTRL2); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_POWER_CTRL3); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_POWER_CTRL4); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_POWER_CTRL5); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 
 | ||||
| 	delay(40); | ||||
| 
 | ||||
| 	writecommand(ILI9225_POWER_CTRL2); | ||||
| 	writedata(0x00);writedata(0x18); | ||||
| 	writecommand(ILI9225_POWER_CTRL3); | ||||
| 	writedata(0x61);writedata(0x21); | ||||
| 	writecommand(ILI9225_POWER_CTRL4); | ||||
| 	writedata(0x00);writedata(0x6F); | ||||
| 	writecommand(ILI9225_POWER_CTRL5); | ||||
| 	writedata(0x49);writedata(0x5F); | ||||
| 	writecommand(ILI9225_POWER_CTRL1); | ||||
| 	writedata(0x08);writedata(0x00); | ||||
| 
 | ||||
| 	delay(10); | ||||
| 
 | ||||
| 	writecommand(ILI9225_POWER_CTRL2); | ||||
| 	writedata(0x10);writedata(0x3B); | ||||
| 
 | ||||
| 	delay(50); | ||||
| 
 | ||||
| 	writecommand(ILI9225_LCD_AC_DRIVING_CTRL); | ||||
| 	writedata(0x01);writedata(0x00); | ||||
| 	writecommand(ILI9225_DISP_CTRL1); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_BLANK_PERIOD_CTRL1); | ||||
| 	writedata(0x08);writedata(0x08); | ||||
| 	writecommand(ILI9225_FRAME_CYCLE_CTRL); | ||||
| 	writedata(0x11);writedata(0x00); | ||||
| 	writecommand(ILI9225_INTERFACE_CTRL); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_OSC_CTRL); | ||||
| 	writedata(0x0D);writedata(0x01); | ||||
| 	writecommand(ILI9225_VCI_RECYCLING); | ||||
| 	writedata(0x00);writedata(0x20); | ||||
| 	writecommand(ILI9225_RAM_ADDR_SET1); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_RAM_ADDR_SET2); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 
 | ||||
| 	writecommand(ILI9225_GATE_SCAN_CTRL); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_VERTICAL_SCROLL_CTRL1); | ||||
| 	writedata(0x00);writedata(0xDB); | ||||
| 	writecommand(ILI9225_VERTICAL_SCROLL_CTRL2); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_VERTICAL_SCROLL_CTRL3); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_PARTIAL_DRIVING_POS1); | ||||
| 	writedata(0x00);writedata(0xDB); | ||||
| 	writecommand(ILI9225_PARTIAL_DRIVING_POS2); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_HORIZONTAL_WINDOW_ADDR1); | ||||
| 	writedata(0x00);writedata(0xAF); | ||||
| 	writecommand(ILI9225_HORIZONTAL_WINDOW_ADDR2); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_VERTICAL_WINDOW_ADDR1); | ||||
| 	writedata(0x00);writedata(0xDB); | ||||
| 	writecommand(ILI9225_VERTICAL_WINDOW_ADDR2); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 
 | ||||
| 	/* Set GAMMA curve */ | ||||
| 	writecommand(ILI9225_GAMMA_CTRL1); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL2); | ||||
| 	writedata(0x08);writedata(0x08); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL3); | ||||
| 	writedata(0x08);writedata(0x0A); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL4); | ||||
| 	writedata(0x00);writedata(0x0A); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL5); | ||||
| 	writedata(0x0A);writedata(0x08); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL6); | ||||
| 	writedata(0x08);writedata(0x08); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL7); | ||||
| 	writedata(0x00);writedata(0x00); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL8); | ||||
| 	writedata(0x0A);writedata(0x00); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL9); | ||||
| 	writedata(0x07);writedata(0x10); | ||||
| 	writecommand(ILI9225_GAMMA_CTRL10); | ||||
| 	writedata(0x07);writedata(0x10); | ||||
| 
 | ||||
| 	writecommand(ILI9225_DISP_CTRL1); | ||||
| 	writedata(0x00);writedata(0x12); | ||||
| 
 | ||||
| 	delay(50); | ||||
| 
 | ||||
| 	writecommand(ILI9225_DISP_CTRL1); | ||||
| 	writedata(0x10);writedata(0x17); | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,39 @@ | |||
| 
 | ||||
| // This is the command sequence that rotates the ILI9225 driver coordinate frame
 | ||||
| 
 | ||||
|   rotation = m % 4; // Limit the range of values to 0-3
 | ||||
| 
 | ||||
|   switch (rotation) { | ||||
|     case 0: | ||||
|     	writecommand(ILI9225_DRIVER_OUTPUT_CTRL); | ||||
| 	    writedata(0x01);writedata(0x1C); | ||||
|       writecommand(ILI9225_ENTRY_MODE); | ||||
|     	writedata(TFT_MAD_COLOR_ORDER);writedata(0x30); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 1: | ||||
|     	writecommand(ILI9225_DRIVER_OUTPUT_CTRL); | ||||
| 	    writedata(0x00);writedata(0x1C); | ||||
|       writecommand(ILI9225_ENTRY_MODE); | ||||
|     	writedata(TFT_MAD_COLOR_ORDER);writedata(0x38); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|     case 2: | ||||
|     	writecommand(ILI9225_DRIVER_OUTPUT_CTRL); | ||||
| 	    writedata(0x02);writedata(0x1C); | ||||
|       writecommand(ILI9225_ENTRY_MODE); | ||||
|     	writedata(TFT_MAD_COLOR_ORDER);writedata(0x30); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 3: | ||||
|     	writecommand(ILI9225_DRIVER_OUTPUT_CTRL); | ||||
| 	    writedata(0x03);writedata(0x1C); | ||||
|       writecommand(ILI9225_ENTRY_MODE); | ||||
|     	writedata(TFT_MAD_COLOR_ORDER);writedata(0x38); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|   } | ||||
|  | @ -1,8 +1,13 @@ | |||
| // Change the width and height if required (defined in portrait mode)
 | ||||
| // or use the constructor to over-ride defaults
 | ||||
| #define TFT_WIDTH  240 | ||||
| #define TFT_HEIGHT 320 | ||||
| 
 | ||||
| #if defined (ILI9341_DRIVER) || defined (ILI9341_2_DRIVER) | ||||
|   #define TFT_WIDTH  240 | ||||
|   #define TFT_HEIGHT 320 | ||||
| #elif defined (ILI9342_DRIVER) | ||||
|   #define TFT_WIDTH  320 | ||||
|   #define TFT_HEIGHT 240 | ||||
| #endif | ||||
| 
 | ||||
| // Color definitions for backwards compatibility with old sketches
 | ||||
| // use colour definitions like TFT_BLACK to make sketches more portable
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| //
 | ||||
| // See ST7735_Setup.h file for an alternative format
 | ||||
| 
 | ||||
| #if defined (ILI9341_DRIVER) || defined (ILI9342_DRIVER) | ||||
| { | ||||
|   writecommand(0xEF); | ||||
|   writedata(0x03); | ||||
|  | @ -121,4 +122,127 @@ | |||
|    | ||||
|   writecommand(ILI9341_DISPON);    //Display on
 | ||||
| 
 | ||||
| } | ||||
| } | ||||
| 
 | ||||
| #elif defined (ILI9341_2_DRIVER) // Alternative init sequence, see https://github.com/Bodmer/TFT_eSPI/issues/1172
 | ||||
| 
 | ||||
| { | ||||
| writecommand(0xCF); | ||||
| writedata(0x00); | ||||
| writedata(0XC1); | ||||
| writedata(0X30); | ||||
| 
 | ||||
| writecommand(0xED); | ||||
| writedata(0x64); | ||||
| writedata(0x03); | ||||
| writedata(0X12); | ||||
| writedata(0X81); | ||||
| 
 | ||||
| writecommand(0xE8); | ||||
| writedata(0x85); | ||||
| writedata(0x00); | ||||
| writedata(0x78); | ||||
| 
 | ||||
| writecommand(0xCB); | ||||
| writedata(0x39); | ||||
| writedata(0x2C); | ||||
| writedata(0x00); | ||||
| writedata(0x34); | ||||
| writedata(0x02); | ||||
| 
 | ||||
| writecommand(0xF7); | ||||
| writedata(0x20); | ||||
| 
 | ||||
| writecommand(0xEA); | ||||
| writedata(0x00); | ||||
| writedata(0x00); | ||||
| 
 | ||||
| writecommand(ILI9341_PWCTR1); //Power control
 | ||||
| writedata(0x10); //VRH[5:0]
 | ||||
| 
 | ||||
| writecommand(ILI9341_PWCTR2); //Power control
 | ||||
| writedata(0x00); //SAP[2:0];BT[3:0]
 | ||||
| 
 | ||||
| writecommand(ILI9341_VMCTR1); //VCM control
 | ||||
| writedata(0x30); | ||||
| writedata(0x30); | ||||
| 
 | ||||
| writecommand(ILI9341_VMCTR2); //VCM control2
 | ||||
| writedata(0xB7); //--
 | ||||
| 
 | ||||
| writecommand(ILI9341_PIXFMT); | ||||
| writedata(0x55); | ||||
| 
 | ||||
| writecommand(0x36); // Memory Access Control
 | ||||
| writedata(0x08); // Rotation 0 (portrait mode)
 | ||||
| 
 | ||||
| writecommand(ILI9341_FRMCTR1); | ||||
| writedata(0x00); | ||||
| writedata(0x1A); | ||||
| 
 | ||||
| writecommand(ILI9341_DFUNCTR); // Display Function Control
 | ||||
| writedata(0x08); | ||||
| writedata(0x82); | ||||
| writedata(0x27); | ||||
| 
 | ||||
| writecommand(0xF2); // 3Gamma Function Disable
 | ||||
| writedata(0x00); | ||||
| 
 | ||||
| writecommand(0x26); //Gamma curve selected
 | ||||
| writedata(0x01); | ||||
| 
 | ||||
| writecommand(0xE0); //Set Gamma
 | ||||
| writedata(0x0F); | ||||
| writedata(0x2A); | ||||
| writedata(0x28); | ||||
| writedata(0x08); | ||||
| writedata(0x0E); | ||||
| writedata(0x08); | ||||
| writedata(0x54); | ||||
| writedata(0xA9); | ||||
| writedata(0x43); | ||||
| writedata(0x0A); | ||||
| writedata(0x0F); | ||||
| writedata(0x00); | ||||
| writedata(0x00); | ||||
| writedata(0x00); | ||||
| writedata(0x00); | ||||
| 
 | ||||
| writecommand(0XE1); //Set Gamma
 | ||||
| writedata(0x00); | ||||
| writedata(0x15); | ||||
| writedata(0x17); | ||||
| writedata(0x07); | ||||
| writedata(0x11); | ||||
| writedata(0x06); | ||||
| writedata(0x2B); | ||||
| writedata(0x56); | ||||
| writedata(0x3C); | ||||
| writedata(0x05); | ||||
| writedata(0x10); | ||||
| writedata(0x0F); | ||||
| writedata(0x3F); | ||||
| writedata(0x3F); | ||||
| writedata(0x0F); | ||||
| 
 | ||||
| writecommand(0x2B); | ||||
| writedata(0x00); | ||||
| writedata(0x00); | ||||
| writedata(0x01); | ||||
| writedata(0x3f); | ||||
| 
 | ||||
| writecommand(0x2A); | ||||
| writedata(0x00); | ||||
| writedata(0x00); | ||||
| writedata(0x00); | ||||
| writedata(0xef); | ||||
| 
 | ||||
| writecommand(ILI9341_SLPOUT); //Exit Sleep
 | ||||
| 
 | ||||
| end_tft_write(); | ||||
| delay(120); | ||||
| begin_tft_write(); | ||||
| 
 | ||||
| writecommand(ILI9341_DISPON); //Display on
 | ||||
| } | ||||
| #endif | ||||
|  | @ -5,7 +5,17 @@ | |||
| //
 | ||||
| // See ST7735_Setup.h file for an alternative format
 | ||||
| 
 | ||||
| #define ILI9481_INIT_1 // Original default
 | ||||
| //#define ILI9481_INIT_2 // CPT29
 | ||||
| //#define ILI9481_INIT_3 // PVI35
 | ||||
| //#define ILI9481_INIT_4 // AUO317
 | ||||
| //#define ILI9481_INIT_5 // CMO35 *****
 | ||||
| //#define ILI9481_INIT_6 // RGB
 | ||||
| //#define ILI9481_INIT_7 // From #1774
 | ||||
| //#define ILI9481_INIT_8 // From #1774
 | ||||
| 
 | ||||
| /////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #ifdef ILI9481_INIT_1 | ||||
| // Configure ILI9481 display
 | ||||
| 
 | ||||
|     writecommand(TFT_SLPOUT); | ||||
|  | @ -53,7 +63,15 @@ | |||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     writedata(0x55); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|       writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
|     writecommand(TFT_CASET); | ||||
|     writedata(0x00); | ||||
|  | @ -72,6 +90,647 @@ | |||
| 
 | ||||
|     delay(25); | ||||
| // End of ILI9481 display configuration
 | ||||
| /////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9481_INIT_2) | ||||
| // Configure ILI9481 display
 | ||||
| 
 | ||||
|     writecommand(TFT_SLPOUT); | ||||
|     delay(20); | ||||
| 
 | ||||
|     writecommand(0xD0); | ||||
|     writedata(0x07); | ||||
|     writedata(0x41); | ||||
|     writedata(0x1D); | ||||
| 
 | ||||
|     writecommand(0xD1); | ||||
|     writedata(0x00); | ||||
|     writedata(0x2B); | ||||
|     writedata(0x1F); | ||||
| 
 | ||||
|     writecommand(0xD2); | ||||
|     writedata(0x01); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC0); | ||||
|     writedata(0x10); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x00); | ||||
|     writedata(0x02); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC5); | ||||
|     writedata(0x03); | ||||
| 
 | ||||
|     writecommand(0xC8); | ||||
|     writedata(0x00); | ||||
|     writedata(0x14); | ||||
|     writedata(0x33); | ||||
|     writedata(0x10); | ||||
|     writedata(0x00); | ||||
|     writedata(0x16); | ||||
|     writedata(0x44); | ||||
|     writedata(0x36); | ||||
|     writedata(0x77); | ||||
|     writedata(0x00); | ||||
|     writedata(0x0F); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xB0); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xE4); | ||||
|     writedata(0xA0); | ||||
|      | ||||
|     writecommand(0xF0); | ||||
|     writedata(0x01); | ||||
| 
 | ||||
|     writecommand(0xF3); | ||||
|     writedata(0x02); | ||||
|     writedata(0x1A); | ||||
| 
 | ||||
|     writecommand(TFT_MADCTL); | ||||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|       writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
|     writecommand(TFT_CASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0x3F); | ||||
| 
 | ||||
|     writecommand(TFT_PASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0xDF); | ||||
| 
 | ||||
|     delay(120); | ||||
|     writecommand(TFT_DISPON); | ||||
| 
 | ||||
|     delay(25); | ||||
| // End of ILI9481 display configuration
 | ||||
| /////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9481_INIT_3) | ||||
| // Configure ILI9481 display
 | ||||
| 
 | ||||
|     writecommand(TFT_SLPOUT); | ||||
|     delay(20); | ||||
| 
 | ||||
|     writecommand(0xD0); | ||||
|     writedata(0x07); | ||||
|     writedata(0x41); | ||||
|     writedata(0x1D); | ||||
| 
 | ||||
|     writecommand(0xD1); | ||||
|     writedata(0x00); | ||||
|     writedata(0x2B); | ||||
|     writedata(0x1F); | ||||
| 
 | ||||
|     writecommand(0xD2); | ||||
|     writedata(0x01); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC0); | ||||
|     writedata(0x10); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x00); | ||||
|     writedata(0x02); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC5); | ||||
|     writedata(0x03); | ||||
| 
 | ||||
|     writecommand(0xC8); | ||||
|     writedata(0x00); | ||||
|     writedata(0x14); | ||||
|     writedata(0x33); | ||||
|     writedata(0x10); | ||||
|     writedata(0x00); | ||||
|     writedata(0x16); | ||||
|     writedata(0x44); | ||||
|     writedata(0x36); | ||||
|     writedata(0x77); | ||||
|     writedata(0x00); | ||||
|     writedata(0x0F); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xB0); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xE4); | ||||
|     writedata(0xA0); | ||||
|      | ||||
|     writecommand(0xF0); | ||||
|     writedata(0x01); | ||||
| 
 | ||||
|     writecommand(0xF3); | ||||
|     writedata(0x40); | ||||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(TFT_MADCTL); | ||||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|       writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
|     writecommand(TFT_CASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0x3F); | ||||
| 
 | ||||
|     writecommand(TFT_PASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0xDF); | ||||
| 
 | ||||
|     delay(120); | ||||
|     writecommand(TFT_DISPON); | ||||
| 
 | ||||
|     delay(25); | ||||
| // End of ILI9481 display configuration
 | ||||
| /////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9481_INIT_4) | ||||
| // Configure ILI9481 display
 | ||||
| 
 | ||||
|     writecommand(TFT_SLPOUT); | ||||
|     delay(20); | ||||
| 
 | ||||
|     writecommand(0xD0); | ||||
|     writedata(0x07); | ||||
|     writedata(0x40); | ||||
|     writedata(0x1D); | ||||
| 
 | ||||
|     writecommand(0xD1); | ||||
|     writedata(0x00); | ||||
|     writedata(0x18); | ||||
|     writedata(0x13); | ||||
| 
 | ||||
|     writecommand(0xD2); | ||||
|     writedata(0x01); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC0); | ||||
|     writedata(0x10); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x00); | ||||
|     writedata(0x02); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC5); | ||||
|     writedata(0x03); | ||||
| 
 | ||||
|     writecommand(0xC8); | ||||
|     writedata(0x00); | ||||
|     writedata(0x44); | ||||
|     writedata(0x06); | ||||
|     writedata(0x44); | ||||
|     writedata(0x0A); | ||||
|     writedata(0x08); | ||||
|     writedata(0x17); | ||||
|     writedata(0x33); | ||||
|     writedata(0x77); | ||||
|     writedata(0x44); | ||||
|     writedata(0x08); | ||||
|     writedata(0x0C); | ||||
| 
 | ||||
|     writecommand(0xB0); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xE4); | ||||
|     writedata(0xA0); | ||||
|      | ||||
|     writecommand(0xF0); | ||||
|     writedata(0x01); | ||||
| 
 | ||||
|     writecommand(TFT_MADCTL); | ||||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|       writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
|     writecommand(TFT_CASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0x3F); | ||||
| 
 | ||||
|     writecommand(TFT_PASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0xDF); | ||||
| 
 | ||||
|     delay(120); | ||||
|     writecommand(TFT_DISPON); | ||||
| 
 | ||||
|     delay(25); | ||||
| // End of ILI9481 display configuration
 | ||||
| /////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9481_INIT_5) | ||||
| // Configure ILI9481 display
 | ||||
| 
 | ||||
|     writecommand(TFT_SLPOUT); | ||||
|     delay(20); | ||||
| 
 | ||||
|     writecommand(0xD0); | ||||
|     writedata(0x07); | ||||
|     writedata(0x41); | ||||
|     writedata(0x1D); | ||||
| 
 | ||||
|     writecommand(0xD1); | ||||
|     writedata(0x00); | ||||
|     writedata(0x1C); | ||||
|     writedata(0x1F); | ||||
| 
 | ||||
|     writecommand(0xD2); | ||||
|     writedata(0x01); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC0); | ||||
|     writedata(0x10); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x00); | ||||
|     writedata(0x02); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC5); | ||||
|     writedata(0x03); | ||||
| 
 | ||||
|     writecommand(0xC6); | ||||
|     writedata(0x83); | ||||
| 
 | ||||
|     writecommand(0xC8); | ||||
|     writedata(0x00); | ||||
|     writedata(0x26); | ||||
|     writedata(0x21); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x1F); | ||||
|     writedata(0x65); | ||||
|     writedata(0x23); | ||||
|     writedata(0x77); | ||||
|     writedata(0x00); | ||||
|     writedata(0x0F); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xB0); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xE4); | ||||
|     writedata(0xA0); | ||||
|      | ||||
|     writecommand(0xF0); | ||||
|     writedata(0x01); | ||||
| 
 | ||||
|     writecommand(TFT_MADCTL); | ||||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|       writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
|     writecommand(TFT_CASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0x3F); | ||||
| 
 | ||||
|     writecommand(TFT_PASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0xDF); | ||||
| 
 | ||||
|     delay(120); | ||||
|     writecommand(TFT_DISPON); | ||||
| 
 | ||||
|     delay(25); | ||||
| // End of ILI9481 display configuration
 | ||||
| /////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #elif defined (ILI9481_INIT_6) | ||||
| // Configure ILI9481 display
 | ||||
| 
 | ||||
|     writecommand(TFT_SLPOUT); | ||||
|     delay(20); | ||||
| 
 | ||||
|     writecommand(0xD0); | ||||
|     writedata(0x07); | ||||
|     writedata(0x41); | ||||
|     writedata(0x1D); | ||||
| 
 | ||||
|     writecommand(0xD1); | ||||
|     writedata(0x00); | ||||
|     writedata(0x2B); | ||||
|     writedata(0x1F); | ||||
| 
 | ||||
|     writecommand(0xD2); | ||||
|     writedata(0x01); | ||||
|     writedata(0x11); | ||||
| 
 | ||||
|     writecommand(0xC0); | ||||
|     writedata(0x10); | ||||
|     writedata(0x3B); | ||||
|     writedata(0x00); | ||||
|     writedata(0x02); | ||||
|     writedata(0x11); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xC5); | ||||
|     writedata(0x03); | ||||
| 
 | ||||
|     writecommand(0xC6); | ||||
|     writedata(0x80); | ||||
| 
 | ||||
|     writecommand(0xC8); | ||||
|     writedata(0x00); | ||||
|     writedata(0x14); | ||||
|     writedata(0x33); | ||||
|     writedata(0x10); | ||||
|     writedata(0x00); | ||||
|     writedata(0x16); | ||||
|     writedata(0x44); | ||||
|     writedata(0x36); | ||||
|     writedata(0x77); | ||||
|     writedata(0x00); | ||||
|     writedata(0x0F); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xB0); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0xE4); | ||||
|     writedata(0xA0); | ||||
|      | ||||
|     writecommand(0xF0); | ||||
|     writedata(0x08); | ||||
| 
 | ||||
|     writecommand(0xF3); | ||||
|     writedata(0x40); | ||||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(0xF6); | ||||
|     writedata(0x84); | ||||
| 
 | ||||
|     writecommand(0xF7); | ||||
|     writedata(0x80); | ||||
| 
 | ||||
|     writecommand(0xB3); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0x06); | ||||
|     writedata(0x30); | ||||
| 
 | ||||
|     writecommand(0xB4); | ||||
|     writedata(0x00); | ||||
| 
 | ||||
|     writecommand(0x0C); | ||||
|     writedata(0x00); | ||||
|     writedata(0x55); | ||||
| 
 | ||||
|     writecommand(TFT_MADCTL); | ||||
|     writedata(0x0A); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|       writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
|     writecommand(TFT_CASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0x3F); | ||||
| 
 | ||||
|     writecommand(TFT_PASET); | ||||
|     writedata(0x00); | ||||
|     writedata(0x00); | ||||
|     writedata(0x01); | ||||
|     writedata(0xDF); | ||||
| 
 | ||||
|     delay(120); | ||||
|     writecommand(TFT_DISPON); | ||||
| 
 | ||||
|     delay(25); | ||||
| // End of ILI9481 display configuration
 | ||||
| /////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| // From #1774
 | ||||
| #elif defined (ILI9481_INIT_7) | ||||
|  ///ili9481+cmi3.5ips //效果不好
 | ||||
| 					//************* Start Initial Sequence **********//
 | ||||
| 					writecommand(0x11); | ||||
| 					delay(20); | ||||
| 					writecommand(0xD0); | ||||
| 					writedata(0x07); | ||||
| 					writedata(0x42); | ||||
| 					writedata(0x1B); | ||||
| 
 | ||||
| 					writecommand(0xD1); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x14); | ||||
| 					writedata(0x1B); | ||||
| 
 | ||||
| 					writecommand(0xD2); | ||||
| 					writedata(0x01); | ||||
| 					writedata(0x12); | ||||
| 
 | ||||
| 					writecommand(0xC0); | ||||
| 					writedata(0x10); | ||||
| 					writedata(0x3B); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x02); | ||||
| 					writedata(0x01); | ||||
| 
 | ||||
| 					writecommand(0xC5); | ||||
| 					writedata(0x03); | ||||
| 
 | ||||
| 					writecommand(0xC8); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x46); | ||||
| 					writedata(0x44); | ||||
| 					writedata(0x50); | ||||
| 					writedata(0x04); | ||||
| 					writedata(0x16); | ||||
| 					writedata(0x33); | ||||
| 					writedata(0x13); | ||||
| 					writedata(0x77); | ||||
| 					writedata(0x05); | ||||
| 					writedata(0x0F); | ||||
| 					writedata(0x00); | ||||
| 
 | ||||
| 					writecommand(0x36); | ||||
| 					writedata(0x0A); | ||||
| 
 | ||||
| 					writecommand(0x3A); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|           writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|           writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
| 					writecommand(0x22); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x01); | ||||
| 					writedata(0x3F); | ||||
| 
 | ||||
| 					writecommand(0x2B); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x01); | ||||
| 					writedata(0xE0); | ||||
| 					delay(120); | ||||
| 					writecommand(0x29); | ||||
| 
 | ||||
| #elif defined (ILI9481_INIT_8) | ||||
| 
 | ||||
| 					//3.5IPS ILI9481+CMI	
 | ||||
| 					writecommand(0x01); //Soft_rese
 | ||||
| 					delay(220); | ||||
| 
 | ||||
| 					writecommand(0x11); | ||||
| 					delay(280); | ||||
| 
 | ||||
| 					writecommand(0xd0); //Power_Setting
 | ||||
| 					writedata(0x07);//07  VC[2:0] Sets the ratio factor of Vci to generate the reference voltages Vci1
 | ||||
| 					writedata(0x44);//41  BT[2:0] Sets the Step up factor and output voltage level from the reference voltages Vci1
 | ||||
| 					writedata(0x1E);//1f  17   1C  VRH[3:0]: Sets the factor to generate VREG1OUT from VCILVL
 | ||||
| 					delay(220); | ||||
| 
 | ||||
| 					writecommand(0xd1); //VCOM Control
 | ||||
| 					writedata(0x00);//00
 | ||||
| 					writedata(0x0C);//1A   VCM [6:0] is used to set factor to generate VCOMH voltage from the reference voltage VREG1OUT  15    09
 | ||||
| 					writedata(0x1A);//1F   VDV[4:0] is used to set the VCOM alternating amplitude in the range of VREG1OUT x 0.70 to VREG1OUT   1F   18
 | ||||
| 
 | ||||
| 					writecommand(0xC5);  //Frame Rate
 | ||||
| 					writedata(0x03); // 03   02
 | ||||
| 
 | ||||
| 					writecommand(0xd2);  //Power_Setting for Normal Mode 
 | ||||
| 					writedata(0x01);  //01
 | ||||
| 					writedata(0x11);  //11
 | ||||
| 
 | ||||
| 					writecommand(0xE4);  //?
 | ||||
| 					writedata(0xa0); | ||||
| 					writecommand(0xf3); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x2a); | ||||
| 
 | ||||
| 					//1  OK
 | ||||
| 					writecommand(0xc8); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x26); | ||||
| 					writedata(0x21); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x1f); | ||||
| 					writedata(0x65); | ||||
| 					writedata(0x23); | ||||
| 					writedata(0x77); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x0f); | ||||
| 					writedata(0x00); | ||||
| 					//GAMMA SETTING
 | ||||
| 
 | ||||
| 					writecommand(0xC0);	//Panel Driving Setting																          
 | ||||
| 					writedata(0x00); //1//00  REV  SM  GS
 | ||||
| 					writedata(0x3B); //2//NL[5:0]: Sets the number of lines to drive the LCD at an interval of 8 lines. 
 | ||||
| 					writedata(0x00); //3//SCN[6:0]
 | ||||
| 					writedata(0x02); //4//PTV: Sets the Vcom output in non-display area drive period
 | ||||
| 					writedata(0x11); //5//NDL: Sets the source output level in non-display area.  PTG: Sets the scan mode in non-display area.
 | ||||
| 
 | ||||
| 					writecommand(0xc6); //Interface Control 
 | ||||
| 					writedata(0x83); | ||||
| 					//GAMMA SETTING 
 | ||||
| 
 | ||||
| 					writecommand(0xf0); //?
 | ||||
| 					writedata(0x01); | ||||
| 
 | ||||
| 					writecommand(0xE4);//?
 | ||||
| 					writedata(0xa0); | ||||
| 
 | ||||
| 					//////倒装设置   NG
 | ||||
| 					writecommand(0x36);    | ||||
| 					writedata(0x0A); //  8C:出来两行   CA:出来一个点
 | ||||
| 
 | ||||
| 					writecommand(0x3a); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|           writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|           writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
|      | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) | ||||
|           writecommand(TFT_INVON); | ||||
|     #endif | ||||
| 
 | ||||
| 					writecommand(0xb4);//Display Mode and Frame Memory Write Mode Setting
 | ||||
| 					writedata(0x02); | ||||
| 					writedata(0x00); //?
 | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x01); | ||||
| 
 | ||||
| 					delay(280); | ||||
| 
 | ||||
| 					writecommand(0x2a); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x01); | ||||
| 					writedata(0x3F); //3F
 | ||||
| 
 | ||||
| 					writecommand(0x2b); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x00); | ||||
| 					writedata(0x01); | ||||
| 					writedata(0xDf); //DF
 | ||||
| 
 | ||||
| 					//writecommand(0x21);
 | ||||
| 					writecommand(0x29);	 | ||||
| 					writecommand(0x2c); | ||||
| 
 | ||||
| #endif | ||||
|  | @ -8,17 +8,27 @@ | |||
| { | ||||
| // From https://github.com/notro/fbtft/blob/master/fb_ili9486.c
 | ||||
| 
 | ||||
|     //writecommand(0x01); // SW reset
 | ||||
|     //delay(120);
 | ||||
| 	 | ||||
|     writecommand(0x01); // SW reset
 | ||||
|     delay(120); | ||||
| 
 | ||||
|     writecommand(0x11); // Sleep out, also SW reset
 | ||||
|     delay(120); | ||||
| 
 | ||||
|     writecommand(0x3A); | ||||
|     writedata(0x55); | ||||
|   | ||||
|     writecommand(0xC2); | ||||
|     writedata(0x44); | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writedata(0x55);           // 16 bit colour interface
 | ||||
|     #else | ||||
|       writedata(0x66);           // 18 bit colour interface
 | ||||
|     #endif | ||||
| 
 | ||||
|     writecommand(0xC0); //                          1100.0000 Power Control 1
 | ||||
|     writedata(0x0E);    //                          0001.0111   ... VRH1
 | ||||
|     writedata(0x0E);    //                          0001.0101   ... VRH2
 | ||||
|     writecommand(0xC1); //                          1100.0001 Power Control 2
 | ||||
|     writedata(0x41);    //                          0100.0001   . SAP BT
 | ||||
|     writedata(0x00);    //                          0000.0000   ..... VC
 | ||||
|     writecommand(0xC2); //                          1100.0010 Power Control 3
 | ||||
|     writedata(0x55);    //     nb. was 0x44         0101.0101   . DCA1 . DCA0
 | ||||
| 
 | ||||
|     writecommand(0xC5); | ||||
|     writedata(0x00); | ||||
|  | @ -60,8 +70,12 @@ | |||
|     writedata(0x20); | ||||
|     writedata(0x00); | ||||
|   | ||||
|     writecommand(0x20);                     // display inversion OFF
 | ||||
|    | ||||
|     #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|       writecommand(TFT_INVOFF); | ||||
|     #else | ||||
|       writecommand(TFT_INVON); | ||||
|     #endif | ||||
|   | ||||
|     writecommand(0x36); | ||||
|     writedata(0x48); | ||||
| 
 | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ | |||
|     writedata(0x48);          // MX, BGR
 | ||||
| 
 | ||||
|     writecommand(0x3A); // Pixel Interface Format
 | ||||
| #if defined (TFT_PARALLEL_8_BIT) | ||||
| #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) | ||||
|     writedata(0x55);  // 16 bit colour for parallel
 | ||||
| #else | ||||
|     writedata(0x66);  // 18 bit colour for SPI
 | ||||
|  |  | |||
|  | @ -0,0 +1,47 @@ | |||
| // Change the width and height if required (defined in portrait mode)
 | ||||
| // or use the constructor to over-ride defaults
 | ||||
| // RM68120_DRIVER
 | ||||
| 
 | ||||
| #define TFT_WIDTH  480 | ||||
| #define TFT_HEIGHT 800 | ||||
| 
 | ||||
| //Set driver type common to all TBD initialisation options
 | ||||
| #ifndef RM68120_DRIVER | ||||
|   #define RM68120_DRIVER | ||||
| #endif | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
| #define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked
 | ||||
| 
 | ||||
| // Generic commands used by TFT_eSPI.cpp
 | ||||
| #define TFT_NOP     0x0000 | ||||
| #define TFT_SWRST   0x0100 | ||||
| 
 | ||||
| #define TFT_CASET   0x2A00 | ||||
| #define TFT_PASET   0x2B00 | ||||
| #define TFT_RAMWR   0x2C00 | ||||
| 
 | ||||
| #define TFT_RAMRD   0x2E00 | ||||
| #define TFT_IDXRD   0xDD00 // ILI9341 only, indexed control register read
 | ||||
| 
 | ||||
| #define TFT_MADCTL  0x3600 | ||||
| #define TFT_MAD_MY  0x80 | ||||
| #define TFT_MAD_MX  0x40 | ||||
| #define TFT_MAD_MV  0x20 | ||||
| #define TFT_MAD_ML  0x10 | ||||
| #define TFT_MAD_BGR 0x08 | ||||
| #define TFT_MAD_MH  0x04 | ||||
| #define TFT_MAD_RGB 0x00 | ||||
| 
 | ||||
| #ifdef TFT_RGB_ORDER | ||||
|   #if (TFT_RGB_ORDER == 1) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
| #endif | ||||
| 
 | ||||
| #define TFT_INVOFF  0x2000 | ||||
| #define TFT_INVON   0x2100 | ||||
|  | @ -0,0 +1,429 @@ | |||
| 
 | ||||
| writeRegister(0xF000, 0x55); | ||||
| writeRegister(0xF001, 0xAA); | ||||
| writeRegister(0xF002, 0x52); | ||||
| writeRegister(0xF003, 0x08); | ||||
| writeRegister(0xF004, 0x01); | ||||
| 
 | ||||
| //GAMMA SETING  RED
 | ||||
| writeRegister(0xD100, 0x00); | ||||
| writeRegister(0xD101, 0x00); | ||||
| writeRegister(0xD102, 0x1b); | ||||
| writeRegister(0xD103, 0x44); | ||||
| writeRegister(0xD104, 0x62); | ||||
| writeRegister(0xD105, 0x00); | ||||
| writeRegister(0xD106, 0x7b); | ||||
| writeRegister(0xD107, 0xa1); | ||||
| writeRegister(0xD108, 0xc0); | ||||
| writeRegister(0xD109, 0xee); | ||||
| writeRegister(0xD10A, 0x55); | ||||
| writeRegister(0xD10B, 0x10); | ||||
| writeRegister(0xD10C, 0x2c); | ||||
| writeRegister(0xD10D, 0x43); | ||||
| writeRegister(0xD10E, 0x57); | ||||
| writeRegister(0xD10F, 0x55); | ||||
| writeRegister(0xD110, 0x68); | ||||
| writeRegister(0xD111, 0x78); | ||||
| writeRegister(0xD112, 0x87); | ||||
| writeRegister(0xD113, 0x94); | ||||
| writeRegister(0xD114, 0x55); | ||||
| writeRegister(0xD115, 0xa0); | ||||
| writeRegister(0xD116, 0xac); | ||||
| writeRegister(0xD117, 0xb6); | ||||
| writeRegister(0xD118, 0xc1); | ||||
| writeRegister(0xD119, 0x55); | ||||
| writeRegister(0xD11A, 0xcb); | ||||
| writeRegister(0xD11B, 0xcd); | ||||
| writeRegister(0xD11C, 0xd6); | ||||
| writeRegister(0xD11D, 0xdf); | ||||
| writeRegister(0xD11E, 0x95); | ||||
| writeRegister(0xD11F, 0xe8); | ||||
| writeRegister(0xD120, 0xf1); | ||||
| writeRegister(0xD121, 0xfa); | ||||
| writeRegister(0xD122, 0x02); | ||||
| writeRegister(0xD123, 0xaa); | ||||
| writeRegister(0xD124, 0x0b); | ||||
| writeRegister(0xD125, 0x13); | ||||
| writeRegister(0xD126, 0x1d); | ||||
| writeRegister(0xD127, 0x26); | ||||
| writeRegister(0xD128, 0xaa); | ||||
| writeRegister(0xD129, 0x30); | ||||
| writeRegister(0xD12A, 0x3c); | ||||
| writeRegister(0xD12B, 0x4A); | ||||
| writeRegister(0xD12C, 0x63); | ||||
| writeRegister(0xD12D, 0xea); | ||||
| writeRegister(0xD12E, 0x79); | ||||
| writeRegister(0xD12F, 0xa6); | ||||
| writeRegister(0xD130, 0xd0); | ||||
| writeRegister(0xD131, 0x20); | ||||
| writeRegister(0xD132, 0x0f); | ||||
| writeRegister(0xD133, 0x8e); | ||||
| writeRegister(0xD134, 0xff); | ||||
| //GAMMA SETING GREEN
 | ||||
| writeRegister(0xD200, 0x00); | ||||
| writeRegister(0xD201, 0x00); | ||||
| writeRegister(0xD202, 0x1b); | ||||
| writeRegister(0xD203, 0x44); | ||||
| writeRegister(0xD204, 0x62); | ||||
| writeRegister(0xD205, 0x00); | ||||
| writeRegister(0xD206, 0x7b); | ||||
| writeRegister(0xD207, 0xa1); | ||||
| writeRegister(0xD208, 0xc0); | ||||
| writeRegister(0xD209, 0xee); | ||||
| writeRegister(0xD20A, 0x55); | ||||
| writeRegister(0xD20B, 0x10); | ||||
| writeRegister(0xD20C, 0x2c); | ||||
| writeRegister(0xD20D, 0x43); | ||||
| writeRegister(0xD20E, 0x57); | ||||
| writeRegister(0xD20F, 0x55); | ||||
| writeRegister(0xD210, 0x68); | ||||
| writeRegister(0xD211, 0x78); | ||||
| writeRegister(0xD212, 0x87); | ||||
| writeRegister(0xD213, 0x94); | ||||
| writeRegister(0xD214, 0x55); | ||||
| writeRegister(0xD215, 0xa0); | ||||
| writeRegister(0xD216, 0xac); | ||||
| writeRegister(0xD217, 0xb6); | ||||
| writeRegister(0xD218, 0xc1); | ||||
| writeRegister(0xD219, 0x55); | ||||
| writeRegister(0xD21A, 0xcb); | ||||
| writeRegister(0xD21B, 0xcd); | ||||
| writeRegister(0xD21C, 0xd6); | ||||
| writeRegister(0xD21D, 0xdf); | ||||
| writeRegister(0xD21E, 0x95); | ||||
| writeRegister(0xD21F, 0xe8); | ||||
| writeRegister(0xD220, 0xf1); | ||||
| writeRegister(0xD221, 0xfa); | ||||
| writeRegister(0xD222, 0x02); | ||||
| writeRegister(0xD223, 0xaa); | ||||
| writeRegister(0xD224, 0x0b); | ||||
| writeRegister(0xD225, 0x13); | ||||
| writeRegister(0xD226, 0x1d); | ||||
| writeRegister(0xD227, 0x26); | ||||
| writeRegister(0xD228, 0xaa); | ||||
| writeRegister(0xD229, 0x30); | ||||
| writeRegister(0xD22A, 0x3c); | ||||
| writeRegister(0xD22B, 0x4a); | ||||
| writeRegister(0xD22C, 0x63); | ||||
| writeRegister(0xD22D, 0xea); | ||||
| writeRegister(0xD22E, 0x79); | ||||
| writeRegister(0xD22F, 0xa6); | ||||
| writeRegister(0xD230, 0xd0); | ||||
| writeRegister(0xD231, 0x20); | ||||
| writeRegister(0xD232, 0x0f); | ||||
| writeRegister(0xD233, 0x8e); | ||||
| writeRegister(0xD234, 0xff); | ||||
| 
 | ||||
| //GAMMA SETING BLUE
 | ||||
| writeRegister(0xD300, 0x00); | ||||
| writeRegister(0xD301, 0x00); | ||||
| writeRegister(0xD302, 0x1b); | ||||
| writeRegister(0xD303, 0x44); | ||||
| writeRegister(0xD304, 0x62); | ||||
| writeRegister(0xD305, 0x00); | ||||
| writeRegister(0xD306, 0x7b); | ||||
| writeRegister(0xD307, 0xa1); | ||||
| writeRegister(0xD308, 0xc0); | ||||
| writeRegister(0xD309, 0xee); | ||||
| writeRegister(0xD30A, 0x55); | ||||
| writeRegister(0xD30B, 0x10); | ||||
| writeRegister(0xD30C, 0x2c); | ||||
| writeRegister(0xD30D, 0x43); | ||||
| writeRegister(0xD30E, 0x57); | ||||
| writeRegister(0xD30F, 0x55); | ||||
| writeRegister(0xD310, 0x68); | ||||
| writeRegister(0xD311, 0x78); | ||||
| writeRegister(0xD312, 0x87); | ||||
| writeRegister(0xD313, 0x94); | ||||
| writeRegister(0xD314, 0x55); | ||||
| writeRegister(0xD315, 0xa0); | ||||
| writeRegister(0xD316, 0xac); | ||||
| writeRegister(0xD317, 0xb6); | ||||
| writeRegister(0xD318, 0xc1); | ||||
| writeRegister(0xD319, 0x55); | ||||
| writeRegister(0xD31A, 0xcb); | ||||
| writeRegister(0xD31B, 0xcd); | ||||
| writeRegister(0xD31C, 0xd6); | ||||
| writeRegister(0xD31D, 0xdf); | ||||
| writeRegister(0xD31E, 0x95); | ||||
| writeRegister(0xD31F, 0xe8); | ||||
| writeRegister(0xD320, 0xf1); | ||||
| writeRegister(0xD321, 0xfa); | ||||
| writeRegister(0xD322, 0x02); | ||||
| writeRegister(0xD323, 0xaa); | ||||
| writeRegister(0xD324, 0x0b); | ||||
| writeRegister(0xD325, 0x13); | ||||
| writeRegister(0xD326, 0x1d); | ||||
| writeRegister(0xD327, 0x26); | ||||
| writeRegister(0xD328, 0xaa); | ||||
| writeRegister(0xD329, 0x30); | ||||
| writeRegister(0xD32A, 0x3c); | ||||
| writeRegister(0xD32B, 0x4A); | ||||
| writeRegister(0xD32C, 0x63); | ||||
| writeRegister(0xD32D, 0xea); | ||||
| writeRegister(0xD32E, 0x79); | ||||
| writeRegister(0xD32F, 0xa6); | ||||
| writeRegister(0xD330, 0xd0); | ||||
| writeRegister(0xD331, 0x20); | ||||
| writeRegister(0xD332, 0x0f); | ||||
| writeRegister(0xD333, 0x8e); | ||||
| writeRegister(0xD334, 0xff); | ||||
| 
 | ||||
| 
 | ||||
| //GAMMA SETING  RED
 | ||||
| writeRegister(0xD400, 0x00); | ||||
| writeRegister(0xD401, 0x00); | ||||
| writeRegister(0xD402, 0x1b); | ||||
| writeRegister(0xD403, 0x44); | ||||
| writeRegister(0xD404, 0x62); | ||||
| writeRegister(0xD405, 0x00); | ||||
| writeRegister(0xD406, 0x7b); | ||||
| writeRegister(0xD407, 0xa1); | ||||
| writeRegister(0xD408, 0xc0); | ||||
| writeRegister(0xD409, 0xee); | ||||
| writeRegister(0xD40A, 0x55); | ||||
| writeRegister(0xD40B, 0x10); | ||||
| writeRegister(0xD40C, 0x2c); | ||||
| writeRegister(0xD40D, 0x43); | ||||
| writeRegister(0xD40E, 0x57); | ||||
| writeRegister(0xD40F, 0x55); | ||||
| writeRegister(0xD410, 0x68); | ||||
| writeRegister(0xD411, 0x78); | ||||
| writeRegister(0xD412, 0x87); | ||||
| writeRegister(0xD413, 0x94); | ||||
| writeRegister(0xD414, 0x55); | ||||
| writeRegister(0xD415, 0xa0); | ||||
| writeRegister(0xD416, 0xac); | ||||
| writeRegister(0xD417, 0xb6); | ||||
| writeRegister(0xD418, 0xc1); | ||||
| writeRegister(0xD419, 0x55); | ||||
| writeRegister(0xD41A, 0xcb); | ||||
| writeRegister(0xD41B, 0xcd); | ||||
| writeRegister(0xD41C, 0xd6); | ||||
| writeRegister(0xD41D, 0xdf); | ||||
| writeRegister(0xD41E, 0x95); | ||||
| writeRegister(0xD41F, 0xe8); | ||||
| writeRegister(0xD420, 0xf1); | ||||
| writeRegister(0xD421, 0xfa); | ||||
| writeRegister(0xD422, 0x02); | ||||
| writeRegister(0xD423, 0xaa); | ||||
| writeRegister(0xD424, 0x0b); | ||||
| writeRegister(0xD425, 0x13); | ||||
| writeRegister(0xD426, 0x1d); | ||||
| writeRegister(0xD427, 0x26); | ||||
| writeRegister(0xD428, 0xaa); | ||||
| writeRegister(0xD429, 0x30); | ||||
| writeRegister(0xD42A, 0x3c); | ||||
| writeRegister(0xD42B, 0x4A); | ||||
| writeRegister(0xD42C, 0x63); | ||||
| writeRegister(0xD42D, 0xea); | ||||
| writeRegister(0xD42E, 0x79); | ||||
| writeRegister(0xD42F, 0xa6); | ||||
| writeRegister(0xD430, 0xd0); | ||||
| writeRegister(0xD431, 0x20); | ||||
| writeRegister(0xD432, 0x0f); | ||||
| writeRegister(0xD433, 0x8e); | ||||
| writeRegister(0xD434, 0xff); | ||||
| 
 | ||||
| //GAMMA SETING GREEN
 | ||||
| writeRegister(0xD500, 0x00); | ||||
| writeRegister(0xD501, 0x00); | ||||
| writeRegister(0xD502, 0x1b); | ||||
| writeRegister(0xD503, 0x44); | ||||
| writeRegister(0xD504, 0x62); | ||||
| writeRegister(0xD505, 0x00); | ||||
| writeRegister(0xD506, 0x7b); | ||||
| writeRegister(0xD507, 0xa1); | ||||
| writeRegister(0xD508, 0xc0); | ||||
| writeRegister(0xD509, 0xee); | ||||
| writeRegister(0xD50A, 0x55); | ||||
| writeRegister(0xD50B, 0x10); | ||||
| writeRegister(0xD50C, 0x2c); | ||||
| writeRegister(0xD50D, 0x43); | ||||
| writeRegister(0xD50E, 0x57); | ||||
| writeRegister(0xD50F, 0x55); | ||||
| writeRegister(0xD510, 0x68); | ||||
| writeRegister(0xD511, 0x78); | ||||
| writeRegister(0xD512, 0x87); | ||||
| writeRegister(0xD513, 0x94); | ||||
| writeRegister(0xD514, 0x55); | ||||
| writeRegister(0xD515, 0xa0); | ||||
| writeRegister(0xD516, 0xac); | ||||
| writeRegister(0xD517, 0xb6); | ||||
| writeRegister(0xD518, 0xc1); | ||||
| writeRegister(0xD519, 0x55); | ||||
| writeRegister(0xD51A, 0xcb); | ||||
| writeRegister(0xD51B, 0xcd); | ||||
| writeRegister(0xD51C, 0xd6); | ||||
| writeRegister(0xD51D, 0xdf); | ||||
| writeRegister(0xD51E, 0x95); | ||||
| writeRegister(0xD51F, 0xe8); | ||||
| writeRegister(0xD520, 0xf1); | ||||
| writeRegister(0xD521, 0xfa); | ||||
| writeRegister(0xD522, 0x02); | ||||
| writeRegister(0xD523, 0xaa); | ||||
| writeRegister(0xD524, 0x0b); | ||||
| writeRegister(0xD525, 0x13); | ||||
| writeRegister(0xD526, 0x1d); | ||||
| writeRegister(0xD527, 0x26); | ||||
| writeRegister(0xD528, 0xaa); | ||||
| writeRegister(0xD529, 0x30); | ||||
| writeRegister(0xD52A, 0x3c); | ||||
| writeRegister(0xD52B, 0x4a); | ||||
| writeRegister(0xD52C, 0x63); | ||||
| writeRegister(0xD52D, 0xea); | ||||
| writeRegister(0xD52E, 0x79); | ||||
| writeRegister(0xD52F, 0xa6); | ||||
| writeRegister(0xD530, 0xd0); | ||||
| writeRegister(0xD531, 0x20); | ||||
| writeRegister(0xD532, 0x0f); | ||||
| writeRegister(0xD533, 0x8e); | ||||
| writeRegister(0xD534, 0xff); | ||||
| 
 | ||||
| //GAMMA SETING BLUE
 | ||||
| writeRegister(0xD600, 0x00); | ||||
| writeRegister(0xD601, 0x00); | ||||
| writeRegister(0xD602, 0x1b); | ||||
| writeRegister(0xD603, 0x44); | ||||
| writeRegister(0xD604, 0x62); | ||||
| writeRegister(0xD605, 0x00); | ||||
| writeRegister(0xD606, 0x7b); | ||||
| writeRegister(0xD607, 0xa1); | ||||
| writeRegister(0xD608, 0xc0); | ||||
| writeRegister(0xD609, 0xee); | ||||
| writeRegister(0xD60A, 0x55); | ||||
| writeRegister(0xD60B, 0x10); | ||||
| writeRegister(0xD60C, 0x2c); | ||||
| writeRegister(0xD60D, 0x43); | ||||
| writeRegister(0xD60E, 0x57); | ||||
| writeRegister(0xD60F, 0x55); | ||||
| writeRegister(0xD610, 0x68); | ||||
| writeRegister(0xD611, 0x78); | ||||
| writeRegister(0xD612, 0x87); | ||||
| writeRegister(0xD613, 0x94); | ||||
| writeRegister(0xD614, 0x55); | ||||
| writeRegister(0xD615, 0xa0); | ||||
| writeRegister(0xD616, 0xac); | ||||
| writeRegister(0xD617, 0xb6); | ||||
| writeRegister(0xD618, 0xc1); | ||||
| writeRegister(0xD619, 0x55); | ||||
| writeRegister(0xD61A, 0xcb); | ||||
| writeRegister(0xD61B, 0xcd); | ||||
| writeRegister(0xD61C, 0xd6); | ||||
| writeRegister(0xD61D, 0xdf); | ||||
| writeRegister(0xD61E, 0x95); | ||||
| writeRegister(0xD61F, 0xe8); | ||||
| writeRegister(0xD620, 0xf1); | ||||
| writeRegister(0xD621, 0xfa); | ||||
| writeRegister(0xD622, 0x02); | ||||
| writeRegister(0xD623, 0xaa); | ||||
| writeRegister(0xD624, 0x0b); | ||||
| writeRegister(0xD625, 0x13); | ||||
| writeRegister(0xD626, 0x1d); | ||||
| writeRegister(0xD627, 0x26); | ||||
| writeRegister(0xD628, 0xaa); | ||||
| writeRegister(0xD629, 0x30); | ||||
| writeRegister(0xD62A, 0x3c); | ||||
| writeRegister(0xD62B, 0x4A); | ||||
| writeRegister(0xD62C, 0x63); | ||||
| writeRegister(0xD62D, 0xea); | ||||
| writeRegister(0xD62E, 0x79); | ||||
| writeRegister(0xD62F, 0xa6); | ||||
| writeRegister(0xD630, 0xd0); | ||||
| writeRegister(0xD631, 0x20); | ||||
| writeRegister(0xD632, 0x0f); | ||||
| writeRegister(0xD633, 0x8e); | ||||
| writeRegister(0xD634, 0xff); | ||||
| 
 | ||||
| //AVDD VOLTAGE SETTING
 | ||||
| writeRegister(0xB000, 0x05); | ||||
| writeRegister(0xB001, 0x05); | ||||
| writeRegister(0xB002, 0x05); | ||||
| //AVEE VOLTAGE SETTING
 | ||||
| writeRegister(0xB100, 0x05); | ||||
| writeRegister(0xB101, 0x05); | ||||
| writeRegister(0xB102, 0x05); | ||||
| 
 | ||||
| //AVDD Boosting
 | ||||
| writeRegister(0xB600, 0x34); | ||||
| writeRegister(0xB601, 0x34); | ||||
| writeRegister(0xB603, 0x34); | ||||
| //AVEE Boosting
 | ||||
| writeRegister(0xB700, 0x24); | ||||
| writeRegister(0xB701, 0x24); | ||||
| writeRegister(0xB702, 0x24); | ||||
| //VCL Boosting
 | ||||
| writeRegister(0xB800, 0x24); | ||||
| writeRegister(0xB801, 0x24); | ||||
| writeRegister(0xB802, 0x24); | ||||
| //VGLX VOLTAGE SETTING
 | ||||
| writeRegister(0xBA00, 0x14); | ||||
| writeRegister(0xBA01, 0x14); | ||||
| writeRegister(0xBA02, 0x14); | ||||
| //VCL Boosting
 | ||||
| writeRegister(0xB900, 0x24); | ||||
| writeRegister(0xB901, 0x24); | ||||
| writeRegister(0xB902, 0x24); | ||||
| //Gamma Voltage
 | ||||
| writeRegister(0xBc00, 0x00); | ||||
| writeRegister(0xBc01, 0xa0);//vgmp=5.0
 | ||||
| writeRegister(0xBc02, 0x00); | ||||
| writeRegister(0xBd00, 0x00); | ||||
| writeRegister(0xBd01, 0xa0);//vgmn=5.0
 | ||||
| writeRegister(0xBd02, 0x00); | ||||
| //VCOM Setting
 | ||||
| writeRegister(0xBe01, 0x3d);//3
 | ||||
| //ENABLE PAGE 0
 | ||||
| writeRegister(0xF000, 0x55); | ||||
| writeRegister(0xF001, 0xAA); | ||||
| writeRegister(0xF002, 0x52); | ||||
| writeRegister(0xF003, 0x08); | ||||
| writeRegister(0xF004, 0x00); | ||||
| //Vivid Color Function Control
 | ||||
| writeRegister(0xB400, 0x10); | ||||
| //Z-INVERSION
 | ||||
| writeRegister(0xBC00, 0x05); | ||||
| writeRegister(0xBC01, 0x05); | ||||
| writeRegister(0xBC02, 0x05); | ||||
| 
 | ||||
| //*************** add on 20111021**********************//
 | ||||
| writeRegister(0xB700, 0x22);//GATE EQ CONTROL
 | ||||
| writeRegister(0xB701, 0x22);//GATE EQ CONTROL
 | ||||
| writeRegister(0xC80B, 0x2A);//DISPLAY TIMING CONTROL
 | ||||
| writeRegister(0xC80C, 0x2A);//DISPLAY TIMING CONTROL
 | ||||
| writeRegister(0xC80F, 0x2A);//DISPLAY TIMING CONTROL
 | ||||
| writeRegister(0xC810, 0x2A);//DISPLAY TIMING CONTROL
 | ||||
| //*************** add on 20111021**********************//
 | ||||
| //PWM_ENH_OE =1
 | ||||
| writeRegister(0xd000, 0x01); | ||||
| //DM_SEL =1
 | ||||
| writeRegister(0xb300, 0x10); | ||||
| //VBPDA=07h
 | ||||
| writeRegister(0xBd02, 0x07); | ||||
| //VBPDb=07h
 | ||||
| writeRegister(0xBe02, 0x07); | ||||
| //VBPDc=07h
 | ||||
| writeRegister(0xBf02, 0x07); | ||||
| //ENABLE PAGE 2
 | ||||
| writeRegister(0xF000, 0x55); | ||||
| writeRegister(0xF001, 0xAA); | ||||
| writeRegister(0xF002, 0x52); | ||||
| writeRegister(0xF003, 0x08); | ||||
| writeRegister(0xF004, 0x02); | ||||
| //SDREG0 =0
 | ||||
| writeRegister(0xc301, 0xa9); | ||||
| //DS=14
 | ||||
| writeRegister(0xfe01, 0x94); | ||||
| //OSC =60h
 | ||||
| writeRegister(0xf600, 0x60); | ||||
| //TE ON
 | ||||
| writeRegister(0x3500, 0x00); | ||||
| //SLEEP OUT
 | ||||
| writecommand(0x1100); | ||||
| delay(100); | ||||
| //DISPLY ON
 | ||||
| writecommand(0x2900); | ||||
| delay(100); | ||||
| 
 | ||||
| writeRegister(0x3A00, 0x55); | ||||
| writeRegister(0x3600, 0xA3); | ||||
|  | @ -0,0 +1,29 @@ | |||
| 
 | ||||
| // This is the command sequence that rotates the RM68120 driver coordinate frame
 | ||||
| 
 | ||||
|   rotation = m % 4; // Limit the range of values to 0-3
 | ||||
| 
 | ||||
|   writecommand(TFT_MADCTL); | ||||
|   switch (rotation) { | ||||
|     case 0: | ||||
|       writedata(TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 1: | ||||
|       writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|     case 2: | ||||
|       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 3: | ||||
|       writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
| 
 | ||||
|   } | ||||
|  | @ -0,0 +1,20 @@ | |||
| #ifndef TFT_WIDTH | ||||
|   #define TFT_WIDTH 128 | ||||
| #endif | ||||
| #ifndef TFT_HEIGHT | ||||
|   #define TFT_HEIGHT 128 | ||||
| #endif | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
| #define TFT_INIT_DELAY 0x80 | ||||
| 
 | ||||
| // Generic commands used by TFT_eSPI.cpp
 | ||||
| #define TFT_NOP     0x00 | ||||
| #define TFT_SWRST   TFT_NOP | ||||
| #define TFT_CASET   0x15 // SETCOLUMN
 | ||||
| #define TFT_PASET   0x75 // SETROW
 | ||||
| #define TFT_RAMWR   0x5C // WRITERAM
 | ||||
| #define TFT_RAMRD   0x5D // READRAM
 | ||||
| #define TFT_IDXRD   TFT_NOP | ||||
| #define TFT_INVOFF  0xA6 // NORMALDISPLAY
 | ||||
| #define TFT_INVON   0xA7 // INVERTDISPLAY
 | ||||
|  | @ -0,0 +1,35 @@ | |||
| { | ||||
|   writecommand(0xFD); // COMMANDLOCK
 | ||||
|   writedata(0x12); | ||||
|   writecommand(0xFD); // COMMANDLOCK
 | ||||
|   writedata(0xB1); | ||||
|   writecommand(0xAE); // DISPLAYOFF
 | ||||
|   writecommand(0xB3); // CLOCKDIV
 | ||||
|   writedata(0xF1); | ||||
|   writecommand(0xCA); // MUXRATIO
 | ||||
|   writedata(127); | ||||
|   writecommand(0xA2); // DISPLAYOFFSET
 | ||||
|   writedata(0x00); | ||||
|   writecommand(0xB5); // SETGPIO
 | ||||
|   writedata(0x00); | ||||
|   writecommand(0xAB); // FUNCTIONSELECT
 | ||||
|   writedata(0x01); | ||||
|   writecommand(0xB1); // PRECHARGE
 | ||||
|   writedata(0x32); | ||||
|   writecommand(0xBE); // VCOMH
 | ||||
|   writedata(0x05); | ||||
|   writecommand(0xA6); // NORMALDISPLAY
 | ||||
|   writecommand(0xC1); // CONTRASTABC
 | ||||
|   writedata(0xC8); | ||||
|   writedata(0x80); | ||||
|   writedata(0xC8); | ||||
|   writecommand(0xC7); // CONTRASTMASTER
 | ||||
|   writedata(0x0F); | ||||
|   writecommand(0xB4); // SETVSL
 | ||||
|   writedata(0xA0); | ||||
|   writedata(0xB5); | ||||
|   writedata(0x55); | ||||
|   writecommand(0xB6); // PRECHARGE2
 | ||||
|   writedata(0x01); | ||||
|   writecommand(0xAF); // DISPLAYON
 | ||||
| } | ||||
|  | @ -0,0 +1,34 @@ | |||
| 
 | ||||
| // This is the command sequence that rotates the SSD1351 driver coordinate frame
 | ||||
| 
 | ||||
|   rotation = m % 4; // Limit the range of values to 0-3
 | ||||
| 
 | ||||
|   uint8_t madctl = 0x64; | ||||
| 
 | ||||
|   switch (rotation) { | ||||
|     case 0: | ||||
|       madctl |= 0x10; | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 1: | ||||
|       madctl |= 0x13; | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|     case 2: | ||||
|       madctl |= 0x02; | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 3: | ||||
|       madctl |= 0x01; | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|   } | ||||
| 
 | ||||
|   writecommand(0xA0); // SETREMAP
 | ||||
|   writedata(madctl); | ||||
|   writecommand(0xA1); // STARTLINE
 | ||||
|   writedata(rotation < 2 ? TFT_HEIGHT : 0); | ||||
|  | @ -0,0 +1,56 @@ | |||
| // Change the width and height if required (defined in portrait mode)
 | ||||
| // or use the constructor to over-ride defaults
 | ||||
| #if defined (SSD1963_480_DRIVER) | ||||
|   #define TFT_WIDTH  272 | ||||
|   #define TFT_HEIGHT 480 | ||||
| #elif defined (SSD1963_800_DRIVER) | ||||
|   #define TFT_WIDTH  480 | ||||
|   #define TFT_HEIGHT 800 | ||||
| #elif defined (SSD1963_800ALT_DRIVER) | ||||
|   #define TFT_WIDTH  480 | ||||
|   #define TFT_HEIGHT 800 | ||||
| #elif defined (SSD1963_800BD_DRIVER) | ||||
|   #define TFT_WIDTH  480 | ||||
|   #define TFT_HEIGHT 800 | ||||
| #endif | ||||
| 
 | ||||
| //Set driver type common to all initialisation options
 | ||||
| #ifndef SSD1963_DRIVER | ||||
|   #define SSD1963_DRIVER | ||||
| #endif | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
| #define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked
 | ||||
| 
 | ||||
| // Generic commands used by TFT_eSPI.cpp
 | ||||
| #define TFT_NOP     0x00 | ||||
| #define TFT_SWRST   0x01 | ||||
| 
 | ||||
| #define TFT_CASET   0x2A | ||||
| #define TFT_PASET   0x2B | ||||
| #define TFT_RAMWR   0x2C | ||||
| 
 | ||||
| #define TFT_RAMRD   0x2E | ||||
| #define TFT_IDXRD   0xDD // ILI9341 only, indexed control register read
 | ||||
| 
 | ||||
| #define TFT_MADCTL  0x36 | ||||
| #define TFT_MAD_MY  0x80 | ||||
| #define TFT_MAD_MX  0x40 | ||||
| #define TFT_MAD_MV  0x20 | ||||
| #define TFT_MAD_ML  0x10 | ||||
| #define TFT_MAD_BGR 0x08 | ||||
| #define TFT_MAD_MH  0x04 | ||||
| #define TFT_MAD_RGB 0x00 | ||||
| 
 | ||||
| #ifdef TFT_RGB_ORDER | ||||
|   #if (TFT_RGB_ORDER == 1) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #else | ||||
|   #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
| #endif | ||||
| 
 | ||||
| #define TFT_INVOFF  0x20 | ||||
| #define TFT_INVON   0x21 | ||||
|  | @ -0,0 +1,398 @@ | |||
| #if defined (SSD1963_480_DRIVER) | ||||
| 
 | ||||
|   writecommand(0xE2);   //PLL multiplier, set PLL clock to 120M
 | ||||
|   writedata(0x23);      //N=0x36 for 6.5M, 0x23 for 10M crystal
 | ||||
|   writedata(0x02); | ||||
|   writedata(0x54); | ||||
|   writecommand(0xE0);   // PLL enable
 | ||||
|   writedata(0x01); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0xE0); | ||||
|   writedata(0x03); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0x01);   // software reset
 | ||||
| 
 | ||||
|   delay(100); | ||||
| 
 | ||||
|   writecommand(0xE6);   //PLL setting for PCLK, depends on resolution
 | ||||
|   writedata(0x01); | ||||
|   writedata(0x1F); | ||||
|   writedata(0xFF); | ||||
| 
 | ||||
|   writecommand(0xB0);   //LCD SPECIFICATION
 | ||||
|   writedata(0x20); | ||||
|   writedata(0x00); | ||||
|   writedata(0x01);    //Set HDP 479
 | ||||
|   writedata(0xDF); | ||||
|   writedata(0x01);    //Set VDP 271
 | ||||
|   writedata(0x0F); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB4);   //HSYNC
 | ||||
|   writedata(0x02);    //Set HT  531
 | ||||
|   writedata(0x13); | ||||
|   writedata(0x00);    //Set HPS 8
 | ||||
|   writedata(0x08); | ||||
|   writedata(0x2B);    //Set HPW 43
 | ||||
|   writedata(0x00);    //Set LPS 2
 | ||||
|   writedata(0x02); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB6);   //VSYNC
 | ||||
|   writedata(0x01);    //Set VT  288
 | ||||
|   writedata(0x20); | ||||
|   writedata(0x00);    //Set VPS 4
 | ||||
|   writedata(0x04); | ||||
|   writedata(0x0c);    //Set VPW 12
 | ||||
|   writedata(0x00);    //Set FPS 2
 | ||||
|   writedata(0x02); | ||||
| 
 | ||||
|   writecommand(0xBA); | ||||
|   writedata(0x0F);    //GPIO[3:0] out 1
 | ||||
| 
 | ||||
|   writecommand(0xB8); | ||||
|   writedata(0x07);      //GPIO3=input, GPIO[2:0]=output
 | ||||
|   writedata(0x01);    //GPIO0 normal
 | ||||
| 
 | ||||
|   writecommand(0x36);   //rotation
 | ||||
|   writedata(0x21 | TFT_MAD_COLOR_ORDER); | ||||
| 
 | ||||
|   writecommand(0xF0);   //pixel data interface
 | ||||
|   writedata(0x00);      //8 bit bus
 | ||||
| 
 | ||||
|   delay(1); | ||||
| 
 | ||||
|   writecommand(0xB8); | ||||
|   writedata(0x0f);    //GPIO is controlled by host GPIO[3:0]=output   GPIO[0]=1  LCD ON  GPIO[0]=1  LCD OFF 
 | ||||
|   writedata(0x01);    //GPIO0 normal
 | ||||
| 
 | ||||
|   writecommand(0xBA); | ||||
|   writedata(0x01);    //GPIO[0] out 1 --- LCD display on/off control PIN
 | ||||
| 
 | ||||
|   writecommand(0x2A);  | ||||
|   writedata(0); | ||||
|   writedata(0); | ||||
|   writedata((271 & 0xFF00)>>8); | ||||
|   writedata(271 & 0xFF); | ||||
| 
 | ||||
|   writecommand(0x2B);  | ||||
|   writedata(0); | ||||
|   writedata(0); | ||||
|   writedata((479 & 0xFF00)>>8); | ||||
|   writedata(479 & 0xFF); | ||||
| 
 | ||||
|   writecommand(0x2C); | ||||
| 
 | ||||
|   writecommand(0x29);   //display on
 | ||||
| 
 | ||||
|   writecommand(0xBE);   //set PWM for B/L
 | ||||
|   writedata(0x06); | ||||
|   writedata(0xf0); | ||||
|   writedata(0x01); | ||||
|   writedata(0xf0); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xd0);  | ||||
|   writedata(0x0d);   | ||||
| 
 | ||||
|   writecommand(0x2C);  | ||||
| 
 | ||||
| #elif defined (SSD1963_800_DRIVER) | ||||
| 
 | ||||
|   writecommand(0xE2);   //PLL multiplier, set PLL clock to 120M
 | ||||
|   writedata(0x1E);      //N=0x36 for 6.5M, 0x23 for 10M crystal
 | ||||
|   writedata(0x02); | ||||
|   writedata(0x54); | ||||
|   writecommand(0xE0);   // PLL enable
 | ||||
|   writedata(0x01); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0xE0); | ||||
|   writedata(0x03); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0x01);   // software reset
 | ||||
| 
 | ||||
|   delay(100); | ||||
| 
 | ||||
|   writecommand(0xE6);   //PLL setting for PCLK, depends on resolution
 | ||||
|   writedata(0x03); | ||||
|   writedata(0xFF); | ||||
|   writedata(0xFF); | ||||
| 
 | ||||
|   writecommand(0xB0);   //LCD SPECIFICATION
 | ||||
|   writedata(0x20); | ||||
|   writedata(0x00); | ||||
|   writedata(0x03);    //Set HDP 799
 | ||||
|   writedata(0x1F); | ||||
|   writedata(0x01);    //Set VDP 479
 | ||||
|   writedata(0xDF); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB4);   //HSYNC
 | ||||
|   writedata(0x03);    //Set HT  928
 | ||||
|   writedata(0xA0); | ||||
|   writedata(0x00);    //Set HPS 46
 | ||||
|   writedata(0x2E); | ||||
|   writedata(0x30);    //Set HPW 48
 | ||||
|   writedata(0x00);    //Set LPS 15
 | ||||
|   writedata(0x0F); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB6);   //VSYNC
 | ||||
|   writedata(0x02);    //Set VT  525
 | ||||
|   writedata(0x0D); | ||||
|   writedata(0x00);    //Set VPS 16
 | ||||
|   writedata(0x10); | ||||
|   writedata(0x10);    //Set VPW 16
 | ||||
|   writedata(0x00);    //Set FPS 8
 | ||||
|   writedata(0x08); | ||||
| 
 | ||||
|   writecommand(0xBA); | ||||
|   writedata(0x0F);    //GPIO[3:0] out 1
 | ||||
| 
 | ||||
|   writecommand(0xB8); | ||||
|   writedata(0x07);      //GPIO3=input, GPIO[2:0]=output
 | ||||
|   writedata(0x01);    //GPIO0 normal
 | ||||
| 
 | ||||
|   writecommand(0x36);   //rotation
 | ||||
|   writedata(0x21 | TFT_MAD_COLOR_ORDER); | ||||
| 
 | ||||
|   writecommand(0xF0);   //pixel data interface
 | ||||
|   writedata(0x00);      //8 bit bus
 | ||||
| 
 | ||||
|   delay(1); | ||||
| 
 | ||||
|   writecommand(0xB8); | ||||
|   writedata(0x0f);    //GPIO is controlled by host GPIO[3:0]=output   GPIO[0]=1  LCD ON  GPIO[0]=1  LCD OFF 
 | ||||
|   writedata(0x01);    //GPIO0 normal
 | ||||
| 
 | ||||
|   writecommand(0xBA); | ||||
|   writedata(0x01);    //GPIO[0] out 1 --- LCD display on/off control PIN
 | ||||
| 
 | ||||
|   writecommand(0x2A);  | ||||
|   writedata(0); | ||||
|   writedata(0); | ||||
|   writedata((479 & 0xFF00)>>8); | ||||
|   writedata(479 & 0xFF); | ||||
| 
 | ||||
|   writecommand(0x2B);  | ||||
|   writedata(0); | ||||
|   writedata(0); | ||||
|   writedata((799 & 0xFF00)>>8); | ||||
|   writedata(799 & 0xFF); | ||||
| 
 | ||||
|   writecommand(0x2C); | ||||
| 
 | ||||
|   writecommand(0x29);   //display on
 | ||||
| 
 | ||||
|   writecommand(0xBE);   //set PWM for B/L
 | ||||
|   writedata(0x06); | ||||
|   writedata(0xf0); | ||||
|   writedata(0x01); | ||||
|   writedata(0xf0); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xd0);  | ||||
|   writedata(0x0d);   | ||||
| 
 | ||||
|   writecommand(0x2C);  | ||||
| 
 | ||||
| #elif defined (SSD1963_800ALT_DRIVER) | ||||
| 
 | ||||
|   writecommand(0xE2);   //PLL multiplier, set PLL clock to 120M
 | ||||
|   writedata(0x23);      //N=0x36 for 6.5M, 0x23 for 10M crystal
 | ||||
|   writedata(0x02); | ||||
|   writedata(0x04); | ||||
|   writecommand(0xE0);   // PLL enable
 | ||||
|   writedata(0x01); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0xE0); | ||||
|   writedata(0x03); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0x01);   // software reset
 | ||||
| 
 | ||||
|   delay(100); | ||||
| 
 | ||||
|   writecommand(0xE6);   //PLL setting for PCLK, depends on resolution
 | ||||
|   writedata(0x04); | ||||
|   writedata(0x93); | ||||
|   writedata(0xE0); | ||||
| 
 | ||||
|   writecommand(0xB0);   //LCD SPECIFICATION
 | ||||
|   writedata(0x00);  // 0x24
 | ||||
|   writedata(0x00); | ||||
|   writedata(0x03);    //Set HDP 799
 | ||||
|   writedata(0x1F); | ||||
|   writedata(0x01);    //Set VDP 479
 | ||||
|   writedata(0xDF); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB4);   //HSYNC
 | ||||
|   writedata(0x03);    //Set HT  928
 | ||||
|   writedata(0xA0); | ||||
|   writedata(0x00);    //Set HPS 46
 | ||||
|   writedata(0x2E); | ||||
|   writedata(0x30);    //Set HPW 48
 | ||||
|   writedata(0x00);    //Set LPS 15
 | ||||
|   writedata(0x0F); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB6);   //VSYNC
 | ||||
|   writedata(0x02);    //Set VT  525
 | ||||
|   writedata(0x0D); | ||||
|   writedata(0x00);    //Set VPS 16
 | ||||
|   writedata(0x10); | ||||
|   writedata(0x10);    //Set VPW 16
 | ||||
|   writedata(0x00);    //Set FPS 8
 | ||||
|   writedata(0x08); | ||||
| 
 | ||||
|   writecommand(0xBA); | ||||
|   writedata(0x05);    //GPIO[3:0] out 1
 | ||||
| 
 | ||||
|   writecommand(0xB8); | ||||
|   writedata(0x07);      //GPIO3=input, GPIO[2:0]=output
 | ||||
|   writedata(0x01);    //GPIO0 normal
 | ||||
| 
 | ||||
|   writecommand(0x36);   //rotation
 | ||||
|   writedata(0x21 | TFT_MAD_COLOR_ORDER);    // -- Set rotation
 | ||||
| 
 | ||||
|   writecommand(0xF0);   //pixel data interface
 | ||||
|   writedata(0x00);      //8 bit bus
 | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0x2A);  | ||||
|   writedata(0); | ||||
|   writedata(0); | ||||
|   writedata((479 & 0xFF00)>>8); | ||||
|   writedata(479 & 0xFF); | ||||
| 
 | ||||
|   writecommand(0x2B);  | ||||
|   writedata(0); | ||||
|   writedata(0); | ||||
|   writedata((799 & 0xFF00)>>8); | ||||
|   writedata(799 & 0xFF); | ||||
| 
 | ||||
|   writecommand(0x2C); | ||||
| 
 | ||||
|   writecommand(0x29);   //display on
 | ||||
| 
 | ||||
|   writecommand(0xBE);   //set PWM for B/L
 | ||||
|   writedata(0x06); | ||||
|   writedata(0xF0); | ||||
|   writedata(0x01); | ||||
|   writedata(0xF0); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xD0);  | ||||
|   writedata(0x0D);   | ||||
| 
 | ||||
|   writecommand(0x2C);  | ||||
| 
 | ||||
| #elif defined (SSD1963_800BD_DRIVER) // Copied from Buy Display code
 | ||||
| 
 | ||||
|   writecommand(0xE2);   //PLL multiplier, set PLL clock to 120M
 | ||||
|   writedata(0x23);      //N=0x36 for 6.5M, 0x23 for 10M crystal
 | ||||
|   writedata(0x02); | ||||
|   writedata(0x54); | ||||
| 
 | ||||
|   writecommand(0xE0);   // PLL enable
 | ||||
|   writedata(0x01); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0xE0); | ||||
|   writedata(0x03); | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0x01);   // software reset
 | ||||
| 
 | ||||
|   delay(100); | ||||
| 
 | ||||
|   writecommand(0xE6);   //PLL setting for PCLK, depends on resolution
 | ||||
|   writedata(0x03); | ||||
|   writedata(0x33); | ||||
|   writedata(0x33); | ||||
| 
 | ||||
|   writecommand(0xB0);    //LCD SPECIFICATION
 | ||||
|   writedata(0x20); | ||||
|   writedata(0x00); | ||||
|   writedata(799 >> 8);   //Set HDP 799
 | ||||
|   writedata(799 & 0xFF); | ||||
|   writedata(479 >> 8);   //Set VDP 479
 | ||||
|   writedata(479 & 0xFF); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB4);   //HSYNC
 | ||||
|   writedata(0x04);      //Set HT
 | ||||
|   writedata(0x1F); | ||||
|   writedata(0x00);      //Set HPS
 | ||||
|   writedata(0xD2); | ||||
|   writedata(0x00);      //Set HPW
 | ||||
|   writedata(0x00);      //Set LPS
 | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB6);   //VSYNC
 | ||||
|   writedata(0x02);    //Set VT
 | ||||
|   writedata(0x0C); | ||||
|   writedata(0x00);    //Set VPS
 | ||||
|   writedata(0x22); | ||||
|   writedata(0x00);    //Set VPW
 | ||||
|   writedata(0x00);    //Set FPS
 | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xB8); | ||||
|   writedata(0x0F);      //GPIO3=input, GPIO[2:0]=output
 | ||||
|   writedata(0x01);      //GPIO0 normal
 | ||||
| 
 | ||||
|   writecommand(0xBA); | ||||
|   writedata(0x01);    //GPIO[0] out 1 --- LCD display on/off control PIN
 | ||||
| 
 | ||||
|   writecommand(0x36);   //rotation
 | ||||
|   writedata(0x21 | TFT_MAD_COLOR_ORDER);      //set to rotate
 | ||||
| 
 | ||||
| 	//writecommand(0x003A); //Set the current pixel format for RGB image data
 | ||||
| 	//writedata(0x0050);    //16-bit/pixel
 | ||||
| 
 | ||||
|   writecommand(0xF0);   //pixel data interface
 | ||||
|   writedata(0x00);      //000 = 8 bit bus, 011 = 16 bit, 110 = 9 bit
 | ||||
| 
 | ||||
|   writecommand(0xBC); | ||||
|   writedata(0x40);     //contrast value
 | ||||
|   writedata(0x80);     //brightness value
 | ||||
|   writedata(0x40);     //saturation value
 | ||||
|   writedata(0x01);     //Post Processor Enable
 | ||||
| 
 | ||||
| 
 | ||||
|   delay(10); | ||||
| 
 | ||||
|   writecommand(0x29);   //display on
 | ||||
| 
 | ||||
|   writecommand(0xBE);   //set PWM for B/L
 | ||||
|   writedata(0x06); | ||||
|   writedata(0x80); | ||||
|   writedata(0x01); | ||||
|   writedata(0xF0); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
| 
 | ||||
|   writecommand(0xD0);  | ||||
|   writedata(0x0D);   | ||||
| 
 | ||||
| #endif | ||||
|  | @ -0,0 +1,29 @@ | |||
| 
 | ||||
| // This is the command sequence that rotates the SSD1963 driver coordinate frame
 | ||||
| 
 | ||||
|   rotation = m % 4; // Limit the range of values to 0-3
 | ||||
| 
 | ||||
|   writecommand(TFT_MADCTL); | ||||
|   switch (rotation) { | ||||
|     case 0: | ||||
|       writedata(0x21 | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 1: | ||||
|       writedata(0x00 | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|     case 2: | ||||
|       writedata(0x22 | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 3: | ||||
|       writedata(0x03 | TFT_MAD_COLOR_ORDER); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
| 
 | ||||
|   } | ||||
|  | @ -17,6 +17,7 @@ | |||
| #define INITR_GREENTAB128    0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1
 | ||||
| #define INITR_GREENTAB160x80 0x6 // Use if you only get part of 128x128 screen in rotation 0 & 1
 | ||||
| #define INITR_REDTAB160x80   0x7 // Added for https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html
 | ||||
| #define INITR_ROBOTLCD       0x8 | ||||
| #define INITB                0xB | ||||
| 
 | ||||
| 
 | ||||
|  | @ -44,6 +45,10 @@ | |||
|   #define TAB_COLOUR INITR_GREENTAB160x80 | ||||
|   #define CGRAM_OFFSET | ||||
| 
 | ||||
| #elif defined (ST7735_ROBOTLCD) | ||||
|   #define TAB_COLOUR INITR_ROBOTLCD | ||||
|   #define CGRAM_OFFSET | ||||
| 
 | ||||
| #elif defined (ST7735_REDTAB160x80) | ||||
|   #define TAB_COLOUR INITR_REDTAB160x80 | ||||
|   #define CGRAM_OFFSET | ||||
|  | @ -106,6 +111,20 @@ | |||
| #define TFT_MAD_MH  0x04 | ||||
| #define TFT_MAD_RGB 0x00 | ||||
| 
 | ||||
| #ifndef TFT_RGB_ORDER | ||||
|   #if defined(ST7735_BLACKTAB) || defined(ST7735_GREENTAB2) || defined(ST7735_INITB) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #else | ||||
|   #if (TFT_RGB_ORDER == 1) | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB | ||||
|   #else | ||||
|     #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #define TFT_INVOFF  0x20 | ||||
| #define TFT_INVON   0x21 | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ | |||
|       0x03,                   //     3 lines back porch
 | ||||
|       10,                     //     10 ms delay
 | ||||
|     ST7735_MADCTL , 1      ,  //  5: Memory access ctrl (directions), 1 arg:
 | ||||
|       0x40,                   //     Row addr/col addr, bottom to top refresh
 | ||||
|       0x40 | TFT_MAD_COLOR_ORDER, //     Row addr/col addr, bottom to top refresh
 | ||||
|     ST7735_DISSET5, 2      ,  //  6: Display settings #5, 2 args, no delay:
 | ||||
|       0x15,                   //     1 clk cycle nonoverlap, 2 cycle gate
 | ||||
|                               //     rise, 3 cycle osc equalize
 | ||||
|  | @ -101,7 +101,7 @@ | |||
|       0x0E, | ||||
|     ST7735_INVOFF , 0      ,  // 13: Don't invert display, no args, no delay
 | ||||
|     ST7735_MADCTL , 1      ,  // 14: Memory access control (directions), 1 arg:
 | ||||
|       0xC8,                   //     row addr/col addr, bottom to top refresh
 | ||||
|       0xC0 | TFT_MAD_COLOR_ORDER, //     row addr/col addr, bottom to top refresh
 | ||||
|     ST7735_COLMOD , 1      ,  // 15: set color mode, 1 arg, no delay:
 | ||||
|       0x05 },                 //     16-bit color
 | ||||
| 
 | ||||
|  | @ -123,6 +123,17 @@ | |||
|       0x00, 0x00,             //     XSTART = 0
 | ||||
|       0x00, 0x9F },           //     XEND = 159
 | ||||
| 
 | ||||
|   // Frame control init for RobotLCD, taken from https://github.com/arduino-libraries/TFT, Adafruit_ST7735.cpp l. 263, commit 61b8a7e
 | ||||
|   Rcmd3RobotLCD[] = { | ||||
|       3, | ||||
|       ST7735_FRMCTR1, 2    ,  //  1: Frame rate ctrl - normal mode, 2 args
 | ||||
|         0x0B, 0x14, | ||||
|       ST7735_FRMCTR2, 2    ,  //  2: Frame rate ctrl - idle mode, 2 args
 | ||||
|         0x0B, 0x14, | ||||
|       ST7735_FRMCTR3, 4    ,  //  3: Frame rate ctrl - partial mode, 4 args
 | ||||
|         0x0B, 0x14, | ||||
|         0x0B, 0x14 }, | ||||
| 
 | ||||
|   Rcmd3[] = {                 // Init for 7735R, part 3 (red or green tab)
 | ||||
|     4,                        //  4 commands in list:
 | ||||
|     ST7735_GMCTRP1, 16      , //  1: 16 args, no delay:
 | ||||
|  | @ -146,7 +157,8 @@ | |||
|      } | ||||
|      else  | ||||
|      { | ||||
| 	  commandList(Rcmd1); | ||||
| 	     commandList(Rcmd1); | ||||
| 
 | ||||
|        if (tabcolor == INITR_GREENTAB) | ||||
|        { | ||||
|          commandList(Rcmd2green); | ||||
|  | @ -157,7 +169,7 @@ | |||
|        { | ||||
|          commandList(Rcmd2green); | ||||
|          writecommand(ST7735_MADCTL); | ||||
|          writedata(0xC0); | ||||
|          writedata(0xC0 | TFT_MAD_COLOR_ORDER); | ||||
|          colstart = 2; | ||||
|          rowstart = 1; | ||||
|        } | ||||
|  | @ -180,6 +192,11 @@ | |||
|          colstart = 26; | ||||
|          rowstart = 1; | ||||
|        } | ||||
|        else if (tabcolor == INITR_ROBOTLCD) | ||||
|        { | ||||
|          commandList(Rcmd2green); | ||||
|          commandList(Rcmd3RobotLCD); | ||||
|        } | ||||
|        else if (tabcolor == INITR_REDTAB160x80) | ||||
|        { | ||||
|          commandList(Rcmd2green); | ||||
|  | @ -193,8 +210,9 @@ | |||
|        else if (tabcolor == INITR_BLACKTAB) | ||||
|        { | ||||
|          writecommand(ST7735_MADCTL); | ||||
|          writedata(0xC0); | ||||
|          writedata(0xC0 | TFT_MAD_COLOR_ORDER); | ||||
|        } | ||||
| 
 | ||||
|        commandList(Rcmd3); | ||||
|      } | ||||
| } | ||||
|  |  | |||
|  | @ -7,149 +7,126 @@ | |||
|   switch (rotation) { | ||||
|     case 0: | ||||
|      if (tabcolor == INITR_BLACKTAB) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|      } else if(tabcolor == INITR_GREENTAB2) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 2; | ||||
|        rowstart = 1; | ||||
|      } else if(tabcolor == INITR_GREENTAB3) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 2; | ||||
|        rowstart = 3; | ||||
|      } else if(tabcolor == INITR_GREENTAB128) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 0; | ||||
|        rowstart = 32; | ||||
|      } else if(tabcolor == INITR_GREENTAB160x80) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 26; | ||||
|        rowstart = 1; | ||||
|      } else if(tabcolor == INITR_REDTAB160x80) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 24; | ||||
|        rowstart = 0; | ||||
|      } else if(tabcolor == INITB) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER); | ||||
|      } else { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|      } | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 1: | ||||
|      if (tabcolor == INITR_BLACKTAB) { | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|      } else if(tabcolor == INITR_GREENTAB2) { | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 1; | ||||
|        rowstart = 2; | ||||
|      } else if(tabcolor == INITR_GREENTAB3) { | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 3; | ||||
|        rowstart = 2; | ||||
|      } else if(tabcolor == INITR_GREENTAB128) { | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 32; | ||||
|        rowstart = 0; | ||||
|      } else if(tabcolor == INITR_GREENTAB160x80) { | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 1; | ||||
|        rowstart = 26; | ||||
|      } else if(tabcolor == INITR_REDTAB160x80) { | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 0; | ||||
|        rowstart = 24; | ||||
|      } else if(tabcolor == INITB) { | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|      } else { | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|      } | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|     case 2: | ||||
|      if (tabcolor == INITR_BLACKTAB) { | ||||
|        writedata(TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_COLOR_ORDER); | ||||
|      } else if(tabcolor == INITR_GREENTAB2) { | ||||
|        writedata(TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 2; | ||||
|        rowstart = 1; | ||||
|      } else if(tabcolor == INITR_GREENTAB3) { | ||||
|        writedata(TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 2; | ||||
|        rowstart = 1; | ||||
|      } else if(tabcolor == INITR_GREENTAB128) { | ||||
|        writedata(TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 0; | ||||
|        rowstart = 0; | ||||
|      } else if(tabcolor == INITR_GREENTAB160x80) { | ||||
|        writedata(TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 26; | ||||
|        rowstart = 1; | ||||
|      } else if(tabcolor == INITR_REDTAB160x80) { | ||||
|        writedata(TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 24; | ||||
|        rowstart = 0; | ||||
|      } else if(tabcolor == INITB) { | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
|      } else { | ||||
|        writedata(TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_COLOR_ORDER); | ||||
|      } | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 3: | ||||
|      if (tabcolor == INITR_BLACKTAB) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|      } else if(tabcolor == INITR_GREENTAB2) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 1; | ||||
|        rowstart = 2; | ||||
|      } else if(tabcolor == INITR_GREENTAB3) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 1; | ||||
|        rowstart = 2; | ||||
|      } else if(tabcolor == INITR_GREENTAB128) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 0; | ||||
|        rowstart = 0; | ||||
|      } else if(tabcolor == INITR_GREENTAB160x80) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 1; | ||||
|        rowstart = 26; | ||||
|      } else if(tabcolor == INITR_REDTAB160x80) { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|        colstart = 0; | ||||
|        rowstart = 24; | ||||
|      } else if(tabcolor == INITB) { | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_RGB); | ||||
|        writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|      } else { | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); | ||||
|        writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
|      } | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
| 
 | ||||
|   // These next rotations are for bottum up BMP drawing
 | ||||
|   /*  case 4:
 | ||||
|       writedata(ST7735_TFT_MAD_MX | ST7735_TFT_MAD_MY | ST7735_TFT_MAD_BGR); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 5: | ||||
|       writedata(ST7735_TFT_MAD_MV | ST7735_TFT_MAD_MX | ST7735_TFT_MAD_BGR); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|     case 6: | ||||
|       writedata(ST7735_TFT_MAD_BGR); | ||||
|       _width  = _init_width; | ||||
|       _height = _init_height; | ||||
|       break; | ||||
|     case 7: | ||||
|       writedata(ST7735_TFT_MAD_MY | ST7735_TFT_MAD_MV | ST7735_TFT_MAD_BGR); | ||||
|       _width  = _init_height; | ||||
|       _height = _init_width; | ||||
|       break; | ||||
|   */ | ||||
|   } | ||||
|  |  | |||
|  | @ -8,7 +8,42 @@ | |||
| #endif | ||||
| 
 | ||||
| #if (TFT_HEIGHT == 240) && (TFT_WIDTH == 240) | ||||
|   #define CGRAM_OFFSET | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Adafruit 1.44 TFT support
 | ||||
| #if (TFT_HEIGHT == 240) && (TFT_WIDTH == 135) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Adafruit 1.69 round corner TFT support
 | ||||
| #if (TFT_HEIGHT == 280) && (TFT_WIDTH == 240) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // 1.47" 172x320 Round Rectangle Color IPS TFT Display
 | ||||
| #if (TFT_HEIGHT == 320) && (TFT_WIDTH == 172) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if (TFT_HEIGHT == 320) && (TFT_WIDTH == 170) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if (TFT_HEIGHT == 300) && (TFT_WIDTH == 240) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
|  |  | |||
|  | @ -5,8 +5,31 @@ | |||
|   switch (rotation) { | ||||
|     case 0: // Portrait
 | ||||
| #ifdef CGRAM_OFFSET | ||||
|       colstart = 0; | ||||
|       rowstart = 0; | ||||
|       if (_init_width == 135) | ||||
|       { | ||||
|         colstart = 52; | ||||
|         rowstart = 40; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 20; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 34; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 35; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 0; | ||||
|       } | ||||
| #endif | ||||
|       writedata(TFT_MAD_COLOR_ORDER); | ||||
| 
 | ||||
|  | @ -16,8 +39,31 @@ | |||
| 
 | ||||
|     case 1: // Landscape (Portrait + 90)
 | ||||
| #ifdef CGRAM_OFFSET | ||||
|       colstart = 0; | ||||
|       rowstart = 0; | ||||
|       if (_init_width == 135) | ||||
|       { | ||||
|         colstart = 40; | ||||
|         rowstart = 53; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 20; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 34; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 35; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 0; | ||||
|       } | ||||
| #endif | ||||
|       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); | ||||
| 
 | ||||
|  | @ -25,10 +71,33 @@ | |||
|       _height = _init_width; | ||||
|       break; | ||||
| 
 | ||||
|     case 2: // Inverter portrait
 | ||||
|       case 2: // Inverter portrait
 | ||||
| #ifdef CGRAM_OFFSET | ||||
|        colstart = 0; | ||||
|        rowstart = 80; | ||||
|       if (_init_width == 135) | ||||
|       { | ||||
|         colstart = 53; | ||||
|         rowstart = 40; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 20; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 34; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 35; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 80; | ||||
|       } | ||||
| #endif | ||||
|       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
| 
 | ||||
|  | @ -37,8 +106,31 @@ | |||
|        break; | ||||
|     case 3: // Inverted landscape
 | ||||
| #ifdef CGRAM_OFFSET | ||||
|       colstart = 80; | ||||
|       rowstart = 0; | ||||
|       if (_init_width == 135) | ||||
|       { | ||||
|         colstart = 40; | ||||
|         rowstart = 52; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 20; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 34; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 35; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 80; | ||||
|         rowstart = 0; | ||||
|       } | ||||
| #endif | ||||
|       writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,7 +8,42 @@ | |||
| #endif | ||||
| 
 | ||||
| #if (TFT_HEIGHT == 240) && (TFT_WIDTH == 240) | ||||
|   #define CGRAM_OFFSET | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Adafruit 1.44 TFT support
 | ||||
| #if (TFT_HEIGHT == 240) && (TFT_WIDTH == 135) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Adafruit 1.69 round corner TFT support
 | ||||
| #if (TFT_HEIGHT == 280) && (TFT_WIDTH == 240) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // 1.47" 172x320 Round Rectangle Color IPS TFT Display
 | ||||
| #if (TFT_HEIGHT == 320) && (TFT_WIDTH == 172) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if (TFT_HEIGHT == 320) && (TFT_WIDTH == 170) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if (TFT_HEIGHT == 300) && (TFT_WIDTH == 240) | ||||
|   #ifndef CGRAM_OFFSET | ||||
|     #define CGRAM_OFFSET | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Delay between some initialisation commands
 | ||||
|  | @ -95,6 +130,7 @@ | |||
| #define ST7789_TEOFF		0x34      // Tearing effect line off
 | ||||
| #define ST7789_TEON			0x35      // Tearing effect line on
 | ||||
| #define ST7789_MADCTL		0x36      // Memory data access control
 | ||||
| #define ST7789_VSCRSADD		0x37      // Vertical screoll address
 | ||||
| #define ST7789_IDMOFF		0x38      // Idle mode off
 | ||||
| #define ST7789_IDMON		0x39      // Idle mode on
 | ||||
| #define ST7789_RAMWRC		0x3C      // Memory write continue (ST7789V)
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| //
 | ||||
| // See ST7735_Setup.h file for an alternative format
 | ||||
| 
 | ||||
| #ifndef INIT_SEQUENCE_3 | ||||
| { | ||||
|   writecommand(ST7789_SLPOUT);   // Sleep out
 | ||||
|   delay(120); | ||||
|  | @ -21,6 +22,10 @@ | |||
|   writedata(0x0A); | ||||
|   writedata(0x82); | ||||
| 
 | ||||
|   writecommand(ST7789_RAMCTRL); | ||||
|   writedata(0x00); | ||||
|   writedata(0xE0); // 5 to 6 bit conversion: r0 = r5, b0 = b5
 | ||||
| 
 | ||||
|   writecommand(ST7789_COLMOD); | ||||
|   writedata(0x55); | ||||
|   delay(10); | ||||
|  | @ -99,7 +104,7 @@ | |||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
|   writedata(0x00); | ||||
|   writedata(0xE5);    // 239
 | ||||
|   writedata(0xEF);    // 239
 | ||||
| 
 | ||||
|   writecommand(ST7789_RASET);    // Row address set
 | ||||
|   writedata(0x00); | ||||
|  | @ -122,3 +127,111 @@ | |||
|   pinMode(TFT_BL, OUTPUT); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #else | ||||
| // TTGO ESP32 S3 T-Display
 | ||||
| { | ||||
|   writecommand(ST7789_SLPOUT);   // Sleep out
 | ||||
|   delay(120); | ||||
| 
 | ||||
|   writecommand(ST7789_NORON);    // Normal display mode on
 | ||||
| 
 | ||||
|   //------------------------------display and color format setting--------------------------------//
 | ||||
|   writecommand(ST7789_MADCTL); | ||||
|   writedata(TFT_MAD_COLOR_ORDER); | ||||
| 
 | ||||
|  // writecommand(ST7789_RAMCTRL);
 | ||||
|  // writedata(0x00);
 | ||||
|  // writedata(0xE0); // 5 to 6 bit conversion: r0 = r5, b0 = b5
 | ||||
| 
 | ||||
|   writecommand(ST7789_COLMOD); | ||||
|   writedata(0x55); | ||||
|   delay(10); | ||||
| 
 | ||||
|   //--------------------------------ST7789V Frame rate setting----------------------------------//
 | ||||
|   writecommand(ST7789_PORCTRL); | ||||
|   writedata(0x0b); | ||||
|   writedata(0x0b); | ||||
|   writedata(0x00); | ||||
|   writedata(0x33); | ||||
|   writedata(0x33); | ||||
| 
 | ||||
|   writecommand(ST7789_GCTRL);      // Voltages: VGH / VGL
 | ||||
|   writedata(0x75); | ||||
| 
 | ||||
|   //---------------------------------ST7789V Power setting--------------------------------------//
 | ||||
|   writecommand(ST7789_VCOMS); | ||||
|   writedata(0x28);		// JLX240 display datasheet
 | ||||
| 
 | ||||
|   writecommand(ST7789_LCMCTRL); | ||||
|   writedata(0x2C); | ||||
| 
 | ||||
|   writecommand(ST7789_VDVVRHEN); | ||||
|   writedata(0x01); | ||||
| 
 | ||||
|   writecommand(ST7789_VRHS);       // voltage VRHS
 | ||||
|   writedata(0x1F); | ||||
| 
 | ||||
|   writecommand(ST7789_FRCTR2); | ||||
|   writedata(0x13); | ||||
| 
 | ||||
|   writecommand(ST7789_PWCTRL1); | ||||
|   writedata(0xa7); | ||||
| 
 | ||||
|   writecommand(ST7789_PWCTRL1); | ||||
|   writedata(0xa4); | ||||
|   writedata(0xa1); | ||||
| 
 | ||||
|   writecommand(0xD6); | ||||
|   writedata(0xa1); | ||||
| 
 | ||||
|   //--------------------------------ST7789V gamma setting---------------------------------------//
 | ||||
|   writecommand(ST7789_PVGAMCTRL); | ||||
|   writedata(0xf0); | ||||
|   writedata(0x05); | ||||
|   writedata(0x0a); | ||||
|   writedata(0x06); | ||||
|   writedata(0x06); | ||||
|   writedata(0x03); | ||||
|   writedata(0x2b); | ||||
|   writedata(0x32); | ||||
|   writedata(0x43); | ||||
|   writedata(0x36); | ||||
|   writedata(0x11); | ||||
|   writedata(0x10); | ||||
|   writedata(0x2b); | ||||
|   writedata(0x32); | ||||
| 
 | ||||
|   writecommand(ST7789_NVGAMCTRL); | ||||
|   writedata(0xf0); | ||||
|   writedata(0x08); | ||||
|   writedata(0x0c); | ||||
|   writedata(0x0b); | ||||
|   writedata(0x09); | ||||
|   writedata(0x24); | ||||
|   writedata(0x2b); | ||||
|   writedata(0x22); | ||||
|   writedata(0x43); | ||||
|   writedata(0x38); | ||||
|   writedata(0x15); | ||||
|   writedata(0x16); | ||||
|   writedata(0x2f); | ||||
|   writedata(0x37); | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
|   end_tft_write(); | ||||
|   delay(120); | ||||
|   begin_tft_write(); | ||||
| 
 | ||||
|   writecommand(ST7789_DISPON);    //Display on
 | ||||
|   delay(120); | ||||
| 
 | ||||
| #ifdef TFT_BL | ||||
|   // Turn on the back-light LED
 | ||||
|   digitalWrite(TFT_BL, HIGH); | ||||
|   pinMode(TFT_BL, OUTPUT); | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
|  | @ -10,6 +10,21 @@ | |||
|         colstart = 52; | ||||
|         rowstart = 40; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 20; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 34; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 35; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 0; | ||||
|  | @ -29,6 +44,21 @@ | |||
|         colstart = 40; | ||||
|         rowstart = 53; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 20; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 34; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 35; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 0; | ||||
|  | @ -48,6 +78,21 @@ | |||
|         colstart = 53; | ||||
|         rowstart = 40; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 20; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 34; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 35; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 0; | ||||
|  | @ -66,6 +111,21 @@ | |||
|         colstart = 40; | ||||
|         rowstart = 52; | ||||
|       } | ||||
|       else if(_init_height == 280) | ||||
|       { | ||||
|         colstart = 20; | ||||
|         rowstart = 0; | ||||
|       } | ||||
|       else if(_init_width == 172) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 34; | ||||
|       } | ||||
|       else if(_init_width == 170) | ||||
|       { | ||||
|         colstart = 0; | ||||
|         rowstart = 35; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         colstart = 80; | ||||
|  |  | |||
|  | @ -25,21 +25,18 @@ | |||
| 	writedata(0x48);    //X-Mirror, Top-Left to right-Buttom, RGB  
 | ||||
| 	 | ||||
| 	writecommand(0x3A); //Interface Pixel Format                                    
 | ||||
| 	writedata(0x05);    //Control interface color format set to 16
 | ||||
| 	writedata(0x55);    //Control interface color format set to 16
 | ||||
| 	 | ||||
| 	 | ||||
| 	writecommand(0xB4); //Column inversion 
 | ||||
| 	writedata(0x01);    //1-dot inversion
 | ||||
| 
 | ||||
| 	writecommand(0xB6); //Display Function Control
 | ||||
| 	writedata(0x20);    //RGB interface for RAM access, RGB transfer in DE mode  
 | ||||
| 						          //display data path in memory
 | ||||
| 						          //Gate outputs in non-display area in Normal scan 
 | ||||
| 						          //Source output in non-display area =V63
 | ||||
| 
 | ||||
| 	writedata(0x80);    //Bypass
 | ||||
| 	writedata(0x02);    //Source Output Scan from S1 to S960, Gate Output scan from G1 to G480, scan cycle=2
 | ||||
| 	writedata(0x3B);    //LCD Drive Line=8*(59+1)
 | ||||
| 
 | ||||
| 
 | ||||
| 	writecommand(0xE8); //Display Output Ctrl Adjust
 | ||||
| 	writedata(0x40); | ||||
| 	writedata(0x8A);	 | ||||
|  |  | |||
|  | @ -0,0 +1,308 @@ | |||
| 
 | ||||
| ///////////////////////////////////////////////////////////
 | ||||
| /*           Support file for ESP32 IDF use              */ | ||||
| /*              See library docs folder                  */ | ||||
| /*                                                       */ | ||||
| /*              DO NOT EDIT THIS FILE                    */ | ||||
| /*                                                       */ | ||||
| ///////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @file   TFT_config.h | ||||
|  * @author Ricard Bitriá Ribes (https://github.com/dracir9)
 | ||||
|  * Created Date: 22-01-2022 | ||||
|  * ----- | ||||
|  * Last Modified: 14-04-2022 | ||||
|  * Modified By: Ricard Bitriá Ribes | ||||
|  * ----- | ||||
|  * @copyright (c) 2022 Ricard Bitriá Ribes | ||||
|  */ | ||||
| 
 | ||||
| #ifndef TFT_CONFIG_H | ||||
| #define TFT_CONFIG_H | ||||
| 
 | ||||
| #include "sdkconfig.h" | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         TFT_eSPI Configuration defines | ||||
| ***************************************************************************************/ | ||||
| // Override defaults
 | ||||
| #define USER_SETUP_LOADED | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 1: Load TFT driver | ||||
| ***************************************************************************************/ | ||||
| #if defined (CONFIG_TFT_ILI9341_DRIVER) | ||||
|     #define ILI9341_DRIVER | ||||
| #elif defined (CONFIG_TFT_ILI9341_2_DRIVER) | ||||
|     #define ILI9341_2_DRIVER | ||||
| #elif defined (CONFIG_TFT_ST7735_DRIVER) | ||||
|     #define ST7735_DRIVER | ||||
| #elif defined (CONFIG_TFT_ILI9163_DRIVER) | ||||
|     #define ILI9163_DRIVER | ||||
| #elif defined (CONFIG_TFT_S6D02A1_DRIVER) | ||||
|     #define S6D02A1_DRIVER | ||||
| #elif defined (CONFIG_TFT_HX8357D_DRIVER) | ||||
|     #define HX8357D_DRIVER | ||||
| #elif defined (CONFIG_TFT_ILI9481_DRIVER) | ||||
|     #define ILI9481_DRIVER | ||||
| #elif defined (CONFIG_TFT_ILI9486_DRIVER) | ||||
|     #define ILI9486_DRIVER | ||||
| #elif defined (CONFIG_TFT_ILI9488_DRIVER) | ||||
|     #define ILI9488_DRIVER | ||||
| #elif defined (CONFIG_TFT_ST7789_DRIVER) | ||||
|     #define ST7789_DRIVER | ||||
| #elif defined (CONFIG_TFT_ST7789_2_DRIVER) | ||||
|     #define ST7789_2_DRIVER | ||||
| #elif defined (CONFIG_TFT_R61581_DRIVER) | ||||
|     #define R61581_DRIVER | ||||
| #elif defined (CONFIG_TFT_RM68140_DRIVER) | ||||
|     #define RM68140_DRIVER | ||||
| #elif defined (CONFIG_TFT_ST7796_DRIVER) | ||||
|     #define ST7796_DRIVER | ||||
| #elif defined (CONFIG_TFT_SSD1351_DRIVER) | ||||
|     #define SSD1351_DRIVER | ||||
| #elif defined (CONFIG_TFT_SSD1963_480_DRIVER) | ||||
|     #define SSD1963_480_DRIVER | ||||
| #elif defined (CONFIG_TFT_SSD1963_800_DRIVER) | ||||
|     #define SSD1963_800_DRIVER | ||||
| #elif defined (CONFIG_TFT_SSD1963_800ALT_DRIVER) | ||||
|     #define SSD1963_800ALT_DRIVER | ||||
| #elif defined (CONFIG_TFT_ILI9225_DRIVER) | ||||
|     #define ILI9225_DRIVER | ||||
| #elif defined (CONFIG_TFT_GC9A01_DRIVER) | ||||
|     #define GC9A01_DRIVER | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_RGB_ORDER | ||||
|     #define TFT_RGB_ORDER TFT_RGB | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_BGR_ORDER | ||||
|     #define TFT_RGB_ORDER TFT_BGR | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_M5STACK | ||||
|     #define M5STACK | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_WIDTH | ||||
|     #define TFT_WIDTH   CONFIG_TFT_WIDTH | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_HEIGHT | ||||
|     #define TFT_HEIGHT   CONFIG_TFT_HEIGHT | ||||
| #endif | ||||
| 
 | ||||
| #if defined (CONFIG_TFT_ST7735_INITB) | ||||
|     #define ST7735_INITB | ||||
| #elif defined (CONFIG_TFT_ST7735_GREENTAB) | ||||
|     #define ST7735_GREENTAB | ||||
| #elif defined (CONFIG_TFT_ST7735_GREENTAB2) | ||||
|     #define ST7735_GREENTAB2 | ||||
| #elif defined (CONFIG_TFT_ST7735_GREENTAB3) | ||||
|     #define ST7735_GREENTAB3 | ||||
| #elif defined (CONFIG_TFT_ST7735_GREENTAB128) | ||||
|     #define ST7735_GREENTAB128 | ||||
| #elif defined (CONFIG_TFT_ST7735_GREENTAB160x80) | ||||
|     #define ST7735_GREENTAB160x80 | ||||
| #elif defined (CONFIG_TFT_ST7735_REDTAB) | ||||
|     #define ST7735_REDTAB | ||||
| #elif defined (CONFIG_TFT_ST7735_BLACKTAB) | ||||
|     #define ST7735_BLACKTAB | ||||
| #elif defined (CONFIG_TFT_ST7735_REDTAB160x80) | ||||
|     #define ST7735_REDTAB160x80 | ||||
| #endif | ||||
| 
 | ||||
| #if defined (CONFIG_TFT_INVERSION_ON) | ||||
|     #define TFT_INVERSION_ON | ||||
| #elif defined (CONFIG_TFT_INVERSION_OFF) | ||||
|     #define TFT_INVERSION_OFF | ||||
| #endif | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 2: General Pin configuration | ||||
| ***************************************************************************************/ | ||||
| // General pins
 | ||||
| #if CONFIG_TFT_CS == -1 | ||||
|     #error "Invalid Chip Select pin. Check TFT_eSPI configuration" | ||||
| #else | ||||
|     #define TFT_CS          CONFIG_TFT_CS | ||||
| #endif | ||||
| 
 | ||||
| #if CONFIG_TFT_DC == -1 | ||||
|     #error "Invalid Data/Command pin. Check TFT_eSPI configuration" | ||||
| #else | ||||
|     #define TFT_DC          CONFIG_TFT_DC | ||||
| #endif | ||||
| 
 | ||||
| #if CONFIG_TFT_RST == -1 | ||||
|     #error "Invalid Reset pin. Check TFT_eSPI configuration" | ||||
| #else | ||||
|     #define TFT_RST         CONFIG_TFT_RST | ||||
| #endif | ||||
| 
 | ||||
| // Backlight config
 | ||||
| #ifdef CONFIG_ENABLE_BL | ||||
|     #if CONFIG_TFT_BL == -1 | ||||
|         #error "Invalid backlight control pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_BL      CONFIG_TFT_BL | ||||
|     #endif | ||||
| 
 | ||||
|     #define TFT_BACKLIGHT_ON CONFIG_TFT_BACKLIGHT_ON | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 3: Data bus Pin configuration | ||||
| ***************************************************************************************/ | ||||
| 
 | ||||
| // 8 BIT PARALLEL BUS
 | ||||
| #ifdef CONFIG_TFT_PARALLEL_8_BIT | ||||
| 
 | ||||
|     #if CONFIG_TFT_D0 == -1 | ||||
|         #error "Invalid Data 0 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D0      CONFIG_TFT_D0 | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_D1 == -1 | ||||
|         #error "Invalid Data 1 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D1      CONFIG_TFT_D1 | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_D2 == -1 | ||||
|         #error "Invalid Data 2 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D2      CONFIG_TFT_D2 | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_D3 == -1 | ||||
|         #error "Invalid Data 3 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D3      CONFIG_TFT_D3 | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_D4 == -1 | ||||
|         #error "Invalid Data 4 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D4      CONFIG_TFT_D4 | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_D5 == -1 | ||||
|         #error "Invalid Data 5 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D5      CONFIG_TFT_D5 | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_D6 == -1 | ||||
|         #error "Invalid Data 6 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D6      CONFIG_TFT_D6 | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_D7 == -1 | ||||
|         #error "Invalid Data 7 pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_D7      CONFIG_TFT_D7 | ||||
|     #endif | ||||
|      | ||||
|     #if CONFIG_TFT_WR == -1 | ||||
|         #error "Invalid Write strobe pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_WR      CONFIG_TFT_WR | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_RD == -1 | ||||
|         #error "Invalid Read strobe pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_RD      CONFIG_TFT_RD | ||||
|     #endif | ||||
| 
 | ||||
| // SPI BUS
 | ||||
| #else | ||||
|     #if CONFIG_TFT_HSPI_PORT | ||||
|         #define USE_HSPI_PORT | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_MISO != -1 | ||||
|         #define TFT_MISO      CONFIG_TFT_MISO | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_MOSI == -1 | ||||
|         #error "Invalid MOSI pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_MOSI      CONFIG_TFT_MOSI | ||||
|     #endif | ||||
| 
 | ||||
|     #if CONFIG_TFT_SCLK == -1 | ||||
|         #error "Invalid Clock pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TFT_SCLK      CONFIG_TFT_SCLK | ||||
|     #endif | ||||
| 
 | ||||
|     #define SPI_FREQUENCY   CONFIG_TFT_SPI_FREQUENCY | ||||
| 
 | ||||
|     #if CONFIG_TFT_SPI_READ_FREQ != -1 | ||||
|         #define SPI_READ_FREQUENCY CONFIG_TFT_SPI_READ_FREQ | ||||
|     #endif | ||||
|      | ||||
|     #ifdef CONFIG_TFT_SDA_READ | ||||
|         #define TFT_SDA_READ | ||||
|     #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 4: Setup Fonts | ||||
| ***************************************************************************************/ | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_LOAD_GLCD | ||||
|     #define LOAD_GLCD       // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_LOAD_FONT2 | ||||
|     #define LOAD_FONT2      // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_LOAD_FONT4 | ||||
|     #define LOAD_FONT4      // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_LOAD_FONT6 | ||||
|     #define LOAD_FONT6      // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_LOAD_FONT7 | ||||
|     #define LOAD_FONT7      // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_LOAD_FONT8 | ||||
|     #define LOAD_FONT8      // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TFT_LOAD_GFXFF | ||||
|     #define LOAD_GFXFF      // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| #endif | ||||
| 
 | ||||
| #if CONFIG_TFT_SMOOTH_FONT | ||||
|     #define SMOOTH_FONT | ||||
| #endif | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 5: Touchscreen configuration | ||||
| ***************************************************************************************/ | ||||
| 
 | ||||
| #ifdef CONFIG_ENABLE_TOUCH | ||||
|     #if CONFIG_TOUCH_CS == -1 | ||||
|         #error "Invalid Touch Chip Select pin. Check TFT_eSPI configuration" | ||||
|     #else | ||||
|         #define TOUCH_CS            CONFIG_TOUCH_CS | ||||
|     #endif | ||||
| 
 | ||||
|     #define SPI_TOUCH_FREQUENCY CONFIG_SPI_TOUCH_FREQUENCY | ||||
| #endif | ||||
| 
 | ||||
| #endif // TFT_CONFIG_H
 | ||||
							
								
								
									
										3183
									
								
								TFT_eSPI.cpp
								
								
								
								
							
							
						
						
									
										3183
									
								
								TFT_eSPI.cpp
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										352
									
								
								TFT_eSPI.h
								
								
								
								
							
							
						
						
									
										352
									
								
								TFT_eSPI.h
								
								
								
								
							|  | @ -2,21 +2,25 @@ | |||
|   Arduino TFT graphics library targeted at ESP8266 | ||||
|   and ESP32 based boards. | ||||
| 
 | ||||
|   This is a standalone library that contains the | ||||
|   This is a stand-alone library that contains the | ||||
|   hardware driver, the graphics functions and the | ||||
|   proportional fonts. | ||||
| 
 | ||||
|   The built-in fonts 4, 6, 7 and 8 are Run Length | ||||
|   Encoded (RLE) to reduce the FLASH footprint. | ||||
| 
 | ||||
|   Last review/edit by Bodmer: 26/01/20 | ||||
|   Last review/edit by Bodmer: 04/02/22 | ||||
|  ****************************************************/ | ||||
| 
 | ||||
| // Stop fonts etc being loaded multiple times
 | ||||
| #ifndef _TFT_eSPIH_ | ||||
| #define _TFT_eSPIH_ | ||||
| 
 | ||||
| #define TFT_ESPI_VERSION "2.1.9" | ||||
| #define TFT_ESPI_VERSION "2.5.21" | ||||
| 
 | ||||
| // Bit level feature flags
 | ||||
| // Bit 0 set: viewport capability
 | ||||
| #define TFT_ESPI_FEATURES 1 | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 1: Load required header files | ||||
|  | @ -32,24 +36,74 @@ | |||
| ***************************************************************************************/ | ||||
| // Include header file that defines the fonts loaded, the TFT drivers
 | ||||
| // available and the pins to be used, etc, etc
 | ||||
| #ifdef CONFIG_TFT_eSPI_ESPIDF | ||||
|   #include "TFT_config.h" | ||||
| #endif | ||||
| 
 | ||||
| // New ESP8266 board package uses ARDUINO_ARCH_ESP8266
 | ||||
| // old package defined ESP8266
 | ||||
| #if defined (ESP8266) | ||||
|   #ifndef ARDUINO_ARCH_ESP8266 | ||||
|     #define ARDUINO_ARCH_ESP8266 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // The following lines allow the user setup to be included in the sketch folder, see
 | ||||
| // "Sketch_with_tft_setup" generic example.
 | ||||
| #if !defined __has_include | ||||
|   #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) | ||||
|     #warning Compiler does not support __has_include, so sketches cannot define the setup | ||||
|   #endif | ||||
| #else | ||||
|   #if __has_include(<tft_setup.h>) | ||||
|     // Include the sketch setup file
 | ||||
|     #include <tft_setup.h> | ||||
|     #ifndef USER_SETUP_LOADED | ||||
|       // Prevent loading further setups
 | ||||
|       #define USER_SETUP_LOADED | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #include <User_Setup_Select.h> | ||||
| 
 | ||||
| // Handle FLASH based storage e.g. PROGMEM
 | ||||
| #ifdef __AVR__ | ||||
| #if defined(ARDUINO_ARCH_RP2040) | ||||
|   #undef pgm_read_byte | ||||
|   #define pgm_read_byte(addr)   (*(const unsigned char *)(addr)) | ||||
|   #undef pgm_read_word | ||||
|   #define pgm_read_word(addr) ({ \ | ||||
|     typeof(addr) _addr = (addr); \ | ||||
|     *(const unsigned short *)(_addr); \ | ||||
|   }) | ||||
|   #undef pgm_read_dword | ||||
|   #define pgm_read_dword(addr) ({ \ | ||||
|     typeof(addr) _addr = (addr); \ | ||||
|     *(const unsigned long *)(_addr); \ | ||||
|   }) | ||||
| #elif defined(__AVR__) | ||||
|   #include <avr/pgmspace.h> | ||||
| #elif defined(ESP8266) || defined(ESP32) | ||||
| #elif defined(ARDUINO_ARCH_ESP8266) || defined(ESP32) | ||||
|   #include <pgmspace.h> | ||||
| #else | ||||
|   #define PROGMEM | ||||
|   #ifndef PROGMEM | ||||
|     #define PROGMEM | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Include the processor specific drivers
 | ||||
| #if defined (ESP32) | ||||
| #if defined(CONFIG_IDF_TARGET_ESP32S3) | ||||
|   #include "Processors/TFT_eSPI_ESP32_S3.h" | ||||
| #elif defined(CONFIG_IDF_TARGET_ESP32C3) | ||||
|   #include "Processors/TFT_eSPI_ESP32_C3.h" | ||||
| #elif defined (ESP32) | ||||
|   #include "Processors/TFT_eSPI_ESP32.h" | ||||
| #elif defined (ESP8266) | ||||
| #elif defined (ARDUINO_ARCH_ESP8266) | ||||
|   #include "Processors/TFT_eSPI_ESP8266.h" | ||||
| #elif defined (STM32) | ||||
|   #include "Processors/TFT_eSPI_STM32.h" | ||||
| #elif defined(ARDUINO_ARCH_RP2040) | ||||
|   #include "Processors/TFT_eSPI_RP2040.h" | ||||
| #else | ||||
|   #include "Processors/TFT_eSPI_Generic.h" | ||||
| #endif | ||||
|  | @ -72,10 +126,12 @@ | |||
| #endif | ||||
| 
 | ||||
| // Some ST7789 boards do not work with Mode 0
 | ||||
| #if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) | ||||
|   #define TFT_SPI_MODE SPI_MODE3 | ||||
| #else | ||||
|   #define TFT_SPI_MODE SPI_MODE0 | ||||
| #ifndef TFT_SPI_MODE | ||||
|   #if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) | ||||
|     #define TFT_SPI_MODE SPI_MODE3 | ||||
|   #else | ||||
|     #define TFT_SPI_MODE SPI_MODE0 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // If the XPT2046 SPI frequency is not defined, set a default
 | ||||
|  | @ -83,6 +139,21 @@ | |||
|   #define SPI_TOUCH_FREQUENCY  2500000 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef SPI_BUSY_CHECK | ||||
|   #define SPI_BUSY_CHECK | ||||
| #endif | ||||
| 
 | ||||
| // If half duplex SDA mode is defined then MISO pin should be -1
 | ||||
| #ifdef TFT_SDA_READ | ||||
|   #ifdef TFT_MISO | ||||
|     #if TFT_MISO != -1 | ||||
|       #undef TFT_MISO | ||||
|       #define TFT_MISO -1 | ||||
|       #warning TFT_MISO set to -1 | ||||
|     #endif | ||||
|   #endif | ||||
| #endif   | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 4: Setup fonts | ||||
| ***************************************************************************************/ | ||||
|  | @ -247,7 +318,7 @@ const PROGMEM fontinfo fontdata [] = { | |||
| #define TFT_WHITE       0xFFFF      /* 255, 255, 255 */ | ||||
| #define TFT_ORANGE      0xFDA0      /* 255, 180,   0 */ | ||||
| #define TFT_GREENYELLOW 0xB7E0      /* 180, 255,   0 */ | ||||
| #define TFT_PINK        0xFE19      /* 255, 192, 203 */ //Lighter pink, was 0xFC9F      
 | ||||
| #define TFT_PINK        0xFE19      /* 255, 192, 203 */ //Lighter pink, was 0xFC9F
 | ||||
| #define TFT_BROWN       0x9A60      /* 150,  75,   0 */ | ||||
| #define TFT_GOLD        0xFEA0      /* 255, 215,   0 */ | ||||
| #define TFT_SILVER      0xC618      /* 192, 192, 192 */ | ||||
|  | @ -290,18 +361,14 @@ static const uint16_t default_4bit_palette[] PROGMEM = { | |||
| typedef struct | ||||
| { | ||||
| String  version = TFT_ESPI_VERSION; | ||||
| String  setup_info;  // Setup reference name available to use in a user setup
 | ||||
| uint32_t setup_id;   // ID available to use in a user setup
 | ||||
| int32_t esp;         // Processor code
 | ||||
| uint8_t trans;       // SPI transaction supoort
 | ||||
| uint8_t trans;       // SPI transaction support
 | ||||
| uint8_t serial;      // Serial (SPI) or parallel
 | ||||
| uint8_t  port;       // SPI port
 | ||||
| uint8_t overlap;     // ESP8266 overlap mode
 | ||||
| 
 | ||||
| #if defined (ESP32)  // TODO: make generic for other processors
 | ||||
|   #if defined (USE_HSPI_PORT) | ||||
|     uint8_t  port = HSPI; | ||||
|   #else | ||||
|     uint8_t  port = VSPI; | ||||
|   #endif | ||||
| #endif | ||||
| uint8_t interface;   // Interface type
 | ||||
| 
 | ||||
| uint16_t tft_driver; // Hexadecimal code
 | ||||
| uint16_t tft_width;  // Rotation 0 width and height
 | ||||
|  | @ -335,6 +402,9 @@ int8_t pin_tft_d5; | |||
| int8_t pin_tft_d6; | ||||
| int8_t pin_tft_d7; | ||||
| 
 | ||||
| int8_t pin_tft_led; | ||||
| int8_t pin_tft_led_on; | ||||
| 
 | ||||
| int8_t pin_tch_cs;   // Touch chip select pin
 | ||||
| 
 | ||||
| int16_t tft_spi_freq;// TFT write SPI frequency
 | ||||
|  | @ -345,15 +415,12 @@ int16_t tch_spi_freq;// Touch controller read/write SPI frequency | |||
| /***************************************************************************************
 | ||||
| **                         Section 8: Class member and support functions | ||||
| ***************************************************************************************/ | ||||
| // Swap any type
 | ||||
| template <typename T> static inline void | ||||
| swap_coord(T& a, T& b) { T t = a; a = b; b = t; } | ||||
| 
 | ||||
| // Callback prototype for smooth font pixel colour read
 | ||||
| typedef uint16_t (*getColorCallback)(uint16_t x, uint16_t y); | ||||
| 
 | ||||
| // Class functions and variables
 | ||||
| class TFT_eSPI : public Print { | ||||
| class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has access to protected members
 | ||||
| 
 | ||||
|  //--------------------------------------- public ------------------------------------//
 | ||||
|  public: | ||||
|  | @ -377,19 +444,51 @@ class TFT_eSPI : public Print { | |||
|                    height(void), | ||||
|                    width(void); | ||||
| 
 | ||||
|                    // Read the colour of a pixel at x,y and return value in 565 format
 | ||||
|   virtual uint16_t readPixel(int32_t x, int32_t y); | ||||
| 
 | ||||
|   virtual void     setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye);   // Note: start + end coordinates
 | ||||
| 
 | ||||
|                    // Push (aka write pixel) colours to the set window
 | ||||
|   virtual void     pushColor(uint16_t color); | ||||
| 
 | ||||
|                    // These are non-inlined to enable override
 | ||||
|   virtual void     begin_nin_write(); | ||||
|   virtual void     end_nin_write(); | ||||
| 
 | ||||
|   void     setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3
 | ||||
|   uint8_t  getRotation(void);      // Read the current rotation
 | ||||
| 
 | ||||
|   // Change the origin position from the default top left
 | ||||
|   // Note: setRotation, setViewport and resetViewport will revert origin to top left corner of screen/sprite
 | ||||
|   void     setOrigin(int32_t x, int32_t y); | ||||
|   int32_t  getOriginX(void); | ||||
|   int32_t  getOriginY(void); | ||||
| 
 | ||||
|   void     invertDisplay(bool i);  // Tell TFT to invert all displayed colours
 | ||||
| 
 | ||||
| 
 | ||||
|   // The TFT_eSprite class inherits the following functions (not all are useful to Sprite class
 | ||||
|   void     setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h), // Note: start coordinates + width and height
 | ||||
|            setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye);   // Note: start + end coordinates
 | ||||
|   void     setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); // Note: start coordinates + width and height
 | ||||
| 
 | ||||
|   // Push (aka write pixel) colours to the TFT (use setAddrWindow() first)
 | ||||
|   void     pushColor(uint16_t color), | ||||
|            pushColor(uint16_t color, uint32_t len),  // Deprecated, use pushBlock()
 | ||||
|   // Viewport commands, see "Viewport_Demo" sketch
 | ||||
|   void     setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true); | ||||
|   bool     checkViewport(int32_t x, int32_t y, int32_t w, int32_t h); | ||||
|   int32_t  getViewportX(void); | ||||
|   int32_t  getViewportY(void); | ||||
|   int32_t  getViewportWidth(void); | ||||
|   int32_t  getViewportHeight(void); | ||||
|   bool     getViewportDatum(void); | ||||
|   void     frameViewport(uint16_t color, int32_t w); | ||||
|   void     resetViewport(void); | ||||
| 
 | ||||
|            // Clip input window to viewport bounds, return false if whole area is out of bounds
 | ||||
|   bool     clipAddrWindow(int32_t* x, int32_t* y, int32_t* w, int32_t* h); | ||||
|            // Clip input window area to viewport bounds, return false if whole area is out of bounds
 | ||||
|   bool     clipWindow(int32_t* xs, int32_t* ys, int32_t* xe, int32_t* ye); | ||||
| 
 | ||||
|            // Push (aka write pixel) colours to the TFT (use setAddrWindow() first)
 | ||||
|   void     pushColor(uint16_t color, uint32_t len),  // Deprecated, use pushBlock()
 | ||||
|            pushColors(uint16_t  *data, uint32_t len, bool swap = true), // With byte swap option
 | ||||
|            pushColors(uint8_t  *data, uint32_t len); // Deprecated, use pushPixels()
 | ||||
| 
 | ||||
|  | @ -399,9 +498,6 @@ class TFT_eSPI : public Print { | |||
|            // Write a set of pixels stored in memory, use setSwapBytes(true/false) function to correct endianess
 | ||||
|   void     pushPixels(const void * data_in, uint32_t len); | ||||
| 
 | ||||
|            // Read the colour of a pixel at x,y and return value in 565 format 
 | ||||
|   uint16_t readPixel(int32_t x, int32_t y); | ||||
| 
 | ||||
|            // Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input
 | ||||
|            #ifdef TFT_SDA_READ | ||||
|              #if defined (TFT_eSPI_ENABLE_8_BIT_READ) | ||||
|  | @ -411,12 +507,15 @@ class TFT_eSPI : public Print { | |||
|   void     end_SDA_Read(void);   // Restore MOSI to output
 | ||||
|            #endif | ||||
| 
 | ||||
| 
 | ||||
|   // Graphics drawing
 | ||||
|   void     fillScreen(uint32_t color), | ||||
|            drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), | ||||
|            drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color), | ||||
|            fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color); | ||||
| 
 | ||||
|   void     fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); | ||||
|   void     fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); | ||||
| 
 | ||||
|   void     drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color), | ||||
|            drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color), | ||||
|  | @ -430,6 +529,53 @@ class TFT_eSPI : public Print { | |||
|            drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color), | ||||
|            fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color); | ||||
| 
 | ||||
| 
 | ||||
|   // Smooth (anti-aliased) graphics drawing
 | ||||
|            // Draw a pixel blended with the background pixel colour (bg_color) specified,  return blended colour
 | ||||
|            // If the bg_color is not specified, the background pixel colour will be read from TFT or sprite
 | ||||
|   uint16_t drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color = 0x00FFFFFF); | ||||
| 
 | ||||
|            // Draw an anti-aliased (smooth) arc between start and end angles. Arc ends are anti-aliased.
 | ||||
|            // By default the arc is drawn with square ends unless the "roundEnds" parameter is included and set true
 | ||||
|            // Angle = 0 is at 6 o'clock position, 90 at 9 o'clock etc. The angles must be in range 0-360 or they will be clipped to these limits
 | ||||
|            // The start angle may be larger than the end angle. Arcs are always drawn clockwise from the start angle.
 | ||||
|   void     drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds = false); | ||||
| 
 | ||||
|            // As per "drawSmoothArc" except the ends of the arc are NOT anti-aliased, this facilitates dynamic arc length changes with
 | ||||
|            // arc segments and ensures clean segment joints. 
 | ||||
|            // The sides of the arc are anti-aliased by default. If smoothArc is false sides will NOT be anti-aliased
 | ||||
|   void     drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smoothArc = true); | ||||
| 
 | ||||
|            // Draw an anti-aliased filled circle at x, y with radius r
 | ||||
|            // Note: The thickness of line is 3 pixels to reduce the visible "braiding" effect of anti-aliasing narrow lines
 | ||||
|            //       this means the inner anti-alias zone is always at r-1 and the outer zone at r+1
 | ||||
|   void     drawSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t fg_color, uint32_t bg_color); | ||||
|    | ||||
|            // Draw an anti-aliased filled circle at x, y with radius r
 | ||||
|            // If bg_color is not included the background pixel colour will be read from TFT or sprite
 | ||||
|   void     fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF); | ||||
| 
 | ||||
|            // Draw a rounded rectangle that has a line thickness of r-ir+1 and bounding box defined by x,y and w,h
 | ||||
|            // The outer corner radius is r, inner corner radius is ir
 | ||||
|            // The inside and outside of the border are anti-aliased
 | ||||
|   void     drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t w, int32_t h, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF, uint8_t quadrants = 0xF); | ||||
| 
 | ||||
|            // Draw a filled rounded rectangle , corner radius r and bounding box defined by x,y and w,h
 | ||||
|   void     fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF); | ||||
| 
 | ||||
|            // Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine)
 | ||||
|            // If bg_color is not included the background pixel colour will be read from TFT or sprite
 | ||||
|   void     drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); | ||||
| 
 | ||||
|            // Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2)
 | ||||
|            // If bg_color is not included the background pixel colour will be read from TFT or sprite
 | ||||
|   void     drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); | ||||
| 
 | ||||
|            // Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends
 | ||||
|            // If bg_color is not included the background pixel colour will be read from TFT or sprite
 | ||||
|   void     drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); | ||||
| 
 | ||||
| 
 | ||||
|   // Image rendering
 | ||||
|            // Swap the byte order for pushImage() and pushPixels() - corrects endianness
 | ||||
|   void     setSwapBytes(bool swap); | ||||
|  | @ -450,7 +596,7 @@ class TFT_eSPI : public Print { | |||
|            // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location
 | ||||
|            // Read a block of pixels to a data buffer, buffer is 16 bit and the size must be at least w * h
 | ||||
|   void     readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); | ||||
|            // Write a block of pixels to the screen - this is a deprecated alternative to pushImage()
 | ||||
|            // Write a block of pixels to the screen which have been read by readRect()
 | ||||
|   void     pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); | ||||
| 
 | ||||
|            // These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp Sprites)
 | ||||
|  | @ -466,16 +612,22 @@ class TFT_eSPI : public Print { | |||
|            // Set bpp8 true for 8bpp sprites, false otherwise. The cmap pointer must be specified for 4bpp
 | ||||
|   void     pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t  *data, bool bpp8 = true, uint16_t *cmap = nullptr); | ||||
|   void     pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t  *data, uint8_t  transparent, bool bpp8 = true, uint16_t *cmap = nullptr); | ||||
|            // FLASH version
 | ||||
|   void     pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8,  uint16_t *cmap = nullptr); | ||||
| 
 | ||||
|            // Render a 16 bit colour image with a 1bpp mask
 | ||||
|   void     pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask); | ||||
| 
 | ||||
|            // This next function has been used successfully to dump the TFT screen to a PC for documentation purposes
 | ||||
|            // It reads a screen area and returns the 3 RGB 8 bit colour values of each pixel in the buffer
 | ||||
|            // Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes
 | ||||
|   void     readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data); | ||||
| 
 | ||||
| 
 | ||||
|   // Text rendering - value returned is the pixel width of the rendered text
 | ||||
|   int16_t  drawNumber(long intNumber, int32_t x, int32_t y, uint8_t font), // Draw integer using specified font number
 | ||||
|            drawNumber(long intNumber, int32_t x, int32_t y),               // Draw integer using current font
 | ||||
|             | ||||
| 
 | ||||
|            // Decimal is the number of decimal places to render
 | ||||
|            // Use with setTextDatum() to position values on TFT, and setTextPadding() to blank old displayed values
 | ||||
|            drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y, uint8_t font), // Draw float using specified font number
 | ||||
|  | @ -483,9 +635,9 @@ class TFT_eSPI : public Print { | |||
| 
 | ||||
|            // Handle char arrays
 | ||||
|            // Use with setTextDatum() to position string on TFT, and setTextPadding() to blank old displayed strings
 | ||||
|            drawString(const char *string, int32_t x, int32_t y, uint8_t font),  // Draw string using specifed font number
 | ||||
|            drawString(const char *string, int32_t x, int32_t y, uint8_t font),  // Draw string using specified font number
 | ||||
|            drawString(const char *string, int32_t x, int32_t y),                // Draw string using current font
 | ||||
|            drawString(const String& string, int32_t x, int32_t y, uint8_t font),// Draw string using specifed font number
 | ||||
|            drawString(const String& string, int32_t x, int32_t y, uint8_t font),// Draw string using specified font number
 | ||||
|            drawString(const String& string, int32_t x, int32_t y),              // Draw string using current font
 | ||||
| 
 | ||||
|            drawCentreString(const char *string, int32_t x, int32_t y, uint8_t font),  // Deprecated, use setTextDatum() and drawString()
 | ||||
|  | @ -493,20 +645,21 @@ class TFT_eSPI : public Print { | |||
|            drawCentreString(const String& string, int32_t x, int32_t y, uint8_t font),// Deprecated, use setTextDatum() and drawString()
 | ||||
|            drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString()
 | ||||
| 
 | ||||
| 
 | ||||
|   // Text rendering and font handling support funtions
 | ||||
|   void     setCursor(int16_t x, int16_t y),                 // Set cursor for tft.print()
 | ||||
|            setCursor(int16_t x, int16_t y, uint8_t font);   // Set cursor and font number for tft.print()
 | ||||
| 
 | ||||
|   int16_t  getCursorX(void),                                // Read current cursor x position (moves with tft.print())
 | ||||
|            getCursorY(void);                                // Read current cursor y position
 | ||||
|             | ||||
| 
 | ||||
|   void     setTextColor(uint16_t color),                    // Set character (glyph) color only (background not over-written)
 | ||||
|            setTextColor(uint16_t fgcolor, uint16_t bgcolor),// Set character (glyph) foreground and backgorund colour
 | ||||
|            setTextColor(uint16_t fgcolor, uint16_t bgcolor, bool bgfill = false),  // Set character (glyph) foreground and background colour, optional background fill for smooth fonts
 | ||||
|            setTextSize(uint8_t size);                       // Set character size multiplier (this increases pixel size)
 | ||||
| 
 | ||||
|   void     setTextWrap(bool wrapX, bool wrapY = false);     // Turn on/off wrapping of text in TFT width and/or height
 | ||||
| 
 | ||||
|   void     setTextDatum(uint8_t datum);                     // Set text datum position (default is top left), see Section 6 above 
 | ||||
|   void     setTextDatum(uint8_t datum);                     // Set text datum position (default is top left), see Section 6 above
 | ||||
|   uint8_t  getTextDatum(void); | ||||
| 
 | ||||
|   void     setTextPadding(uint16_t x_width);                // Set text padding (background blanking/over-write) width in pixels
 | ||||
|  | @ -533,17 +686,23 @@ class TFT_eSPI : public Print { | |||
| 
 | ||||
|            // Support function to UTF8 decode and draw characters piped through print stream
 | ||||
|   size_t   write(uint8_t); | ||||
|    | ||||
|            // size_t   write(const uint8_t *buf, size_t len);
 | ||||
| 
 | ||||
|            // Used by Smooth font class to fetch a pixel colour for the anti-aliasing
 | ||||
|   void     setCallback(getColorCallback getCol); | ||||
| 
 | ||||
|   uint16_t fontsLoaded(void); // Each bit in returned value represents a font type that is loaded - used for debug/error handling only
 | ||||
| 
 | ||||
| 
 | ||||
|   // Low level read/write
 | ||||
|   void     spiwrite(uint8_t);        // legacy support only
 | ||||
| 
 | ||||
|   void     writecommand(uint8_t c),  // Send a command, function resets DC/RS high ready for data
 | ||||
|            writedata(uint8_t d);     // Send data with DC/RS set high
 | ||||
| #ifndef RM68120_DRIVER | ||||
|   void     writecommand(uint8_t c);  // Send a command, function resets DC/RS high ready for data
 | ||||
| #else | ||||
|   void     writecommand(uint16_t c); // Send a command, function resets DC/RS high ready for data
 | ||||
|   void     writeRegister(uint16_t c, uint8_t d); // Write data to 16 bit command register
 | ||||
| #endif | ||||
|   void     writedata(uint8_t d);     // Send data with DC/RS set high
 | ||||
| 
 | ||||
|   void     commandList(const uint8_t *addr); // Send a initialisation sequence to TFT stored in FLASH
 | ||||
| 
 | ||||
|  | @ -568,14 +727,15 @@ class TFT_eSPI : public Print { | |||
|            // Alpha blend 2 colours, see generic "alphaBlend_Test" example
 | ||||
|            // alpha =   0 = 100% background colour
 | ||||
|            // alpha = 255 = 100% foreground colour
 | ||||
|   uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); | ||||
|   inline uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); | ||||
|            // 16 bit colour alphaBlend with alpha dither (dither reduces colour banding)
 | ||||
|   uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither); | ||||
|            // 24 bit colour alphaBlend with optional alpha dither
 | ||||
|   uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0); | ||||
| 
 | ||||
| 
 | ||||
|   // DMA support functions - these are currently just for SPI writes whe using the STM32 processors
 | ||||
|   // Direct Memory Access (DMA) support functions
 | ||||
|   // These can be used for SPI writes when using the ESP32 (original) or STM32 processors.
 | ||||
|   // DMA also works on a RP2040 processor with PIO based SPI and parallel (8 and 16 bit) interfaces
 | ||||
|            // Bear in mind DMA will only be of benefit in particular circumstances and can be tricky
 | ||||
|            // to manage by noobs. The functions have however been designed to be noob friendly and
 | ||||
|            // avoid a few DMA behaviour "gotchas".
 | ||||
|  | @ -590,7 +750,7 @@ class TFT_eSPI : public Print { | |||
|            // processor leaves a function or its content being changed while the DMA engine is reading it.
 | ||||
|            //
 | ||||
|            // The compiler MAY change the implied scope of a buffer which has been set aside by creating
 | ||||
|            // and an array. For example a buffer defined before a "for-next" loop may get de-allocated when
 | ||||
|            // an array. For example a buffer defined before a "for-next" loop may get de-allocated when
 | ||||
|            // the loop ends. To avoid this use, for example, malloc() and free() to take control of when
 | ||||
|            // the buffer space is available and ensure it is not released until DMA is complete.
 | ||||
|            //
 | ||||
|  | @ -600,25 +760,37 @@ class TFT_eSPI : public Print { | |||
|            // function will wait for the DMA to complete, so this may defeat any DMA performance benefit.
 | ||||
|            //
 | ||||
| 
 | ||||
|   bool     initDMA(void);     // Initialise the DMA engine and attach to SPI bus - typically used in setup()
 | ||||
|   bool     initDMA(bool ctrl_cs = false);  // Initialise the DMA engine and attach to SPI bus - typically used in setup()
 | ||||
|                                            // Parameter "true" enables DMA engine control of TFT chip select (ESP32 only)
 | ||||
|                                            // For ESP32 only, TFT reads will not work if parameter is true
 | ||||
|   void     deInitDMA(void);   // De-initialise the DMA engine and detach from SPI bus - typically not used
 | ||||
|    | ||||
| 
 | ||||
|            // Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image
 | ||||
|            // Use the buffer if the image data will get over-written or destroyed while DMA is in progress
 | ||||
|            // If swapping colour bytes is defined, and the double buffer option is NOT used then the bytes
 | ||||
|            // in the original data image will be swapped by the function before DMA is initiated.
 | ||||
|            //
 | ||||
|            // Note 1: If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes
 | ||||
|            // in the original image buffer content will be byte swapped by the function before DMA is initiated.
 | ||||
|            //
 | ||||
|            // Note 2: If part of the image will be off screen or outside of a set viewport, then the the original
 | ||||
|            // image buffer content will be altered to a correctly clipped image before DMA is initiated.
 | ||||
|            //
 | ||||
|            // The function will wait for the last DMA to complete if it is called while a previous DMA is still
 | ||||
|            // in progress, this simplifies the sketch and helps avoid "gotchas".
 | ||||
|   void     pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr); | ||||
| 
 | ||||
| #if defined (ESP32) // ESP32 only at the moment
 | ||||
|            // For case where pointer is a const and the image data must not be modified (clipped or byte swapped)
 | ||||
|   void     pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* data); | ||||
| #endif | ||||
|            // Push a block of pixels into a window set up using setAddrWindow()
 | ||||
|   void     pushPixelsDMA(uint16_t* image, uint32_t len); | ||||
| 
 | ||||
|            // Check if the DMA is complete - use while(tft.dmaBusy); for a blocking wait
 | ||||
|   bool     dmaBusy(void); | ||||
| 
 | ||||
|   bool     DMA_Enabled = false; // Flag for DMA enabled state
 | ||||
|   bool     dmaBusy(void); // returns true if DMA is still in progress
 | ||||
|   void     dmaWait(void); // wait until DMA is complete
 | ||||
| 
 | ||||
|   bool     DMA_Enabled = false;   // Flag for DMA enabled state
 | ||||
|   uint8_t  spiBusyCheck = 0;      // Number of ESP32 transfer buffers to check
 | ||||
| 
 | ||||
|   // Bare metal functions
 | ||||
|   void     startWrite(void);                         // Begin SPI transaction
 | ||||
|  | @ -627,7 +799,7 @@ class TFT_eSPI : public Print { | |||
| 
 | ||||
|   // Set/get an arbitrary library configuration attribute or option
 | ||||
|   //       Use to switch ON/OFF capabilities such as UTF8 decoding - each attribute has a unique ID
 | ||||
|   //       id = 0: reserved - may be used in fuuture to reset all attributes to a default state
 | ||||
|   //       id = 0: reserved - may be used in future to reset all attributes to a default state
 | ||||
|   //       id = 1: Turn on (a=true) or off (a=false) GLCD cp437 font character error correction
 | ||||
|   //       id = 2: Turn on (a=true) or off (a=false) UTF8 decoding
 | ||||
|   //       id = 3: Enable or disable use of ESP32 PSRAM (if available)
 | ||||
|  | @ -639,11 +811,11 @@ class TFT_eSPI : public Print { | |||
| 
 | ||||
|            // Used for diagnostic sketch to see library setup adopted by compiler, see Section 7 above
 | ||||
|   void     getSetup(setup_t& tft_settings); // Sketch provides the instance to populate
 | ||||
|   bool     verifySetupID(uint32_t id); | ||||
| 
 | ||||
|   // Global variables
 | ||||
|   static   SPIClass& getSPIinstance(void); // Get SPI class handle
 | ||||
| 
 | ||||
|   int32_t  cursor_x, cursor_y, padX;       // Text cursor x,y and padding setting
 | ||||
|   uint32_t textcolor, textbgcolor;         // Text foreground and background colours
 | ||||
| 
 | ||||
|   uint32_t bitmap_fg, bitmap_bg;           // Bitmap foreground (bit=1) and background (bit=0) colours
 | ||||
|  | @ -653,9 +825,6 @@ class TFT_eSPI : public Print { | |||
|            textdatum, // Text reference datum
 | ||||
|            rotation;  // Display rotation (0-3)
 | ||||
| 
 | ||||
|   int16_t  _xpivot;   // TFT x pivot point coordinate for rotated Sprites
 | ||||
|   int16_t  _ypivot;   // TFT x pivot point coordinate for rotated Sprites
 | ||||
| 
 | ||||
|   uint8_t  decoderState = 0;   // UTF8 decoder state        - not for user access
 | ||||
|   uint16_t decoderBuffer;      // Unicode code-point buffer - not for user access
 | ||||
| 
 | ||||
|  | @ -671,13 +840,16 @@ class TFT_eSPI : public Print { | |||
|            // New begin and end prototypes
 | ||||
|            // begin/end a TFT write transaction
 | ||||
|            // For SPI bus the transmit clock rate is set
 | ||||
|   inline void begin_tft_write()      __attribute__((always_inline)); | ||||
|   inline void end_tft_write()        __attribute__((always_inline)); | ||||
|   inline void begin_tft_write() __attribute__((always_inline)); | ||||
|   inline void end_tft_write()   __attribute__((always_inline)); | ||||
| 
 | ||||
|            // begin/end a TFT read transaction
 | ||||
|            // For SPI bus: begin lowers SPI clock rate, end reinstates transmit clock rate
 | ||||
|   inline void begin_tft_read() __attribute__((always_inline)); | ||||
|   inline void end_tft_read()   __attribute__((always_inline)); | ||||
|   inline void begin_tft_read()  __attribute__((always_inline)); | ||||
|   inline void end_tft_read()    __attribute__((always_inline)); | ||||
| 
 | ||||
|            // Initialise the data bus GPIO and hardware interfaces
 | ||||
|   void     initBus(void); | ||||
| 
 | ||||
|            // Temporary  library development function  TODO: remove need for this
 | ||||
|   void     pushSwapBytePixels(const void* data_in, uint32_t len); | ||||
|  | @ -694,6 +866,12 @@ class TFT_eSPI : public Print { | |||
|            // Single GPIO input/output direction control
 | ||||
|   void     gpioMode(uint8_t gpio, uint8_t mode); | ||||
| 
 | ||||
|            // Smooth graphics helper
 | ||||
|   uint8_t  sqrt_fraction(uint32_t num); | ||||
| 
 | ||||
|            // Helper function: calculate distance of a point from a finite length line between two points
 | ||||
|   float    wedgeLineDistance(float pax, float pay, float bax, float bay, float dr); | ||||
| 
 | ||||
|            // Display variant settings
 | ||||
|   uint8_t  tabcolor,                   // ST7735 screen protector "tab" colour (now invalid)
 | ||||
|            colstart = 0, rowstart = 0; // Screen display area to CGRAM area coordinate offsets
 | ||||
|  | @ -715,6 +893,8 @@ class TFT_eSPI : public Print { | |||
| 
 | ||||
|   getColorCallback getColor = nullptr; // Smooth font callback function pointer
 | ||||
| 
 | ||||
|   bool     locked, inTransaction, lockTransaction; // SPI transaction and mutex lock flags
 | ||||
| 
 | ||||
|  //-------------------------------------- protected ----------------------------------//
 | ||||
|  protected: | ||||
| 
 | ||||
|  | @ -724,6 +904,22 @@ class TFT_eSPI : public Print { | |||
|   int32_t  _width, _height;           // Display w/h as modified by current rotation
 | ||||
|   int32_t  addr_row, addr_col;        // Window position - used to minimise window commands
 | ||||
| 
 | ||||
|   int16_t  _xPivot;   // TFT x pivot point coordinate for rotated Sprites
 | ||||
|   int16_t  _yPivot;   // TFT x pivot point coordinate for rotated Sprites
 | ||||
| 
 | ||||
|   // Viewport variables
 | ||||
|   int32_t  _vpX, _vpY, _vpW, _vpH;    // Note: x start, y start, x end + 1, y end + 1
 | ||||
|   int32_t  _xDatum; | ||||
|   int32_t  _yDatum; | ||||
|   int32_t  _xWidth; | ||||
|   int32_t  _yHeight; | ||||
|   bool     _vpDatum; | ||||
|   bool     _vpOoB; | ||||
| 
 | ||||
|   int32_t  cursor_x, cursor_y, padX;       // Text cursor x,y and padding setting
 | ||||
|   int32_t  bg_cursor_x;                    // Background fill cursor
 | ||||
|   int32_t  last_cursor_x;                  // Previous text cursor position when fill used
 | ||||
| 
 | ||||
|   uint32_t fontsloaded;               // Bit field of fonts loaded
 | ||||
| 
 | ||||
|   uint8_t  glyph_ab,   // Smooth font glyph delta Y (height) above baseline
 | ||||
|  | @ -732,10 +928,9 @@ class TFT_eSPI : public Print { | |||
|   bool     isDigits;   // adjust bounding box for numbers to reduce visual jiggling
 | ||||
|   bool     textwrapX, textwrapY;  // If set, 'wrap' text at right and optionally bottom edge of display
 | ||||
|   bool     _swapBytes; // Swap the byte order for TFT pushImage()
 | ||||
|   bool     locked, inTransaction; // SPI transaction and mutex lock flags
 | ||||
| 
 | ||||
|   bool     _booted;    // init() or begin() has already run once
 | ||||
|    | ||||
| 
 | ||||
|                        // User sketch manages these via set/getAttribute()
 | ||||
|   bool     _cp437;        // If set, use correct CP437 charset (default is ON)
 | ||||
|   bool     _utf8;         // If set, use UTF-8 decoder in print stream 'write()' function (default ON)
 | ||||
|  | @ -743,6 +938,13 @@ class TFT_eSPI : public Print { | |||
| 
 | ||||
|   uint32_t _lastColor; // Buffered value of last colour used
 | ||||
| 
 | ||||
|   bool     _fillbg;    // Fill background flag (just for for smooth fonts at the moment)
 | ||||
| 
 | ||||
| #if defined (SSD1963_DRIVER) | ||||
|   uint16_t Cswap;      // Swap buffer for SSD1963
 | ||||
|   uint8_t r6, g6, b6;  // RGB buffer for SSD1963
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef LOAD_GFXFF | ||||
|   GFXfont  *gfxFont; | ||||
| #endif | ||||
|  | @ -752,7 +954,17 @@ class TFT_eSPI : public Print { | |||
| ***************************************************************************************/ | ||||
| // Load the Touch extension
 | ||||
| #ifdef TOUCH_CS | ||||
|   #include "Extensions/Touch.h"        // Loaded if TOUCH_CS is defined by user | ||||
|   #if defined (TFT_PARALLEL_8_BIT) || defined (RP2040_PIO_INTERFACE) | ||||
|     #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) | ||||
|       #error >>>>------>> Touch functions not supported in 8/16 bit parallel mode or with RP2040 PIO. | ||||
|     #endif | ||||
|   #else | ||||
|     #include "Extensions/Touch.h"        // Loaded if TOUCH_CS is defined by user | ||||
|   #endif | ||||
| #else | ||||
|     #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) | ||||
|       #warning >>>>------>> TOUCH_CS pin not defined, TFT_eSPI touch functions will not be available! | ||||
|     #endif | ||||
| #endif | ||||
| 
 | ||||
| // Load the Anti-aliased font extension
 | ||||
|  | @ -762,6 +974,10 @@ class TFT_eSPI : public Print { | |||
| 
 | ||||
| }; // End of class TFT_eSPI
 | ||||
| 
 | ||||
| // Swap any type
 | ||||
| template <typename T> static inline void | ||||
| transpose(T& a, T& b) { T t = a; a = b; b = t; } | ||||
| 
 | ||||
| /***************************************************************************************
 | ||||
| **                         Section 10: Additional extension classes | ||||
| ***************************************************************************************/ | ||||
|  |  | |||
|  | @ -147,7 +147,7 @@ int displayFontSize = 28; | |||
| static final int[] unicodeBlocks = { | ||||
|   // The list below has been created from the table here: https://en.wikipedia.org/wiki/Unicode_block | ||||
|   // Remove // at start of lines below to include that unicode block, different code ranges can also be specified by | ||||
|   // editting the start and end-of-range values. Multiple lines from the list below can be included, limited only by | ||||
|   // editing the start and end-of-range values. Multiple lines from the list below can be included, limited only by | ||||
|   // the final font file size! | ||||
| 
 | ||||
|   // Block range,   //Block name, Code points, Assigned characters, Scripts | ||||
|  |  | |||
|  | @ -1,33 +0,0 @@ | |||
| PlatformIO User notes: | ||||
| 
 | ||||
| It is possible to load settings from the calling program rather than modifying | ||||
| the library for each project by modifying the "platformio.ini" file. | ||||
| 
 | ||||
| The User_Setup_Select.h file will not load the user setting header files if | ||||
| USER_SETUP_LOADED is defined. | ||||
| 
 | ||||
| Instead of using #define, use the -D prefix, for example: | ||||
| 
 | ||||
| [env:esp32dev] | ||||
| platform = https://github.com/platformio/platform-espressif32.git#feature/stage | ||||
| board = esp32dev | ||||
| framework = arduino | ||||
| upload_port = ESP32-Test-2481CE9C.local | ||||
| 
 | ||||
| build_flags = | ||||
|   -Os | ||||
|   -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG | ||||
|   -DUSER_SETUP_LOADED=1 | ||||
|   -DILI9163_DRIVER=1 | ||||
|   -DTFT_WIDTH=128 | ||||
|   -DTFT_HEIGHT=160 | ||||
|   -DTFT_MISO=19 | ||||
|   -DTFT_MOSI=23 | ||||
|   -DTFT_SCLK=18 | ||||
|   -DTFT_CS=5 | ||||
|   -DTFT_DC=19 | ||||
|   -DTFT_RST=-1 | ||||
|   -DLOAD_GLCD=1 | ||||
|   -DSPI_FREQUENCY=27000000 | ||||
| 
 | ||||
| lib_extra_dirs = B:\Projects\ESP32\ESP32Lib | ||||
|  | @ -0,0 +1,26 @@ | |||
| ## bmp2array4bit | ||||
| 
 | ||||
| bmp2array4bit.py reads a bmp file, and creates C (or C++) code that contains two arrays for adding images to four-bit sprites.  See [Sprite_image_4bit](../../examples/Sprite/Sprite_image_4bit) for an example. | ||||
| 
 | ||||
| It is loosely based on Spark Fun's bmp2array script, https://github.com/sparkfun/BMPtoArray/blob/master/bmp2array.py.  The bmp file format is documented in https://en.wikipedia.org/wiki/BMP_file_format. | ||||
| 
 | ||||
| You'll need python 3.6 (the original uses Python 2.7) | ||||
| 
 | ||||
| `usage: python bmp2array4bit.py [-v] star.bmp [-o myfile.c]` | ||||
| 
 | ||||
| Create the bmp file in Gimp (www.gimp.org) from any image as follows: | ||||
| 
 | ||||
| * Remove the alpha channel (if it has one) | ||||
|         Layer -> Transparency -> Remove Alpha Channel | ||||
| * Set the mode to indexed. | ||||
|         Image -> Mode -> Indexed... | ||||
| * Select Generate optimum palette with 16 colors (max) | ||||
| * Export the file with a .bmp extension. Do **NOT** select options: | ||||
|   * Run-Length Encoded | ||||
|   * Compatibility Options: "Do not write color space information"  | ||||
|   * There are no Advanced Options available with these settings | ||||
| 
 | ||||
| (There are other tools that will produce bmp files, and these should work provided you don't use run-length encoding or other advanced features). | ||||
| 
 | ||||
| The first array produced is the palette for the image. | ||||
| The second is the image itself. | ||||
|  | @ -0,0 +1,251 @@ | |||
| ''' | ||||
| 
 | ||||
|     This script takes in a bitmap and outputs a text file that is a | ||||
|     byte array used in Arduino files. | ||||
| 
 | ||||
|     It is loosely based on Spark Fun's bmp2array script. | ||||
| 
 | ||||
|     You'll need python 3.6 (the original use Python 2.7) | ||||
| 
 | ||||
|     usage: python fourbitbmp2array.py [-v] star.bmp [-o myfile.c] | ||||
|      | ||||
|     Create the bmp file in Gimp by : | ||||
| 
 | ||||
|     . Remove the alpha channel (if it has one) Layer -> Transparency -> Remove Alpha Channel | ||||
|     . Set the mode to indexed.  Image -> Mode -> Indexed... | ||||
|     . Select Generate optimum palette with 16 colors (max) | ||||
|     . Export the file with a .bmp extension. Options are: | ||||
|         . Run-Length Encoded: not selected | ||||
|         . Compatibility Options: "Do not write color space information" not selected | ||||
|         . There are no Advanced Options available with these settings | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| import sys | ||||
| import struct | ||||
| import math | ||||
| import argparse | ||||
| import os | ||||
| 
 | ||||
| debug = None | ||||
| 
 | ||||
| def debugOut(s): | ||||
|     if debug: | ||||
|         print(s) | ||||
| 
 | ||||
| # look at arguments | ||||
| parser = argparse.ArgumentParser(description="Convert bmp file to C array") | ||||
| parser.add_argument("-v", "--verbose", help="debug output", action="store_true") | ||||
| parser.add_argument("input", help="input file name") | ||||
| parser.add_argument("-o", "--output", help="output file name") | ||||
| args = parser.parse_args() | ||||
| 
 | ||||
| if not os.path.exists(args.input): | ||||
|     parser.print_help() | ||||
|     print("The input file {} does not exist".format(args.input)) | ||||
|     sys.exit(1) | ||||
| 
 | ||||
| if args.output == None: | ||||
|     output = os.path.basename(args.input).replace(".bmp", ".c") | ||||
| else: | ||||
|     output = args.output | ||||
| 
 | ||||
| debug = args.verbose | ||||
| 
 | ||||
| try: | ||||
|     #Open our input file which is defined by the first commandline argument | ||||
|     #then dump it into a list of bytes | ||||
|     infile = open(args.input,"rb") #b is for binary | ||||
|     contents = bytearray(infile.read()) | ||||
|     infile.close() | ||||
| except: | ||||
|     print("could not read input file {}".format(args.input)) | ||||
|     sys.exit(1) | ||||
| 
 | ||||
| # first two bytes should be "BM" | ||||
| upto = 2 | ||||
| #Get the size of this image | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| fileSize = struct.unpack("I", bytearray(data)) | ||||
| 
 | ||||
| upto += 4 | ||||
| # four bytes are reserved | ||||
| 
 | ||||
| upto += 4 | ||||
| 
 | ||||
| debugOut("Size of file: {}".format(fileSize[0])) | ||||
| 
 | ||||
| #Get the header offset amount | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| offset = struct.unpack("I", bytearray(data)) | ||||
| 
 | ||||
| debugOut("Offset: {}".format(offset[0])) | ||||
| upto += 4 | ||||
| 
 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| headersize = struct.unpack("I", bytearray(data)) | ||||
| headerLength = headersize[0] | ||||
| startOfDefinitions = headerLength + upto | ||||
| debugOut("header size: {}, up to {}, startOfDefinitions {}".format(headersize[0], upto, startOfDefinitions)) | ||||
| upto += 4 | ||||
| 
 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("width: {}".format(t[0])) | ||||
| width = t[0] | ||||
| 
 | ||||
| upto += 4 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("height: {}".format(t[0])) | ||||
| height = t[0] | ||||
| 
 | ||||
| # 26 | ||||
| upto += 4 | ||||
| 
 | ||||
| data = struct.pack("BB", contents[upto], contents[upto+1]) | ||||
| t = struct.unpack("H", bytearray(data)) | ||||
| debugOut("planes: {}".format(t[0])) | ||||
| 
 | ||||
| upto = upto + 2 | ||||
| data = struct.pack("BB", contents[upto], contents[upto+1]) | ||||
| t = struct.unpack("H", bytearray(data)) | ||||
| debugOut("bits per pixel: {}".format(t[0])) | ||||
| bitsPerPixel = t[0] | ||||
| 
 | ||||
| upto = upto + 2 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("biCompression: {}".format(t[0])) | ||||
| 
 | ||||
| upto = upto + 4 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("biSizeImage: {}".format(t[0])) | ||||
| 
 | ||||
| upto = upto + 4 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("biXPelsPerMeter: {}".format(t[0])) | ||||
| 
 | ||||
| upto = upto + 4 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("biYPelsPerMeter: {}".format(t[0])) | ||||
| 
 | ||||
| upto = upto + 4 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("biClrUsed: {}".format(t[0])) | ||||
| colorsUsed = t | ||||
| 
 | ||||
| upto = upto + 4 | ||||
| data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
| t = struct.unpack("I", bytearray(data)) | ||||
| debugOut("biClrImportant: {}".format(t[0])) | ||||
| 
 | ||||
| upto += 4 | ||||
| 
 | ||||
| debugOut("Upto: {} Number of colors used: {} definitions start at: {}".format(upto, colorsUsed[0],  startOfDefinitions)) | ||||
| 
 | ||||
| #Create color definition array and init the array of color values | ||||
| colorIndex = [] #(colorsUsed[0]) | ||||
| for i in range(colorsUsed[0]): | ||||
|     colorIndex.append(0) | ||||
| 
 | ||||
| #Assign the colors to the array.  upto = 54 | ||||
| # startOfDefinitions = upto | ||||
| for i in range(colorsUsed[0]): | ||||
|     upto =  startOfDefinitions + (i * 4) | ||||
|     blue = contents[upto] | ||||
|     green = contents[upto + 1] | ||||
|     red = contents[upto + 2] | ||||
|     # ignore the alpha channel. | ||||
| 
 | ||||
|     # data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) | ||||
|     # t = struct.unpack("I", bytearray(data)) | ||||
|     # colorIndex[i] = t[0] | ||||
| 
 | ||||
|     colorIndex[i] = (((red & 0xf8)<<8) + ((green & 0xfc)<<3)+(blue>>3)) | ||||
|     debugOut("color at index {0} is {1:04x}, (r,g,b,a) = ({2:02x}, {3:02x}, {4:02x}, {5:02x})".format(i,  colorIndex[i], red, green, blue, contents[upto+3])) | ||||
| 
 | ||||
| #debugOut(the color definitions | ||||
| # for i in range(colorsUsed[0]):     | ||||
| #     print hex(colorIndex[i]) | ||||
| 
 | ||||
| # perfect, except upside down. | ||||
| 
 | ||||
| #Make a string to hold the output of our script | ||||
| arraySize = (len(contents) - offset[0])  | ||||
| outputString = "/* This was generated using a script based on the SparkFun BMPtoArray python script" + '\n' | ||||
| outputString += " See https://github.com/sparkfun/BMPtoArray for more info */" + '\n\n' | ||||
| outputString += "static const uint16_t palette[" + str(colorsUsed[0]) + "] = {"; | ||||
| for i in range(colorsUsed[0]):  | ||||
|     # print hexlify(colorIndex[i]) | ||||
|     if i % 4 == 0: | ||||
|         outputString += "\n\t" | ||||
|     outputString += "0x{:04x}, ".format(colorIndex[i]) | ||||
| 
 | ||||
| outputString = outputString[:-2] | ||||
| outputString += "\n};\n\n" | ||||
| outputString += "// width is " + str(width) + ", height is " + str(height) + "\n" | ||||
| outputString += "static const uint8_t myGraphic[" + str(arraySize) + "] PROGMEM = {" + '\n' | ||||
| 
 | ||||
| if bitsPerPixel != 4: | ||||
|     print("Expected 4 bits per pixel; found {}".format(bitsPerPixel)) | ||||
|     sys.exit(1) | ||||
|      | ||||
| #Start converting spots to values | ||||
| #Start at the offset and go to the end of the file | ||||
| dropLastNumber = True #(width % 4) == 2 or (width % 4) == 1 | ||||
| paddedWidth = int(math.ceil(bitsPerPixel * width / 32.0) * 4) | ||||
| debugOut("array range is {} {} len(contents) is {} paddedWidth is {} width is {}".format(offset[0], fileSize[0], len(contents), paddedWidth, width)) | ||||
| 
 | ||||
| r = 0 | ||||
| width = int(width / 2) | ||||
| #for i in range(offset[0], fileSize[0]):                 # close but image is upside down.  Each row is correct but need to swap columns. | ||||
| #for i in range(fileSize[0], offset[0], -1): | ||||
| 
 | ||||
| for col in range(height-1, -1, -1): | ||||
|     i = 0 | ||||
|     for row in range(width): | ||||
|         colorCode1 = contents[row + col*paddedWidth + offset[0]]   | ||||
| 
 | ||||
|         if r > 0 and r % width == 0: | ||||
|             i = 0 | ||||
|             outputString += '\n\n' | ||||
|         elif (i + 1) % 12 == 0 : | ||||
|             outputString += '\n' | ||||
|             i = 0 | ||||
|          | ||||
|         #debugOut("cell ({0}, {1})".format(row, col) | ||||
| 
 | ||||
|         r = r + 1 | ||||
|         i = i + 1 | ||||
|         outputString += "0x{:02x}, ".format(colorCode1) | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
| #Once we've reached the end of our input string, pull the last two | ||||
| #characters off (the last comma and space) since we don't need | ||||
| #them. Top it off with a closing bracket and a semicolon. | ||||
| outputString = outputString[:-2] | ||||
| outputString += "};" | ||||
| 
 | ||||
| try: | ||||
|     #Write the output string to our output file | ||||
|     outfile = open(output, "w") | ||||
|     outfile.write(outputString) | ||||
|     outfile.close() | ||||
| except: | ||||
|     print("could not write output to file {}".format(output)) | ||||
|     sys.exit(1) | ||||
| 
 | ||||
| debugOut("{} complete".format(output)) | ||||
| debugOut("Copy and paste this array into a image.h or other header file") | ||||
| 
 | ||||
| if not debug: | ||||
|     print("Completed; the output is in {}".format(output)) | ||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 13 KiB | 
							
								
								
									
										97
									
								
								User_Setup.h
								
								
								
								
							
							
						
						
									
										97
									
								
								User_Setup.h
								
								
								
								
							|  | @ -8,6 +8,11 @@ | |||
| //   run without the need to make any more changes for a particular hardware setup!
 | ||||
| //   Note that some sketches are designed for a particular TFT pixel width/height
 | ||||
| 
 | ||||
| // User defined information reported by "Read_User_Setup" test & diagnostics example
 | ||||
| #define USER_SETUP_INFO "User_Setup" | ||||
| 
 | ||||
| // Define to disable all #warnings in library (can be put in User_Setup_Select.h)
 | ||||
| //#define DISABLE_ALL_LIBRARY_WARNINGS
 | ||||
| 
 | ||||
| // ##################################################################################
 | ||||
| //
 | ||||
|  | @ -27,16 +32,18 @@ | |||
| // If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
 | ||||
| // then this will improve rendering performance by a factor of ~8x
 | ||||
| //#define STM_PORTA_DATA_BUS
 | ||||
| //#define STM_PORTA_DATA_BUS
 | ||||
| //#define STM_PORTB_DATA_BUS
 | ||||
| 
 | ||||
| // Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
 | ||||
| // Tell the library to use parallel mode (otherwise SPI is assumed)
 | ||||
| //#define TFT_PARALLEL_8_BIT
 | ||||
| //#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor ****
 | ||||
| 
 | ||||
| // Display type -  only define if RPi display
 | ||||
| //#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
 | ||||
| 
 | ||||
| // Only define one driver, the other ones must be commented out
 | ||||
| #define ILI9341_DRIVER | ||||
| #define ILI9341_DRIVER       // Generic driver for common displays
 | ||||
| //#define ILI9341_2_DRIVER     // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
 | ||||
| //#define ST7735_DRIVER      // Define additional parameters below for this display
 | ||||
| //#define ILI9163_DRIVER     // Define additional parameters below for this display
 | ||||
| //#define S6D02A1_DRIVER
 | ||||
|  | @ -50,14 +57,20 @@ | |||
| //#define R61581_DRIVER
 | ||||
| //#define RM68140_DRIVER
 | ||||
| //#define ST7796_DRIVER
 | ||||
| //#define SSD1351_DRIVER
 | ||||
| //#define SSD1963_480_DRIVER
 | ||||
| //#define SSD1963_800_DRIVER
 | ||||
| //#define SSD1963_800ALT_DRIVER
 | ||||
| //#define ILI9225_DRIVER
 | ||||
| //#define GC9A01_DRIVER
 | ||||
| 
 | ||||
| // Some displays support SPI reads via the MISO pin, other displays have a single
 | ||||
| // bi-directional SDA pin and the library will try to read this via the MOSI line.
 | ||||
| // To use the SDA line for reading data from the TFT uncomment the following line:
 | ||||
| 
 | ||||
| // #define TFT_SDA_READ      // This option is for ESP32 ONLY, tested with ST7789 display only
 | ||||
| // #define TFT_SDA_READ      // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
 | ||||
| 
 | ||||
| // For ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
 | ||||
| // For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
 | ||||
| // Try ONE option at a time to find the correct colour order for your display
 | ||||
| 
 | ||||
| //  #define TFT_RGB_ORDER TFT_RGB  // Colour order Red-Green-Blue
 | ||||
|  | @ -67,19 +80,21 @@ | |||
| 
 | ||||
| // #define M5STACK
 | ||||
| 
 | ||||
| // For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation
 | ||||
| // For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
 | ||||
| // #define TFT_WIDTH  80
 | ||||
| // #define TFT_WIDTH  128
 | ||||
| // #define TFT_WIDTH  172 // ST7789 172 x 320
 | ||||
| // #define TFT_WIDTH  240 // ST7789 240 x 240 and 240 x 320
 | ||||
| // #define TFT_HEIGHT 160
 | ||||
| // #define TFT_HEIGHT 128
 | ||||
| // #define TFT_HEIGHT 240 // ST7789 240 x 240
 | ||||
| // #define TFT_HEIGHT 320 // ST7789 240 x 320
 | ||||
| // #define TFT_HEIGHT 240 // GC9A01 240 x 240
 | ||||
| 
 | ||||
| // For ST7735 ONLY, define the type of display, originally this was based on the
 | ||||
| // colour of the tab on the screen protector film but this is not always true, so try
 | ||||
| // out the different options below if the screen does not display graphics correctly,
 | ||||
| // e.g. colours wrong, mirror images, or tray pixels at the edges.
 | ||||
| // e.g. colours wrong, mirror images, or stray pixels at the edges.
 | ||||
| // Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
 | ||||
| // this User_Setup file, then rebuild and upload the sketch to the board again:
 | ||||
| 
 | ||||
|  | @ -89,6 +104,7 @@ | |||
| // #define ST7735_GREENTAB3
 | ||||
| // #define ST7735_GREENTAB128    // For 128 x 128 display
 | ||||
| // #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
 | ||||
| // #define ST7735_ROBOTLCD       // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
 | ||||
| // #define ST7735_REDTAB
 | ||||
| // #define ST7735_BLACKTAB
 | ||||
| // #define ST7735_REDTAB160x80   // For 160 x 80 display with 24 pixel offset
 | ||||
|  | @ -132,7 +148,7 @@ | |||
| //
 | ||||
| // The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
 | ||||
| //
 | ||||
| // The DC (Data Command) pin may be labeled AO or RS (Register Select)
 | ||||
| // The DC (Data Command) pin may be labelled AO or RS (Register Select)
 | ||||
| //
 | ||||
| // With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
 | ||||
| // SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
 | ||||
|  | @ -166,7 +182,9 @@ | |||
| 
 | ||||
| // Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
 | ||||
| // but saves pins for other functions. It is best not to connect MISO as some displays
 | ||||
| // do not tristate that line wjen chip select is high!
 | ||||
| // do not tristate that line when chip select is high!
 | ||||
| // Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
 | ||||
| // cannot be connected as well to the same SPI signals.
 | ||||
| // On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
 | ||||
| // On NodeMCU V3  S0 =MISO, S1 =MOSI, S2 =SCLK
 | ||||
| // In ESP8266 overlap mode the following must be defined
 | ||||
|  | @ -193,6 +211,16 @@ | |||
| //#define TFT_RST   4  // Reset pin (could connect to RST pin)
 | ||||
| //#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
 | ||||
| 
 | ||||
| // For ESP32 Dev board (only tested with GC9A01 display)
 | ||||
| // The hardware SPI can be mapped to any pins
 | ||||
| 
 | ||||
| //#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
 | ||||
| //#define TFT_SCLK 14
 | ||||
| //#define TFT_CS   5  // Chip select control pin
 | ||||
| //#define TFT_DC   27  // Data Command control pin
 | ||||
| //#define TFT_RST  33  // Reset pin (could connect to Arduino RESET pin)
 | ||||
| //#define TFT_BL   22  // LED back-light
 | ||||
| 
 | ||||
| //#define TOUCH_CS 21     // Chip select pin (T_CS) of touch screen
 | ||||
| 
 | ||||
| //#define TFT_WR 22    // Write strobe for modified Raspberry Pi TFT only
 | ||||
|  | @ -236,6 +264,31 @@ | |||
| //#define TFT_D6   27
 | ||||
| //#define TFT_D7   14
 | ||||
| 
 | ||||
| // ######       EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP        ######
 | ||||
| 
 | ||||
| // The TFT can be connected to SPI port 1 or 2
 | ||||
| //#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
 | ||||
| //#define TFT_MOSI PA7
 | ||||
| //#define TFT_MISO PA6
 | ||||
| //#define TFT_SCLK PA5
 | ||||
| 
 | ||||
| //#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
 | ||||
| //#define TFT_MOSI PB15
 | ||||
| //#define TFT_MISO PB14
 | ||||
| //#define TFT_SCLK PB13
 | ||||
| 
 | ||||
| // Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
 | ||||
| //#define TFT_CS   D5 // Chip select control pin to TFT CS
 | ||||
| //#define TFT_DC   D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
 | ||||
| //#define TFT_RST  D7 // Reset pin to TFT RST (or RESET)
 | ||||
| // OR alternatively, we can use STM32 port reference names PXnn
 | ||||
| //#define TFT_CS   PE11 // Nucleo-F767ZI equivalent of D5
 | ||||
| //#define TFT_DC   PE9  // Nucleo-F767ZI equivalent of D6
 | ||||
| //#define TFT_RST  PF13 // Nucleo-F767ZI equivalent of D7
 | ||||
| 
 | ||||
| //#define TFT_RST  -1   // Set TFT_RST to -1 if the display RESET is connected to processor reset
 | ||||
|                         // Use an Arduino pin for initial testing as connecting to processor reset
 | ||||
|                         // may not work (pulse too short at power up?)
 | ||||
| 
 | ||||
| // ##################################################################################
 | ||||
| //
 | ||||
|  | @ -268,6 +321,29 @@ | |||
| //
 | ||||
| // ##################################################################################
 | ||||
| 
 | ||||
| // For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
 | ||||
| //#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
 | ||||
| 
 | ||||
| // For RP2040 processor and 8 or 16 bit parallel displays:
 | ||||
| // The parallel interface write cycle period is derived from a division of the CPU clock
 | ||||
| // speed so scales with the processor clock. This means that the divider ratio may need
 | ||||
| // to be increased when overclocking. I may also need to be adjusted dependant on the
 | ||||
| // display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined
 | ||||
| // the library will set default values which may not suit your display.
 | ||||
| // The display controller data sheet will specify the minimum write cycle period. The
 | ||||
| // controllers often work reliably for shorter periods, however if the period is too short
 | ||||
| // the display may not initialise or graphics will become corrupted.
 | ||||
| // PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
 | ||||
| //#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
 | ||||
| //#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
 | ||||
| //#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
 | ||||
| 
 | ||||
| // For the RP2040 processor define the SPI port channel used (default 0 if undefined)
 | ||||
| //#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
 | ||||
| 
 | ||||
| // For the STM32 processor define the SPI port channel used (default 1 if undefined)
 | ||||
| //#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
 | ||||
| 
 | ||||
| // Define the SPI clock frequency, this affects the graphics rendering speed. Too
 | ||||
| // fast and the TFT driver will not keep up and display corruption appears.
 | ||||
| // With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
 | ||||
|  | @ -278,8 +354,9 @@ | |||
| // #define SPI_FREQUENCY   5000000
 | ||||
| // #define SPI_FREQUENCY  10000000
 | ||||
| // #define SPI_FREQUENCY  20000000
 | ||||
| #define SPI_FREQUENCY  27000000 // Actually sets it to 26.67MHz = 80/3
 | ||||
| #define SPI_FREQUENCY  27000000 | ||||
| // #define SPI_FREQUENCY  40000000
 | ||||
| // #define SPI_FREQUENCY  55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
 | ||||
| // #define SPI_FREQUENCY  80000000
 | ||||
| 
 | ||||
| // Optional reduced SPI frequency for reading TFT
 | ||||
|  |  | |||
|  | @ -1,45 +1,53 @@ | |||
| // This header file contains a list of user setup files and defines which one the
 | ||||
| // compiler uses when the IDE performs a Verify/Compile or Upload.
 | ||||
| //
 | ||||
| // Users can create configurations for different Espressif boards and TFT displays.
 | ||||
| // Users can create configurations for different boards and TFT displays.
 | ||||
| // This makes selecting between hardware setups easy by "uncommenting" one line.
 | ||||
| 
 | ||||
| // The advantage of this hardware configuration method is that the examples provided
 | ||||
| // with the library should work with different setups immediately without any other
 | ||||
| // changes being needed. It also improves the portability of users sketches to other
 | ||||
| // hardware configurations and compatible libraries.
 | ||||
| // with the library should work with immediately without any other changes being
 | ||||
| // needed. It also improves the portability of users sketches to other hardware
 | ||||
| // configurations and compatible libraries.
 | ||||
| //
 | ||||
| // Create a shortcut to this file on your desktop to permit quick access for editing.
 | ||||
| // Re-compile and upload after making and saving any changes to this file.
 | ||||
| 
 | ||||
| // Customised User_Setup files are stored in the "User_Setups" folder.
 | ||||
| 
 | ||||
| // It is also possible for the user tft settings to be included with the sketch, see
 | ||||
| // the "Sketch_with_tft_setup" generic example. This may be more convenient for
 | ||||
| // multiple projects.
 | ||||
| 
 | ||||
| #ifndef USER_SETUP_LOADED //  Lets PlatformIO users define settings in
 | ||||
|                           //  platformio.ini, see notes in "Tools" folder.
 | ||||
| 
 | ||||
| // Only ONE line below should be uncommented.  Add extra lines and files as needed.
 | ||||
| ///////////////////////////////////////////////////////
 | ||||
| //   User configuration selection lines are below    //
 | ||||
| ///////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // Only ONE line below should be uncommented to define your setup.  Add extra lines and files as needed.
 | ||||
| 
 | ||||
| #include <User_Setup.h>           // Default setup is root library folder | ||||
| 
 | ||||
| //#include <User_Setups/Setup1_ILI9341.h>  // Setup file configured for my ILI9341
 | ||||
| //#include <User_Setups/Setup2_ST7735.h>   // Setup file configured for my ST7735
 | ||||
| //#include <User_Setups/Setup3_ILI9163.h>  // Setup file configured for my ILI9163
 | ||||
| //#include <User_Setups/Setup4_S6D02A1.h>  // Setup file configured for my S6D02A1
 | ||||
| //#include <User_Setups/Setup5_RPi_ILI9486.h>        // Setup file configured for my stock RPi TFT
 | ||||
| //#include <User_Setups/Setup6_RPi_Wr_ILI9486.h>     // Setup file configured for my modified RPi TFT
 | ||||
| //#include <User_Setups/Setup7_ST7735_128x128.h>     // Setup file configured for my ST7735 128x128 display
 | ||||
| //#include <User_Setups/Setup8_ILI9163_128x128.h>    // Setup file configured for my ILI9163 128x128 display
 | ||||
| //#include <User_Setups/Setup9_ST7735_Overlap.h>     // Setup file configured for my ST7735
 | ||||
| //#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file configured for ESP8266 and RPi TFT with touch
 | ||||
| //#include <User_Setups/Setup1_ILI9341.h>  // Setup file for ESP8266 configured for my ILI9341
 | ||||
| //#include <User_Setups/Setup2_ST7735.h>   // Setup file for ESP8266 configured for my ST7735
 | ||||
| //#include <User_Setups/Setup3_ILI9163.h>  // Setup file for ESP8266 configured for my ILI9163
 | ||||
| //#include <User_Setups/Setup4_S6D02A1.h>  // Setup file for ESP8266 configured for my S6D02A1
 | ||||
| //#include <User_Setups/Setup5_RPi_ILI9486.h>        // Setup file for ESP8266 configured for my stock RPi TFT
 | ||||
| //#include <User_Setups/Setup6_RPi_Wr_ILI9486.h>     // Setup file for ESP8266 configured for my modified RPi TFT
 | ||||
| //#include <User_Setups/Setup7_ST7735_128x128.h>     // Setup file for ESP8266 configured for my ST7735 128x128 display
 | ||||
| //#include <User_Setups/Setup8_ILI9163_128x128.h>    // Setup file for ESP8266 configured for my ILI9163 128x128 display
 | ||||
| //#include <User_Setups/Setup9_ST7735_Overlap.h>     // Setup file for ESP8266 configured for my ST7735
 | ||||
| //#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file for ESP8266 configured for ESP8266 and RPi TFT with touch
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup11_RPi_touch_ILI9486.h> // Setup file configured for ESP32 and RPi TFT with touch
 | ||||
| //#include <User_Setups/Setup12_M5Stack.h>           // Setup file for the ESP32 based M5Stack
 | ||||
| //#include <User_Setups/Setup12_M5Stack_Basic_Core.h>// Setup file for the ESP32 based M5Stack (Basic Core only)
 | ||||
| //#include <User_Setups/Setup13_ILI9481_Parallel.h>  // Setup file for the ESP32 with parallel bus TFT
 | ||||
| //#include <User_Setups/Setup14_ILI9341_Parallel.h>  // Setup file for the ESP32 with parallel bus TFT
 | ||||
| //#include <User_Setups/Setup15_HX8357D.h>           // Setup file configured for HX8357D (untested)
 | ||||
| //#include <User_Setups/Setup15_HX8357D.h>           // Setup file for ESP8266 configured for HX8357D
 | ||||
| //#include <User_Setups/Setup16_ILI9488_Parallel.h>  // Setup file for the ESP32 with parallel bus TFT
 | ||||
| //#include <User_Setups/Setup17_ePaper.h>            // Setup file for any Waveshare ePaper display
 | ||||
| //#include <User_Setups/Setup18_ST7789.h>            // Setup file configured for ST7789
 | ||||
| //#include <User_Setups/Setup17_ePaper.h>            // Setup file for ESP8266 and any Waveshare ePaper display
 | ||||
| //#include <User_Setups/Setup18_ST7789.h>            // Setup file for ESP8266 configured for ST7789
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup19_RM68140_Parallel.h>	 // Setup file configured for RM68140 with parallel bus
 | ||||
| 
 | ||||
|  | @ -49,7 +57,7 @@ | |||
| //#include <User_Setups/Setup22_TTGO_T4.h>           // Setup file for ESP32 and TTGO T4 version 1.2
 | ||||
| //#include <User_Setups/Setup22_TTGO_T4_v1.3.h>      // Setup file for ESP32 and TTGO T4 version 1.3
 | ||||
| //#include <User_Setups/Setup23_TTGO_TM.h>           // Setup file for ESP32 and TTGO TM ST7789 SPI bus TFT
 | ||||
| //#include <User_Setups/Setup24_ST7789.h>            // Setup file configured for ST7789 240 x 240
 | ||||
| //#include <User_Setups/Setup24_ST7789.h>            // Setup file for DSTIKE/ESP32/ESP8266 configured for ST7789 240 x 240
 | ||||
| //#include <User_Setups/Setup25_TTGO_T_Display.h>    // Setup file for ESP32 and TTGO T-Display ST7789V SPI bus TFT
 | ||||
| //#include <User_Setups/Setup26_TTGO_T_Wristband.h>  // Setup file for ESP32 and TTGO T-Wristband ST7735 SPI bus TFT
 | ||||
| 
 | ||||
|  | @ -59,23 +67,84 @@ | |||
| //#include <User_Setups/Setup29_ILI9341_STM32.h>          // Setup for Nucleo board
 | ||||
| //#include <User_Setups/Setup30_ILI9341_Parallel_STM32.h> // Setup for Nucleo board and parallel display
 | ||||
| //#include <User_Setups/Setup31_ST7796_Parallel_STM32.h>  // Setup for Nucleo board and parallel display
 | ||||
| //#include <User_Setups/Setup32_ILI9341_STM32F103.h>        // Setup for "Blue Pill"
 | ||||
| //#include <User_Setups/Setup32_ILI9341_STM32F103.h>      // Setup for "Blue/Black Pill"
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup33_RPi_ILI9486_STM32.h>      // Setup for Nucleo board
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup34_ILI9481_Parallel_STM32.h> // Setup for Nucleo board and parallel display
 | ||||
| //#include <User_Setups/Setup35_ILI9341_STM32_Port_Bus.h> // Setup for STM32 port A parallel display
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup36_RPi_touch_ILI9341.h>      // Setup file configured for ESP32 and RPi TFT with touch
 | ||||
| //#include <User_Setups/Setup36_RPi_touch_ST7796.h>      // Setup file configured for ESP32 and RPi ST7796 TFT with touch
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup43_ST7735.h>            // Setup file configured for my ST7735S 80x160
 | ||||
| //#include <User_Setups/Setup44_TTGO_CameraPlus.h>  // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT    240x240
 | ||||
| //#include <User_Setups/Setup45_TTGO_T_Watch.h>     // Setup file for ESP32 and TTGO T-Watch ST7789 SPI bus TFT  240x240
 | ||||
| //#include <User_Setups/Setup42_ILI9341_ESP32.h>           // Setup file for ESP32 and SPI ILI9341 240x320
 | ||||
| //#include <User_Setups/Setup43_ST7735.h>            // Setup file for ESP8266 & ESP32 configured for my ST7735S 80x160
 | ||||
| //#include <User_Setups/Setup44_TTGO_CameraPlus.h>   // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT    240x240
 | ||||
| //#include <User_Setups/Setup45_TTGO_T_Watch.h>      // Setup file for ESP32 and TTGO T-Watch ST7789 SPI bus TFT  240x240
 | ||||
| //#include <User_Setups/Setup46_GC9A01_ESP32.h>      // Setup file for ESP32 and GC9A01 SPI bus TFT  240x240
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup47_ST7735.h>            // Setup file for ESP32 configured for ST7735 128 x 128 animated eyes
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup50_SSD1963_Parallel.h>  // Setup file for ESP32 and SSD1963 TFT display
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup51_LilyPi_ILI9481.h>    // Setup file for LilyGo LilyPi with ILI9481 display
 | ||||
| //#include <User_Setups/Setup52_LilyPi_ST7796.h>     // Setup file for LilyGo LilyPi with ST7796 display
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup60_RP2040_ILI9341.h>    // Setup file for RP2040 with SPI ILI9341
 | ||||
| //#include <User_Setups/Setup61_RP2040_ILI9341_PIO_SPI.h>    // Setup file for RP2040 with PIO SPI ILI9341
 | ||||
| //#include <User_Setups/Setup62_RP2040_Nano_Connect_ILI9341.h>    // Setup file for RP2040 with SPI ILI9341
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup70_ESP32_S2_ILI9341.h>     // Setup file for ESP32 S2 with SPI ILI9341
 | ||||
| //#include <User_Setups/Setup70b_ESP32_S3_ILI9341.h>    // Setup file for ESP32 S3 with SPI ILI9341
 | ||||
| //#include <User_Setups/Setup70c_ESP32_C3_ILI9341.h>    // Setup file for ESP32 C3 with SPI ILI9341
 | ||||
| //#include <User_Setups/Setup70d_ILI9488_S3_Parallel.h> // Setup file for ESP32 S3 with SPI ILI9488
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup71_ESP32_S2_ST7789.h>       // Setup file for ESP32 S2 with ST7789
 | ||||
| //#include <User_Setups/Setup72_ESP32_ST7789_172x320.h>  // Setup file for ESP32 with ST7789 1.47" 172x320
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup100_RP2040_ILI9488_parallel.h> // Setup file for Pico/RP2040 with 8 bit parallel ILI9488
 | ||||
| //#include <User_Setups/Setup101_RP2040_ILI9481_parallel.h> // Setup file for Pico/RP2040 with 8 bit parallel ILI9481
 | ||||
| //#include <User_Setups/Setup102_RP2040_ILI9341_parallel.h> // Setup file for Pico/RP2040 with 8 bit parallel ILI9341
 | ||||
| //#include <User_Setups/Setup103_RP2040_ILI9486_parallel.h> // Setup file for Pico/RP2040 with 8 bit parallel ILI9486
 | ||||
| //#include <User_Setups/Setup104_RP2040_ST7796_parallel.h>  // Setup file for Pico/RP2040 with 8 bit parallel ST7796
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup105_RP2040_ST7796_16bit_parallel.h>  // Setup file for RP2040 16 bit parallel display
 | ||||
| //#include <User_Setups/Setup106_RP2040_ILI9481_16bit_parallel.h> // Setup file for RP2040 16 bit parallel display
 | ||||
| //#include <User_Setups/Setup107_RP2040_ILI9341_16bit_parallel.h> // Setup file for RP2040 16 bit parallel display
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup135_ST7789.h>           // Setup file for ESP8266 and ST7789 135 x 240 TFT
 | ||||
| 
 | ||||
| //#include <User_Setups/SetupX_Template.h>
 | ||||
| //#include <User_Setups/Setup136_LilyGo_TTV.h>       // Setup file for ESP32 and Lilygo TTV ST7789 SPI bus TFT  135x240
 | ||||
| //#include <User_Setups/Setup137_LilyGo_TDisplay_RP2040.h>  // Setup file for Lilygo T-Display RP2040 (ST7789 on SPI bus with 135x240 TFT)
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup200_GC9A01.h>           // Setup file for ESP32 and GC9A01 240 x 240 TFT
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup201_WT32_SC01.h>        // Setup file for ESP32 based WT32_SC01 from Seeed
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup202_SSD1351_128.h>      // Setup file for ESP32/ESP8266 based SSD1351 128x128 1.5inch OLED display
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup203_ST7789.h>     // Setup file for ESP32/ESP8266 based ST7789 240X280 1.69inch TFT 
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup204_ESP32_TouchDown.h>     // Setup file for the ESP32 TouchDown based on ILI9488 480 x 320 TFT 
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup205_ESP32_TouchDown_S3.h>     // Setup file for the ESP32 TouchDown S3 based on ILI9488 480 x 320 TFT 
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup206_LilyGo_T_Display_S3.h>
 | ||||
| //#include <User_Setups/Setup207_LilyGo_T_HMI.h>
 | ||||
| 
 | ||||
| //#include <User_Setups/Setup301_BW16_ST7735.h>            // Setup file for Bw16-based boards with ST7735 160 x 80 TFT
 | ||||
| 
 | ||||
| //#include <User_Setups/SetupX_Template.h>     // Template file for a setup
 | ||||
| 
 | ||||
| 
 | ||||
| //#include <User_Setups/Dustin_ILI9488.h>           // Setup file for Dustin Watts PCB with ILI9488
 | ||||
| //#include <User_Setups/Dustin_ST7796.h>           // Setup file for Dustin Watts PCB with ST7796
 | ||||
| //#include <User_Setups/Dustin_ILI9488_Pico.h>        // Setup file for Dustin Watts Pico PCB with ST7796
 | ||||
| //#include <User_Setups/Dustin_ST7789_Pico.h>           // Setup file for Dustin Watts PCB with ST7789 240 x 240 on 3.3V adapter board
 | ||||
| //#include <User_Setups/Dustin_GC9A01_Pico.h>           // Setup file for Dustin Watts PCB with GC9A01 240 x 240 on 3.3V adapter board
 | ||||
| //#include <User_Setups/Dustin_GC9A01_ESP32.h>           // Setup file for Dustin Watts PCB with GC9A01 240 x 240 on 3.3V adapter board
 | ||||
| //#include <User_Setups/Dustin_STT7789_ESP32.h>           // Setup file for Dustin Watts PCB with ST7789 240 x 240 on 3.3V adapter board
 | ||||
| //#include <User_Setups/Dustin_ILI9341_ESP32.h>           // Setup file for Dustin Watts PCB with ILI9341
 | ||||
| //#include <User_Setups/ILI9225.h>
 | ||||
| 
 | ||||
| #endif // USER_SETUP_LOADED
 | ||||
| 
 | ||||
|  | @ -111,8 +180,15 @@ | |||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Invoke 18 bit colour for selected displays
 | ||||
| #if !defined (RPI_DISPLAY_TYPE) && !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) && !defined (ESP32_PARALLEL) | ||||
|   #if defined (ILI9481_DRIVER) || defined (ILI9486_DRIVER) || defined (ILI9488_DRIVER) | ||||
|     #define SPI_18BIT_DRIVER | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| // Load the right driver definition - do not tinker here !
 | ||||
| #if   defined (ILI9341_DRIVER) | ||||
| #if   defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9342_DRIVER) | ||||
|      #include <TFT_Drivers/ILI9341_Defines.h> | ||||
|      #define  TFT_DRIVER 0x9341 | ||||
| #elif defined (ST7735_DRIVER) | ||||
|  | @ -154,8 +230,39 @@ | |||
| #elif defined (RM68140_DRIVER) | ||||
|      #include "TFT_Drivers/RM68140_Defines.h" | ||||
|      #define  TFT_DRIVER 0x6814 | ||||
| #elif defined (SSD1351_DRIVER) | ||||
|      #include "TFT_Drivers/SSD1351_Defines.h" | ||||
|      #define  TFT_DRIVER 0x1351 | ||||
| #elif defined (SSD1963_480_DRIVER) | ||||
|      #include "TFT_Drivers/SSD1963_Defines.h" | ||||
|      #define  TFT_DRIVER 0x1963 | ||||
| #elif defined (SSD1963_800_DRIVER) | ||||
|      #include "TFT_Drivers/SSD1963_Defines.h" | ||||
|      #define  TFT_DRIVER 0x1963 | ||||
| #elif defined (SSD1963_800ALT_DRIVER) | ||||
|      #include "TFT_Drivers/SSD1963_Defines.h" | ||||
|      #define  TFT_DRIVER 0x1963 | ||||
| #elif defined (SSD1963_800BD_DRIVER) | ||||
|      #include "TFT_Drivers/SSD1963_Defines.h" | ||||
|      #define  TFT_DRIVER 0x1963 | ||||
| #elif defined (GC9A01_DRIVER) | ||||
|      #include "TFT_Drivers/GC9A01_Defines.h" | ||||
|      #define  TFT_DRIVER 0x9A01 | ||||
| #elif defined (ILI9225_DRIVER) | ||||
|      #include "TFT_Drivers/ILI9225_Defines.h" | ||||
|      #define  TFT_DRIVER 0x9225 | ||||
| #elif defined (RM68120_DRIVER) | ||||
|      #include "TFT_Drivers/RM68120_Defines.h" | ||||
|      #define  TFT_DRIVER 0x6812 | ||||
| #elif defined (HX8357B_DRIVER) | ||||
|      #include "TFT_Drivers/HX8357B_Defines.h" | ||||
|      #define  TFT_DRIVER 0x835B | ||||
| #elif defined (HX8357C_DRIVER) | ||||
|      #include "TFT_Drivers/HX8357C_Defines.h" | ||||
|      #define  TFT_DRIVER 0x835C | ||||
| 
 | ||||
|                               // <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE
 | ||||
|                               // XYZZY_init.h and XYZZY_rotation.h must also be added in TFT_eSPI.c
 | ||||
|                               // XYZZY_init.h and XYZZY_rotation.h must also be added in TFT_eSPI.cpp
 | ||||
| #elif defined (XYZZY_DRIVER) | ||||
|      #include "TFT_Drivers/XYZZY_Defines.h" | ||||
|      #define  TFT_DRIVER 0x0000 | ||||
|  | @ -163,7 +270,6 @@ | |||
|      #define  TFT_DRIVER 0x0000 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| // These are the pins for ESP8266 boards
 | ||||
| //      Name   GPIO    NodeMCU      Function
 | ||||
| #define PIN_D0  16  // GPIO16       WAKE
 | ||||
|  |  | |||
|  | @ -0,0 +1,56 @@ | |||
| // This setup is for the RP2040 processor only when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 100 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define TFT_PARALLEL_8_BIT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ILI9488_DRIVER | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| //#define TFT_CS   -1  // Do not define, chip select control pin permanently connected to 0V
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_DC   28    // Data Command control pin
 | ||||
| #define TFT_RST   2    // Reset pin
 | ||||
| 
 | ||||
| //#define TFT_RD   -1  // Do not define, read pin permanently connected to 3V3
 | ||||
| 
 | ||||
| // Note: All the following pins are PIO hardware configured and driven
 | ||||
| // The pins are hard-coded at the moment and must not be changed here
 | ||||
| // Connections MUST use the pins below
 | ||||
|   #define TFT_WR   22 | ||||
| 
 | ||||
|   // PIO requires these to be sequentially increasing - do not change
 | ||||
|   #define TFT_D0    6 | ||||
|   #define TFT_D1    7 | ||||
|   #define TFT_D2    8 | ||||
|   #define TFT_D3    9 | ||||
|   #define TFT_D4   10 | ||||
|   #define TFT_D5   11 | ||||
|   #define TFT_D6   12 | ||||
|   #define TFT_D7   13 | ||||
| //*/
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,56 @@ | |||
| // This setup is for the RP2040 processor only when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 101 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define TFT_PARALLEL_8_BIT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ILI9481_DRIVER | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| //#define TFT_CS   -1  // Do not define, chip select control pin permanently connected to 0V
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_DC   28    // Data Command control pin
 | ||||
| #define TFT_RST   2    // Reset pin
 | ||||
| 
 | ||||
| //#define TFT_RD   -1  // Do not define, read pin permanently connected to 3V3
 | ||||
| 
 | ||||
| // Note: All the following pins are PIO hardware configured and driven
 | ||||
| // The pins are hard-coded at the moment and must not be changed here
 | ||||
| // Connections MUST use the pins below
 | ||||
|   #define TFT_WR   22 | ||||
| 
 | ||||
|   // PIO requires these to be sequentially increasing - do not change
 | ||||
|   #define TFT_D0    6 | ||||
|   #define TFT_D1    7 | ||||
|   #define TFT_D2    8 | ||||
|   #define TFT_D3    9 | ||||
|   #define TFT_D4   10 | ||||
|   #define TFT_D5   11 | ||||
|   #define TFT_D6   12 | ||||
|   #define TFT_D7   13 | ||||
| //*/
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,56 @@ | |||
| // This setup is for the RP2040 processor only when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 102 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define TFT_PARALLEL_8_BIT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ILI9341_DRIVER | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| //#define TFT_CS   -1  // Do not define, chip select control pin permanently connected to 0V
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_DC   28    // Data Command control pin
 | ||||
| #define TFT_RST   2    // Reset pin
 | ||||
| 
 | ||||
| //#define TFT_RD   -1  // Do not define, read pin permanently connected to 3V3
 | ||||
| 
 | ||||
| // Note: All the following pins are PIO hardware configured and driven
 | ||||
| // The pins are hard-coded at the moment and must not be changed here
 | ||||
| // Connections MUST use the pins below
 | ||||
|   #define TFT_WR   22 | ||||
| 
 | ||||
|   // PIO requires these to be sequentially increasing - do not change
 | ||||
|   #define TFT_D0    6 | ||||
|   #define TFT_D1    7 | ||||
|   #define TFT_D2    8 | ||||
|   #define TFT_D3    9 | ||||
|   #define TFT_D4   10 | ||||
|   #define TFT_D5   11 | ||||
|   #define TFT_D6   12 | ||||
|   #define TFT_D7   13 | ||||
| //*/
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,56 @@ | |||
| // This setup is for the RP2040 processor only when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 103 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define TFT_PARALLEL_8_BIT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ILI9486_DRIVER | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| //#define TFT_CS   -1  // Do not define, chip select control pin permanently connected to 0V
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_DC   28    // Data Command control pin
 | ||||
| #define TFT_RST   2    // Reset pin
 | ||||
| 
 | ||||
| //#define TFT_RD   -1  // Do not define, read pin permanently connected to 3V3
 | ||||
| 
 | ||||
| // Note: All the following pins are PIO hardware configured and driven
 | ||||
| // The pins are hard-coded at the moment and must not be changed here
 | ||||
| // Connections MUST use the pins below
 | ||||
|   #define TFT_WR   22 | ||||
| 
 | ||||
|   // PIO requires these to be sequentially increasing - do not change
 | ||||
|   #define TFT_D0    6 | ||||
|   #define TFT_D1    7 | ||||
|   #define TFT_D2    8 | ||||
|   #define TFT_D3    9 | ||||
|   #define TFT_D4   10 | ||||
|   #define TFT_D5   11 | ||||
|   #define TFT_D6   12 | ||||
|   #define TFT_D7   13 | ||||
| //*/
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,56 @@ | |||
| // This setup is for the RP2040 processor only when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 104 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define TFT_PARALLEL_8_BIT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ST7796_DRIVER | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| //#define TFT_CS   -1  // Do not define, chip select control pin permanently connected to 0V
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_DC   28    // Data Command control pin
 | ||||
| #define TFT_RST   2    // Reset pin
 | ||||
| 
 | ||||
| //#define TFT_RD   -1  // Do not define, read pin permanently connected to 3V3
 | ||||
| 
 | ||||
| // Note: All the following pins are PIO hardware configured and driven
 | ||||
| // The pins are hard-coded at the moment and must not be changed here
 | ||||
| // Connections MUST use the pins below
 | ||||
|   #define TFT_WR   22 | ||||
| 
 | ||||
|   // PIO requires these to be sequentially increasing - do not change
 | ||||
|   #define TFT_D0    6 | ||||
|   #define TFT_D1    7 | ||||
|   #define TFT_D2    8 | ||||
|   #define TFT_D3    9 | ||||
|   #define TFT_D4   10 | ||||
|   #define TFT_D5   11 | ||||
|   #define TFT_D6   12 | ||||
|   #define TFT_D7   13 | ||||
| //*/
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,60 @@ | |||
| // This setup is for the RP2040 processor only when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 105 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define TFT_PARALLEL_16_BIT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ST7796_DRIVER | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| //#define TFT_CS   -1  // Do not define, chip select control pin permanently connected to 0V
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_DC    3    // Data Command control pin
 | ||||
| #define TFT_RST   2    // Reset pin
 | ||||
| 
 | ||||
| //#define TFT_RD   -1  // Do not define, read pin must be permanently connected to 3V3
 | ||||
| #define TFT_WR   4 | ||||
| 
 | ||||
| // PIO requires these to be sequentially increasing GPIO with no gaps
 | ||||
| #define TFT_D0    6 | ||||
| #define TFT_D1    7 | ||||
| #define TFT_D2    8 | ||||
| #define TFT_D3    9 | ||||
| #define TFT_D4   10 | ||||
| #define TFT_D5   11 | ||||
| #define TFT_D6   12 | ||||
| #define TFT_D7   13 | ||||
| #define TFT_D8   14 | ||||
| #define TFT_D9   15 | ||||
| #define TFT_D10  16 | ||||
| #define TFT_D11  17 | ||||
| #define TFT_D12  18 | ||||
| #define TFT_D13  19 | ||||
| #define TFT_D14  20 | ||||
| #define TFT_D15  21 | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,64 @@ | |||
| // This setup is for the RP2040 processor when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 106 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| //#define TFT_PARALLEL_8_BIT
 | ||||
| #define TFT_PARALLEL_16_BIT | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ILI9481_DRIVER | ||||
| //#define HX8357B_DRIVER
 | ||||
| //#define HX8357C_DRIVER
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_RST   18  // Reset pin
 | ||||
| #define TFT_CS    19  // Do not define if chip select control pin permanently connected to 0V
 | ||||
| //#define TFT_RD   -1   // Do not define, read pin must be permanently connected to 3V3
 | ||||
| 
 | ||||
| // Note: All the following pins are PIO hardware configured and driven
 | ||||
|   #define TFT_WR   16    // Write strobe pin
 | ||||
|   #define TFT_DC   17    // Data Command control pin
 | ||||
| 
 | ||||
|   // PIO requires these to be sequentially increasing
 | ||||
|   #define TFT_D0    0 | ||||
|   #define TFT_D1    1 | ||||
|   #define TFT_D2    2 | ||||
|   #define TFT_D3    3 | ||||
|   #define TFT_D4    4 | ||||
|   #define TFT_D5    5 | ||||
|   #define TFT_D6    6 | ||||
|   #define TFT_D7    7 | ||||
|   #define TFT_D8    8 | ||||
|   #define TFT_D9    9 | ||||
|   #define TFT_D10  10 | ||||
|   #define TFT_D11  11 | ||||
|   #define TFT_D12  12 | ||||
|   #define TFT_D13  13 | ||||
|   #define TFT_D14  14 | ||||
|   #define TFT_D15  15 | ||||
| //*/
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -0,0 +1,65 @@ | |||
| // This setup is for the RP2040 processor only when used with 8 bit parallel displays
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 107 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Interface
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| //#define TFT_PARALLEL_8_BIT
 | ||||
| #define TFT_PARALLEL_16_BIT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Display driver type
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define ILI9341_DRIVER | ||||
| //#define ILI9481_DRIVER // Tested
 | ||||
| //#define HX8357B_DRIVER // Tested
 | ||||
| //#define HX8357C_DRIVER // Tested
 | ||||
| //#define SSD1963_800_DRIVER
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // RP2040 pins used
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| // These pins can be moved and are controlled directly by the library software
 | ||||
| #define TFT_RST   18  // Reset pin
 | ||||
| #define TFT_CS    19  // Do not define if chip select control pin permanently connected to 0V
 | ||||
| //#define TFT_RD   -1   // Do not define, read pin must be permanently connected to 3V3
 | ||||
| 
 | ||||
| // Note: All the following pins are PIO hardware configured and driven
 | ||||
|   #define TFT_WR   16    // Write strobe pin
 | ||||
|   #define TFT_DC   17    // Data Command control pin
 | ||||
| 
 | ||||
|   // PIO requires these to be sequentially increasing
 | ||||
|   #define TFT_D0    0 | ||||
|   #define TFT_D1    1 | ||||
|   #define TFT_D2    2 | ||||
|   #define TFT_D3    3 | ||||
|   #define TFT_D4    4 | ||||
|   #define TFT_D5    5 | ||||
|   #define TFT_D6    6 | ||||
|   #define TFT_D7    7 | ||||
|   #define TFT_D8    8 | ||||
|   #define TFT_D9    9 | ||||
|   #define TFT_D10  10 | ||||
|   #define TFT_D11  11 | ||||
|   #define TFT_D12  12 | ||||
|   #define TFT_D13  13 | ||||
|   #define TFT_D14  14 | ||||
|   #define TFT_D15  15 | ||||
| //*/
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Fonts to be available
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -1,7 +1,9 @@ | |||
| // For ESP8266
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 10 | ||||
| 
 | ||||
| #define RPI_DISPLAY_TYPE | ||||
| #define ILI9486_DRIVER // 20MHz maximum SPI
 | ||||
| #define ILI9486_DRIVER | ||||
| 
 | ||||
| // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
 | ||||
| #define TFT_CS   PIN_D2  // Chip select control pin D2
 | ||||
|  | @ -23,7 +25,7 @@ | |||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| 
 | ||||
| #define SPI_FREQUENCY  16000000 | ||||
| #define SPI_FREQUENCY  16000000 // Some displays will operate at higher frequencies
 | ||||
| 
 | ||||
| #define SPI_TOUCH_FREQUENCY  2500000 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| // For ESP32
 | ||||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 11 | ||||
| 
 | ||||
| #define RPI_DISPLAY_TYPE | ||||
| #define ILI9486_DRIVER // 20MHz maximum SPI
 | ||||
| #define ILI9486_DRIVER | ||||
| 
 | ||||
| #define TFT_MISO 19 | ||||
| #define TFT_MOSI 23 | ||||
|  | @ -24,6 +27,6 @@ | |||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| 
 | ||||
| #define SPI_FREQUENCY  20000000 | ||||
| #define SPI_FREQUENCY  20000000 // Some displays will operate at higher frequencies
 | ||||
| 
 | ||||
| #define SPI_TOUCH_FREQUENCY  2500000 | ||||
|  |  | |||
|  | @ -1,11 +1,12 @@ | |||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 12 | ||||
| 
 | ||||
| //Setup file for the M5Stack Basic Core
 | ||||
| 
 | ||||
| #define ILI9341_DRIVER | ||||
| 
 | ||||
| 
 | ||||
| #define M5STACK | ||||
| 
 | ||||
| 
 | ||||
| #define TFT_MISO 19 | ||||
| #define TFT_MOSI 23 | ||||
| #define TFT_SCLK 18 | ||||
|  | @ -1,4 +1,5 @@ | |||
| // ST7789 135 x 240 display with no chip select line
 | ||||
| #define USER_SETUP_ID 135 | ||||
| 
 | ||||
| #define ST7789_DRIVER     // Configure all registers
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,35 @@ | |||
| // ST7789 135 x 240 display with no chip select line
 | ||||
| #define USER_SETUP_ID 136 | ||||
| 
 | ||||
| #define ST7789_DRIVER     // Configure all registers
 | ||||
| 
 | ||||
| #define TFT_WIDTH  135 | ||||
| #define TFT_HEIGHT 240 | ||||
| 
 | ||||
| #define CGRAM_OFFSET      // Library will add offsets required
 | ||||
| 
 | ||||
| // Generic ESP32 setup
 | ||||
| //#define TFT_MISO 19
 | ||||
| #define TFT_MOSI 23 | ||||
| #define TFT_SCLK 18 | ||||
| #define TFT_CS    5  | ||||
| #define TFT_DC    19 | ||||
| #define TFT_RST   4   | ||||
| 
 | ||||
| 
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| 
 | ||||
| // #define SPI_FREQUENCY  27000000
 | ||||
| #define SPI_FREQUENCY  40000000 | ||||
| 
 | ||||
| // #define SUPPORT_TRANSACTIONS
 | ||||
|  | @ -0,0 +1,33 @@ | |||
| // LilyGo T-Display RP2040 (ST7789 135 x 240 display)
 | ||||
| #define USER_SETUP_ID 137 | ||||
| 
 | ||||
| #define ST7789_DRIVER     // Configure all registers
 | ||||
| 
 | ||||
| #define TFT_WIDTH  135 | ||||
| #define TFT_HEIGHT 240 | ||||
| 
 | ||||
| #define CGRAM_OFFSET      // Library will add offsets required
 | ||||
| 
 | ||||
| // For LilyGo T-Display RP2040
 | ||||
| #define TFT_CS   5  // Chip Select pin
 | ||||
| #define TFT_DC   1  // Data Command control pin
 | ||||
| #define TFT_RST  0  // Reset pin
 | ||||
| #define TFT_MOSI 3 | ||||
| #define TFT_SCLK 2 | ||||
| // Don't uncomment next line if you want PWM control of the backlight in the sketch
 | ||||
| //#define TFT_BL 4
 | ||||
| 
 | ||||
| #define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
 | ||||
| #define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
 | ||||
| #define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
 | ||||
| #define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
 | ||||
| #define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
 | ||||
| //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
 | ||||
| #define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
 | ||||
| 
 | ||||
| #define SMOOTH_FONT | ||||
| 
 | ||||
| #define SPI_FREQUENCY  40000000 | ||||
| #define SPI_READ_FREQUENCY  20000000 | ||||
| #define SPI_TOUCH_FREQUENCY  2500000 | ||||
|  | @ -1,4 +1,5 @@ | |||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 13 | ||||
| 
 | ||||
| #define ESP32_PARALLEL | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 14 | ||||
| 
 | ||||
| #define ESP32_PARALLEL | ||||
| #define TFT_PARALLEL_8_BIT | ||||
| 
 | ||||
| 
 | ||||
| #define ILI9341_DRIVER | ||||
|  |  | |||
|  | @ -1,7 +1,12 @@ | |||
| // See SetupX_Template.h for all options available
 | ||||
| #define USER_SETUP_ID 15 | ||||
| 
 | ||||
| #define HX8357D_DRIVER | ||||
| 
 | ||||
| // If green and blue swapped on display then change the RGB colour order
 | ||||
| // Only uncomment ONE of the following options
 | ||||
| #define TFT_RGB_ORDER TFT_RGB    //   Red-Green-Blue
 | ||||
| //#define TFT_RGB_ORDER TFT_BGR    //   Blue-Green-RED
 | ||||
| 
 | ||||
| // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
 | ||||
| #define TFT_CS   PIN_D8  // Chip select control pin D8
 | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue