├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── components ├── GCodeRenderer │ ├── CMakeLists.txt │ ├── GCodeRenderer.cpp │ └── include │ │ └── GCodeRenderer.h └── dbg_log │ ├── CMakeLists.txt │ ├── LICENSE │ ├── dbg_log.c │ └── include │ └── dbg_log.h ├── data ├── Move_48.bmp ├── SDcard_64.bmp ├── Settings_48.bmp ├── arrowL_48.bmp ├── arrowR_48.bmp ├── extruder_32.bmp ├── fan_32.bmp ├── file_24.bmp ├── folder_24.bmp ├── gcode_24.bmp ├── heatbed_32.bmp ├── home_24.bmp └── return_48.bmp ├── dependencies.lock ├── hardware └── 3D_Printer_Screen_V2.pdf ├── images ├── screenshots │ ├── screenshot_2021_1_15_23_4_27.png │ ├── screenshot_2021_1_15_23_4_46.png │ ├── screenshot_2021_1_15_23_4_5.png │ ├── screenshot_2021_1_15_23_4_56.png │ ├── screenshot_2021_1_15_23_5_20.png │ ├── screenshot_2021_1_15_23_6_17.png │ ├── screenshot_2021_1_15_23_7_13.png │ ├── screenshot_2021_1_18_18_55_15.png │ └── screenshot_2021_1_18_3_1_7.png └── wiring.jpg ├── main ├── CMakeLists.txt ├── Free_Fonts.h ├── Kconfig.projbuild ├── Menu │ ├── black_Scr.cpp │ ├── black_Scr.h │ ├── config_Scr.cpp │ ├── config_Scr.h │ ├── displayConf_Scr.cpp │ ├── displayConf_Scr.h │ ├── fileBrowser_Scr.cpp │ ├── fileBrowser_Scr.h │ ├── info_Scr.cpp │ ├── info_Scr.h │ ├── preview_Scr.cpp │ └── preview_Scr.h ├── Screen.cpp ├── Screen.h ├── lcdUI.cpp ├── lcdUI.h ├── main.cpp ├── tftLCD.cpp ├── tftLCD.h ├── utility.cpp └── utility.h ├── partitions_two_ota_SPIFFS.csv └── sdkconfig /.gitignore: -------------------------------------------------------------------------------- 1 | # Our automatic versioning scheme generates the following file 2 | # NEVER put it in the repository 3 | _Version.h 4 | 5 | # 6 | # OS 7 | # 8 | applet/ 9 | *.DS_Store 10 | 11 | 12 | # 13 | # Misc 14 | # 15 | *~ 16 | *.orig 17 | *.rej 18 | *.bak 19 | *.idea 20 | *.s 21 | *.i 22 | *.ii 23 | *.swp 24 | tags 25 | 26 | # 27 | # C++ 28 | # 29 | # Compiled Object files 30 | *.slo 31 | *.lo 32 | *.o 33 | *.obj 34 | *.ino.cpp 35 | 36 | # Precompiled Headers 37 | *.gch 38 | *.pch 39 | 40 | # Compiled Dynamic libraries 41 | *.so 42 | *.dylib 43 | *.dll 44 | 45 | # Fortran module files 46 | *.mod 47 | *.smod 48 | 49 | # Compiled Static libraries 50 | *.lai 51 | *.la 52 | *.a 53 | *.lib 54 | 55 | # Executables 56 | *.exe 57 | *.out 58 | *.app 59 | 60 | 61 | # 62 | # C 63 | # 64 | # Object files 65 | *.o 66 | *.ko 67 | *.obj 68 | *.elf 69 | 70 | # Precompiled Headers 71 | *.gch 72 | *.pch 73 | 74 | # Libraries 75 | *.lib 76 | *.a 77 | *.la 78 | *.lo 79 | 80 | # Shared objects (inc. Windows DLLs) 81 | *.dll 82 | *.so 83 | *.so.* 84 | *.dylib 85 | 86 | # Executables 87 | *.exe 88 | *.out 89 | *.app 90 | *.i*86 91 | *.x86_64 92 | *.hex 93 | 94 | # Debug files 95 | *.dSYM/ 96 | *.su 97 | 98 | # PlatformIO files/dirs 99 | .pio* 100 | .pioenvs 101 | .piolibdeps 102 | lib/readme.txt 103 | 104 | #Visual Studio 105 | *.sln 106 | *.vcxproj 107 | *.vcxproj.user 108 | *.vcxproj.filters 109 | Release/ 110 | Debug/ 111 | __vm/ 112 | .vs/ 113 | vc-fileutils.settings 114 | 115 | #Visual Studio Code 116 | .vscode 117 | .vscode/.browse.c_cpp.db* 118 | .vscode/c_cpp_properties.json 119 | .vscode/launch.json 120 | .vscode/*.db 121 | .code-workspace 122 | 123 | #CLion 124 | cmake-build-* 125 | BetsyScreen.code-workspace 126 | 127 | # ESP-IDF default build directory name 128 | build 129 | sdkconfig.old 130 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "components/arduino"] 2 | path = components/arduino 3 | url = https://github.com/espressif/arduino-esp32.git 4 | [submodule "components/TchScr_Drv"] 5 | path = components/TchScr_Drv 6 | url = https://github.com/dracir9/TchScr_Drv.git 7 | [submodule "components/Vector"] 8 | path = components/Vector 9 | url = https://github.com/dracir9/Vector.git 10 | [submodule "components/TFT_eSPI"] 11 | path = components/TFT_eSPI 12 | url = https://github.com/Bodmer/TFT_eSPI 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(3DPrintScreen) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | 3 | GNU GENERAL PUBLIC LICENSE 4 | Version 3, 29 June 2007 5 | 6 | Copyright (c) 2007 Free Software Foundation, Inc. 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | Preamble 11 | 12 | The GNU General Public License is a free, copyleft license for 13 | software and other kinds of works. 14 | 15 | The licenses for most software and other practical works are designed 16 | to take away your freedom to share and change the works. By contrast, 17 | the GNU General Public License is intended to guarantee your freedom to 18 | share and change all versions of a program--to make sure it remains free 19 | software for all its users. We, the Free Software Foundation, use the 20 | GNU General Public License for most of our software; it applies also to 21 | any other work released this way by its authors. You can apply it to 22 | your programs, too. 23 | 24 | When we speak of free software, we are referring to freedom, not 25 | price. Our General Public Licenses are designed to make sure that you 26 | have the freedom to distribute copies of free software (and charge for 27 | them if you wish), that you receive source code or can get it if you 28 | want it, that you can change the software or use pieces of it in new 29 | free programs, and that you know you can do these things. 30 | 31 | To protect your rights, we need to prevent others from denying you 32 | these rights or asking you to surrender the rights. Therefore, you have 33 | certain responsibilities if you distribute copies of the software, or if 34 | you modify it: responsibilities to respect the freedom of others. 35 | 36 | For example, if you distribute copies of such a program, whether 37 | gratis or for a fee, you must pass on to the recipients the same 38 | freedoms that you received. You must make sure that they, too, receive 39 | or can get the source code. And you must show them these terms so they 40 | know their rights. 41 | 42 | Developers that use the GNU GPL protect your rights with two steps: 43 | (1) assert copyright on the software, and (2) offer you this License 44 | giving you legal permission to copy, distribute and/or modify it. 45 | 46 | For the developers' and authors' protection, the GPL clearly explains 47 | that there is no warranty for this free software. For both users' and 48 | authors' sake, the GPL requires that modified versions be marked as 49 | changed, so that their problems will not be attributed erroneously to 50 | authors of previous versions. 51 | 52 | Some devices are designed to deny users access to install or run 53 | modified versions of the software inside them, although the manufacturer 54 | can do so. This is fundamentally incompatible with the aim of 55 | protecting users' freedom to change the software. The systematic 56 | pattern of such abuse occurs in the area of products for individuals to 57 | use, which is precisely where it is most unacceptable. Therefore, we 58 | have designed this version of the GPL to prohibit the practice for those 59 | products. If such problems arise substantially in other domains, we 60 | stand ready to extend this provision to those domains in future versions 61 | of the GPL, as needed to protect the freedom of users. 62 | 63 | Finally, every program is threatened constantly by software patents. 64 | States should not allow patents to restrict development and use of 65 | software on general-purpose computers, but in those that do, we wish to 66 | avoid the special danger that patents applied to a free program could 67 | make it effectively proprietary. To prevent this, the GPL assures that 68 | patents cannot be used to render the program non-free. 69 | 70 | The precise terms and conditions for copying, distribution and 71 | modification follow. 72 | 73 | TERMS AND CONDITIONS 74 | 75 | 0. Definitions. 76 | 77 | "This License" refers to version 3 of the GNU General Public License. 78 | 79 | "Copyright" also means copyright-like laws that apply to other kinds of 80 | works, such as semiconductor masks. 81 | 82 | "The Program" refers to any copyrightable work licensed under this 83 | License. Each licensee is addressed as "you". "Licensees" and 84 | "recipients" may be individuals or organizations. 85 | 86 | To "modify" a work means to copy from or adapt all or part of the work 87 | in a fashion requiring copyright permission, other than the making of an 88 | exact copy. The resulting work is called a "modified version" of the 89 | earlier work or a work "based on" the earlier work. 90 | 91 | A "covered work" means either the unmodified Program or a work based 92 | on the Program. 93 | 94 | To "propagate" a work means to do anything with it that, without 95 | permission, would make you directly or secondarily liable for 96 | infringement under applicable copyright law, except executing it on a 97 | computer or modifying a private copy. Propagation includes copying, 98 | distribution (with or without modification), making available to the 99 | public, and in some countries other activities as well. 100 | 101 | To "convey" a work means any kind of propagation that enables other 102 | parties to make or receive copies. Mere interaction with a user through 103 | a computer network, with no transfer of a copy, is not conveying. 104 | 105 | An interactive user interface displays "Appropriate Legal Notices" 106 | to the extent that it includes a convenient and prominently visible 107 | feature that (1) displays an appropriate copyright notice, and (2) 108 | tells the user that there is no warranty for the work (except to the 109 | extent that warranties are provided), that licensees may convey the 110 | work under this License, and how to view a copy of this License. If 111 | the interface presents a list of user commands or options, such as a 112 | menu, a prominent item in the list meets this criterion. 113 | 114 | 1. Source Code. 115 | 116 | The "source code" for a work means the preferred form of the work 117 | for making modifications to it. "Object code" means any non-source 118 | form of a work. 119 | 120 | A "Standard Interface" means an interface that either is an official 121 | standard defined by a recognized standards body, or, in the case of 122 | interfaces specified for a particular programming language, one that 123 | is widely used among developers working in that language. 124 | 125 | The "System Libraries" of an executable work include anything, other 126 | than the work as a whole, that (a) is included in the normal form of 127 | packaging a Major Component, but which is not part of that Major 128 | Component, and (b) serves only to enable use of the work with that 129 | Major Component, or to implement a Standard Interface for which an 130 | implementation is available to the public in source code form. A 131 | "Major Component", in this context, means a major essential component 132 | (kernel, window system, and so on) of the specific operating system 133 | (if any) on which the executable work runs, or a compiler used to 134 | produce the work, or an object code interpreter used to run it. 135 | 136 | The "Corresponding Source" for a work in object code form means all 137 | the source code needed to generate, install, and (for an executable 138 | work) run the object code and to modify the work, including scripts to 139 | control those activities. However, it does not include the work's 140 | System Libraries, or general-purpose tools or generally available free 141 | programs which are used unmodified in performing those activities but 142 | which are not part of the work. For example, Corresponding Source 143 | includes interface definition files associated with source files for 144 | the work, and the source code for shared libraries and dynamically 145 | linked subprograms that the work is specifically designed to require, 146 | such as by intimate data communication or control flow between those 147 | subprograms and other parts of the work. 148 | 149 | The Corresponding Source need not include anything that users 150 | can regenerate automatically from other parts of the Corresponding 151 | Source. 152 | 153 | The Corresponding Source for a work in source code form is that 154 | same work. 155 | 156 | 2. Basic Permissions. 157 | 158 | All rights granted under this License are granted for the term of 159 | copyright on the Program, and are irrevocable provided the stated 160 | conditions are met. This License explicitly affirms your unlimited 161 | permission to run the unmodified Program. The output from running a 162 | covered work is covered by this License only if the output, given its 163 | content, constitutes a covered work. This License acknowledges your 164 | rights of fair use or other equivalent, as provided by copyright law. 165 | 166 | You may make, run and propagate covered works that you do not 167 | convey, without conditions so long as your license otherwise remains 168 | in force. You may convey covered works to others for the sole purpose 169 | of having them make modifications exclusively for you, or provide you 170 | with facilities for running those works, provided that you comply with 171 | the terms of this License in conveying all material for which you do 172 | not control copyright. Those thus making or running the covered works 173 | for you must do so exclusively on your behalf, under your direction 174 | and control, on terms that prohibit them from making any copies of 175 | your copyrighted material outside their relationship with you. 176 | 177 | Conveying under any other circumstances is permitted solely under 178 | the conditions stated below. Sublicensing is not allowed; section 10 179 | makes it unnecessary. 180 | 181 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 182 | 183 | No covered work shall be deemed part of an effective technological 184 | measure under any applicable law fulfilling obligations under article 185 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 186 | similar laws prohibiting or restricting circumvention of such 187 | measures. 188 | 189 | When you convey a covered work, you waive any legal power to forbid 190 | circumvention of technological measures to the extent such circumvention 191 | is effected by exercising rights under this License with respect to 192 | the covered work, and you disclaim any intention to limit operation or 193 | modification of the work as a means of enforcing, against the work's 194 | users, your or third parties' legal rights to forbid circumvention of 195 | technological measures. 196 | 197 | 4. Conveying Verbatim Copies. 198 | 199 | You may convey verbatim copies of the Program's source code as you 200 | receive it, in any medium, provided that you conspicuously and 201 | appropriately publish on each copy an appropriate copyright notice; 202 | keep intact all notices stating that this License and any 203 | non-permissive terms added in accord with section 7 apply to the code; 204 | keep intact all notices of the absence of any warranty; and give all 205 | recipients a copy of this License along with the Program. 206 | 207 | You may charge any price or no price for each copy that you convey, 208 | and you may offer support or warranty protection for a fee. 209 | 210 | 5. Conveying Modified Source Versions. 211 | 212 | You may convey a work based on the Program, or the modifications to 213 | produce it from the Program, in the form of source code under the 214 | terms of section 4, provided that you also meet all of these conditions: 215 | 216 | a) The work must carry prominent notices stating that you modified 217 | it, and giving a relevant date. 218 | 219 | b) The work must carry prominent notices stating that it is 220 | released under this License and any conditions added under section 221 | 7. This requirement modifies the requirement in section 4 to 222 | "keep intact all notices". 223 | 224 | c) You must license the entire work, as a whole, under this 225 | License to anyone who comes into possession of a copy. This 226 | License will therefore apply, along with any applicable section 7 227 | additional terms, to the whole of the work, and all its parts, 228 | regardless of how they are packaged. This License gives no 229 | permission to license the work in any other way, but it does not 230 | invalidate such permission if you have separately received it. 231 | 232 | d) If the work has interactive user interfaces, each must display 233 | Appropriate Legal Notices; however, if the Program has interactive 234 | interfaces that do not display Appropriate Legal Notices, your 235 | work need not make them do so. 236 | 237 | A compilation of a covered work with other separate and independent 238 | works, which are not by their nature extensions of the covered work, 239 | and which are not combined with it such as to form a larger program, 240 | in or on a volume of a storage or distribution medium, is called an 241 | "aggregate" if the compilation and its resulting copyright are not 242 | used to limit the access or legal rights of the compilation's users 243 | beyond what the individual works permit. Inclusion of a covered work 244 | in an aggregate does not cause this License to apply to the other 245 | parts of the aggregate. 246 | 247 | 6. Conveying Non-Source Forms. 248 | 249 | You may convey a covered work in object code form under the terms 250 | of sections 4 and 5, provided that you also convey the 251 | machine-readable Corresponding Source under the terms of this License, 252 | in one of these ways: 253 | 254 | a) Convey the object code in, or embodied in, a physical product 255 | (including a physical distribution medium), accompanied by the 256 | Corresponding Source fixed on a durable physical medium 257 | customarily used for software interchange. 258 | 259 | b) Convey the object code in, or embodied in, a physical product 260 | (including a physical distribution medium), accompanied by a 261 | written offer, valid for at least three years and valid for as 262 | long as you offer spare parts or customer support for that product 263 | model, to give anyone who possesses the object code either (1) a 264 | copy of the Corresponding Source for all the software in the 265 | product that is covered by this License, on a durable physical 266 | medium customarily used for software interchange, for a price no 267 | more than your reasonable cost of physically performing this 268 | conveying of source, or (2) access to copy the 269 | Corresponding Source from a network server at no charge. 270 | 271 | c) Convey individual copies of the object code with a copy of the 272 | written offer to provide the Corresponding Source. This 273 | alternative is allowed only occasionally and noncommercially, and 274 | only if you received the object code with such an offer, in accord 275 | with subsection 6b. 276 | 277 | d) Convey the object code by offering access from a designated 278 | place (gratis or for a charge), and offer equivalent access to the 279 | Corresponding Source in the same way through the same place at no 280 | further charge. You need not require recipients to copy the 281 | Corresponding Source along with the object code. If the place to 282 | copy the object code is a network server, the Corresponding Source 283 | may be on a different server (operated by you or a third party) 284 | that supports equivalent copying facilities, provided you maintain 285 | clear directions next to the object code saying where to find the 286 | Corresponding Source. Regardless of what server hosts the 287 | Corresponding Source, you remain obligated to ensure that it is 288 | available for as long as needed to satisfy these requirements. 289 | 290 | e) Convey the object code using peer-to-peer transmission, provided 291 | you inform other peers where the object code and Corresponding 292 | Source of the work are being offered to the general public at no 293 | charge under subsection 6d. 294 | 295 | A separable portion of the object code, whose source code is excluded 296 | from the Corresponding Source as a System Library, need not be 297 | included in conveying the object code work. 298 | 299 | A "User Product" is either (1) a "consumer product", which means any 300 | tangible personal property which is normally used for personal, family, 301 | or household purposes, or (2) anything designed or sold for incorporation 302 | into a dwelling. In determining whether a product is a consumer product, 303 | doubtful cases shall be resolved in favor of coverage. For a particular 304 | product received by a particular user, "normally used" refers to a 305 | typical or common use of that class of product, regardless of the status 306 | of the particular user or of the way in which the particular user 307 | actually uses, or expects or is expected to use, the product. A product 308 | is a consumer product regardless of whether the product has substantial 309 | commercial, industrial or non-consumer uses, unless such uses represent 310 | the only significant mode of use of the product. 311 | 312 | "Installation Information" for a User Product means any methods, 313 | procedures, authorization keys, or other information required to install 314 | and execute modified versions of a covered work in that User Product from 315 | a modified version of its Corresponding Source. The information must 316 | suffice to ensure that the continued functioning of the modified object 317 | code is in no case prevented or interfered with solely because 318 | modification has been made. 319 | 320 | If you convey an object code work under this section in, or with, or 321 | specifically for use in, a User Product, and the conveying occurs as 322 | part of a transaction in which the right of possession and use of the 323 | User Product is transferred to the recipient in perpetuity or for a 324 | fixed term (regardless of how the transaction is characterized), the 325 | Corresponding Source conveyed under this section must be accompanied 326 | by the Installation Information. But this requirement does not apply 327 | if neither you nor any third party retains the ability to install 328 | modified object code on the User Product (for example, the work has 329 | been installed in ROM). 330 | 331 | The requirement to provide Installation Information does not include a 332 | requirement to continue to provide support service, warranty, or updates 333 | for a work that has been modified or installed by the recipient, or for 334 | the User Product in which it has been modified or installed. Access to a 335 | network may be denied when the modification itself materially and 336 | adversely affects the operation of the network or violates the rules and 337 | protocols for communication across the network. 338 | 339 | Corresponding Source conveyed, and Installation Information provided, 340 | in accord with this section must be in a format that is publicly 341 | documented (and with an implementation available to the public in 342 | source code form), and must require no special password or key for 343 | unpacking, reading or copying. 344 | 345 | 7. Additional Terms. 346 | 347 | "Additional permissions" are terms that supplement the terms of this 348 | License by making exceptions from one or more of its conditions. 349 | Additional permissions that are applicable to the entire Program shall 350 | be treated as though they were included in this License, to the extent 351 | that they are valid under applicable law. If additional permissions 352 | apply only to part of the Program, that part may be used separately 353 | under those permissions, but the entire Program remains governed by 354 | this License without regard to the additional permissions. 355 | 356 | When you convey a copy of a covered work, you may at your option 357 | remove any additional permissions from that copy, or from any part of 358 | it. (Additional permissions may be written to require their own 359 | removal in certain cases when you modify the work.) You may place 360 | additional permissions on material, added by you to a covered work, 361 | for which you have or can give appropriate copyright permission. 362 | 363 | Notwithstanding any other provision of this License, for material you 364 | add to a covered work, you may (if authorized by the copyright holders of 365 | that material) supplement the terms of this License with terms: 366 | 367 | a) Disclaiming warranty or limiting liability differently from the 368 | terms of sections 15 and 16 of this License; or 369 | 370 | b) Requiring preservation of specified reasonable legal notices or 371 | author attributions in that material or in the Appropriate Legal 372 | Notices displayed by works containing it; or 373 | 374 | c) Prohibiting misrepresentation of the origin of that material, or 375 | requiring that modified versions of such material be marked in 376 | reasonable ways as different from the original version; or 377 | 378 | d) Limiting the use for publicity purposes of names of licensors or 379 | authors of the material; or 380 | 381 | e) Declining to grant rights under trademark law for use of some 382 | trade names, trademarks, or service marks; or 383 | 384 | f) Requiring indemnification of licensors and authors of that 385 | material by anyone who conveys the material (or modified versions of 386 | it) with contractual assumptions of liability to the recipient, for 387 | any liability that these contractual assumptions directly impose on 388 | those licensors and authors. 389 | 390 | All other non-permissive additional terms are considered "further 391 | restrictions" within the meaning of section 10. If the Program as you 392 | received it, or any part of it, contains a notice stating that it is 393 | governed by this License along with a term that is a further 394 | restriction, you may remove that term. If a license document contains 395 | a further restriction but permits relicensing or conveying under this 396 | License, you may add to a covered work material governed by the terms 397 | of that license document, provided that the further restriction does 398 | not survive such relicensing or conveying. 399 | 400 | If you add terms to a covered work in accord with this section, you 401 | must place, in the relevant source files, a statement of the 402 | additional terms that apply to those files, or a notice indicating 403 | where to find the applicable terms. 404 | 405 | Additional terms, permissive or non-permissive, may be stated in the 406 | form of a separately written license, or stated as exceptions; 407 | the above requirements apply either way. 408 | 409 | 8. Termination. 410 | 411 | You may not propagate or modify a covered work except as expressly 412 | provided under this License. Any attempt otherwise to propagate or 413 | modify it is void, and will automatically terminate your rights under 414 | this License (including any patent licenses granted under the third 415 | paragraph of section 11). 416 | 417 | However, if you cease all violation of this License, then your 418 | license from a particular copyright holder is reinstated (a) 419 | provisionally, unless and until the copyright holder explicitly and 420 | finally terminates your license, and (b) permanently, if the copyright 421 | holder fails to notify you of the violation by some reasonable means 422 | prior to 60 days after the cessation. 423 | 424 | Moreover, your license from a particular copyright holder is 425 | reinstated permanently if the copyright holder notifies you of the 426 | violation by some reasonable means, this is the first time you have 427 | received notice of violation of this License (for any work) from that 428 | copyright holder, and you cure the violation prior to 30 days after 429 | your receipt of the notice. 430 | 431 | Termination of your rights under this section does not terminate the 432 | licenses of parties who have received copies or rights from you under 433 | this License. If your rights have been terminated and not permanently 434 | reinstated, you do not qualify to receive new licenses for the same 435 | material under section 10. 436 | 437 | 9. Acceptance Not Required for Having Copies. 438 | 439 | You are not required to accept this License in order to receive or 440 | run a copy of the Program. Ancillary propagation of a covered work 441 | occurring solely as a consequence of using peer-to-peer transmission 442 | to receive a copy likewise does not require acceptance. However, 443 | nothing other than this License grants you permission to propagate or 444 | modify any covered work. These actions infringe copyright if you do 445 | not accept this License. Therefore, by modifying or propagating a 446 | covered work, you indicate your acceptance of this License to do so. 447 | 448 | 10. Automatic Licensing of Downstream Recipients. 449 | 450 | Each time you convey a covered work, the recipient automatically 451 | receives a license from the original licensors, to run, modify and 452 | propagate that work, subject to this License. You are not responsible 453 | for enforcing compliance by third parties with this License. 454 | 455 | An "entity transaction" is a transaction transferring control of an 456 | organization, or substantially all assets of one, or subdividing an 457 | organization, or merging organizations. If propagation of a covered 458 | work results from an entity transaction, each party to that 459 | transaction who receives a copy of the work also receives whatever 460 | licenses to the work the party's predecessor in interest had or could 461 | give under the previous paragraph, plus a right to possession of the 462 | Corresponding Source of the work from the predecessor in interest, if 463 | the predecessor has it or can get it with reasonable efforts. 464 | 465 | You may not impose any further restrictions on the exercise of the 466 | rights granted or affirmed under this License. For example, you may 467 | not impose a license fee, royalty, or other charge for exercise of 468 | rights granted under this License, and you may not initiate litigation 469 | (including a cross-claim or counterclaim in a lawsuit) alleging that 470 | any patent claim is infringed by making, using, selling, offering for 471 | sale, or importing the Program or any portion of it. 472 | 473 | 11. Patents. 474 | 475 | A "contributor" is a copyright holder who authorizes use under this 476 | License of the Program or a work on which the Program is based. The 477 | work thus licensed is called the contributor's "contributor version". 478 | 479 | A contributor's "essential patent claims" are all patent claims 480 | owned or controlled by the contributor, whether already acquired or 481 | hereafter acquired, that would be infringed by some manner, permitted 482 | by this License, of making, using, or selling its contributor version, 483 | but do not include claims that would be infringed only as a 484 | consequence of further modification of the contributor version. For 485 | purposes of this definition, "control" includes the right to grant 486 | patent sublicenses in a manner consistent with the requirements of 487 | this License. 488 | 489 | Each contributor grants you a non-exclusive, worldwide, royalty-free 490 | patent license under the contributor's essential patent claims, to 491 | make, use, sell, offer for sale, import and otherwise run, modify and 492 | propagate the contents of its contributor version. 493 | 494 | In the following three paragraphs, a "patent license" is any express 495 | agreement or commitment, however denominated, not to enforce a patent 496 | (such as an express permission to practice a patent or covenant not to 497 | sue for patent infringement). To "grant" such a patent license to a 498 | party means to make such an agreement or commitment not to enforce a 499 | patent against the party. 500 | 501 | If you convey a covered work, knowingly relying on a patent license, 502 | and the Corresponding Source of the work is not available for anyone 503 | to copy, free of charge and under the terms of this License, through a 504 | publicly available network server or other readily accessible means, 505 | then you must either (1) cause the Corresponding Source to be so 506 | available, or (2) arrange to deprive yourself of the benefit of the 507 | patent license for this particular work, or (3) arrange, in a manner 508 | consistent with the requirements of this License, to extend the patent 509 | license to downstream recipients. "Knowingly relying" means you have 510 | actual knowledge that, but for the patent license, your conveying the 511 | covered work in a country, or your recipient's use of the covered work 512 | in a country, would infringe one or more identifiable patents in that 513 | country that you have reason to believe are valid. 514 | 515 | If, pursuant to or in connection with a single transaction or 516 | arrangement, you convey, or propagate by procuring conveyance of, a 517 | covered work, and grant a patent license to some of the parties 518 | receiving the covered work authorizing them to use, propagate, modify 519 | or convey a specific copy of the covered work, then the patent license 520 | you grant is automatically extended to all recipients of the covered 521 | work and works based on it. 522 | 523 | A patent license is "discriminatory" if it does not include within 524 | the scope of its coverage, prohibits the exercise of, or is 525 | conditioned on the non-exercise of one or more of the rights that are 526 | specifically granted under this License. You may not convey a covered 527 | work if you are a party to an arrangement with a third party that is 528 | in the business of distributing software, under which you make payment 529 | to the third party based on the extent of your activity of conveying 530 | the work, and under which the third party grants, to any of the 531 | parties who would receive the covered work from you, a discriminatory 532 | patent license (a) in connection with copies of the covered work 533 | conveyed by you (or copies made from those copies), or (b) primarily 534 | for and in connection with specific products or compilations that 535 | contain the covered work, unless you entered into that arrangement, 536 | or that patent license was granted, prior to 28 March 2007. 537 | 538 | Nothing in this License shall be construed as excluding or limiting 539 | any implied license or other defenses to infringement that may 540 | otherwise be available to you under applicable patent law. 541 | 542 | 12. No Surrender of Others' Freedom. 543 | 544 | If conditions are imposed on you (whether by court order, agreement or 545 | otherwise) that contradict the conditions of this License, they do not 546 | excuse you from the conditions of this License. If you cannot convey a 547 | covered work so as to satisfy simultaneously your obligations under this 548 | License and any other pertinent obligations, then as a consequence you may 549 | not convey it at all. For example, if you agree to terms that obligate you 550 | to collect a royalty for further conveying from those to whom you convey 551 | the Program, the only way you could satisfy both those terms and this 552 | License would be to refrain entirely from conveying the Program. 553 | 554 | 13. Use with the GNU Affero General Public License. 555 | 556 | Notwithstanding any other provision of this License, you have 557 | permission to link or combine any covered work with a work licensed 558 | under version 3 of the GNU Affero General Public License into a single 559 | combined work, and to convey the resulting work. The terms of this 560 | License will continue to apply to the part which is the covered work, 561 | but the special requirements of the GNU Affero General Public License, 562 | section 13, concerning interaction through a network will apply to the 563 | combination as such. 564 | 565 | 14. Revised Versions of this License. 566 | 567 | The Free Software Foundation may publish revised and/or new versions of 568 | the GNU General Public License from time to time. Such new versions will 569 | be similar in spirit to the present version, but may differ in detail to 570 | address new problems or concerns. 571 | 572 | Each version is given a distinguishing version number. If the 573 | Program specifies that a certain numbered version of the GNU General 574 | Public License "or any later version" applies to it, you have the 575 | option of following the terms and conditions either of that numbered 576 | version or of any later version published by the Free Software 577 | Foundation. If the Program does not specify a version number of the 578 | GNU General Public License, you may choose any version ever published 579 | by the Free Software Foundation. 580 | 581 | If the Program specifies that a proxy can decide which future 582 | versions of the GNU General Public License can be used, that proxy's 583 | public statement of acceptance of a version permanently authorizes you 584 | to choose that version for the Program. 585 | 586 | Later license versions may give you additional or different 587 | permissions. However, no additional obligations are imposed on any 588 | author or copyright holder as a result of your choosing to follow a 589 | later version. 590 | 591 | 15. Disclaimer of Warranty. 592 | 593 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 594 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 595 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 596 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 597 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 598 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 599 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 600 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 601 | 602 | 16. Limitation of Liability. 603 | 604 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 605 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 606 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 607 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 608 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 609 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 610 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 611 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 612 | SUCH DAMAGES. 613 | 614 | 17. Interpretation of Sections 15 and 16. 615 | 616 | If the disclaimer of warranty and limitation of liability provided 617 | above cannot be given local legal effect according to their terms, 618 | reviewing courts shall apply local law that most closely approximates 619 | an absolute waiver of all civil liability in connection with the 620 | Program, unless a warranty or assumption of liability accompanies a 621 | copy of the Program in return for a fee. 622 | 623 | END OF TERMS AND CONDITIONS 624 | 625 | How to Apply These Terms to Your New Programs 626 | 627 | If you develop a new program, and you want it to be of the greatest 628 | possible use to the public, the best way to achieve this is to make it 629 | free software which everyone can redistribute and change under these terms. 630 | 631 | To do so, attach the following notices to the program. It is safest 632 | to attach them to the start of each source file to most effectively 633 | state the exclusion of warranty; and each file should have at least 634 | the "copyright" line and a pointer to where the full notice is found. 635 | 636 | {one line to give the program's name and a brief idea of what it does.} 637 | Copyright (c) {year} {name of author} 638 | 639 | This program is free software: you can redistribute it and/or modify 640 | it under the terms of the GNU General Public License as published by 641 | the Free Software Foundation, either version 3 of the License, or 642 | (at your option) any later version. 643 | 644 | This program is distributed in the hope that it will be useful, 645 | but WITHOUT ANY WARRANTY; without even the implied warranty of 646 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 647 | GNU General Public License for more details. 648 | 649 | You should have received a copy of the GNU General Public License 650 | along with this program. If not, see . 651 | 652 | Also add information on how to contact you by electronic and paper mail. 653 | 654 | If the program does terminal interaction, make it output a short 655 | notice like this when it starts in an interactive mode: 656 | 657 | {project} Copyright (c) {year} {fullname} 658 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 659 | This is free software, and you are welcome to redistribute it 660 | under certain conditions; type `show c' for details. 661 | 662 | The hypothetical commands `show w' and `show c' should show the appropriate 663 | parts of the General Public License. Of course, your program's commands 664 | might be different; for a GUI interface, you would use an "about box". 665 | 666 | You should also get your employer (if you work as a programmer) or school, 667 | if any, to sign a "copyright disclaimer" for the program, if necessary. 668 | For more information on this, and how to apply and follow the GNU GPL, see 669 | . 670 | 671 | The GNU General Public License does not permit incorporating your program 672 | into proprietary programs. If your program is a subroutine library, you 673 | may consider it more useful to permit linking proprietary applications with 674 | the library. If this is what you want to do, use the GNU Lesser General 675 | Public License instead of this License. But first, please read 676 | . 677 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3D Printer Screen 2 | 3D Printer Screen is a 3d printer controller project based arround ESP32. The purpose of this project is to add wireless connectivity to the printer and simplify its operation through LCD and touchscreen interfaces. 3 | 4 | **_Early development_** 5 | 6 | ## Hardware Prerequisites 7 | - ![This custom board](hardware/3D_Printer_Screen_V2.pdf) or another with similar wiring similar 8 | - TFT LCD display compatible with [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) library and SPI communication 9 | - ESP32 Wrover-e Rev 3 with at least 4MB of SPIRAM 10 | - EFM8BB10F8G microcontroller 11 | 12 | ## Current features 13 | - [x] SD card browser 14 | - [x] Gcode preview 15 | 16 | ## Screenshots 17 | #### Main screen 18 | ![info](/images/screenshots/screenshot_2021_1_18_3_1_7.png) 19 | #### SD card browser 20 | ![browser](/images/screenshots/screenshot_2021_1_15_23_4_5.png) 21 | ![browser](/images/screenshots/screenshot_2021_1_15_23_4_56.png) 22 | ![browser](/images/screenshots/screenshot_2021_1_15_23_4_27.png) 23 | ![browser](/images/screenshots/screenshot_2021_1_15_23_4_46.png) 24 | #### Gcode preview 25 | ![preview](/images/screenshots/screenshot_2021_1_18_18_55_15.png) Based on [this design](https://www.thingiverse.com/thing:2508515) 26 | ![preview](/images/screenshots/screenshot_2021_1_15_23_5_20.png) Based on [this design](https://www.thingiverse.com/thing:2914080) 27 | ![preview](/images/screenshots/screenshot_2021_1_15_23_6_17.png) Based on [this design](https://www.thingiverse.com/thing:826836) 28 | ![preview](/images/screenshots/screenshot_2021_1_15_23_7_13.png) Based on [this design](https://www.thingiverse.com/thing:1657791) 29 | 30 | ## Planned features 31 | - [ ] Movement, temperature, settings, file selection, etc. menus 32 | - [ ] SD card printing 33 | - [ ] WiFi printing 34 | -------------------------------------------------------------------------------- /components/GCodeRenderer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "GCodeRenderer.cpp" 2 | INCLUDE_DIRS "include" 3 | PRIV_REQUIRES Vector dbg_log) -------------------------------------------------------------------------------- /components/GCodeRenderer/include/GCodeRenderer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file GCodeRenderer.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 07-12-2021 5 | * ----- 6 | * Last Modified: 26-03-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2021 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef GCODERENDERER_H 26 | #define GCODERENDERER_H 27 | 28 | #include 29 | #include 30 | #include "freertos/FreeRTOS.h" 31 | #include "freertos/queue.h" 32 | #include "freertos/task.h" 33 | #include "freertos/semphr.h" 34 | #include "Vector.h" 35 | #include "dbg_log.h" 36 | #include "Matrix.h" 37 | 38 | struct FileInfo 39 | { 40 | bool filamentReady:1; 41 | bool timeReady:1; 42 | Vec3f camPos; 43 | time_t timestamp; 44 | float filament = 0.0f; 45 | uint32_t printTime = 0; 46 | }; 47 | 48 | class GCodeRenderer 49 | { 50 | public: 51 | constexpr static int32_t cacheLen = 3500000; 52 | constexpr static uint8_t rQueueLen = 2; 53 | constexpr static int32_t bufferLen = 4096; 54 | constexpr static uint8_t vecQueueLen = 2; 55 | constexpr static int32_t vecBufferLen = 350; 56 | constexpr static int32_t maxLineLen = 96; 57 | 58 | private: 59 | struct Pixel 60 | { 61 | int16_t x; 62 | int16_t y; 63 | uint16_t color; 64 | float z; 65 | }; 66 | 67 | struct JobData 68 | { 69 | int32_t size = -1; 70 | char* data = nullptr; 71 | }; 72 | 73 | struct VectorData 74 | { 75 | int32_t size = -1; 76 | Vec3f* data = nullptr; 77 | }; 78 | 79 | struct PrinterState 80 | { 81 | bool absPos = true; 82 | bool absEPos = true; 83 | Vec3f currentPos = Vec3f(); 84 | Vec3f nextPos = Vec3f(); 85 | Vec3f offset = Vec3f(); 86 | float currentE = 0.0f; 87 | float nextE = 0.0f; 88 | float offsetE = 0.0f; 89 | }; 90 | 91 | /** 92 | * Block contains 93 | * · Header: 94 | * - Table of the stored vector components 95 | * - Size: number of float values stored 96 | * · Data: 97 | * The actual float values corresponding to 3D vector components (X,Y,Z) 98 | */ 99 | struct GBlock 100 | { 101 | uint32_t table : 24; 102 | uint32_t size : 8; 103 | float data[]; 104 | 105 | constexpr static int32_t headBytes() { return sizeof(uint32_t); } 106 | constexpr static int32_t minBytes() { return sizeof(uint32_t) + sizeof(float)*3; } 107 | constexpr static int32_t maxSize() { return 24; } 108 | void reset(); 109 | uint16_t addPoint(Vec3f &vec, Vec3f &oldV, uint8_t &i); 110 | }; 111 | 112 | /** 113 | * Chunk contains 114 | * · Header: 115 | * - Size: number of bytes occupied by the chunk 116 | * · block: A bunch of blocks 117 | */ 118 | struct GChunk 119 | { 120 | constexpr static int32_t headBytes() { return sizeof(chunkSize[0]); } 121 | void nextBlock(); 122 | void reset(); 123 | void rewind(); 124 | int16_t addPoint(Vec3f &vec, Vec3f &oldV); 125 | int16_t readPoint(Vec3f &oldP); 126 | 127 | /** 128 | * @brief Load chunk from file 129 | * 130 | * @param buff Memory buffer to store the chunk. MUST BE OF AT LEAST 'bufferLen' BYTES! 131 | * @param file File struct where the chunk is stored 132 | * @return size_t Return the number of bytes read. Returns 0 on error. 133 | */ 134 | size_t read(void* buff, FILE* file); 135 | void setChunk(void* ptr); 136 | int16_t getSize() const { return *chunkSize; } 137 | 138 | private: 139 | uint8_t idx = 0; 140 | uint32_t mask = 1; 141 | int16_t* chunkSize; 142 | GBlock* block; 143 | }; 144 | 145 | /** 146 | * Cache contains 147 | * · size: number of bytes stored in cache 148 | * · camPos: Calculated camera position 149 | * · chunk: the current active chunk being written 150 | */ 151 | struct GCache 152 | { 153 | Vec3f camPos; 154 | GChunk chunk; 155 | 156 | GCache(); 157 | ~GCache(); 158 | void nextChunk(); 159 | void reset(); 160 | void rewind(); 161 | 162 | /** 163 | * @brief Add point to cache 164 | * 165 | * @param vec New point 166 | * @param oldV Previous point 167 | * @return int16_t Returns number of bytes written. Returns -1 on error 168 | */ 169 | int16_t addPoint(Vec3f &vec, Vec3f &oldV); 170 | size_t write(int32_t maxSize, FILE* file); 171 | 172 | /** 173 | * @brief Load cache from file. Only one chunk is read 174 | * 175 | * @param buff Memory buffer to store the cache. MUST BE OF AT LEAST 'bufferLen' BYTES! 176 | * @param file File struct where the cache is stored 177 | * @return size_t Return the number of bytes read. Returns 0 on error. 178 | */ 179 | size_t read(void* buff, FILE* file); 180 | int16_t readPoint(Vec3f &oldP); 181 | 182 | int32_t getSize() const { return size; } 183 | 184 | private: 185 | char* buffer; 186 | int32_t size = 0; 187 | int32_t readPtr = 0; 188 | int32_t nextStop = 0; 189 | int32_t lastReadPtr = 0; 190 | }; 191 | 192 | struct Boundary 193 | { 194 | Vec3f Xmax; 195 | Vec3f Xmin; 196 | Vec3f Ymax; 197 | Vec3f Ymin; 198 | }; 199 | 200 | enum renderState 201 | { 202 | STOP, // Suspended state 203 | READY, // Task ready 204 | INIT, // Initialize G Code rendering 205 | PRE_PROCESS, // PreProcess step 206 | RENDER, // Render step 207 | END, // Finalize G Code rendering 208 | ERROR 209 | }; 210 | 211 | static bool _init; 212 | static GCodeRenderer _instance; 213 | 214 | static uint8_t eState; 215 | static uint8_t isReady; // Bitmap [0: main task, 1: worker, 2: assembler] 216 | float progress = 0.0f; 217 | 218 | GCache tmpCache; 219 | bool isTmpOnRam = false; 220 | uint16_t* outImg = nullptr; 221 | float* zbuf = nullptr; 222 | 223 | FILE* rfile; 224 | FILE* wfile; 225 | char readBuffers[rQueueLen][bufferLen]; // Buffers where data to be processed is stored 226 | char vectorBuffer[vecQueueLen][vecBufferLen*sizeof(Vec3f)]; // Buffer for movement vectors and pixel data 227 | char tmpBuffer[maxLineLen]; // Temporal buffer to hold incomplete lines when reading gcode 228 | char rBuffer[bufferLen]; // System buffer for fread 229 | char wBuffer[bufferLen]; // System buffer for fwrite 230 | std::string filePath; 231 | std::string tmpPath; 232 | std::string imgPath; 233 | 234 | Vec3f camPos; 235 | static constexpr int32_t near = 200; 236 | static constexpr Vec3f lightDir = Vec3f(1.0f, 0.0f, 0.0f); 237 | static constexpr Vec3f scrOff = Vec3f(160.0f, 160.0f, 0.0f); 238 | static constexpr float camTheta = M_PI/6.0f; 239 | static constexpr float camPhi = M_PI*2.0f/3.0f; 240 | Mat3 rotMat; 241 | Mat4 projMat; 242 | 243 | FileInfo info; 244 | bool isShell = true; 245 | 246 | QueueHandle_t threadQueue; 247 | QueueHandle_t thrdRetQueue; 248 | QueueHandle_t vectorQueue; 249 | QueueHandle_t vectRetQueue; 250 | SemaphoreHandle_t readyFlag; 251 | 252 | TaskHandle_t main; 253 | TaskHandle_t worker; 254 | TaskHandle_t assembler; 255 | 256 | GCodeRenderer(); 257 | ~GCodeRenderer(); 258 | 259 | static void mainTask(void* arg); 260 | static void threadTask(void* arg); 261 | static void assemblerTask(void* arg); 262 | 263 | // Stage 1 264 | esp_err_t readFile(); 265 | esp_err_t readTmp(); 266 | 267 | // Stage 2 268 | void processGcode(); 269 | 270 | // Stage 3 271 | esp_err_t generatePath(); 272 | esp_err_t renderMesh(); 273 | 274 | // Helpers 275 | int8_t parseGcode(char* &p, PrinterState &state); 276 | void parseComment(const char* str); 277 | void checkCamPos(const Vec3f &u, Boundary &limit); 278 | 279 | // Rendering 280 | void projectLine(const Vec3f &u, const Vec3f &v); 281 | void drawLine(const Vec3f &u, const Vec3f &v, uint16_t color); 282 | void putPixel(const Pixel pix); 283 | 284 | // General functions 285 | void generateFilenames(); 286 | esp_err_t loadImg(); 287 | void init(); 288 | void stopTasks(); 289 | esp_err_t waitIdle(); 290 | 291 | public: 292 | esp_err_t begin(std::string file); 293 | void stop(); 294 | esp_err_t getRender(uint16_t** outPtr, TickType_t timeout); 295 | static GCodeRenderer* instance(); 296 | void printMinStack(); 297 | float getProgress() { return progress; }; 298 | const FileInfo* getInfo() { return &info; }; 299 | }; 300 | 301 | #endif // GCODERENDERER_H 302 | -------------------------------------------------------------------------------- /components/dbg_log/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "dbg_log.c" 2 | INCLUDE_DIRS "include") -------------------------------------------------------------------------------- /components/dbg_log/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | 3 | GNU GENERAL PUBLIC LICENSE 4 | Version 3, 29 June 2007 5 | 6 | Copyright (c) 2007 Free Software Foundation, Inc. 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | Preamble 11 | 12 | The GNU General Public License is a free, copyleft license for 13 | software and other kinds of works. 14 | 15 | The licenses for most software and other practical works are designed 16 | to take away your freedom to share and change the works. By contrast, 17 | the GNU General Public License is intended to guarantee your freedom to 18 | share and change all versions of a program--to make sure it remains free 19 | software for all its users. We, the Free Software Foundation, use the 20 | GNU General Public License for most of our software; it applies also to 21 | any other work released this way by its authors. You can apply it to 22 | your programs, too. 23 | 24 | When we speak of free software, we are referring to freedom, not 25 | price. Our General Public Licenses are designed to make sure that you 26 | have the freedom to distribute copies of free software (and charge for 27 | them if you wish), that you receive source code or can get it if you 28 | want it, that you can change the software or use pieces of it in new 29 | free programs, and that you know you can do these things. 30 | 31 | To protect your rights, we need to prevent others from denying you 32 | these rights or asking you to surrender the rights. Therefore, you have 33 | certain responsibilities if you distribute copies of the software, or if 34 | you modify it: responsibilities to respect the freedom of others. 35 | 36 | For example, if you distribute copies of such a program, whether 37 | gratis or for a fee, you must pass on to the recipients the same 38 | freedoms that you received. You must make sure that they, too, receive 39 | or can get the source code. And you must show them these terms so they 40 | know their rights. 41 | 42 | Developers that use the GNU GPL protect your rights with two steps: 43 | (1) assert copyright on the software, and (2) offer you this License 44 | giving you legal permission to copy, distribute and/or modify it. 45 | 46 | For the developers' and authors' protection, the GPL clearly explains 47 | that there is no warranty for this free software. For both users' and 48 | authors' sake, the GPL requires that modified versions be marked as 49 | changed, so that their problems will not be attributed erroneously to 50 | authors of previous versions. 51 | 52 | Some devices are designed to deny users access to install or run 53 | modified versions of the software inside them, although the manufacturer 54 | can do so. This is fundamentally incompatible with the aim of 55 | protecting users' freedom to change the software. The systematic 56 | pattern of such abuse occurs in the area of products for individuals to 57 | use, which is precisely where it is most unacceptable. Therefore, we 58 | have designed this version of the GPL to prohibit the practice for those 59 | products. If such problems arise substantially in other domains, we 60 | stand ready to extend this provision to those domains in future versions 61 | of the GPL, as needed to protect the freedom of users. 62 | 63 | Finally, every program is threatened constantly by software patents. 64 | States should not allow patents to restrict development and use of 65 | software on general-purpose computers, but in those that do, we wish to 66 | avoid the special danger that patents applied to a free program could 67 | make it effectively proprietary. To prevent this, the GPL assures that 68 | patents cannot be used to render the program non-free. 69 | 70 | The precise terms and conditions for copying, distribution and 71 | modification follow. 72 | 73 | TERMS AND CONDITIONS 74 | 75 | 0. Definitions. 76 | 77 | "This License" refers to version 3 of the GNU General Public License. 78 | 79 | "Copyright" also means copyright-like laws that apply to other kinds of 80 | works, such as semiconductor masks. 81 | 82 | "The Program" refers to any copyrightable work licensed under this 83 | License. Each licensee is addressed as "you". "Licensees" and 84 | "recipients" may be individuals or organizations. 85 | 86 | To "modify" a work means to copy from or adapt all or part of the work 87 | in a fashion requiring copyright permission, other than the making of an 88 | exact copy. The resulting work is called a "modified version" of the 89 | earlier work or a work "based on" the earlier work. 90 | 91 | A "covered work" means either the unmodified Program or a work based 92 | on the Program. 93 | 94 | To "propagate" a work means to do anything with it that, without 95 | permission, would make you directly or secondarily liable for 96 | infringement under applicable copyright law, except executing it on a 97 | computer or modifying a private copy. Propagation includes copying, 98 | distribution (with or without modification), making available to the 99 | public, and in some countries other activities as well. 100 | 101 | To "convey" a work means any kind of propagation that enables other 102 | parties to make or receive copies. Mere interaction with a user through 103 | a computer network, with no transfer of a copy, is not conveying. 104 | 105 | An interactive user interface displays "Appropriate Legal Notices" 106 | to the extent that it includes a convenient and prominently visible 107 | feature that (1) displays an appropriate copyright notice, and (2) 108 | tells the user that there is no warranty for the work (except to the 109 | extent that warranties are provided), that licensees may convey the 110 | work under this License, and how to view a copy of this License. If 111 | the interface presents a list of user commands or options, such as a 112 | menu, a prominent item in the list meets this criterion. 113 | 114 | 1. Source Code. 115 | 116 | The "source code" for a work means the preferred form of the work 117 | for making modifications to it. "Object code" means any non-source 118 | form of a work. 119 | 120 | A "Standard Interface" means an interface that either is an official 121 | standard defined by a recognized standards body, or, in the case of 122 | interfaces specified for a particular programming language, one that 123 | is widely used among developers working in that language. 124 | 125 | The "System Libraries" of an executable work include anything, other 126 | than the work as a whole, that (a) is included in the normal form of 127 | packaging a Major Component, but which is not part of that Major 128 | Component, and (b) serves only to enable use of the work with that 129 | Major Component, or to implement a Standard Interface for which an 130 | implementation is available to the public in source code form. A 131 | "Major Component", in this context, means a major essential component 132 | (kernel, window system, and so on) of the specific operating system 133 | (if any) on which the executable work runs, or a compiler used to 134 | produce the work, or an object code interpreter used to run it. 135 | 136 | The "Corresponding Source" for a work in object code form means all 137 | the source code needed to generate, install, and (for an executable 138 | work) run the object code and to modify the work, including scripts to 139 | control those activities. However, it does not include the work's 140 | System Libraries, or general-purpose tools or generally available free 141 | programs which are used unmodified in performing those activities but 142 | which are not part of the work. For example, Corresponding Source 143 | includes interface definition files associated with source files for 144 | the work, and the source code for shared libraries and dynamically 145 | linked subprograms that the work is specifically designed to require, 146 | such as by intimate data communication or control flow between those 147 | subprograms and other parts of the work. 148 | 149 | The Corresponding Source need not include anything that users 150 | can regenerate automatically from other parts of the Corresponding 151 | Source. 152 | 153 | The Corresponding Source for a work in source code form is that 154 | same work. 155 | 156 | 2. Basic Permissions. 157 | 158 | All rights granted under this License are granted for the term of 159 | copyright on the Program, and are irrevocable provided the stated 160 | conditions are met. This License explicitly affirms your unlimited 161 | permission to run the unmodified Program. The output from running a 162 | covered work is covered by this License only if the output, given its 163 | content, constitutes a covered work. This License acknowledges your 164 | rights of fair use or other equivalent, as provided by copyright law. 165 | 166 | You may make, run and propagate covered works that you do not 167 | convey, without conditions so long as your license otherwise remains 168 | in force. You may convey covered works to others for the sole purpose 169 | of having them make modifications exclusively for you, or provide you 170 | with facilities for running those works, provided that you comply with 171 | the terms of this License in conveying all material for which you do 172 | not control copyright. Those thus making or running the covered works 173 | for you must do so exclusively on your behalf, under your direction 174 | and control, on terms that prohibit them from making any copies of 175 | your copyrighted material outside their relationship with you. 176 | 177 | Conveying under any other circumstances is permitted solely under 178 | the conditions stated below. Sublicensing is not allowed; section 10 179 | makes it unnecessary. 180 | 181 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 182 | 183 | No covered work shall be deemed part of an effective technological 184 | measure under any applicable law fulfilling obligations under article 185 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 186 | similar laws prohibiting or restricting circumvention of such 187 | measures. 188 | 189 | When you convey a covered work, you waive any legal power to forbid 190 | circumvention of technological measures to the extent such circumvention 191 | is effected by exercising rights under this License with respect to 192 | the covered work, and you disclaim any intention to limit operation or 193 | modification of the work as a means of enforcing, against the work's 194 | users, your or third parties' legal rights to forbid circumvention of 195 | technological measures. 196 | 197 | 4. Conveying Verbatim Copies. 198 | 199 | You may convey verbatim copies of the Program's source code as you 200 | receive it, in any medium, provided that you conspicuously and 201 | appropriately publish on each copy an appropriate copyright notice; 202 | keep intact all notices stating that this License and any 203 | non-permissive terms added in accord with section 7 apply to the code; 204 | keep intact all notices of the absence of any warranty; and give all 205 | recipients a copy of this License along with the Program. 206 | 207 | You may charge any price or no price for each copy that you convey, 208 | and you may offer support or warranty protection for a fee. 209 | 210 | 5. Conveying Modified Source Versions. 211 | 212 | You may convey a work based on the Program, or the modifications to 213 | produce it from the Program, in the form of source code under the 214 | terms of section 4, provided that you also meet all of these conditions: 215 | 216 | a) The work must carry prominent notices stating that you modified 217 | it, and giving a relevant date. 218 | 219 | b) The work must carry prominent notices stating that it is 220 | released under this License and any conditions added under section 221 | 7. This requirement modifies the requirement in section 4 to 222 | "keep intact all notices". 223 | 224 | c) You must license the entire work, as a whole, under this 225 | License to anyone who comes into possession of a copy. This 226 | License will therefore apply, along with any applicable section 7 227 | additional terms, to the whole of the work, and all its parts, 228 | regardless of how they are packaged. This License gives no 229 | permission to license the work in any other way, but it does not 230 | invalidate such permission if you have separately received it. 231 | 232 | d) If the work has interactive user interfaces, each must display 233 | Appropriate Legal Notices; however, if the Program has interactive 234 | interfaces that do not display Appropriate Legal Notices, your 235 | work need not make them do so. 236 | 237 | A compilation of a covered work with other separate and independent 238 | works, which are not by their nature extensions of the covered work, 239 | and which are not combined with it such as to form a larger program, 240 | in or on a volume of a storage or distribution medium, is called an 241 | "aggregate" if the compilation and its resulting copyright are not 242 | used to limit the access or legal rights of the compilation's users 243 | beyond what the individual works permit. Inclusion of a covered work 244 | in an aggregate does not cause this License to apply to the other 245 | parts of the aggregate. 246 | 247 | 6. Conveying Non-Source Forms. 248 | 249 | You may convey a covered work in object code form under the terms 250 | of sections 4 and 5, provided that you also convey the 251 | machine-readable Corresponding Source under the terms of this License, 252 | in one of these ways: 253 | 254 | a) Convey the object code in, or embodied in, a physical product 255 | (including a physical distribution medium), accompanied by the 256 | Corresponding Source fixed on a durable physical medium 257 | customarily used for software interchange. 258 | 259 | b) Convey the object code in, or embodied in, a physical product 260 | (including a physical distribution medium), accompanied by a 261 | written offer, valid for at least three years and valid for as 262 | long as you offer spare parts or customer support for that product 263 | model, to give anyone who possesses the object code either (1) a 264 | copy of the Corresponding Source for all the software in the 265 | product that is covered by this License, on a durable physical 266 | medium customarily used for software interchange, for a price no 267 | more than your reasonable cost of physically performing this 268 | conveying of source, or (2) access to copy the 269 | Corresponding Source from a network server at no charge. 270 | 271 | c) Convey individual copies of the object code with a copy of the 272 | written offer to provide the Corresponding Source. This 273 | alternative is allowed only occasionally and noncommercially, and 274 | only if you received the object code with such an offer, in accord 275 | with subsection 6b. 276 | 277 | d) Convey the object code by offering access from a designated 278 | place (gratis or for a charge), and offer equivalent access to the 279 | Corresponding Source in the same way through the same place at no 280 | further charge. You need not require recipients to copy the 281 | Corresponding Source along with the object code. If the place to 282 | copy the object code is a network server, the Corresponding Source 283 | may be on a different server (operated by you or a third party) 284 | that supports equivalent copying facilities, provided you maintain 285 | clear directions next to the object code saying where to find the 286 | Corresponding Source. Regardless of what server hosts the 287 | Corresponding Source, you remain obligated to ensure that it is 288 | available for as long as needed to satisfy these requirements. 289 | 290 | e) Convey the object code using peer-to-peer transmission, provided 291 | you inform other peers where the object code and Corresponding 292 | Source of the work are being offered to the general public at no 293 | charge under subsection 6d. 294 | 295 | A separable portion of the object code, whose source code is excluded 296 | from the Corresponding Source as a System Library, need not be 297 | included in conveying the object code work. 298 | 299 | A "User Product" is either (1) a "consumer product", which means any 300 | tangible personal property which is normally used for personal, family, 301 | or household purposes, or (2) anything designed or sold for incorporation 302 | into a dwelling. In determining whether a product is a consumer product, 303 | doubtful cases shall be resolved in favor of coverage. For a particular 304 | product received by a particular user, "normally used" refers to a 305 | typical or common use of that class of product, regardless of the status 306 | of the particular user or of the way in which the particular user 307 | actually uses, or expects or is expected to use, the product. A product 308 | is a consumer product regardless of whether the product has substantial 309 | commercial, industrial or non-consumer uses, unless such uses represent 310 | the only significant mode of use of the product. 311 | 312 | "Installation Information" for a User Product means any methods, 313 | procedures, authorization keys, or other information required to install 314 | and execute modified versions of a covered work in that User Product from 315 | a modified version of its Corresponding Source. The information must 316 | suffice to ensure that the continued functioning of the modified object 317 | code is in no case prevented or interfered with solely because 318 | modification has been made. 319 | 320 | If you convey an object code work under this section in, or with, or 321 | specifically for use in, a User Product, and the conveying occurs as 322 | part of a transaction in which the right of possession and use of the 323 | User Product is transferred to the recipient in perpetuity or for a 324 | fixed term (regardless of how the transaction is characterized), the 325 | Corresponding Source conveyed under this section must be accompanied 326 | by the Installation Information. But this requirement does not apply 327 | if neither you nor any third party retains the ability to install 328 | modified object code on the User Product (for example, the work has 329 | been installed in ROM). 330 | 331 | The requirement to provide Installation Information does not include a 332 | requirement to continue to provide support service, warranty, or updates 333 | for a work that has been modified or installed by the recipient, or for 334 | the User Product in which it has been modified or installed. Access to a 335 | network may be denied when the modification itself materially and 336 | adversely affects the operation of the network or violates the rules and 337 | protocols for communication across the network. 338 | 339 | Corresponding Source conveyed, and Installation Information provided, 340 | in accord with this section must be in a format that is publicly 341 | documented (and with an implementation available to the public in 342 | source code form), and must require no special password or key for 343 | unpacking, reading or copying. 344 | 345 | 7. Additional Terms. 346 | 347 | "Additional permissions" are terms that supplement the terms of this 348 | License by making exceptions from one or more of its conditions. 349 | Additional permissions that are applicable to the entire Program shall 350 | be treated as though they were included in this License, to the extent 351 | that they are valid under applicable law. If additional permissions 352 | apply only to part of the Program, that part may be used separately 353 | under those permissions, but the entire Program remains governed by 354 | this License without regard to the additional permissions. 355 | 356 | When you convey a copy of a covered work, you may at your option 357 | remove any additional permissions from that copy, or from any part of 358 | it. (Additional permissions may be written to require their own 359 | removal in certain cases when you modify the work.) You may place 360 | additional permissions on material, added by you to a covered work, 361 | for which you have or can give appropriate copyright permission. 362 | 363 | Notwithstanding any other provision of this License, for material you 364 | add to a covered work, you may (if authorized by the copyright holders of 365 | that material) supplement the terms of this License with terms: 366 | 367 | a) Disclaiming warranty or limiting liability differently from the 368 | terms of sections 15 and 16 of this License; or 369 | 370 | b) Requiring preservation of specified reasonable legal notices or 371 | author attributions in that material or in the Appropriate Legal 372 | Notices displayed by works containing it; or 373 | 374 | c) Prohibiting misrepresentation of the origin of that material, or 375 | requiring that modified versions of such material be marked in 376 | reasonable ways as different from the original version; or 377 | 378 | d) Limiting the use for publicity purposes of names of licensors or 379 | authors of the material; or 380 | 381 | e) Declining to grant rights under trademark law for use of some 382 | trade names, trademarks, or service marks; or 383 | 384 | f) Requiring indemnification of licensors and authors of that 385 | material by anyone who conveys the material (or modified versions of 386 | it) with contractual assumptions of liability to the recipient, for 387 | any liability that these contractual assumptions directly impose on 388 | those licensors and authors. 389 | 390 | All other non-permissive additional terms are considered "further 391 | restrictions" within the meaning of section 10. If the Program as you 392 | received it, or any part of it, contains a notice stating that it is 393 | governed by this License along with a term that is a further 394 | restriction, you may remove that term. If a license document contains 395 | a further restriction but permits relicensing or conveying under this 396 | License, you may add to a covered work material governed by the terms 397 | of that license document, provided that the further restriction does 398 | not survive such relicensing or conveying. 399 | 400 | If you add terms to a covered work in accord with this section, you 401 | must place, in the relevant source files, a statement of the 402 | additional terms that apply to those files, or a notice indicating 403 | where to find the applicable terms. 404 | 405 | Additional terms, permissive or non-permissive, may be stated in the 406 | form of a separately written license, or stated as exceptions; 407 | the above requirements apply either way. 408 | 409 | 8. Termination. 410 | 411 | You may not propagate or modify a covered work except as expressly 412 | provided under this License. Any attempt otherwise to propagate or 413 | modify it is void, and will automatically terminate your rights under 414 | this License (including any patent licenses granted under the third 415 | paragraph of section 11). 416 | 417 | However, if you cease all violation of this License, then your 418 | license from a particular copyright holder is reinstated (a) 419 | provisionally, unless and until the copyright holder explicitly and 420 | finally terminates your license, and (b) permanently, if the copyright 421 | holder fails to notify you of the violation by some reasonable means 422 | prior to 60 days after the cessation. 423 | 424 | Moreover, your license from a particular copyright holder is 425 | reinstated permanently if the copyright holder notifies you of the 426 | violation by some reasonable means, this is the first time you have 427 | received notice of violation of this License (for any work) from that 428 | copyright holder, and you cure the violation prior to 30 days after 429 | your receipt of the notice. 430 | 431 | Termination of your rights under this section does not terminate the 432 | licenses of parties who have received copies or rights from you under 433 | this License. If your rights have been terminated and not permanently 434 | reinstated, you do not qualify to receive new licenses for the same 435 | material under section 10. 436 | 437 | 9. Acceptance Not Required for Having Copies. 438 | 439 | You are not required to accept this License in order to receive or 440 | run a copy of the Program. Ancillary propagation of a covered work 441 | occurring solely as a consequence of using peer-to-peer transmission 442 | to receive a copy likewise does not require acceptance. However, 443 | nothing other than this License grants you permission to propagate or 444 | modify any covered work. These actions infringe copyright if you do 445 | not accept this License. Therefore, by modifying or propagating a 446 | covered work, you indicate your acceptance of this License to do so. 447 | 448 | 10. Automatic Licensing of Downstream Recipients. 449 | 450 | Each time you convey a covered work, the recipient automatically 451 | receives a license from the original licensors, to run, modify and 452 | propagate that work, subject to this License. You are not responsible 453 | for enforcing compliance by third parties with this License. 454 | 455 | An "entity transaction" is a transaction transferring control of an 456 | organization, or substantially all assets of one, or subdividing an 457 | organization, or merging organizations. If propagation of a covered 458 | work results from an entity transaction, each party to that 459 | transaction who receives a copy of the work also receives whatever 460 | licenses to the work the party's predecessor in interest had or could 461 | give under the previous paragraph, plus a right to possession of the 462 | Corresponding Source of the work from the predecessor in interest, if 463 | the predecessor has it or can get it with reasonable efforts. 464 | 465 | You may not impose any further restrictions on the exercise of the 466 | rights granted or affirmed under this License. For example, you may 467 | not impose a license fee, royalty, or other charge for exercise of 468 | rights granted under this License, and you may not initiate litigation 469 | (including a cross-claim or counterclaim in a lawsuit) alleging that 470 | any patent claim is infringed by making, using, selling, offering for 471 | sale, or importing the Program or any portion of it. 472 | 473 | 11. Patents. 474 | 475 | A "contributor" is a copyright holder who authorizes use under this 476 | License of the Program or a work on which the Program is based. The 477 | work thus licensed is called the contributor's "contributor version". 478 | 479 | A contributor's "essential patent claims" are all patent claims 480 | owned or controlled by the contributor, whether already acquired or 481 | hereafter acquired, that would be infringed by some manner, permitted 482 | by this License, of making, using, or selling its contributor version, 483 | but do not include claims that would be infringed only as a 484 | consequence of further modification of the contributor version. For 485 | purposes of this definition, "control" includes the right to grant 486 | patent sublicenses in a manner consistent with the requirements of 487 | this License. 488 | 489 | Each contributor grants you a non-exclusive, worldwide, royalty-free 490 | patent license under the contributor's essential patent claims, to 491 | make, use, sell, offer for sale, import and otherwise run, modify and 492 | propagate the contents of its contributor version. 493 | 494 | In the following three paragraphs, a "patent license" is any express 495 | agreement or commitment, however denominated, not to enforce a patent 496 | (such as an express permission to practice a patent or covenant not to 497 | sue for patent infringement). To "grant" such a patent license to a 498 | party means to make such an agreement or commitment not to enforce a 499 | patent against the party. 500 | 501 | If you convey a covered work, knowingly relying on a patent license, 502 | and the Corresponding Source of the work is not available for anyone 503 | to copy, free of charge and under the terms of this License, through a 504 | publicly available network server or other readily accessible means, 505 | then you must either (1) cause the Corresponding Source to be so 506 | available, or (2) arrange to deprive yourself of the benefit of the 507 | patent license for this particular work, or (3) arrange, in a manner 508 | consistent with the requirements of this License, to extend the patent 509 | license to downstream recipients. "Knowingly relying" means you have 510 | actual knowledge that, but for the patent license, your conveying the 511 | covered work in a country, or your recipient's use of the covered work 512 | in a country, would infringe one or more identifiable patents in that 513 | country that you have reason to believe are valid. 514 | 515 | If, pursuant to or in connection with a single transaction or 516 | arrangement, you convey, or propagate by procuring conveyance of, a 517 | covered work, and grant a patent license to some of the parties 518 | receiving the covered work authorizing them to use, propagate, modify 519 | or convey a specific copy of the covered work, then the patent license 520 | you grant is automatically extended to all recipients of the covered 521 | work and works based on it. 522 | 523 | A patent license is "discriminatory" if it does not include within 524 | the scope of its coverage, prohibits the exercise of, or is 525 | conditioned on the non-exercise of one or more of the rights that are 526 | specifically granted under this License. You may not convey a covered 527 | work if you are a party to an arrangement with a third party that is 528 | in the business of distributing software, under which you make payment 529 | to the third party based on the extent of your activity of conveying 530 | the work, and under which the third party grants, to any of the 531 | parties who would receive the covered work from you, a discriminatory 532 | patent license (a) in connection with copies of the covered work 533 | conveyed by you (or copies made from those copies), or (b) primarily 534 | for and in connection with specific products or compilations that 535 | contain the covered work, unless you entered into that arrangement, 536 | or that patent license was granted, prior to 28 March 2007. 537 | 538 | Nothing in this License shall be construed as excluding or limiting 539 | any implied license or other defenses to infringement that may 540 | otherwise be available to you under applicable patent law. 541 | 542 | 12. No Surrender of Others' Freedom. 543 | 544 | If conditions are imposed on you (whether by court order, agreement or 545 | otherwise) that contradict the conditions of this License, they do not 546 | excuse you from the conditions of this License. If you cannot convey a 547 | covered work so as to satisfy simultaneously your obligations under this 548 | License and any other pertinent obligations, then as a consequence you may 549 | not convey it at all. For example, if you agree to terms that obligate you 550 | to collect a royalty for further conveying from those to whom you convey 551 | the Program, the only way you could satisfy both those terms and this 552 | License would be to refrain entirely from conveying the Program. 553 | 554 | 13. Use with the GNU Affero General Public License. 555 | 556 | Notwithstanding any other provision of this License, you have 557 | permission to link or combine any covered work with a work licensed 558 | under version 3 of the GNU Affero General Public License into a single 559 | combined work, and to convey the resulting work. The terms of this 560 | License will continue to apply to the part which is the covered work, 561 | but the special requirements of the GNU Affero General Public License, 562 | section 13, concerning interaction through a network will apply to the 563 | combination as such. 564 | 565 | 14. Revised Versions of this License. 566 | 567 | The Free Software Foundation may publish revised and/or new versions of 568 | the GNU General Public License from time to time. Such new versions will 569 | be similar in spirit to the present version, but may differ in detail to 570 | address new problems or concerns. 571 | 572 | Each version is given a distinguishing version number. If the 573 | Program specifies that a certain numbered version of the GNU General 574 | Public License "or any later version" applies to it, you have the 575 | option of following the terms and conditions either of that numbered 576 | version or of any later version published by the Free Software 577 | Foundation. If the Program does not specify a version number of the 578 | GNU General Public License, you may choose any version ever published 579 | by the Free Software Foundation. 580 | 581 | If the Program specifies that a proxy can decide which future 582 | versions of the GNU General Public License can be used, that proxy's 583 | public statement of acceptance of a version permanently authorizes you 584 | to choose that version for the Program. 585 | 586 | Later license versions may give you additional or different 587 | permissions. However, no additional obligations are imposed on any 588 | author or copyright holder as a result of your choosing to follow a 589 | later version. 590 | 591 | 15. Disclaimer of Warranty. 592 | 593 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 594 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 595 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 596 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 597 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 598 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 599 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 600 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 601 | 602 | 16. Limitation of Liability. 603 | 604 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 605 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 606 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 607 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 608 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 609 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 610 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 611 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 612 | SUCH DAMAGES. 613 | 614 | 17. Interpretation of Sections 15 and 16. 615 | 616 | If the disclaimer of warranty and limitation of liability provided 617 | above cannot be given local legal effect according to their terms, 618 | reviewing courts shall apply local law that most closely approximates 619 | an absolute waiver of all civil liability in connection with the 620 | Program, unless a warranty or assumption of liability accompanies a 621 | copy of the Program in return for a fee. 622 | 623 | END OF TERMS AND CONDITIONS 624 | 625 | How to Apply These Terms to Your New Programs 626 | 627 | If you develop a new program, and you want it to be of the greatest 628 | possible use to the public, the best way to achieve this is to make it 629 | free software which everyone can redistribute and change under these terms. 630 | 631 | To do so, attach the following notices to the program. It is safest 632 | to attach them to the start of each source file to most effectively 633 | state the exclusion of warranty; and each file should have at least 634 | the "copyright" line and a pointer to where the full notice is found. 635 | 636 | {one line to give the program's name and a brief idea of what it does.} 637 | Copyright (c) {year} {name of author} 638 | 639 | This program is free software: you can redistribute it and/or modify 640 | it under the terms of the GNU General Public License as published by 641 | the Free Software Foundation, either version 3 of the License, or 642 | (at your option) any later version. 643 | 644 | This program is distributed in the hope that it will be useful, 645 | but WITHOUT ANY WARRANTY; without even the implied warranty of 646 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 647 | GNU General Public License for more details. 648 | 649 | You should have received a copy of the GNU General Public License 650 | along with this program. If not, see . 651 | 652 | Also add information on how to contact you by electronic and paper mail. 653 | 654 | If the program does terminal interaction, make it output a short 655 | notice like this when it starts in an interactive mode: 656 | 657 | {project} Copyright (c) {year} {fullname} 658 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 659 | This is free software, and you are welcome to redistribute it 660 | under certain conditions; type `show c' for details. 661 | 662 | The hypothetical commands `show w' and `show c' should show the appropriate 663 | parts of the General Public License. Of course, your program's commands 664 | might be different; for a GUI interface, you would use an "about box". 665 | 666 | You should also get your employer (if you work as a programmer) or school, 667 | if any, to sign a "copyright disclaimer" for the program, if necessary. 668 | For more information on this, and how to apply and follow the GNU GPL, see 669 | . 670 | 671 | The GNU General Public License does not permit incorporating your program 672 | into proprietary programs. If your program is a subroutine library, you 673 | may consider it more useful to permit linking proprietary applications with 674 | the library. If this is what you want to do, use the GNU Lesser General 675 | Public License instead of this License. But first, please read 676 | . 677 | -------------------------------------------------------------------------------- /components/dbg_log/dbg_log.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dbg_log.c 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 04-12-2021 5 | * ----- 6 | * Last Modified: 12-02-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2021 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include 26 | #include "esp_bit_defs.h" 27 | #include "dbg_log.h" 28 | 29 | static uint8_t activeSection = 0; 30 | static uint64_t sectionD_state = UINT64_MAX; 31 | static uint64_t sectionV_state = 0; 32 | 33 | void dbg_log_define_section(uint8_t id) 34 | { 35 | if (id >= 64) return; 36 | 37 | activeSection = id; 38 | } 39 | 40 | void dbg_log_Dlevel_set(uint8_t id, bool state) 41 | { 42 | if (id >= 64) return; 43 | if (state) 44 | { 45 | sectionD_state |= BIT64(id); 46 | } 47 | else 48 | { 49 | sectionD_state &= ~BIT64(id); 50 | } 51 | } 52 | 53 | void dbg_log_Vlevel_set(uint8_t id, bool state) 54 | { 55 | if (id >= 64) return; 56 | if (state) 57 | { 58 | sectionV_state |= BIT64(id); 59 | } 60 | else 61 | { 62 | sectionV_state &= ~BIT64(id); 63 | } 64 | } 65 | 66 | static bool should_output(uint8_t level, uint8_t section) 67 | { 68 | if (level == DBG_LOG_DEBUG) 69 | { 70 | return (bool)(sectionD_state & BIT64(section)); 71 | } 72 | else if (level == DBG_LOG_VERBOSE) 73 | { 74 | return (bool)(sectionV_state & BIT64(section)); 75 | } 76 | 77 | return true; 78 | } 79 | 80 | void dbg_log_write_s(uint8_t level, const char *format, ...) 81 | { 82 | va_list list; 83 | va_start(list, format); 84 | if (should_output(level, activeSection)) 85 | { 86 | vprintf(format, list); 87 | } 88 | va_end(list); 89 | } 90 | 91 | void dbg_log_write(const char *format, ...) 92 | { 93 | va_list list; 94 | va_start(list, format); 95 | vprintf(format, list); 96 | va_end(list); 97 | } 98 | -------------------------------------------------------------------------------- /components/dbg_log/include/dbg_log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dbg_log.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 28-09-2021 5 | * ----- 6 | * Last Modified: 13-02-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2021 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef DBG_LOG_H 26 | #define DBG_LOG_H 27 | 28 | #include "esp_log.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | #define DBG_LOG_NONE 0 /*!< No log output */ 35 | #define DBG_LOG_ERROR 1 /*!< Critical errors, software module can not recover on its own */ 36 | #define DBG_LOG_WARN 2 /*!< Error conditions from which recovery measures have been taken */ 37 | #define DBG_LOG_INFO 3 /*!< Information messages which describe normal flow of events */ 38 | #define DBG_LOG_DEBUG 4 /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ 39 | #define DBG_LOG_VERBOSE 5 /*!< All information of the process. */ 40 | 41 | #define CONFIG_DBG_LOG_LEVEL DBG_LOG_DEBUG 42 | 43 | 44 | /** 45 | * @brief Create new section 46 | * 47 | * @param id Section number ID (0 < id < 64) 48 | */ 49 | void dbg_log_define_section(uint8_t id); 50 | 51 | /** 52 | * @brief Enable/disable debug level sections 53 | * 54 | * @param id Section ID 55 | * @param state New section state 56 | */ 57 | void dbg_log_Dlevel_set(uint8_t id, bool state); 58 | 59 | /** 60 | * @brief Enable/disable verbose level sections 61 | * 62 | * @param id Section ID 63 | * @param state New section state 64 | */ 65 | void dbg_log_Vlevel_set(uint8_t id, bool state); 66 | 67 | /** 68 | * @brief If section is enabled for the corresponding level print message to UART 69 | * 70 | * @param level Logging level 71 | * @param format Message 72 | * @param ... 73 | */ 74 | void dbg_log_write_s(uint8_t level, const char *format, ...); 75 | 76 | /** 77 | * @brief Print message to UART 78 | * 79 | * @param format Message 80 | * @param ... 81 | */ 82 | void dbg_log_write(const char *format, ...); 83 | 84 | #ifndef __FILENAME__ 85 | #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) 86 | #endif 87 | 88 | #if CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 89 | #define DBG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%u) %s:%u: " format LOG_RESET_COLOR "\n", esp_log_timestamp(), __FILENAME__, __LINE__ 90 | #elif CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM 91 | #define DBG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%s) %s:%u: " format LOG_RESET_COLOR "\n", esp_log_system_timestamp(), __FILENAME__, __LINE__ 92 | #endif //CONFIG_LOG_TIMESTAMP_SOURCE_xxx 93 | 94 | #define DBG_LOG_EARLY_IMPL(format, level, letter, ...) if (LOG_LOCAL_LEVEL >= level) \ 95 | esp_rom_printf(DBG_FORMAT(letter, format), ##__VA_ARGS__) 96 | 97 | /// macro to output logs in startup code, before heap allocator and syscalls have been initialized. 98 | #define DBG_EARLY_LOGE(format, ... ) DBG_LOG_EARLY_IMPL(format, ESP_LOG_ERROR, E, ##__VA_ARGS__) 99 | #define DBG_EARLY_LOGW(format, ... ) DBG_LOG_EARLY_IMPL(format, ESP_LOG_WARN, W, ##__VA_ARGS__) 100 | #define DBG_EARLY_LOGI(format, ... ) DBG_LOG_EARLY_IMPL(format, ESP_LOG_INFO, I, ##__VA_ARGS__) 101 | #define DBG_EARLY_LOGD(format, ... ) DBG_LOG_EARLY_IMPL(format, ESP_LOG_DEBUG, D, ##__VA_ARGS__) 102 | #define DBG_EARLY_LOGV(format, ... ) DBG_LOG_EARLY_IMPL(format, ESP_LOG_VERBOSE, V, ##__VA_ARGS__) 103 | 104 | // Macros 105 | #ifndef BOOTLOADER_BUILD 106 | #if CONFIG_DBG_LOG_LEVEL >= DBG_LOG_VERBOSE 107 | #define DBG_LOGV(format, ...) dbg_log_write_s(DBG_LOG_VERBOSE, DBG_FORMAT(V, format), ##__VA_ARGS__) 108 | #else 109 | #define DBG_LOGV(format, ...) 110 | #endif 111 | 112 | #if CONFIG_DBG_LOG_LEVEL >= DBG_LOG_DEBUG 113 | #define DBG_LOGD(format, ...) dbg_log_write_s(DBG_LOG_DEBUG, DBG_FORMAT(D, format), ##__VA_ARGS__) 114 | #define DBG_LOGD_IF(__e, format, ...) ({if (__e) {DBG_LOGD(format, ##__VA_ARGS__);}}) 115 | #else 116 | #define DBG_LOGD(format, ...) 117 | #define DBG_LOGD_IF(__e, format, ...) 118 | #endif 119 | 120 | #if CONFIG_DBG_LOG_LEVEL >= DBG_LOG_INFO 121 | #define DBG_LOGI(format, ...) dbg_log_write(DBG_FORMAT(I, format), ##__VA_ARGS__) 122 | #else 123 | #define DBG_LOGI(format, ...) 124 | #endif 125 | 126 | #if CONFIG_DBG_LOG_LEVEL >= DBG_LOG_WARN 127 | #define DBG_LOGW(format, ...) dbg_log_write(DBG_FORMAT(W, format), ##__VA_ARGS__) 128 | #define DBG_LOGW_IF(__e, format, ...) ({if (__e) {DBG_LOGW(format, ##__VA_ARGS__);}}) 129 | #else 130 | #define DBG_LOGW(format, ...) 131 | #define DBG_LOGW_IF(__e, format, ...) 132 | #endif 133 | 134 | #if CONFIG_DBG_LOG_LEVEL >= DBG_LOG_ERROR 135 | #define DBG_LOGE(format, ...) dbg_log_write(DBG_FORMAT(E, format), ##__VA_ARGS__) 136 | #define DBG_LOGE_IF(__e, format, ...) ({if (__e) {DBG_LOGE(format, ##__VA_ARGS__);}}) 137 | #define DBG_LOGE_AND_RETURN_IF(__e, ret, format, ...) ({ \ 138 | if (__e) { \ 139 | DBG_LOGE(format, ##__VA_ARGS__); \ 140 | return ret; \ 141 | }}) 142 | #else 143 | #define DBG_LOGE(format, ...) 144 | #define DBG_LOGE_IF(__e, format, ...) 145 | #define DBG_LOGE_AND_RETURN_IF(__e, ret, format, ...) 146 | #endif 147 | #else 148 | #define DBG_LOGV(format, ...) DBG_EARLY_LOGE(tag, format, ##__VA_ARGS__) 149 | #define DBG_LOGD(format, ...) DBG_EARLY_LOGW(tag, format, ##__VA_ARGS__) 150 | #define DBG_LOGI(format, ...) DBG_EARLY_LOGI(tag, format, ##__VA_ARGS__) 151 | #define DBG_LOGW(format, ...) DBG_EARLY_LOGD(tag, format, ##__VA_ARGS__) 152 | #define DBG_LOGE(format, ...) DBG_EARLY_LOGV(tag, format, ##__VA_ARGS__) 153 | #endif // BOOTLOADER_BUILD 154 | 155 | #ifdef __cplusplus 156 | } 157 | #endif 158 | 159 | #endif // SAFESERIAL_H 160 | -------------------------------------------------------------------------------- /data/Move_48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/Move_48.bmp -------------------------------------------------------------------------------- /data/SDcard_64.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/SDcard_64.bmp -------------------------------------------------------------------------------- /data/Settings_48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/Settings_48.bmp -------------------------------------------------------------------------------- /data/arrowL_48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/arrowL_48.bmp -------------------------------------------------------------------------------- /data/arrowR_48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/arrowR_48.bmp -------------------------------------------------------------------------------- /data/extruder_32.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/extruder_32.bmp -------------------------------------------------------------------------------- /data/fan_32.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/fan_32.bmp -------------------------------------------------------------------------------- /data/file_24.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/file_24.bmp -------------------------------------------------------------------------------- /data/folder_24.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/folder_24.bmp -------------------------------------------------------------------------------- /data/gcode_24.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/gcode_24.bmp -------------------------------------------------------------------------------- /data/heatbed_32.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/heatbed_32.bmp -------------------------------------------------------------------------------- /data/home_24.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/home_24.bmp -------------------------------------------------------------------------------- /data/return_48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/data/return_48.bmp -------------------------------------------------------------------------------- /dependencies.lock: -------------------------------------------------------------------------------- 1 | manifest_hash: c770a695e065f94af8cb38482af465269b65b1f159ce7f6157a3d0b20bea8145 2 | target: esp32 3 | version: 1.0.0 4 | -------------------------------------------------------------------------------- /hardware/3D_Printer_Screen_V2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/hardware/3D_Printer_Screen_V2.pdf -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_15_23_4_27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_15_23_4_27.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_15_23_4_46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_15_23_4_46.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_15_23_4_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_15_23_4_5.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_15_23_4_56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_15_23_4_56.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_15_23_5_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_15_23_5_20.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_15_23_6_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_15_23_6_17.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_15_23_7_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_15_23_7_13.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_18_18_55_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_18_18_55_15.png -------------------------------------------------------------------------------- /images/screenshots/screenshot_2021_1_18_3_1_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/screenshots/screenshot_2021_1_18_3_1_7.png -------------------------------------------------------------------------------- /images/wiring.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dracir9/3DPrinterScreen/3b9736767de0456ea1097454431573c981c682da/images/wiring.jpg -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FILE(GLOB_RECURSE cpp_sources ${CMAKE_SOURCE_DIR}/main/*.cpp) 2 | FILE(GLOB_RECURSE c_sources ${CMAKE_SOURCE_DIR}/main/*.c) 3 | 4 | idf_component_register( 5 | # SRCS "main.cpp" "lcdUI.cpp" "tftLCD.cpp" "utility.cpp" "widgets.cpp" "Menu/blac_w.cpp" "Menu/fileBrowser_Scr.cpp" "Menu/gcodePreview_Scr.cpp" "Menu/info_w.cpp" 6 | SRCS ${cpp_sources} ${c_sources} 7 | INCLUDE_DIRS "" 8 | ) 9 | 10 | #spiffs_create_partition_image(storage ../data FLASH_IN_PROJECT) 11 | -------------------------------------------------------------------------------- /main/Free_Fonts.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FREE_FONTS_H 3 | #define FREE_FONTS_H 4 | 5 | // Attach this header file to your sketch to use the GFX Free Fonts. You can write 6 | // sketches without it, but it makes referencing them easier. 7 | 8 | // This calls up ALL the fonts but they only get loaded if you actually 9 | // use them in your sketch. 10 | // 11 | // No changes are needed to this header file unless new fonts are added to the 12 | // library "Fonts/GFXFF" folder. 13 | // 14 | // To save a lot of typing long names, each font can easily be referenced in the 15 | // sketch in three ways, either with: 16 | // 17 | // 1. Font file name with the & in front such as &FreeSansBoldOblique24pt7b 18 | // an example being: 19 | // 20 | // tft.setFreeFont(&FreeSansBoldOblique24pt7b); 21 | // 22 | // 2. FF# where # is a number determined by looking at the list below 23 | // an example being: 24 | // 25 | // tft.setFreeFont(FF32); 26 | // 27 | // 3. An abbreviation of the file name. Look at the list below to see 28 | // the abbreviations used, for example: 29 | // 30 | // tft.setFreeFont(FSSBO24) 31 | // 32 | // Where the letters mean: 33 | // F = Free font 34 | // M = Mono 35 | // SS = Sans Serif (double S to distinguish is form serif fonts) 36 | // S = Serif 37 | // B = Bold 38 | // O = Oblique (letter O not zero) 39 | // I = Italic 40 | // # = point size, either 9, 12, 18 or 24 41 | // 42 | // Setting the font to NULL will select the GLCD font: 43 | // 44 | // tft.setFreeFont(NULL); // Set font to GLCD 45 | 46 | //#define LOAD_GFXFF 47 | 48 | #ifdef LOAD_GFXFF // Only include the fonts if LOAD_GFXFF is defined in User_Setup.h 49 | 50 | // Use these when printing or drawing text in GLCD and high rendering speed fonts 51 | // Call up the font using tft.setTextFont() 52 | #define GFXFF 1 53 | #define GLCD 0 54 | #define FONT2 2 55 | #define FONT4 4 56 | #define FONT6 6 57 | #define FONT7 7 58 | #define FONT8 8 59 | 60 | // Use the following when calling tft.setFreeFont() 61 | // 62 | // Reserved for GLCD font // FF0 63 | // 64 | 65 | #define TT1 &TomThumb 66 | 67 | #define FM9 &FreeMono9pt7b 68 | #define FM12 &FreeMono12pt7b 69 | #define FM18 &FreeMono18pt7b 70 | #define FM24 &FreeMono24pt7b 71 | 72 | #define FMB9 &FreeMonoBold9pt7b 73 | #define FMB12 &FreeMonoBold12pt7b 74 | #define FMB18 &FreeMonoBold18pt7b 75 | #define FMB24 &FreeMonoBold24pt7b 76 | 77 | #define FMO9 &FreeMonoOblique9pt7b 78 | #define FMO12 &FreeMonoOblique12pt7b 79 | #define FMO18 &FreeMonoOblique18pt7b 80 | #define FMO24 &FreeMonoOblique24pt7b 81 | 82 | #define FMBO9 &FreeMonoBoldOblique9pt7b 83 | #define FMBO12 &FreeMonoBoldOblique12pt7b 84 | #define FMBO18 &FreeMonoBoldOblique18pt7b 85 | #define FMBO24 &FreeMonoBoldOblique24pt7b 86 | 87 | #define FSS9 &FreeSans9pt7b 88 | #define FSS12 &FreeSans12pt7b 89 | #define FSS18 &FreeSans18pt7b 90 | #define FSS24 &FreeSans24pt7b 91 | 92 | #define FSSB9 &FreeSansBold9pt7b 93 | #define FSSB12 &FreeSansBold12pt7b 94 | #define FSSB18 &FreeSansBold18pt7b 95 | #define FSSB24 &FreeSansBold24pt7b 96 | 97 | #define FSSO9 &FreeSansOblique9pt7b 98 | #define FSSO12 &FreeSansOblique12pt7b 99 | #define FSSO18 &FreeSansOblique18pt7b 100 | #define FSSO24 &FreeSansOblique24pt7b 101 | 102 | #define FSSBO9 &FreeSansBoldOblique9pt7b 103 | #define FSSBO12 &FreeSansBoldOblique12pt7b 104 | #define FSSBO18 &FreeSansBoldOblique18pt7b 105 | #define FSSBO24 &FreeSansBoldOblique24pt7b 106 | 107 | #define FS9 &FreeSerif9pt7b 108 | #define FS12 &FreeSerif12pt7b 109 | #define FS18 &FreeSerif18pt7b 110 | #define FS24 &FreeSerif24pt7b 111 | 112 | #define FSI9 &FreeSerifItalic9pt7b 113 | #define FSI12 &FreeSerifItalic12pt7b 114 | #define FSI19 &FreeSerifItalic18pt7b 115 | #define FSI24 &FreeSerifItalic24pt7b 116 | 117 | #define FSB9 &FreeSerifBold9pt7b 118 | #define FSB12 &FreeSerifBold12pt7b 119 | #define FSB18 &FreeSerifBold18pt7b 120 | #define FSB24 &FreeSerifBold24pt7b 121 | 122 | #define FSBI9 &FreeSerifBoldItalic9pt7b 123 | #define FSBI12 &FreeSerifBoldItalic12pt7b 124 | #define FSBI18 &FreeSerifBoldItalic18pt7b 125 | #define FSBI24 &FreeSerifBoldItalic24pt7b 126 | 127 | #define FF0 NULL //ff0 reserved for GLCD 128 | #define FF1 &FreeMono9pt7b 129 | #define FF2 &FreeMono12pt7b 130 | #define FF3 &FreeMono18pt7b 131 | #define FF4 &FreeMono24pt7b 132 | 133 | #define FF5 &FreeMonoBold9pt7b 134 | #define FF6 &FreeMonoBold12pt7b 135 | #define FF7 &FreeMonoBold18pt7b 136 | #define FF8 &FreeMonoBold24pt7b 137 | 138 | #define FF9 &FreeMonoOblique9pt7b 139 | #define FF10 &FreeMonoOblique12pt7b 140 | #define FF11 &FreeMonoOblique18pt7b 141 | #define FF12 &FreeMonoOblique24pt7b 142 | 143 | #define FF13 &FreeMonoBoldOblique9pt7b 144 | #define FF14 &FreeMonoBoldOblique12pt7b 145 | #define FF15 &FreeMonoBoldOblique18pt7b 146 | #define FF16 &FreeMonoBoldOblique24pt7b 147 | 148 | #define FF17 &FreeSans9pt7b 149 | #define FF18 &FreeSans12pt7b 150 | #define FF19 &FreeSans18pt7b 151 | #define FF20 &FreeSans24pt7b 152 | 153 | #define FF21 &FreeSansBold9pt7b 154 | #define FF22 &FreeSansBold12pt7b 155 | #define FF23 &FreeSansBold18pt7b 156 | #define FF24 &FreeSansBold24pt7b 157 | 158 | #define FF25 &FreeSansOblique9pt7b 159 | #define FF26 &FreeSansOblique12pt7b 160 | #define FF27 &FreeSansOblique18pt7b 161 | #define FF28 &FreeSansOblique24pt7b 162 | 163 | #define FF29 &FreeSansBoldOblique9pt7b 164 | #define FF30 &FreeSansBoldOblique12pt7b 165 | #define FF31 &FreeSansBoldOblique18pt7b 166 | #define FF32 &FreeSansBoldOblique24pt7b 167 | 168 | #define FF33 &FreeSerif9pt7b 169 | #define FF34 &FreeSerif12pt7b 170 | #define FF35 &FreeSerif18pt7b 171 | #define FF36 &FreeSerif24pt7b 172 | 173 | #define FF37 &FreeSerifItalic9pt7b 174 | #define FF38 &FreeSerifItalic12pt7b 175 | #define FF39 &FreeSerifItalic18pt7b 176 | #define FF40 &FreeSerifItalic24pt7b 177 | 178 | #define FF41 &FreeSerifBold9pt7b 179 | #define FF42 &FreeSerifBold12pt7b 180 | #define FF43 &FreeSerifBold18pt7b 181 | #define FF44 &FreeSerifBold24pt7b 182 | 183 | #define FF45 &FreeSerifBoldItalic9pt7b 184 | #define FF46 &FreeSerifBoldItalic12pt7b 185 | #define FF47 &FreeSerifBoldItalic18pt7b 186 | #define FF48 &FreeSerifBoldItalic24pt7b 187 | 188 | // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 189 | // Now we define "s"tring versions for easy printing of the font name so: 190 | // tft.println(sFF5); 191 | // will print 192 | // Mono bold 9 193 | // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 194 | 195 | #define sFF0 "GLCD" 196 | #define sTT1 "Tom Thumb" 197 | #define sFF1 "Mono 9" 198 | #define sFF2 "Mono 12" 199 | #define sFF3 "Mono 18" 200 | #define sFF4 "Mono 24" 201 | 202 | #define sFF5 "Mono bold 9" 203 | #define sFF6 "Mono bold 12" 204 | #define sFF7 "Mono bold 18" 205 | #define sFF8 "Mono bold 24" 206 | 207 | #define sFF9 "Mono oblique 9" 208 | #define sFF10 "Mono oblique 12" 209 | #define sFF11 "Mono oblique 18" 210 | #define sFF12 "Mono oblique 24" 211 | 212 | #define sFF13 "Mono bold oblique 9" 213 | #define sFF14 "Mono bold oblique 12" 214 | #define sFF15 "Mono bold oblique 18" 215 | #define sFF16 "Mono bold oblique 24" // Full text line is too big for 480 pixel wide screen 216 | 217 | #define sFF17 "Sans 9" 218 | #define sFF18 "Sans 12" 219 | #define sFF19 "Sans 18" 220 | #define sFF20 "Sans 24" 221 | 222 | #define sFF21 "Sans bold 9" 223 | #define sFF22 "Sans bold 12" 224 | #define sFF23 "Sans bold 18" 225 | #define sFF24 "Sans bold 24" 226 | 227 | #define sFF25 "Sans oblique 9" 228 | #define sFF26 "Sans oblique 12" 229 | #define sFF27 "Sans oblique 18" 230 | #define sFF28 "Sans oblique 24" 231 | 232 | #define sFF29 "Sans bold oblique 9" 233 | #define sFF30 "Sans bold oblique 12" 234 | #define sFF31 "Sans bold oblique 18" 235 | #define sFF32 "Sans bold oblique 24" 236 | 237 | #define sFF33 "Serif 9" 238 | #define sFF34 "Serif 12" 239 | #define sFF35 "Serif 18" 240 | #define sFF36 "Serif 24" 241 | 242 | #define sFF37 "Serif italic 9" 243 | #define sFF38 "Serif italic 12" 244 | #define sFF39 "Serif italic 18" 245 | #define sFF40 "Serif italic 24" 246 | 247 | #define sFF41 "Serif bold 9" 248 | #define sFF42 "Serif bold 12" 249 | #define sFF43 "Serif bold 18" 250 | #define sFF44 "Serif bold 24" 251 | 252 | #define sFF45 "Serif bold italic 9" 253 | #define sFF46 "Serif bold italic 12" 254 | #define sFF47 "Serif bold italic 18" 255 | #define sFF48 "Serif bold italic 24" 256 | 257 | #else // LOAD_GFXFF not defined so setup defaults to prevent error messages 258 | 259 | // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 260 | // Free fonts are not loaded in User_Setup.h so we must define all as font 1 261 | // to prevent compile error messages 262 | // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 263 | 264 | #define GFXFF 1 265 | #define GLCD 1 266 | #define FONT2 2 267 | #define FONT4 4 268 | #define FONT6 6 269 | #define FONT7 7 270 | #define FONT8 8 271 | 272 | #define FF0 1 273 | #define FF1 1 274 | #define FF2 1 275 | #define FF3 1 276 | #define FF4 1 277 | #define FF5 1 278 | #define FF6 1 279 | #define FF7 1 280 | #define FF8 1 281 | #define FF9 1 282 | #define FF10 1 283 | #define FF11 1 284 | #define FF12 1 285 | #define FF13 1 286 | #define FF14 1 287 | #define FF15 1 288 | #define FF16 1 289 | #define FF17 1 290 | #define FF18 1 291 | #define FF19 1 292 | #define FF20 1 293 | #define FF21 1 294 | #define FF22 1 295 | #define FF23 1 296 | #define FF24 1 297 | #define FF25 1 298 | #define FF26 1 299 | #define FF27 1 300 | #define FF28 1 301 | #define FF29 1 302 | #define FF30 1 303 | #define FF31 1 304 | #define FF32 1 305 | #define FF33 1 306 | #define FF34 1 307 | #define FF35 1 308 | #define FF36 1 309 | #define FF37 1 310 | #define FF38 1 311 | #define FF39 1 312 | #define FF40 1 313 | #define FF41 1 314 | #define FF42 1 315 | #define FF43 1 316 | #define FF44 1 317 | #define FF45 1 318 | #define FF46 1 319 | #define FF47 1 320 | #define FF48 1 321 | 322 | #define FM9 1 323 | #define FM12 1 324 | #define FM18 1 325 | #define FM24 1 326 | 327 | #define FMB9 1 328 | #define FMB12 1 329 | #define FMB18 1 330 | #define FMB24 1 331 | 332 | #define FMO9 1 333 | #define FMO12 1 334 | #define FMO18 1 335 | #define FMO24 1 336 | 337 | #define FMBO9 1 338 | #define FMBO12 1 339 | #define FMBO18 1 340 | #define FMBO24 1 341 | 342 | #define FSS9 1 343 | #define FSS12 1 344 | #define FSS18 1 345 | #define FSS24 1 346 | 347 | #define FSSB9 1 348 | #define FSSB12 1 349 | #define FSSB18 1 350 | #define FSSB24 1 351 | 352 | #define FSSO9 1 353 | #define FSSO12 1 354 | #define FSSO18 1 355 | #define FSSO24 1 356 | 357 | #define FSSBO9 1 358 | #define FSSBO12 1 359 | #define FSSBO18 1 360 | #define FSSBO24 1 361 | 362 | #define FS9 1 363 | #define FS12 1 364 | #define FS18 1 365 | #define FS24 1 366 | 367 | #define FSI9 1 368 | #define FSI12 1 369 | #define FSI19 1 370 | #define FSI24 1 371 | 372 | #define FSB9 1 373 | #define FSB12 1 374 | #define FSB18 1 375 | #define FSB24 1 376 | 377 | #define FSBI9 1 378 | #define FSBI12 1 379 | #define FSBI18 1 380 | #define FSBI24 1 381 | 382 | #endif // LOAD_GFXFF 383 | #endif // FREE_FONTS_H 384 | -------------------------------------------------------------------------------- /main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Project Configuration" 2 | menu "Debug" 3 | config TOUCH_DBG 4 | bool 5 | prompt "Display touch points in LCD" 6 | default "n" 7 | help 8 | Draws a colored dot on screen when touch input is detected. 9 | 10 | config ENABLE_TIMER 11 | bool 12 | prompt "Enable tic-toc timer" 13 | default "n" 14 | help 15 | allows time to be measured with TIC and TOC macros 16 | 17 | endmenu 18 | endmenu 19 | -------------------------------------------------------------------------------- /main/Menu/black_Scr.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file black_Scr.cpp 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 11-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include "black_Scr.h" 26 | 27 | /*#################################################### 28 | Black screen 29 | ####################################################*/ 30 | Black_Scr::Black_Scr(lcdUI* UI, tftLCD& tft): 31 | Screen(UI) 32 | { 33 | tft.fillScreen(TFT_BLACK); 34 | } 35 | 36 | void Black_Scr::update(uint32_t deltaTime, TchScr_Drv& ts) 37 | { 38 | 39 | } 40 | 41 | void Black_Scr::render(tftLCD& tft) 42 | { 43 | 44 | } 45 | -------------------------------------------------------------------------------- /main/Menu/black_Scr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file black_Scr.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 11-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef BLACK_W_H 26 | #define BLACK_W_H 27 | 28 | #include "../lcdUI.h" 29 | 30 | class Black_Scr final: public Screen 31 | { 32 | public: 33 | Black_Scr(lcdUI* UI, tftLCD& tft); 34 | 35 | void update(uint32_t deltaTime, TchScr_Drv& ts) override; 36 | void render(tftLCD& tft) override; 37 | 38 | private: 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /main/Menu/config_Scr.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file config_Scr.cpp 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 11-04-2022 5 | * ----- 6 | * Last Modified: 11-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include "config_Scr.h" 26 | 27 | Config_Scr::Config_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts): 28 | Screen(UI) 29 | { 30 | tft.fillScreen(TFT_BLACK); 31 | 32 | // Bottom menu 33 | tft.drawBmpSPIFFS("/spiffs/return_48.bmp", 53, 272); 34 | tft.drawRoundRect(0, 256, 155, 64, 4, TFT_ORANGE); 35 | 36 | // Settings buttons 37 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 38 | tft.setTextFont(2); 39 | tft.setTextSize(1); 40 | tft.setTextDatum(CL_DATUM); 41 | tft.setTextPadding(202); 42 | tft.drawString("Display Settings", 10, 75); 43 | tft.drawRoundRect(0, 51, 239, 48, 4, TFT_OLIVE); 44 | 45 | Button tmpBut; 46 | tmpBut.id = 0; 47 | tmpBut.xmin = 0; 48 | tmpBut.xmax = 160; 49 | tmpBut.ymin = 256; 50 | tmpBut.ymax = 320; 51 | tmpBut.enReleaseEv = true; 52 | 53 | ts.setButton(&tmpBut); // Back to Info screen 54 | 55 | for (int i = 0; i < 2; i++) // Menu buttons 56 | { 57 | for (int j = 0; j < 4; j++) 58 | { 59 | tmpBut.id = j + i*4 + 1; 60 | tmpBut.xmin = i * 240; 61 | tmpBut.xmax = i * 240 + 240; 62 | tmpBut.ymin = 50 * j + 50; 63 | tmpBut.ymax = 50 * j + 100; 64 | ts.setButton(&tmpBut); 65 | } 66 | } 67 | } 68 | 69 | void Config_Scr::update(uint32_t deltaTime, TchScr_Drv& ts) 70 | { 71 | 72 | } 73 | 74 | void Config_Scr::render(tftLCD& tft) 75 | { 76 | 77 | } 78 | 79 | void Config_Scr::handleTouch(const TchEvent& event) 80 | { 81 | if (event.trigger != TrgSrc::RELEASE) return; 82 | if (event.id == 0) 83 | { 84 | _UI->setScreen(lcdUI::Info); 85 | } 86 | else if(event.id == 1) 87 | { 88 | _UI->setScreen(lcdUI::DisplayConf); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /main/Menu/config_Scr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file config_Scr.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 11-04-2022 5 | * ----- 6 | * Last Modified: 11-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef CONFIG_SCR_H 26 | #define CONFIG_SCR_H 27 | 28 | #include "../lcdUI.h" 29 | 30 | class Config_Scr final: public Screen 31 | { 32 | public: 33 | Config_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts); 34 | 35 | void update(uint32_t deltaTime, TchScr_Drv& ts) override; 36 | void render(tftLCD& tft) override; 37 | void handleTouch(const TchEvent& event) override; 38 | }; 39 | 40 | #endif // CONFIG_SCR_H 41 | -------------------------------------------------------------------------------- /main/Menu/displayConf_Scr.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file displayConf_Scr.cpp 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 11-04-2022 5 | * ----- 6 | * Last Modified: 15-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include "displayConf_Scr.h" 26 | 27 | DisplayConf_Scr::DisplayConf_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts): 28 | Screen(UI) 29 | { 30 | tft.fillScreen(TFT_BLACK); 31 | 32 | // Bottom menu 33 | tft.drawBmpSPIFFS("/spiffs/return_48.bmp", 53, 272); 34 | tft.drawRoundRect(0, 256, 155, 64, 4, TFT_ORANGE); 35 | 36 | // Slider 37 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 38 | tft.setTextFont(2); 39 | tft.setTextSize(1); 40 | tft.setTextDatum(CL_DATUM); 41 | tft.setTextPadding(0); 42 | tft.drawString("Display Brightness:", 10, 75); 43 | tft.drawRoundRect(0, 51, 239, 48, 4, TFT_OLIVE); 44 | sliderX = _UI->getBrightness()*190/255; 45 | tft.drawRoundRect(241, 51, 239, 48, 4, TFT_OLIVE); 46 | 47 | Button tmpBut; 48 | tmpBut.id = 0; 49 | tmpBut.xmin = 0; 50 | tmpBut.xmax = 160; 51 | tmpBut.ymin = 256; 52 | tmpBut.ymax = 320; 53 | tmpBut.enReleaseEv = true; 54 | 55 | ts.setButton(&tmpBut); // Back to Config screen 56 | 57 | tmpBut.id = 1; 58 | tmpBut.enHoldEv = true; 59 | tmpBut.enHoldTickEv = true; 60 | tmpBut.enReleaseEv = false; 61 | tmpBut.holdTime = 0; 62 | tmpBut.xmin = 261; 63 | tmpBut.xmax = 461; 64 | tmpBut.ymin = 50; 65 | tmpBut.ymax = 100; 66 | 67 | ts.setButton(&tmpBut); // Brightness slider 68 | } 69 | 70 | void DisplayConf_Scr::update(uint32_t deltaTime, TchScr_Drv& ts) 71 | { 72 | _UI->setBrightness(sliderX*255/190); 73 | } 74 | 75 | void DisplayConf_Scr::render(tftLCD& tft) 76 | { 77 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 78 | tft.setTextFont(2); 79 | tft.setTextSize(1); 80 | tft.setTextDatum(CR_DATUM); 81 | tft.setTextPadding(40); 82 | tft.drawString(String(sliderX*100/190) + String(" %"), 229, 75); 83 | 84 | tft.img.setColorDepth(16); 85 | tft.img.createSprite(200, 40); 86 | //tft.img.fillSprite(TFT_BLACK); 87 | tft.img.fillRect(5, 20, 190, 2, TFT_WHITE); 88 | tft.img.fillRoundRect(sliderX, 0, 10, 40, 4, TFT_WHITE); 89 | tft.img.pushSprite(261, 55); 90 | tft.img.deleteSprite(); 91 | } 92 | 93 | void DisplayConf_Scr::handleTouch(const TchEvent& event) 94 | { 95 | if (event.trigger == TrgSrc::RELEASE) 96 | { 97 | if (event.id == 0) 98 | { 99 | _UI->setScreen(lcdUI::Config); 100 | } 101 | } 102 | else if (event.trigger == TrgSrc::HOLD_TICK) 103 | { 104 | sliderX = event.pos.x - 266; 105 | if (sliderX > 190) 106 | { 107 | sliderX = 190; 108 | } 109 | else if (sliderX < 0) 110 | { 111 | sliderX = 0; 112 | } 113 | _UI->requestUpdate(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /main/Menu/displayConf_Scr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file displayConf_Scr.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 11-04-2022 5 | * ----- 6 | * Last Modified: 14-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef DISPLAY_CONF_SCR_H 26 | #define DISPLAY_CONF_SCR_H 27 | 28 | #include "../lcdUI.h" 29 | 30 | class DisplayConf_Scr final: public Screen 31 | { 32 | public: 33 | DisplayConf_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts); 34 | 35 | void update(uint32_t deltaTime, TchScr_Drv& ts) override; 36 | void render(tftLCD& tft) override; 37 | void handleTouch(const TchEvent& event) override; 38 | 39 | private: 40 | int16_t sliderX = 100; 41 | }; 42 | 43 | #endif // DISPLAY_CONF_SCR_H 44 | -------------------------------------------------------------------------------- /main/Menu/fileBrowser_Scr.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fileBrowser_Scr.cpp 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 12-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include "fileBrowser_Scr.h" 26 | #include "dbg_log.h" 27 | 28 | FileBrowser_Scr::FileBrowser_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts): 29 | Screen(UI) 30 | { 31 | tft.fillScreen(TFT_BLACK); 32 | 33 | // SD Home 34 | tft.drawRoundRect(0, 0, 50, 50, 4, TFT_ORANGE); 35 | tft.drawBmpSPIFFS("/spiffs/home_24.bmp", 13, 13); 36 | 37 | tft.drawBmpSPIFFS("/spiffs/return_48.bmp", 53, 272); 38 | tft.drawRoundRect(0, 256, 155, 64, 4, TFT_ORANGE); 39 | tft.drawRoundRect(288, 256, 66, 64, 4, TFT_CYAN); 40 | 41 | // Setup buttons 42 | Button tmpBut; 43 | tmpBut.id = 0; 44 | tmpBut.xmin = 0; 45 | tmpBut.xmax = 160; 46 | tmpBut.ymin = 256; 47 | tmpBut.ymax = 320; 48 | tmpBut.enReleaseEv = true; 49 | 50 | ts.setButton(&tmpBut); // Back to Info screen 51 | 52 | tmpBut.id = 1; 53 | tmpBut.xmin = 163; 54 | tmpBut.xmax = 280; 55 | tmpBut.ymin = 256; 56 | tmpBut.ymax = 320; 57 | 58 | ts.setButton(&tmpBut); // Prev page 59 | 60 | tmpBut.id = 2; 61 | tmpBut.xmin = 362; 62 | tmpBut.xmax = 480; 63 | tmpBut.ymin = 256; 64 | tmpBut.ymax = 320; 65 | 66 | ts.setButton(&tmpBut); // Next page 67 | 68 | for (int i = 0; i < 2; i++) // File buttons 69 | { 70 | for (int j = 0; j < 4; j++) 71 | { 72 | tmpBut.id = j + i*4 + 3; 73 | tmpBut.xmin = i * 240; 74 | tmpBut.xmax = i * 240 + 240; 75 | tmpBut.ymin = 50 * j + 50; 76 | tmpBut.ymax = 50 * j + 100; 77 | ts.setButton(&tmpBut); 78 | } 79 | } 80 | 81 | tmpBut.id = 11; 82 | tmpBut.xmin = 0; 83 | tmpBut.xmax = 50; 84 | tmpBut.ymin = 0; 85 | tmpBut.ymax = 50; 86 | tmpBut.enHoldEv = true; 87 | tmpBut.holdTime = 100; 88 | 89 | ts.setButton(&tmpBut); // Return to SD root 90 | tmpBut.enHoldEv = false; 91 | 92 | for (int i = 0; i < 5; i++) // Folder navigation 93 | { 94 | tmpBut.id = i + 12; 95 | tmpBut.xmin = 50 + 86*i; 96 | tmpBut.xmax = 136 + 86*i; 97 | tmpBut.ymin = 0; 98 | tmpBut.ymax = 50; 99 | ts.setButton(&tmpBut); 100 | } 101 | } 102 | 103 | void FileBrowser_Scr::update(const uint32_t deltaTime, TchScr_Drv& ts) 104 | { 105 | if (_UI->isSDinit()) 106 | { 107 | loadPage(); 108 | } 109 | else 110 | { 111 | _UI->setScreen(lcdUI::Info); 112 | } 113 | } 114 | 115 | void FileBrowser_Scr::render(tftLCD& tft) 116 | { 117 | renderPage(tft); 118 | } 119 | 120 | bool FileBrowser_Scr::isPageLoaded() 121 | { 122 | return pageLoaded == filePage; 123 | } 124 | 125 | void FileBrowser_Scr::setPageLoaded() 126 | { 127 | pageLoaded = filePage; 128 | pageRendered = false; 129 | } 130 | 131 | void FileBrowser_Scr::updatePath(const std::string &newPath, const bool relativePath) 132 | { 133 | if (relativePath) 134 | { 135 | size_t dot = newPath.find("/.."); 136 | if (dot == -1) 137 | { 138 | path += "/" + newPath; 139 | } 140 | else 141 | { 142 | dot += 3; 143 | size_t slash = path.rfind('/'); 144 | if (slash == -1 || (newPath[dot] < '0' && newPath[dot] > '9')) 145 | { 146 | DBG_LOGE("Invalid path!"); 147 | return; 148 | } 149 | 150 | for (uint8_t i = newPath[dot]-'0'; i > 0; i--) 151 | { 152 | if (path.compare("/sdcard") == 0) break; 153 | path.erase(slash); 154 | slash = path.rfind('/'); 155 | if (slash == -1) return; 156 | } 157 | } 158 | } else 159 | { 160 | path = newPath; 161 | } 162 | DBG_LOGD("New path: %s", path.c_str()); 163 | numFilePages = 0; // Mark as new folder for reading 164 | filePage++; // Trigger page load 165 | } 166 | 167 | void FileBrowser_Scr::handleTouch(const TchEvent& event) 168 | { 169 | if (event.trigger == TrgSrc::HOLD_STRT && event.id == 11) 170 | { 171 | if (removeDir("/sdcard/.cache") == ESP_OK) 172 | DBG_LOGI("Cache deleted!"); 173 | else 174 | DBG_LOGI("Failed to delete cache"); 175 | return; 176 | } 177 | 178 | if (event.trigger != TrgSrc::RELEASE) return; 179 | 180 | bool update = true; 181 | 182 | if (event.id == 0) // Back to Main menu 183 | { 184 | _UI->setScreen(lcdUI::Info); 185 | } 186 | else if (event.id == 1 && filePage > 0) // Prev page 187 | { 188 | filePage--; 189 | } 190 | else if (event.id == 2 && filePage < numFilePages-1) // Next page 191 | { 192 | filePage++; 193 | } 194 | else if (event.id > 2 && event.id <= 10) // Open file 195 | { 196 | uint8_t idx = event.id - 3; 197 | DBG_LOGV("IDX: %d", idx); 198 | if ((isDir & (1 << idx)) > 0) updatePath(dirList[idx], true); 199 | else if (isGcode(dirList[idx])) 200 | sendFile(dirList[idx]); 201 | else 202 | update = false; 203 | } 204 | else if (event.id == 11) // Return to root 205 | { 206 | updatePath("/sdcard", false); 207 | } 208 | else if (event.id > 11 && event.id <= 16) // Navigation bar 209 | { 210 | int8_t k = fileDepth > 5 ? 5 : fileDepth; 211 | k -= event.id - 12; 212 | switch (k) 213 | { 214 | case 1: 215 | filePage = 0; 216 | break; 217 | 218 | case 2: 219 | updatePath("/..1", true); 220 | break; 221 | 222 | case 3: 223 | updatePath("/..2", true); 224 | break; 225 | 226 | case 4: 227 | updatePath("/..3", true); 228 | break; 229 | 230 | case 5: 231 | updatePath("/..4", true); 232 | break; 233 | 234 | default: 235 | update = false; 236 | break; 237 | } 238 | } 239 | else 240 | { 241 | update = false; 242 | } 243 | 244 | if (update) 245 | _UI->requestUpdate(); 246 | } 247 | 248 | esp_err_t FileBrowser_Scr::removeDir(const char* path) 249 | { 250 | static char fullName[128]; 251 | DIR *dp = opendir (path); 252 | 253 | if (dp != NULL) 254 | { 255 | struct dirent *ep; 256 | while ((ep = readdir (dp))) 257 | { 258 | if (ep->d_type == DT_DIR) 259 | { 260 | if (removeDir(ep->d_name) != ESP_OK) 261 | { 262 | closedir (dp); 263 | return ESP_FAIL; 264 | } 265 | } 266 | else 267 | { 268 | strcpy(fullName, path); 269 | strcat(fullName, "/"); 270 | strcat(fullName, ep->d_name); 271 | DBG_LOGD("%s", fullName); 272 | if (remove(fullName) != 0) 273 | { 274 | closedir (dp); 275 | return ESP_FAIL; 276 | } 277 | } 278 | } 279 | 280 | closedir (dp); 281 | remove(path); 282 | } 283 | else 284 | { 285 | DBG_LOGE("Couldn't open the directory"); 286 | return ESP_FAIL; 287 | } 288 | return ESP_OK; 289 | } 290 | 291 | void FileBrowser_Scr::renderPage(tftLCD& tft) 292 | { 293 | if (pageRendered) return; 294 | 295 | // Draw controls 296 | // Page + 297 | if (pageLoaded == 0) 298 | { 299 | tft.fillRect(163, 256, 117, 64, TFT_BLACK); 300 | } 301 | else 302 | { 303 | tft.drawBmpSPIFFS("/spiffs/arrowL_48.bmp", 197, 268); 304 | tft.drawRoundRect(163, 256, 117, 64, 4, TFT_ORANGE); 305 | } 306 | 307 | // Page - 308 | if (pageLoaded == numFilePages-1) 309 | { 310 | tft.fillRect(362, 256, 118, 64, TFT_BLACK); 311 | } 312 | else 313 | { 314 | tft.drawBmpSPIFFS("/spiffs/arrowR_48.bmp", 397, 268); 315 | tft.drawRoundRect(362, 256, 118, 64, 4, TFT_ORANGE); 316 | } 317 | 318 | // Folder path names 319 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 320 | tft.setTextFont(2); 321 | tft.setTextPadding(0); 322 | tft.setTextDatum(CC_DATUM); 323 | 324 | uint8_t idx = path.length()-1; 325 | for (uint8_t i = 5; i > 0; i--) // For each of the last 5 folders 326 | { 327 | if (i <= fileDepth) 328 | { 329 | tft.fillRect(86*i - 35, 1, 84, 48, TFT_BLACK); 330 | tft.drawRoundRect(86*i - 36, 0, 86, 50, 4, TFT_ORANGE); 331 | uint8_t len = 0; 332 | for (; idx > 0; idx--, len++) 333 | { 334 | if (path[idx] == '/') break; 335 | } 336 | 337 | std::string folderName = path.substr(idx-- +1, len); 338 | tft.drawStringWr(folderName.c_str(), 7 + 86*i, 25, 80, 48); 339 | } 340 | else 341 | { 342 | tft.fillRect(86*i - 36, 0, 86, 50, TFT_BLACK); 343 | } 344 | } 345 | 346 | tft.setTextPadding(48); 347 | tft.drawString("Page", 321, 280); 348 | tft.drawString(String(pageLoaded+1) + " of " + String(numFilePages), 321, 296); 349 | 350 | // Draw file table 351 | tft.setTextDatum(CL_DATUM); 352 | tft.setTextPadding(202); // Set pading to clear old text 353 | uint8_t k = 0; 354 | for (uint8_t i = 0; i < 2; i++) 355 | { 356 | for (uint8_t j = 0; j < 4; j++, k++) 357 | { 358 | if (dirList[k].length() == 0) 359 | { 360 | tft.fillRect(241*i, 51 + 50*j, 239, 48, TFT_BLACK); // Clear unused slots 361 | continue; 362 | } 363 | tft.fillRect(10 + 240*i, 52 + 50*j, 200, 46, TFT_BLACK); 364 | 365 | tft.drawStringWr(dirList[k].c_str(), 10 + 240*i, 75 + 50*j, 200, 48); // Write file name 366 | 367 | if ((isDir & 1< 0) 368 | tft.drawBmpSPIFFS("/spiffs/folder_24.bmp", 212 + 240*i, 63 + 50*j); // Draw folder icon 369 | else if (isGcode(dirList[k])) 370 | tft.drawBmpSPIFFS("/spiffs/gcode_24.bmp", 212 + 240*i, 63 + 50*j); // Draw gcode icon 371 | else 372 | tft.drawBmpSPIFFS("/spiffs/file_24.bmp", 212 + 240*i, 63 + 50*j); // Draw file icon 373 | 374 | tft.drawRoundRect(241*i, 51 + 50*j, 239, 48, 4, TFT_OLIVE); // Draw grid 375 | } 376 | } 377 | pageRendered = true; 378 | } 379 | 380 | void FileBrowser_Scr::loadPage() 381 | { 382 | if (isPageLoaded()) return; 383 | struct dirent *entry; 384 | DIR * dir = opendir(path.c_str()); 385 | if (!dir) 386 | { 387 | DBG_LOGE("Error opening folder %s", path.c_str()); 388 | return; 389 | } 390 | 391 | if (numFilePages == 0) // First directory read 392 | { 393 | uint16_t hidden = 0; 394 | while ((entry = readdir(dir)) && numFilePages < 255) 395 | { 396 | if (isHidden(entry->d_name)) 397 | { 398 | hidden++; 399 | continue; 400 | } 401 | numFilePages++; // Count number of files 402 | 403 | if (numFilePages % 8 == 0) hiddenFiles[numFilePages / 8] = hidden; 404 | } 405 | 406 | if (numFilePages != 0) 407 | numFilePages = (numFilePages - 1) / 8; // Translate to screen pages 408 | numFilePages++; 409 | DBG_LOGD("File Pages: %d", numFilePages); 410 | 411 | fileDepth = 0; 412 | for (uint8_t i = 1; i < path.length(); i++) 413 | { 414 | if (path[i] == '/') fileDepth++; 415 | } 416 | 417 | rewinddir(dir); 418 | filePage = 0; 419 | } 420 | 421 | isDir = 0; 422 | seekdir(dir, filePage*8 + hiddenFiles[filePage]); 423 | uint8_t i = 0; 424 | while (i < 8) 425 | { 426 | entry = readdir(dir); 427 | if (!entry) break; // No more files 428 | 429 | if (isHidden(entry->d_name)) continue; 430 | 431 | dirList[i] = entry->d_name; // Save file name 432 | 433 | if (entry->d_type == DT_DIR) isDir |= 1<setFile(path + "/" + file) == ESP_OK) 473 | _UI->setScreen(lcdUI::GcodePreview); 474 | } 475 | -------------------------------------------------------------------------------- /main/Menu/fileBrowser_Scr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fileBrowser_Scr.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 06-03-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef FILE_BROWSER_SCR_H 26 | #define FILE_BROWSER_SCR_H 27 | 28 | #include "stdio.h" 29 | #include "../lcdUI.h" 30 | #include "dirent.h" 31 | 32 | class FileBrowser_Scr final: public Screen 33 | { 34 | public: 35 | FileBrowser_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts); 36 | 37 | void update(const uint32_t deltaTime, TchScr_Drv& ts) override; 38 | 39 | void render(tftLCD& tft) override; 40 | 41 | void handleTouch(const TchEvent& event) override; 42 | 43 | private: 44 | esp_err_t removeDir(const char* path); 45 | void loadPage(); 46 | void renderPage(tftLCD& tft); 47 | bool isPageLoaded(); 48 | void setPageLoaded(); 49 | void updatePath(const std::string &newPath, const bool relativePath); 50 | bool isHidden(const char * name); 51 | bool isGcode(const std::string &file); 52 | void sendFile(const std::string &file); 53 | 54 | std::string path = "/sdcard"; 55 | std::string dirList[8]; 56 | uint8_t fileDepth = 0; 57 | uint8_t isDir = 0; 58 | uint8_t numFilePages = 0; 59 | uint8_t filePage = 0; 60 | uint8_t pageLoaded = 1; 61 | bool pageRendered = false; 62 | uint8_t hiddenFiles[32] = {0}; 63 | }; 64 | 65 | #endif -------------------------------------------------------------------------------- /main/Menu/info_Scr.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file info_w.cpp 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 12-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include "info_Scr.h" 26 | 27 | Info_Scr::Info_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts): 28 | Screen(UI), cellAdv(416.0f/(items)), cellW(cellAdv-8) 29 | { 30 | tft.fillScreen(TFT_BLACK); 31 | tft.setTextFont(2); 32 | tft.setTextSize(1); 33 | tft.setTextPadding(0); 34 | tft.setTextDatum(CC_DATUM); 35 | 36 | tft.setTextColor(TFT_BLACK); 37 | uint8_t e = 1; 38 | for (uint8_t i = 0; i < items; i++) 39 | { 40 | tft.fillRoundRect(72 + cellAdv*i, 58, cellW, 25, 4, TFT_DARKCYAN); 41 | tft.fillRoundRect(72 + cellAdv*i, 91, cellW, 25, 4, TFT_DARKCYAN); 42 | if (i < heatbed) 43 | { 44 | tft.drawBmpSPIFFS("/spiffs/heatbed_32.bmp", 72+(cellW-32)/2+cellAdv*i, 13); 45 | } 46 | else if (i < tools+heatbed) 47 | { 48 | tft.drawBmpSPIFFS("/spiffs/extruder_32.bmp", 72+(cellW-32)/2+cellAdv*i, 13); 49 | if (tools > 1) tft.drawString(String(e++), 72+cellW/2+cellAdv*i, 22); 50 | } 51 | else 52 | { 53 | tft.drawBmpSPIFFS("/spiffs/fan_32.bmp", 72+(cellW-32)/2+cellAdv*i, 13); 54 | } 55 | } 56 | tft.fillRoundRect(0, 58, 64, 25, 4, TFT_NAVY); 57 | tft.setTextColor(TFT_WHITE); 58 | tft.drawString("Current", 32, 70); 59 | tft.fillRoundRect(0, 91, 64, 25, 4, TFT_NAVY); 60 | tft.drawString("Target", 32, 103); 61 | tft.drawRoundRect(0, 0, 480, 117, 4, TFT_GREEN); 62 | 63 | tft.drawRoundRect(0, 125, 480, 25, 4, TFT_GREEN); 64 | 65 | tft.drawString("Time:", 40, 195); 66 | tft.drawString("--D --:--:--", 40, 211); 67 | tft.drawString("Remaining:", 440, 195); 68 | tft.drawString("--D --:--:--", 440, 211); 69 | tft.drawRoundRect(0, 158, 480, 90, 4, TFT_GREEN); 70 | 71 | tft.drawBmpSPIFFS("/spiffs/SDcard_64.bmp", 45, 264); 72 | tft.drawRoundRect(0, 256, 155, 64, 4, TFT_ORANGE); 73 | tft.drawBmpSPIFFS("/spiffs/move_48.bmp", 216, 264); 74 | tft.drawRoundRect(163, 256, 154, 64, 4, TFT_ORANGE); 75 | tft.drawBmpSPIFFS("/spiffs/settings_48.bmp", 378, 264); 76 | tft.drawRoundRect(325, 256, 155, 64, 4, TFT_ORANGE); 77 | 78 | // Setup buttons 79 | Button tmpBut; 80 | tmpBut.id = 0; 81 | tmpBut.xmin = 0; 82 | tmpBut.xmax = 160; 83 | tmpBut.ymin = 256; 84 | tmpBut.ymax = 320; 85 | tmpBut.enReleaseEv = true; 86 | 87 | ts.setButton(&tmpBut); // SD card button 88 | 89 | tmpBut.id = 1; 90 | tmpBut.xmin = 160; 91 | tmpBut.xmax = 320; 92 | tmpBut.enHoldEv = true; 93 | tmpBut.holdTime = 100; 94 | 95 | ts.setButton(&tmpBut); // Move button 96 | 97 | tmpBut.id = 2; 98 | tmpBut.xmin = 320; 99 | tmpBut.xmax = 480; 100 | tmpBut.enHoldEv = false; 101 | 102 | ts.setButton(&tmpBut); // Config button 103 | } 104 | 105 | void Info_Scr::update(uint32_t deltaTime, TchScr_Drv& ts) 106 | { 107 | 108 | } 109 | 110 | void Info_Scr::render(tftLCD& tft) 111 | { 112 | _UI->requestUpdate(); 113 | if (millis() < nextP) return; 114 | tft.setTextFont(2); 115 | tft.setTextSize(1); 116 | tft.setTextDatum(CC_DATUM); 117 | tft.setTextPadding(40); 118 | 119 | // Draw temperatures 120 | tft.setTextColor(TFT_WHITE, TFT_DARKCYAN); 121 | for (uint8_t i = 0; i < items; i++) 122 | { 123 | if (i < heatbed) 124 | { 125 | tft.drawString(String(random(50, 70)) + "`C", 72+cellW/2+cellAdv*i, 70); 126 | tft.drawString(String(random(50, 70)) + "`C", 72+cellW/2+cellAdv*i, 103); 127 | } 128 | else if (i < tools+heatbed) 129 | { 130 | tft.drawString(String(random(180, 250)) + "`C", 72+cellW/2+cellAdv*i, 70); 131 | tft.drawString(String(random(180, 250)) + "`C", 72+cellW/2+cellAdv*i, 103); 132 | } 133 | else 134 | { 135 | tft.drawString(String(random(0, 100)) + "%", 72+cellW/2+cellAdv*i, 70); 136 | tft.drawString(String(random(0, 100)) + "%", 72+cellW/2+cellAdv*i, 103); 137 | } 138 | } 139 | 140 | // Draw positions 141 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 142 | tft.setTextPadding(115); 143 | tft.drawString("X: " + String(random(-100, 500)), 60, 137); 144 | tft.drawString("Y: " + String(random(-100, 500)), 180, 137); 145 | tft.drawString("Z: " + String(random(-100, 500)), 300, 137); 146 | tft.drawString("Fr: " + String(random(70, 150)) + "%", 420, 137); 147 | 148 | nextP = millis() + 1000; 149 | } 150 | 151 | void Info_Scr::handleTouch(const TchEvent& event) 152 | { 153 | if (event.trigger != TrgSrc::RELEASE) return; 154 | if (event.id == 0) 155 | { 156 | if (_UI->isSDinit()) _UI->setScreen(lcdUI::FileBrowser); 157 | } 158 | else if (event.id == 1) 159 | { 160 | /* code */ 161 | } 162 | else if (event.id == 2) 163 | { 164 | _UI->setScreen(lcdUI::Config); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /main/Menu/info_Scr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file info_w.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 11-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef INFO_W_H 26 | #define INFO_W_H 27 | 28 | #include "../lcdUI.h" 29 | 30 | class Info_Scr final: public Screen 31 | { 32 | public: 33 | Info_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts); 34 | 35 | void update(uint32_t deltaTime, TchScr_Drv& ts) override; 36 | void render(tftLCD& tft) override; 37 | void handleTouch(const TchEvent& event) override; 38 | 39 | private: 40 | const uint8_t heatbed = 1;//random(0,2); 41 | const uint8_t tools = 2;//random(1,6); 42 | const uint8_t fans = 2;//random(0, min(8-tools-heatbed, 4)); 43 | const uint8_t items = heatbed + tools + fans; 44 | const float cellAdv; 45 | const uint16_t cellW; 46 | int nextP = 0; 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /main/Menu/preview_Scr.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gcodePreview_Scr.cpp 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 14-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include "preview_Scr.h" 26 | #include "dbg_log.h" 27 | 28 | Preview_Scr::Preview_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts): 29 | Screen(UI) 30 | { 31 | renderEngine = GCodeRenderer::instance(); 32 | if (renderEngine == nullptr) 33 | DBG_LOGE("Render engine uninitialized!"); 34 | 35 | displayed.reset(); 36 | tft.fillScreen(TFT_BLACK); 37 | tft.drawRoundRect(0, 0, 320, 320, 4, TFT_GREEN); 38 | tft.drawRoundRect(320, 0, 160, 50, 4, TFT_BLUE); 39 | tft.fillRoundRect(320, 220, 160, 50, 4, 0x0AE0); 40 | tft.drawRoundRect(320, 270, 160, 50, 4, TFT_ORANGE); 41 | tft.setTextFont(2); 42 | tft.setTextSize(1); 43 | tft.setTextDatum(CC_DATUM); 44 | tft.setTextPadding(0); 45 | tft.drawStringWr(_UI->getFile().substr(_UI->getFile().rfind('/')+1).c_str(), 400, 25, 150, 48); // Display filename 46 | tft.setTextColor(TFT_WHITE); 47 | tft.drawString("Start!", 400, 245); 48 | tft.drawString("Loading...", 160, 152); 49 | tft.drawBmpSPIFFS("/spiffs/return_48.bmp", 376, 277); 50 | 51 | // Setup buttons 52 | Button tmpBut; 53 | tmpBut.id = 0; 54 | tmpBut.xmin = 320; 55 | tmpBut.xmax = 480; 56 | tmpBut.ymin = 270; 57 | tmpBut.ymax = 320; 58 | tmpBut.enReleaseEv = true; 59 | 60 | ts.setButton(&tmpBut); // Back to Info screen 61 | } 62 | 63 | void Preview_Scr::update(const uint32_t deltaTime, TchScr_Drv& ts) 64 | { 65 | if (!started) 66 | { 67 | if (renderEngine->begin(_UI->getFile().c_str()) == ESP_OK) 68 | started = true; 69 | else 70 | _UI->requestUpdate(); 71 | } 72 | 73 | if (!_UI->isSDinit()) 74 | { 75 | _UI->setScreen(lcdUI::Info); 76 | } 77 | } 78 | 79 | void Preview_Scr::render(tftLCD& tft) 80 | { 81 | if (rendered) return; 82 | uint16_t* img = nullptr; 83 | // Main update loop is paused here 84 | esp_err_t ret = renderEngine->getRender(&img, pdMS_TO_TICKS(100)); 85 | if (ret == ESP_OK) 86 | { 87 | bool oldBytes = tft.getSwapBytes(); 88 | tft.setSwapBytes(true); 89 | tft.pushImage(0, 0, 320, 320, img); 90 | tft.setSwapBytes(oldBytes); 91 | tft.drawRoundRect(0, 0, 320, 320, 4, TFT_GREEN); 92 | rendered = true; 93 | drawInfo(tft); 94 | } 95 | else if (ret == ESP_FAIL) 96 | { 97 | tft.setTextDatum(CC_DATUM); 98 | tft.setTextFont(4); 99 | tft.setTextSize(1); 100 | tft.setTextPadding(150); 101 | tft.setTextColor(TFT_WHITE, TFT_RED); 102 | tft.drawString("Render error", 160, 160); 103 | rendered = true; 104 | } 105 | else 106 | { 107 | drawInfo(tft); 108 | _UI->requestUpdate(); 109 | } 110 | } 111 | 112 | void Preview_Scr::handleTouch(const TchEvent& event) 113 | { 114 | if (event.trigger == TrgSrc::RELEASE && event.id == 0) 115 | { 116 | _UI->clearFile(); 117 | _UI->setScreen(lcdUI::FileBrowser); 118 | } 119 | } 120 | 121 | void Preview_Scr::drawInfo(tftLCD& tft) 122 | { 123 | // Text settings 124 | tft.setTextDatum(TL_DATUM); 125 | tft.setTextFont(2); 126 | tft.setTextSize(1); 127 | tft.setTextPadding(0); 128 | tft.setTextColor(TFT_WHITE); 129 | String txt; 130 | 131 | const FileInfo* info = renderEngine->getInfo(); 132 | 133 | if (info->filamentReady && !displayed[0]) 134 | { 135 | tft.drawString("Filament cost: " , 328, 55); 136 | txt = String(info->filament, 3) + " m"; 137 | tft.drawString(txt, 335, 71); 138 | displayed[0] = true; 139 | } 140 | 141 | if (info->timeReady && !displayed[1]) 142 | { 143 | tft.drawString("Estimated time: " , 328, 95); 144 | int16_t seconds = info->printTime % 60; 145 | int16_t minutes = info->printTime/60 % 60; 146 | int16_t hours = info->printTime/3600 % 24; 147 | int16_t days = info->printTime/86400; 148 | txt = ""; 149 | if (days > 0) txt += String(days) + "d "; 150 | if (hours > 0) txt += String(hours) + "h "; 151 | if (minutes > 0) txt += String(minutes) + "min "; 152 | txt += String(seconds) + "s"; 153 | tft.drawString(txt, 335, 111); 154 | displayed[1] = true; 155 | } 156 | 157 | if (!rendered) 158 | { 159 | tft.setTextDatum(CC_DATUM); 160 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 161 | tft.drawString(String(renderEngine->getProgress(), 0) + String("%"), 160, 168); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /main/Menu/preview_Scr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gcodePreview_Scr.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 24-03-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef GCODEPREVIEW_SCR_H 26 | #define GCODEPREVIEW_SCR_H 27 | 28 | #include "../lcdUI.h" 29 | #include 30 | #include "../utility.h" 31 | #include "GCodeRenderer.h" 32 | 33 | class Preview_Scr final : public Screen 34 | { 35 | public: 36 | Preview_Scr(lcdUI* UI, tftLCD& tft, TchScr_Drv& ts); 37 | 38 | void update(const uint32_t deltaTime, TchScr_Drv& ts) override; 39 | 40 | void render(tftLCD& tft) override; 41 | 42 | void handleTouch(const TchEvent& event) override; 43 | 44 | private: 45 | void drawInfo(tftLCD& tft); 46 | 47 | // Status and info 48 | std::bitset<2> displayed; 49 | GCodeRenderer* renderEngine; 50 | bool started = false; 51 | bool rendered = false; 52 | }; 53 | 54 | #endif -------------------------------------------------------------------------------- /main/Screen.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Screen.h" 3 | #include "dbg_log.h" 4 | 5 | /******************************************************************************** 6 | Screen 7 | ********************************************************************************/ 8 | Screen::Screen(lcdUI* UI) 9 | { 10 | DBG_LOGV("Create Screen\n"); 11 | _UI = UI; 12 | } 13 | 14 | Screen::~Screen() 15 | { 16 | DBG_LOGV("Delete Screen\n"); 17 | } 18 | 19 | void Screen::handleTouch(const TchEvent& event) 20 | { 21 | return; 22 | } 23 | -------------------------------------------------------------------------------- /main/Screen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef WIDGETS_H 4 | #define WIDGETS_H 5 | 6 | #include "tftLCD.h" 7 | #include "TchScr_Drv.h" 8 | 9 | class lcdUI; 10 | 11 | /************************************************************************** 12 | Base frame of the UI 13 | **************************************************************************/ 14 | class Screen 15 | { 16 | protected: 17 | lcdUI *_UI; 18 | 19 | public: 20 | Screen(lcdUI* UI); 21 | virtual ~Screen(); 22 | 23 | virtual void render(tftLCD& tft) = 0; 24 | virtual void update(const uint32_t deltaTime, TchScr_Drv& ts) = 0; 25 | virtual void handleTouch(const TchEvent& event); 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /main/lcdUI.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lcdUI.cpp 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 15-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include "lcdUI.h" 26 | #include "dbg_log.h" 27 | #include 28 | #include "driver/ledc.h" 29 | #include "Menu/info_Scr.h" 30 | #include "Menu/black_Scr.h" 31 | #include "Menu/fileBrowser_Scr.h" 32 | #include "Menu/preview_Scr.h" 33 | #include "Menu/config_Scr.h" 34 | #include "Menu/displayConf_Scr.h" 35 | 36 | bool lcdUI::init; 37 | lcdUI lcdUI::_instance; 38 | constexpr TchCalib lcdUI::calib; 39 | 40 | lcdUI::lcdUI() : 41 | touchScreen(I2C_NUM_0) 42 | { 43 | init = true; 44 | } 45 | 46 | lcdUI::~lcdUI() 47 | { 48 | vTaskDelete(cardTaskH); 49 | vTaskDelete(touchTaskH); 50 | vTaskDelete(updateTaskH); 51 | delete base; 52 | } 53 | 54 | lcdUI* lcdUI::instance() 55 | { 56 | return init ? &_instance : nullptr; 57 | } 58 | 59 | void IRAM_ATTR lcdUI::cardISRhandle(void* arg) 60 | { 61 | BaseType_t xHigherPriorityTaskWoken = false; 62 | 63 | lcdUI* UI = static_cast(arg); 64 | if (UI) 65 | vTaskNotifyGiveFromISR(UI->cardTaskH, &xHigherPriorityTaskWoken) 66 | 67 | portYIELD_FROM_ISR(xHigherPriorityTaskWoken); 68 | } 69 | 70 | void lcdUI::cardDetectTask(void* arg) 71 | { 72 | DBG_LOGI("Starting card detect task"); 73 | 74 | lcdUI* UI = static_cast(arg); 75 | gpio_config_t cardEmpty = { 76 | .pin_bit_mask = GPIO_SEL_27, 77 | .mode = GPIO_MODE_INPUT, 78 | .pull_up_en = GPIO_PULLUP_DISABLE, 79 | .pull_down_en = GPIO_PULLDOWN_DISABLE, 80 | .intr_type = GPIO_INTR_DISABLE 81 | }; 82 | 83 | gpio_config_t cardInserted = { 84 | .pin_bit_mask = GPIO_SEL_27, 85 | .mode = GPIO_MODE_OUTPUT, 86 | .pull_up_en = GPIO_PULLUP_DISABLE, 87 | .pull_down_en = GPIO_PULLDOWN_DISABLE, 88 | .intr_type = GPIO_INTR_DISABLE 89 | }; 90 | bool connected = false; 91 | 92 | while (UI) 93 | { 94 | bool prevRead = gpio_get_level(GPIO_NUM_34); 95 | if (prevRead && connected) 96 | { 97 | gpio_config(&cardEmpty); 98 | 99 | DBG_LOGD("Card disconnected"); 100 | UI->endSD(); 101 | connected = false; 102 | UI->requestUpdate(); 103 | } 104 | else if (!prevRead && !connected) 105 | { 106 | gpio_config(&cardInserted); 107 | gpio_set_level(GPIO_NUM_27, HIGH); 108 | 109 | DBG_LOGD("Card connected"); 110 | connected = UI->initSD(); 111 | UI->requestUpdate(); 112 | } 113 | ulTaskNotifyTake(pdTRUE, portMAX_DELAY); 114 | } 115 | 116 | vTaskDelete(nullptr); 117 | } 118 | 119 | void lcdUI::touchTask(void* arg) 120 | { 121 | DBG_LOGI("Starting touch task"); 122 | lcdUI* UI = static_cast(arg); 123 | 124 | esp_err_t err; 125 | err = UI->touchScreen.begin(I2C_MODE_MASTER, GPIO_NUM_32, GPIO_NUM_33, 0x22); 126 | if (err != ESP_OK) 127 | { 128 | DBG_LOGE("Error initializing touch driver"); 129 | } 130 | 131 | err = UI->touchScreen.setCalibration(&UI->calib); 132 | if (err != ESP_OK) 133 | { 134 | DBG_LOGE("Error initializing touch driver"); 135 | } 136 | 137 | err = UI->touchScreen.setThresholds(400, 10000); 138 | if (err != ESP_OK) 139 | { 140 | DBG_LOGE("Error initializing touch driver"); 141 | } 142 | 143 | err = UI->touchScreen.setNotifications(false, true, true); 144 | if (err != ESP_OK) 145 | { 146 | DBG_LOGE("Error initializing touch driver"); 147 | } 148 | 149 | while (UI) UI->processTouch(); 150 | 151 | vTaskDelete(nullptr); 152 | } 153 | 154 | void lcdUI::updateTask(void* arg) 155 | { 156 | DBG_LOGI("Starting render task"); 157 | lcdUI* UI = static_cast(arg); 158 | TickType_t xLastWakeTime = xTaskGetTickCount(); 159 | const TickType_t xFrameTime = pdMS_TO_TICKS(100); 160 | 161 | while (UI) 162 | { 163 | esp_err_t ret = UI->updateDisplay(); 164 | if (ret != ESP_OK) 165 | { 166 | DBG_LOGE("Update display failed"); 167 | break; 168 | } 169 | ulTaskNotifyTake(pdTRUE, portMAX_DELAY); 170 | vTaskDelayUntil(&xLastWakeTime, xFrameTime); 171 | xLastWakeTime = xTaskGetTickCount(); 172 | } 173 | vTaskDelete(nullptr); 174 | } 175 | 176 | esp_err_t lcdUI::begin() 177 | { 178 | if (booted) return ESP_OK; 179 | 180 | tft.begin(); 181 | tft.setRotation(1); 182 | tft.fillScreen(TFT_RED); 183 | 184 | // Crete semaphores 185 | touchMutex = xSemaphoreCreateMutex(); 186 | if (touchMutex == nullptr) 187 | { 188 | DBG_LOGE("Failed to create touch mutex"); 189 | return ESP_FAIL; 190 | } 191 | 192 | // Create tasks 193 | xTaskCreate(touchTask, "touch task", 4096, this, 1, &touchTaskH); 194 | if (touchTaskH == nullptr) 195 | { 196 | DBG_LOGE("Failed to create touch task"); 197 | return ESP_FAIL; 198 | } 199 | vTaskDelay(pdMS_TO_TICKS(100)); 200 | 201 | xTaskCreate(cardDetectTask, "cardTask", 4096, this, 0, &cardTaskH); 202 | if (cardTaskH == nullptr) 203 | { 204 | DBG_LOGE("Failed to create card detect task"); 205 | return ESP_FAIL; 206 | } 207 | vTaskDelay(pdMS_TO_TICKS(100)); 208 | 209 | xTaskCreate(updateTask, "Render task", 4096, this, 2, &updateTaskH); 210 | if (updateTaskH == nullptr) 211 | { 212 | DBG_LOGE("Failed to create render task"); 213 | return ESP_FAIL; 214 | } 215 | vTaskDelay(pdMS_TO_TICKS(100)); // Allow some time for the task to start 216 | 217 | // Configure interrupts 218 | gpio_set_intr_type(GPIO_NUM_34, GPIO_INTR_ANYEDGE); 219 | gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1); 220 | gpio_isr_handler_add(GPIO_NUM_34, cardISRhandle, this); 221 | 222 | // Configure backlight PWM 223 | ledc_timer_config_t ledcTimer = { 224 | .speed_mode = LEDC_LOW_SPEED_MODE, 225 | .duty_resolution = LEDC_TIMER_8_BIT, 226 | .timer_num = LEDC_TIMER_0, 227 | .freq_hz = 10000, 228 | .clk_cfg = LEDC_AUTO_CLK 229 | }; 230 | 231 | ESP_ERROR_CHECK(ledc_timer_config(&ledcTimer)); 232 | 233 | ledc_channel_config_t ledcChannel = { 234 | .gpio_num = 26, 235 | .speed_mode = LEDC_LOW_SPEED_MODE, 236 | .channel = LEDC_CHANNEL_0, 237 | .intr_type = LEDC_INTR_DISABLE, 238 | .timer_sel = LEDC_TIMER_0, 239 | .duty = 255, // Set duty to 100% 240 | .hpoint = 0 241 | }; 242 | 243 | ESP_ERROR_CHECK(ledc_channel_config(&ledcChannel)); 244 | 245 | booted = true; 246 | return ESP_OK; 247 | } 248 | 249 | void lcdUI::setScreen(const menu screen) 250 | { 251 | newMenuID = screen; 252 | xTaskNotifyGive(updateTaskH); 253 | } 254 | 255 | bool lcdUI::initSD() 256 | { 257 | if (!SDinit && SD_MMC.begin("/sdcard")) 258 | { 259 | DBG_LOGD("SD Card initialized"); 260 | SDinit = true; 261 | } 262 | return SDinit; 263 | } 264 | 265 | void lcdUI::endSD() 266 | { 267 | GCodeRenderer::instance()->stop(); 268 | if (SDinit) 269 | SD_MMC.end(); 270 | 271 | SDinit = false; 272 | } 273 | 274 | bool lcdUI::isSDinit() const 275 | { 276 | return SDinit; 277 | } 278 | 279 | esp_err_t lcdUI::setFile(const std::string& file) 280 | { 281 | if (access(file.c_str(), F_OK) == 0) 282 | { 283 | DBG_LOGD("Set file %s", file.c_str()); 284 | selectedFile = file; 285 | } 286 | else 287 | return ESP_ERR_NOT_FOUND; 288 | return ESP_OK; 289 | } 290 | 291 | void lcdUI::processTouch() 292 | { 293 | TchEvent event; 294 | if (touchScreen.getEvent(&event, portMAX_DELAY) != ESP_OK) return; 295 | 296 | #ifdef CONFIG_TOUCH_DBG 297 | if (event.trigger == TrgSrc::PRESS) tft.fillCircle(event.pos.x, event.pos.y, 1, TFT_YELLOW); 298 | else if (event.trigger == TrgSrc::HOLD_STRT) tft.fillCircle(event.pos.x, event.pos.y, 1, TFT_MAGENTA); 299 | else if (event.trigger == TrgSrc::HOLD_TICK) tft.fillCircle(event.pos.x, event.pos.y, 1, TFT_RED); 300 | else if (event.trigger == TrgSrc::HOLD_END) tft.fillCircle(event.pos.x, event.pos.y, 1, TFT_ORANGE); 301 | else if (event.trigger == TrgSrc::RELEASE) tft.fillCircle(event.pos.x, event.pos.y, 1, TFT_CYAN); 302 | #endif 303 | 304 | if (!base) return; 305 | xSemaphoreTake(touchMutex, portMAX_DELAY); 306 | base->handleTouch(event); 307 | xSemaphoreGive(touchMutex); 308 | } 309 | 310 | esp_err_t lcdUI::updateDisplay() 311 | { 312 | int64_t deltaTime = esp_timer_get_time() - lastRender; 313 | lastRender = esp_timer_get_time(); 314 | 315 | xSemaphoreTake(touchMutex, portMAX_DELAY); 316 | esp_err_t ret = updateObjects(); // Update to the latest screen 317 | xSemaphoreGive(touchMutex); 318 | if (ret != ESP_OK) return ret; 319 | 320 | base->update(deltaTime, touchScreen); // Update logic 321 | 322 | vTaskDelay(2); // Allow some time for other tasks 323 | 324 | base->render(tft); // Render frame 325 | 326 | updateTime = esp_timer_get_time() - lastRender; 327 | 328 | return ESP_OK; 329 | } 330 | 331 | esp_err_t lcdUI::updateObjects() 332 | { 333 | menu localMenu = newMenuID; // Local copy so that it remains unchanged 334 | if (menuID == localMenu) return ESP_OK; 335 | DBG_LOGD("Change screen to ID: %d", localMenu); 336 | 337 | tft.fillScreen(TFT_BLACK); 338 | Button clearBtn; 339 | clearBtn.id = 31; 340 | touchScreen.setButton(&clearBtn, portMAX_DELAY); 341 | 342 | delete base; 343 | base = nullptr; 344 | 345 | switch (localMenu) 346 | { 347 | case menu::black: 348 | base = new Black_Scr(this, tft); 349 | break; 350 | case menu::Info: 351 | base = new Info_Scr(this, tft, touchScreen); 352 | break; 353 | case menu::main: 354 | break; 355 | case menu::FileBrowser: 356 | base = new FileBrowser_Scr(this, tft, touchScreen); 357 | break; 358 | case menu::Config: 359 | base = new Config_Scr(this, tft, touchScreen); 360 | break; 361 | case menu::control: 362 | break; 363 | case menu::GcodePreview: 364 | base = new Preview_Scr(this, tft, touchScreen); 365 | break; 366 | case menu::DisplayConf: 367 | base = new DisplayConf_Scr(this, tft, touchScreen); 368 | break; 369 | default: 370 | base = nullptr; 371 | } 372 | 373 | if (base == nullptr) 374 | return ESP_ERR_NO_MEM; 375 | 376 | menuID = localMenu; 377 | return ESP_OK; 378 | } 379 | 380 | void lcdUI::requestUpdate() 381 | { 382 | xTaskNotifyGive(updateTaskH); 383 | } 384 | 385 | esp_err_t lcdUI::setBrightness(uint32_t duty) 386 | { 387 | if (duty > 255) 388 | duty = 255; 389 | 390 | esp_err_t ret = ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty); 391 | if (ret != ESP_OK) 392 | return ret; 393 | 394 | // Update duty 395 | ret = ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); 396 | if (ret != ESP_OK) 397 | return ret; 398 | 399 | return ESP_OK; 400 | } 401 | 402 | uint32_t lcdUI::getBrightness() 403 | { 404 | return ledc_get_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); 405 | } 406 | -------------------------------------------------------------------------------- /main/lcdUI.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lcdUI.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 15-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef LCD_UI_H 26 | #define LCD_UI_H 27 | 28 | #include "tftLCD.h" 29 | #include "Screen.h" 30 | #include "TchScr_Drv.h" 31 | 32 | class lcdUI 33 | { 34 | public: 35 | enum menu : uint8_t 36 | { 37 | none, 38 | black, 39 | Info, 40 | main, 41 | Config, 42 | FileBrowser, 43 | control, 44 | GcodePreview, 45 | DisplayConf 46 | }; 47 | 48 | private: 49 | static lcdUI _instance; 50 | static bool init; 51 | 52 | static constexpr TchCalib calib = { 53 | .dx = 480, 54 | .rx_min = 900, 55 | .rx_max = 80, 56 | .dy = 320, 57 | .ry_min = 830, 58 | .ry_max = 100 59 | }; 60 | 61 | tftLCD tft; 62 | Screen* base = nullptr; 63 | TchScr_Drv touchScreen; 64 | 65 | bool booted = false; 66 | bool SDinit = false; 67 | 68 | xTaskHandle updateTaskH = nullptr; 69 | xTaskHandle touchTaskH = nullptr; 70 | xTaskHandle cardTaskH = nullptr; 71 | SemaphoreHandle_t touchMutex; 72 | 73 | menu menuID = menu::none; 74 | menu newMenuID = menu::black; 75 | int64_t lastRender = 0; 76 | int64_t updateTime = 0; 77 | 78 | std::string selectedFile; 79 | 80 | lcdUI(/* args */); 81 | ~lcdUI(); 82 | 83 | static void updateTask(void* arg); 84 | static void touchTask(void* arg); 85 | static void cardDetectTask(void* arg); 86 | static void cardISRhandle(void* arg); 87 | 88 | bool initSD(); 89 | void processTouch(); 90 | esp_err_t updateDisplay(); 91 | esp_err_t updateObjects(); 92 | public: 93 | 94 | static lcdUI* instance(); 95 | esp_err_t begin(); 96 | void setScreen(const menu screen); 97 | void endSD(); 98 | bool isSDinit() const; 99 | esp_err_t setFile(const std::string& file); 100 | const std::string& getFile() const { return selectedFile; } 101 | void clearFile() { selectedFile.clear(); } 102 | void requestUpdate(); 103 | esp_err_t setBrightness(uint32_t duty); 104 | uint32_t getBrightness(); 105 | }; 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /main/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 21-01-2022 5 | * ----- 6 | * Last Modified: 12-02-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #include 26 | #include 27 | #include "esp_system.h" 28 | #include "esp_spi_flash.h" 29 | #include "dbg_log.h" 30 | #include "esp_spiffs.h" 31 | #include "lcdUI.h" 32 | 33 | gpio_config_t input_conf = { 34 | .pin_bit_mask = GPIO_SEL_34 | GPIO_SEL_27, 35 | .mode = GPIO_MODE_INPUT, 36 | .pull_up_en = GPIO_PULLUP_DISABLE, 37 | .pull_down_en = GPIO_PULLDOWN_DISABLE, 38 | .intr_type = GPIO_INTR_DISABLE 39 | }; 40 | 41 | extern "C" void app_main(void) 42 | { 43 | gpio_config(&input_conf); 44 | initArduino(); 45 | 46 | esp_reset_reason_t reason = esp_reset_reason(); 47 | if (reason != ESP_RST_POWERON) 48 | { 49 | DBG_LOGE("System unexpected reboot!"); 50 | while (true) vTaskDelay(100); 51 | } 52 | 53 | printf("System ready!\n"); 54 | 55 | printf("Free Heap at start: %d of %d\n", esp_get_free_heap_size(), ESP.getHeapSize()); 56 | 57 | // INITIALIZE SPIFFS STORAGE 58 | DBG_LOGI("Initializing SPIFFS"); 59 | 60 | esp_vfs_spiffs_conf_t conf = { 61 | .base_path = "/spiffs", 62 | .partition_label = NULL, 63 | .max_files = 5, 64 | .format_if_mount_failed = false 65 | }; 66 | 67 | esp_err_t ret = esp_vfs_spiffs_register(&conf); 68 | 69 | if (ret != ESP_OK) { 70 | if (ret == ESP_FAIL) { 71 | DBG_LOGE("Failed to mount or format filesystem"); 72 | } else if (ret == ESP_ERR_NOT_FOUND) { 73 | DBG_LOGE("Failed to find SPIFFS partition"); 74 | } else { 75 | DBG_LOGE("Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); 76 | } 77 | return; 78 | } 79 | 80 | // INITIALIZE UI 81 | ret = lcdUI::instance()->begin(); 82 | if (ret != ESP_OK) 83 | { 84 | DBG_LOGE("Failed to initialize UI. Rebooting NOW!"); 85 | esp_restart(); 86 | } 87 | 88 | lcdUI::instance()->setScreen(lcdUI::Info); 89 | 90 | while (1) 91 | { 92 | vTaskDelay(1000); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /main/tftLCD.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "tftLCD.h" 3 | #include 4 | 5 | #ifdef LOAD_GFXFF 6 | inline GFXglyph * pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c) 7 | { 8 | #ifdef __AVR__ 9 | return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); 10 | #else 11 | // expression in __AVR__ section may generate "dereferencing type-punned pointer will break strict-aliasing rules" warning 12 | // In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way 13 | // So expression may be simplified 14 | return gfxFont->glyph + c; 15 | #endif //__AVR__ 16 | } 17 | 18 | inline uint8_t * pgm_read_bitmap_ptr(const GFXfont *gfxFont) 19 | { 20 | #ifdef __AVR__ 21 | return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); 22 | #else 23 | // expression in __AVR__ section generates "dereferencing type-punned pointer will break strict-aliasing rules" warning 24 | // In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way 25 | // So expression may be simplified 26 | return gfxFont->bitmap; 27 | #endif //__AVR__ 28 | } 29 | #endif 30 | 31 | /*#################################################### 32 | tft Sprite class 33 | ####################################################*/ 34 | 35 | /**************************************************************************/ 36 | /*! 37 | @brief Print a string centered at cursor location (supports multy-line text) 38 | @param String to print 39 | */ 40 | /**************************************************************************/ 41 | void tftSprite::printCenter(const String &str) 42 | { 43 | uint8_t h = 1; 44 | for (unsigned int i = 0; i < str.length(); i++) 45 | { 46 | if(str[i] == '\n') h++; 47 | } 48 | h *= fontHeight(); 49 | cursor_y -= h/2; 50 | int16_t center = cursor_x; 51 | setTextDatum(TC_DATUM); 52 | if (str.indexOf('\n') == -1) 53 | { 54 | drawString(str, cursor_x, cursor_y); 55 | } 56 | else 57 | { 58 | int a = 0; 59 | int b = str.indexOf('\n'); 60 | while (a < str.length()) 61 | { 62 | drawString(str.substring(a, b), center, cursor_y); 63 | print('\n'); 64 | a = b+1; 65 | b = str.indexOf('\n', a); 66 | if (b == -1) b = str.length(); 67 | } 68 | } 69 | } 70 | 71 | void tftSprite::printCenter(const char *str) 72 | { 73 | printCenter(String(str)); 74 | } 75 | 76 | /*#################################################### 77 | tft LCD class 78 | ####################################################*/ 79 | 80 | /**************************************************************************/ 81 | /*! 82 | @brief Draw single character over any rectangle without flickering (Only free fonts supported yet) 83 | May be slower than using sprites but less RAM intesive. 84 | @param pos Cursor position (2D vector) 85 | @param c Character to draw 86 | @param color Text color 87 | @param bg Rectangle color 88 | @param size Text size 89 | @param start Upper Left corner of the rectagle (2D vector) 90 | @param dim Width and height of the rectangle (2D vector) 91 | */ 92 | /**************************************************************************/ 93 | void tftLCD::drawCharBg(Vec2h pos, uint8_t c, uint16_t color, uint16_t bg, uint8_t size, Vec2h *start, Vec2h dim) 94 | { 95 | #ifdef LOAD_GFXFF 96 | int16_t minx = 0, miny = 0, maxx = 5, maxy = 8; 97 | if(gfxFont) // 'Classic' built-in font 98 | { // Custom font 99 | c -= (uint8_t)pgm_read_byte(&gfxFont->first); 100 | GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c); 101 | uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont); 102 | 103 | uint16_t bo = pgm_read_word(&glyph->bitmapOffset); 104 | int16_t w = pgm_read_byte(&glyph->width), 105 | h = pgm_read_byte(&glyph->height); 106 | int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset), 107 | yo = (int8_t)pgm_read_byte(&glyph->yOffset); 108 | uint8_t bits = 0, 109 | oldbits = pgm_read_byte(&bitmap[bo]), 110 | bit = 0, 111 | oldbit = 0; 112 | uint16_t oldbo = bo; 113 | if (size > 1) 114 | { 115 | w *= size; 116 | h *= size; 117 | xo *= size; 118 | yo *= size; 119 | } 120 | maxx = w, maxy = h; 121 | 122 | if (dim.x != 0) 123 | { 124 | if ((*start).x < 0) (*start).x = 0; 125 | minx = (*start).x - pos.x - xo; 126 | maxx = dim.x + minx; 127 | } 128 | else if ((*start).x >= 0) 129 | { 130 | minx = (*start).x - pos.x - xo; 131 | } 132 | 133 | if (dim.y != 0) 134 | { 135 | if ((*start).y < 0) (*start).y = 0; 136 | miny = (*start).y - pos.y - yo; 137 | maxy = dim.y + miny; 138 | } 139 | else if ((*start).y >= 0) 140 | { 141 | miny = (*start).y - pos.y - yo; 142 | } 143 | dim.x = maxx-minx; 144 | dim.y = maxy-miny; 145 | 146 | if (miny < 0) 147 | { 148 | fillRect((*start).x, (*start).y, dim.x, min((int)dim.y, -miny), bg); 149 | } 150 | if (maxy > h) 151 | { 152 | fillRect((*start).x, max((int)(*start).y, h + pos.y + yo), dim.x, min(maxy-h, (int)dim.y), bg); 153 | dim.y -= maxy-h; 154 | } 155 | dim.y -= max(0, -miny); 156 | if (dim.y < 0) dim.y = 0; 157 | if (minx < 0) 158 | { 159 | fillRect((*start).x, max((int)(*start).y, pos.y+yo), min((int)dim.x, -minx), dim.y, bg); 160 | } 161 | if (maxx > w) 162 | { 163 | fillRect(max((int)(*start).x, w + pos.x + xo), max((int)(*start).y, pos.y+yo), min(maxx-w, (int)dim.x), dim.y, bg); 164 | } 165 | 166 | startWrite(); 167 | for(uint16_t yy = 0; yy < h; yy++) // Start drawing 168 | { 169 | for(uint16_t xx = 0; xx < w; xx++) 170 | { 171 | if (xx % size == 0) 172 | { 173 | if(!(bit++ & 7)) 174 | { 175 | bits = pgm_read_byte(&bitmap[bo++]); 176 | } 177 | if(bits & 0x80) 178 | { 179 | if(size == 1) 180 | { 181 | drawPixel(pos.x+xo+xx, pos.y+yo+yy, color); 182 | } 183 | else 184 | { 185 | drawFastHLine(pos.x+xo+xx, pos.y+yo+yy, size, color); 186 | xx += size-1; 187 | } 188 | } 189 | else if (bg != color && xx >= minx && xx < maxx && yy >= miny && yy < maxy) 190 | { 191 | drawPixel(pos.x+xo+xx, pos.y+yo+yy, bg); 192 | } 193 | bits <<= 1; 194 | } 195 | else if (xx >= minx && xx < maxx && yy >= miny && yy < maxy) 196 | { 197 | drawPixel(pos.x+xo+xx, pos.y+yo+yy, bg); 198 | } 199 | } 200 | if (yy % size == (size-1)) 201 | { 202 | oldbit = bit; 203 | oldbo = bo; 204 | oldbits = bits; 205 | } 206 | else 207 | { 208 | bit = oldbit; 209 | bo = oldbo; 210 | bits = oldbits; 211 | } 212 | } 213 | endWrite(); 214 | (*start).x = pos.x+xo+maxx; 215 | } // End classic vs custom font 216 | else 217 | #endif 218 | { 219 | if((pos.x >= _width) || // Clip right 220 | (pos.y >= _height) || // Clip bottom 221 | ((pos.x + 6 * size - 1) < 0) || // Clip left 222 | ((pos.y + 8 * size - 1) < 0)) // Clip top 223 | return; 224 | 225 | if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior 226 | 227 | startWrite(); 228 | for(int8_t i=0; i<5; i++ ) 229 | { // Char bitmap = 5 columns 230 | uint8_t line = pgm_read_byte(&font[c * 5 + i]); 231 | for(int8_t j=0; j<8; j++, line >>= 1) 232 | { 233 | if(line & 1) 234 | { 235 | if(size == 1) 236 | drawPixel(pos.x+i, pos.y+j, color); 237 | else 238 | fillRect(pos.x+i*size, pos.y+j*size, size, size, color); 239 | } 240 | else if(bg != color) 241 | { 242 | if(size == 1) 243 | drawPixel(pos.x+i, pos.y+j, bg); 244 | else 245 | fillRect(pos.x+i*size, pos.y+j*size, size, size, bg); 246 | } 247 | } 248 | } 249 | if(bg != color) 250 | { // If opaque, draw vertical line for last column 251 | if(size == 1) drawFastVLine(pos.x+5, pos.y, 8, bg); 252 | else fillRect(pos.x+5*size, pos.y, size, 8*size, bg); 253 | } 254 | endWrite(); 255 | } 256 | } 257 | 258 | /**************************************************************************/ 259 | /*! 260 | @brief Draw single character over any rectangle without flickering (Only free fonts supported yet) 261 | May be slower than using sprites but less RAM intesive. 262 | @param c Character to draw 263 | @param pos Upper Left corner of the rectagle (2D vector) 264 | @param dim Width and height of the rectangle (2D vector) 265 | */ 266 | /**************************************************************************/ 267 | size_t tftLCD::writeBg(uint8_t c, Vec2h *pos, Vec2h dim) 268 | { 269 | #ifdef LOAD_GFXFF 270 | if(gfxFont) 271 | { 272 | if(c == '\n') 273 | { 274 | cursor_x = 0; 275 | cursor_y += (int16_t)textsize * 276 | (uint8_t)pgm_read_byte(&gfxFont->yAdvance); 277 | } else if(c != '\r') 278 | { 279 | uint8_t first = pgm_read_byte(&gfxFont->first); 280 | if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) 281 | { 282 | GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); 283 | uint8_t w = pgm_read_byte(&glyph->width), 284 | h = pgm_read_byte(&glyph->height); 285 | if((w > 0) && (h > 0)) 286 | { // Is there an associated bitmap? 287 | int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic 288 | if(textwrapX && ((cursor_x + textsize * (xo + w)) > _width)) 289 | { 290 | cursor_x = 0; 291 | cursor_y += (int16_t)textsize * 292 | (uint8_t)pgm_read_byte(&gfxFont->yAdvance); 293 | } 294 | drawCharBg(Vec2h(cursor_x, cursor_y), c, textcolor, textbgcolor, textsize, pos, dim); 295 | } 296 | cursor_x += (uint8_t)pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; 297 | } 298 | } 299 | } 300 | else // Custom font 301 | #endif 302 | { // 'Classic' built-in font 303 | if(c == '\n') { // Newline? 304 | cursor_x = 0; // Reset x to zero, 305 | cursor_y += textsize * 8; // advance y one line 306 | } else if(c != '\r') { // Ignore carriage returns 307 | if(textwrapX && ((cursor_x + textsize * 6) > _width)) { // Off right? 308 | cursor_x = 0; // Reset x to zero, 309 | cursor_y += textsize * 8; // advance y one line 310 | } 311 | drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); 312 | cursor_x += textsize * 6; // Advance x one char 313 | } 314 | } 315 | return 1; 316 | } 317 | 318 | /**************************************************************************/ 319 | /*! 320 | @brief Draw string with filled background without flickering (Support multy-line) 321 | May be slower than using sprites but less RAM intesive. 322 | @param str String to draw 323 | */ 324 | /**************************************************************************/ 325 | void tftLCD::printBg(const String &str) 326 | { 327 | printBg(str, Vector2()); 328 | } 329 | 330 | /**************************************************************************/ 331 | /*! 332 | @brief Draw string with filled background without flickering (Support multy-line) 333 | May be slower than using sprites but less RAM intesive. 334 | @param str String to draw 335 | @param pad Border width arround text 336 | */ 337 | /**************************************************************************/ 338 | void tftLCD::printBg(const String &str, uint8_t pad) 339 | { 340 | printBg(str, Vector2(pad, pad)); 341 | } 342 | 343 | /**************************************************************************/ 344 | /*! 345 | @brief Draw string with filled background without flickering (Support multy-line) 346 | May be slower than using sprites but less RAM intesive. 347 | @param str String to draw 348 | @param pad Border width arround text in X and Y directions (2D vector) 349 | */ 350 | /**************************************************************************/ 351 | void tftLCD::printBg(const String &str, Vector2 pad) 352 | { 353 | if (str.indexOf('\n') == -1) 354 | { 355 | int16_t x = 0, y = 0; 356 | Vec2h size = getTextBounds(str, &x, &y); 357 | Vec2h pos(x + cursor_x - pad.x, y + cursor_y - pad.y); 358 | size.y += 2*pad.y; 359 | for (unsigned int i = 0; i < str.length(); i++) 360 | { 361 | writeBg(str[i], &pos, Vec2h(0, size.y)); 362 | } 363 | fillRect(pos.x, pos.y, pad.x, size.y, textbgcolor); 364 | } 365 | else 366 | { 367 | String buf; 368 | int a = 0; 369 | int b = str.indexOf('\n'); 370 | while (a < str.length()) 371 | { 372 | buf = str.substring(a, b); 373 | printBg(buf); 374 | print('\n'); 375 | a = b+1; 376 | b = str.indexOf('\n', a); 377 | if (b == -1) b = str.length(); 378 | } 379 | } 380 | } 381 | 382 | /**************************************************************************/ 383 | /*! 384 | @brief Draw string over any rectangle without flickering (Support multy-line) ########## TO DO: -Add multy line, -Fix some single line issues 385 | May be slower than using sprites but less RAM intesive. 386 | @param str String to draw 387 | @param pos Upper Left corner of the rectagle (2D vector) 388 | @param dim Width and height of the rectangle (2D vector) 389 | */ 390 | /**************************************************************************/ 391 | void tftLCD::printBg(const String &str, Vec2h pos, Vector2 dim) 392 | { 393 | int16_t x = 0, y = 0; 394 | Vec2h start = pos; 395 | Vec2h end(0, 0); 396 | 397 | for (unsigned int i = 0; i < str.length(); i++) 398 | { 399 | Vec2h size = getTextBounds(String(str[i]), &x, &y); 400 | x += cursor_x; 401 | y += cursor_y; 402 | //charBounds(str[i], &x, &y, &minx, &miny, &maxx, &maxy); 403 | 404 | if (x < pos.x + dim.x && x+size.x > pos.x && y < pos.y + dim.y && y+size.y > pos.y) // Check for character and rectangle overlap 405 | { 406 | if (pos.x+dim.x < x+size.x || i == str.length()-1) end.x = pos.x+dim.x-start.x; 407 | if (pos.y+dim.y < y+size.y) end.y = pos.y+dim.y-start.y; 408 | writeBg(str[i], &start, end); 409 | } 410 | else 411 | { 412 | write(str[i]); 413 | } 414 | } 415 | } 416 | 417 | /**************************************************************************/ 418 | /*! 419 | @brief Helper to determine size of a character with current font/size. 420 | Broke this out as it's used by both the PROGMEM- and RAM-resident getTextBounds() functions. 421 | @param c The ascii character in question 422 | @param x Pointer to x location of character 423 | @param y Pointer to y location of character 424 | @param minx Minimum clipping value for X 425 | @param miny Minimum clipping value for Y 426 | @param maxx Maximum clipping value for X 427 | @param maxy Maximum clipping value for Y 428 | */ 429 | /**************************************************************************/ 430 | #if defined(LOAD_GFXFF) || defined(LOAD_GLCD) 431 | void tftLCD::charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy) 432 | { 433 | #ifdef LOAD_GFXFF 434 | if(gfxFont) 435 | { 436 | if(c == '\n') 437 | { // Newline? 438 | *x = 0; // Reset x to zero, advance y by one line 439 | *y += textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); 440 | } 441 | else if(c != '\r') 442 | { // Not a carriage return; is normal char 443 | uint8_t first = pgm_read_byte(&gfxFont->first), 444 | last = pgm_read_byte(&gfxFont->last); 445 | if((c >= first) && (c <= last)) { // Char present in this font? 446 | GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); 447 | uint8_t gw = pgm_read_byte(&glyph->width), 448 | gh = pgm_read_byte(&glyph->height), 449 | xa = pgm_read_byte(&glyph->xAdvance); 450 | int8_t xo = pgm_read_byte(&glyph->xOffset), 451 | yo = pgm_read_byte(&glyph->yOffset); 452 | if(textwrapX && ((*x+(((int16_t)xo+gw)*textsize)) > _width)) 453 | { 454 | *x = 0; // Reset x to zero, advance y by one line 455 | *y += textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); 456 | } 457 | int16_t tsx = (int16_t)textsize, 458 | tsy = (int16_t)textsize, 459 | x1 = *x + xo * tsx, 460 | y1 = *y + yo * tsy, 461 | x2 = x1 + gw * tsx - 1, 462 | y2 = y1 + gh * tsy - 1; 463 | if(x1 < *minx) *minx = x1; 464 | if(y1 < *miny) *miny = y1; 465 | if(x2 > *maxx) *maxx = x2; 466 | if(y2 > *maxy) *maxy = y2; 467 | *x += xa * tsx; 468 | } 469 | } 470 | 471 | } 472 | else 473 | #endif 474 | { // Default font 475 | 476 | if(c == '\n') 477 | { // Newline? 478 | *x = 0; // Reset x to zero, 479 | *y += textsize * 8; // advance y one line 480 | // min/max x/y unchaged -- that waits for next 'normal' character 481 | } else if(c != '\r') 482 | { // Normal char; ignore carriage returns 483 | if(textwrapX && ((*x + textsize * 6) > _width)) 484 | { // Off right? 485 | *x = 0; // Reset x to zero, 486 | *y += textsize * 8; // advance y one line 487 | } 488 | int x2 = *x + textsize * 6 - 1, // Lower-right pixel of char 489 | y2 = *y + textsize * 8 - 1; 490 | if(x2 > *maxx) *maxx = x2; // Track max x, y 491 | if(y2 > *maxy) *maxy = y2; 492 | if(*x < *minx) *minx = *x; // Track min x, y 493 | if(*y < *miny) *miny = *y; 494 | *x += textsize * 6; // Advance x one char 495 | } 496 | } 497 | } 498 | #endif 499 | 500 | /**************************************************************************/ 501 | /*! 502 | @brief Return a vector with the width and height of a text 503 | @param str String to evaluate 504 | */ 505 | /**************************************************************************/ 506 | Vec2h tftLCD::getTextBounds(const String &str) 507 | { 508 | int b = str.indexOf('\n'); 509 | if (b == -1) // Single line 510 | { 511 | return Vec2h(textWidth(str), fontHeight()); 512 | } 513 | else // Multy-line 514 | { 515 | int16_t w = 0, h = 0; 516 | String buf; 517 | int a = 0; 518 | while (a < str.length()) 519 | { 520 | buf = str.substring(a, b)+'\n'; 521 | w = max(textWidth(buf), w); // Find the widest line 522 | a = b+1; 523 | b = str.indexOf('\n', a); 524 | if (b == -1) b = str.length(); 525 | h++; // number of lines 526 | } 527 | h *= fontHeight(); // Total height 528 | return Vec2h(w,h); 529 | } 530 | return Vec2h(); 531 | } 532 | 533 | Vec2h tftLCD::getTextBounds(const String &str, int16_t *x, int16_t *y) 534 | { 535 | if(str.length() != 0) 536 | { 537 | return getTextBounds(str.c_str(), x, y); 538 | } 539 | return Vec2h(); 540 | } 541 | 542 | Vec2h tftLCD::getTextBounds(const char *str) 543 | { 544 | ESP_LOGV(__FILE__, "getTextBounds start\n"); 545 | 546 | return getTextBounds(String(str)); 547 | } 548 | 549 | /**************************************************************************/ 550 | /*! 551 | @brief Return the bounding box of a text 552 | @param str String to evaluate 553 | @param x X offset from cursor X position 554 | @param y Y offset from cursor Y position 555 | */ 556 | /**************************************************************************/ 557 | Vec2h tftLCD::getTextBounds(const char *str, int16_t *x, int16_t *y) 558 | { 559 | if (textfont != 1) 560 | { 561 | return getTextBounds(str); 562 | } 563 | #if defined(LOAD_GFXFF) || defined(LOAD_GLCD) 564 | uint8_t c; // Current character 565 | 566 | *x = 0; 567 | *y = 0; 568 | Vec2h size = Vec2h(); 569 | 570 | int16_t minx = _width, miny = _height, maxx = -1, maxy = -1; 571 | 572 | while((c = *str++)) 573 | charBounds(c, x, y, &minx, &miny, &maxx, &maxy); 574 | 575 | if(maxx >= minx) { 576 | *x = minx; 577 | size.x = maxx - minx + 1; 578 | } 579 | if(maxy >= miny) { 580 | *y = miny; 581 | size.y = maxy - miny + 1; 582 | } 583 | return size; 584 | #else 585 | return Vec2h(); 586 | #endif 587 | } 588 | 589 | /**************************************************************************/ 590 | /*! 591 | @brief Print a string centered at cursor location (supports multy-line text) 592 | @param String to print 593 | */ 594 | /**************************************************************************/ 595 | void tftLCD::printCenter(const String &str) 596 | { 597 | int16_t x,y; 598 | int16_t center; 599 | 600 | center = cursor_x; // Save central X position for later 601 | Vec2h size = getTextBounds(str, &x, &y); // Get bounding box 602 | int b = str.indexOf('\n'); 603 | if (b == -1) // Single line text 604 | { 605 | setCursor(getCursorX()-size.x/2-x, getCursorY()-size.y/2-y); 606 | printBg(str); 607 | 608 | } 609 | else // Multy-line text 610 | { 611 | String buf; 612 | cursor_y -= size.y/2+y; 613 | int a = 0; 614 | while (a < str.length()) // handle each line at once 615 | { 616 | buf = str.substring(a, b)+'\n'; 617 | size = getTextBounds(buf, &x, &y); 618 | cursor_x = center-size.x/2-x; 619 | printBg(buf); 620 | a = b+1; 621 | b = str.indexOf('\n', a); 622 | if (b == -1) b = str.length(); 623 | } 624 | } 625 | } 626 | 627 | void tftLCD::printCenter(const char *str) 628 | { 629 | printCenter(String(str)); 630 | } 631 | 632 | /** 633 | * @brief Draw string wrapped 634 | * 635 | * @param str String to draw 636 | * @param x String X position 637 | * @param y String Y position 638 | * @param w Max string width 639 | * @param h Max string height 640 | */ 641 | void tftLCD::drawStringWr(const char *str, int32_t x, int32_t y, uint16_t w, uint16_t h) 642 | { 643 | const uint16_t cheight = fontHeight(); 644 | const int16_t lines = min(textWidth(str)/w, h/cheight-1); 645 | 646 | uint16_t len = strlen(str); 647 | uint16_t cnt = 0; 648 | const uint16_t maxChar = w/3; 649 | char buffer[maxChar+1]; 650 | for (int16_t i = 0; i <= lines; i++) 651 | { 652 | uint8_t charN = maxChar; 653 | strncpy(buffer, &str[cnt], maxChar); 654 | buffer[maxChar] = '\0'; 655 | 656 | while (textWidth(buffer) > w) 657 | buffer[--charN] = '\0'; 658 | 659 | drawString(buffer, x, y - cheight/2*lines + i*cheight); 660 | 661 | cnt += charN; 662 | if (cnt > len) break; // All characters read 663 | } 664 | } 665 | 666 | // These read 16- and 32-bit types from the SD card file. 667 | // BMP data is stored little-endian, Arduino is little-endian too. 668 | // May need to reverse subscript order if porting elsewhere. 669 | 670 | uint16_t SPIFFS_read16(FILE *f) { 671 | uint16_t result; 672 | ((uint8_t *)&result)[0] = fgetc(f); // LSB 673 | ((uint8_t *)&result)[1] = fgetc(f); // MSB 674 | return result; 675 | } 676 | 677 | uint32_t SPIFFS_read32(FILE *f) { 678 | uint32_t result; 679 | ((uint8_t *)&result)[0] = fgetc(f); // LSB 680 | ((uint8_t *)&result)[1] = fgetc(f); 681 | ((uint8_t *)&result)[2] = fgetc(f); 682 | ((uint8_t *)&result)[3] = fgetc(f); // MSB 683 | return result; 684 | } 685 | 686 | void tftLCD::drawBmpSPIFFS(const char *filename, int16_t x, int16_t y) 687 | { 688 | if ((x >= _width) || (y >= _height)) return; 689 | 690 | // Open requested file on SPIFFS 691 | FILE *bmpFS = fopen(filename, "r"); 692 | 693 | if (!bmpFS) 694 | { 695 | ESP_LOGE(__FILE__, "File \"%s\" not found!", filename); 696 | return; 697 | } 698 | 699 | uint32_t seekOffset; 700 | uint16_t w, h, row; 701 | 702 | if (SPIFFS_read16(bmpFS) == 0x4D42) 703 | { 704 | SPIFFS_read32(bmpFS); 705 | SPIFFS_read32(bmpFS); 706 | seekOffset = SPIFFS_read32(bmpFS); 707 | SPIFFS_read32(bmpFS); 708 | w = SPIFFS_read32(bmpFS); 709 | h = SPIFFS_read32(bmpFS); 710 | 711 | if (SPIFFS_read16(bmpFS) == 1 && SPIFFS_read16(bmpFS) == 16 && SPIFFS_read32(bmpFS) == 3) 712 | { 713 | y += h - 1; 714 | 715 | bool oldSwapBytes = getSwapBytes(); 716 | setSwapBytes(true); 717 | fseek(bmpFS, seekOffset, SEEK_SET); 718 | uint8_t lineBuffer[w * 2 + ((w & 1) << 1)]; 719 | 720 | for (row = 0; row < h; row++) 721 | { 722 | fread(lineBuffer, 1, sizeof(lineBuffer), bmpFS); 723 | 724 | // Push the pixel row to screen, pushImage will crop the line if needed 725 | // y is decremented as the BMP image is drawn bottom up 726 | pushImage(x, y--, w, 1, (uint16_t*)lineBuffer); 727 | } 728 | setSwapBytes(oldSwapBytes); 729 | } 730 | else 731 | ESP_LOGE(__FILE__, "BMP format not recognized."); 732 | } 733 | fclose(bmpFS); 734 | } 735 | -------------------------------------------------------------------------------- /main/tftLCD.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef TFTLCD_H 3 | #define TFTLCD_H 4 | 5 | #include 6 | #include 7 | #include "Free_Fonts.h" 8 | #include "Vector.h" 9 | 10 | class tftSprite : public TFT_eSprite 11 | { 12 | public: 13 | tftSprite(TFT_eSPI* tft): TFT_eSprite(tft){} 14 | 15 | void printCenter(const String &str); 16 | void printCenter(const char *str); 17 | }; 18 | 19 | class tftLCD : public TFT_eSPI 20 | { 21 | public: 22 | void drawCharBg(Vec2h pos, uint8_t c, uint16_t color, uint16_t bg, uint8_t size, Vec2h *start, Vec2h dim); 23 | size_t writeBg(uint8_t c, Vec2h *pos, Vec2h dim); 24 | void printBg(const String &str); 25 | void printBg(const String &str, Vector2 pad); 26 | void printBg(const String &str, uint8_t pad); 27 | void printBg(const String &str, Vec2h pos, Vector2 dim); 28 | 29 | void charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy); 30 | Vec2h getTextBounds(const char *str); 31 | Vec2h getTextBounds(const String &str); 32 | Vec2h getTextBounds(const char *str, int16_t *x, int16_t *y); 33 | Vec2h getTextBounds(const String &str, int16_t *x, int16_t *y); 34 | 35 | void printCenter(const String &str); 36 | void printCenter(const char *str); 37 | 38 | void drawStringWr(const char *str, int32_t x, int32_t y, uint16_t w, uint16_t h); 39 | 40 | void drawBmpSPIFFS(const char *filename, int16_t x, int16_t y); 41 | 42 | tftSprite img = tftSprite(this); 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /main/utility.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "utility.h" 3 | 4 | #ifdef CONFIG_ENABLE_TIMER 5 | int64_t Timer::startTime; 6 | 7 | void Timer::tic() 8 | { 9 | startTime = esp_timer_get_time(); 10 | } 11 | 12 | const int64_t Timer::toc() 13 | { 14 | int64_t eTime = esp_timer_get_time()-startTime; 15 | ESP_LOGD("Utility", "\nElapsed time: %lu\n", (unsigned long)eTime); 16 | return eTime; 17 | } 18 | #endif 19 | 20 | #ifdef SCREEN_SERVER_U 21 | bool ScreenServer::screenServer(TFT_eSPI& tft) 22 | { 23 | // With no filename the screenshot will be saved with a default name e.g. tft_screen_#.xxx 24 | // where # is a number 0-9 and xxx is a file type specified below 25 | return screenServer(DEFAULT_FILENAME, tft); 26 | } 27 | 28 | bool ScreenServer::screenServer(String filename, TFT_eSPI& tft) 29 | { 30 | uint32_t clearTime; 31 | uint32_t lastCmdTime = millis(); // Initialise start of command time-out 32 | 33 | // Check serial buffer 34 | if (Serial.available() > 0) { 35 | // Read the command byte 36 | uint8_t cmd = Serial.read(); 37 | // If it is 'S' (start command) then clear the serial buffer for 100ms and stop waiting 38 | if ( cmd == 'S' ) { 39 | // Precautionary receive buffer garbage flush for 50ms 40 | clearTime = millis() + 50; 41 | while ( millis() < clearTime && Serial.read() >= 0) delay(1); 42 | 43 | lastCmdTime = millis(); // Set last received command time 44 | 45 | // Send screen size etc using a simple header with delimiters for client checks 46 | sendParameters(filename, tft); 47 | } 48 | else 49 | return false; 50 | } 51 | else 52 | return false; 53 | 54 | uint8_t color[3 * NPIXELS]; // RGB and 565 format color buffer for N pixels 55 | 56 | // Send all the pixels on the whole screen 57 | for ( uint32_t y = 0; y < tft.height(); y++) 58 | { 59 | // Increment x by NPIXELS as we send NPIXELS for every byte received 60 | for ( uint32_t x = 0; x < tft.width(); x += NPIXELS) 61 | { 62 | yield(); 63 | 64 | // Wait here for serial data to arrive or a time-out elapses 65 | while ( Serial.available() == 0 ) 66 | { 67 | if ( millis() > lastCmdTime + PIXEL_TIMEOUT) return false; 68 | delay(1); 69 | } 70 | 71 | // Serial data must be available to get here, read 1 byte and 72 | // respond with N pixels, i.e. N x 3 RGB bytes or N x 2 565 format bytes 73 | if ( Serial.read() == 'X' ) { 74 | // X command byte means abort, so clear the buffer and return 75 | clearTime = millis() + 50; 76 | while ( millis() < clearTime && Serial.read() >= 0) yield(); 77 | return false; 78 | } 79 | // Save arrival time of the read command (for later time-out check) 80 | lastCmdTime = millis(); 81 | 82 | #if defined BITS_PER_PIXEL && BITS_PER_PIXEL >= 24 && NPIXELS > 1 83 | // Fetch N RGB pixels from x,y and put in buffer 84 | tft.readRectRGB(x, y, NPIXELS, 1, color); 85 | // Send buffer to client 86 | Serial.write(color, 3 * NPIXELS); // Write all pixels in the buffer 87 | #else 88 | // Fetch N 565 format pixels from x,y and put in buffer 89 | #if NPIXELS > 1 90 | tft.readRect(x, y, NPIXELS, 1, (uint16_t *)color); 91 | #else 92 | uint16_t c = tft.readPixel(x, y); 93 | color[0] = c>>8; 94 | color[1] = c & 0xFF; // Swap bytes 95 | #endif 96 | // Send buffer to client 97 | Serial.write(color, 2 * NPIXELS); // Write all pixels in the buffer 98 | #endif 99 | } 100 | } 101 | 102 | Serial.flush(); // Make sure all pixel bytes have been despatched 103 | 104 | return true; 105 | } 106 | 107 | void ScreenServer::sendParameters(String filename, TFT_eSPI& tft) 108 | { 109 | Serial.write('W'); // Width 110 | Serial.write(tft.width() >> 8); 111 | Serial.write(tft.width() & 0xFF); 112 | 113 | Serial.write('H'); // Height 114 | Serial.write(tft.height() >> 8); 115 | Serial.write(tft.height() & 0xFF); 116 | 117 | Serial.write('Y'); // Bits per pixel (16 or 24) 118 | if (NPIXELS > 1) Serial.write(BITS_PER_PIXEL); 119 | else Serial.write(16); // readPixel() only provides 16 bit values 120 | 121 | Serial.write('?'); // Filename next 122 | Serial.print(filename); 123 | 124 | Serial.write('.'); // End of filename marker 125 | 126 | Serial.write(FILE_EXT); // Filename extension identifier 127 | 128 | Serial.write(*FILE_TYPE); // First character defines file type j,b,p,t 129 | } 130 | #endif 131 | -------------------------------------------------------------------------------- /main/utility.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file utility.h 3 | * @author Ricard Bitriá Ribes (https://github.com/dracir9) 4 | * Created Date: 22-01-2022 5 | * ----- 6 | * Last Modified: 10-04-2022 7 | * Modified By: Ricard Bitriá Ribes 8 | * ----- 9 | * @copyright (c) 2022 Ricard Bitriá Ribes 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | */ 24 | 25 | #ifndef UTILITY_H 26 | #define UTILITY_H 27 | 28 | #ifdef CONFIG_ENABLE_TIMER 29 | #include 30 | class Timer 31 | { 32 | public: 33 | 34 | /** 35 | * @brief Sets time mark 36 | */ 37 | static void tic(); 38 | 39 | /** 40 | * @brief Print time elapsed since last tic() call in microseconds 41 | * 42 | * @return const int64_t Time elapsed in microseconds 43 | */ 44 | static const int64_t toc(); 45 | 46 | private: 47 | static int64_t startTime; 48 | }; 49 | 50 | #define TIC Timer::tic(); 51 | #define TOC Timer::toc(); 52 | #else 53 | #define TIC 54 | #define TOC 55 | #endif 56 | 57 | #ifdef SCREEN_SERVER_U 58 | #if CORE_DEBUG_LEVEL > 3 59 | #warning "Debug messages may interfere in the image transfer. Please define CORE_DEBUG_LEVEL to be <= 3" 60 | #endif 61 | #include 62 | // Based on Bodmer's example sketch 63 | 64 | // Reads a screen image off the TFT and send it to a processing client sketch 65 | // over the serial port. 66 | 67 | // This sketch has been created to work with the TFT_eSPI library here: 68 | // https://github.com/Bodmer/TFT_eSPI 69 | 70 | // Created by: Bodmer 27/1/17 71 | // Updated by: Bodmer 10/3/17 72 | // Updated by: Bodmer 23/11/18 to support SDA reads and the ESP32 73 | // Updated by: dracir9 12/1/21 adapted to own project 74 | // Version: 0.08 75 | 76 | // MIT licence applies, all text above must be included in derivative works 77 | //==================================================================================== 78 | // Definitions 79 | //==================================================================================== 80 | #define PIXEL_TIMEOUT 100 // 100ms Time-out between pixel requests 81 | #define START_TIMEOUT 10000 // 10s Maximum time to wait at start transfer 82 | 83 | #define BITS_PER_PIXEL 16 // 24 for RGB colour format, 16 for 565 colour format 84 | 85 | // File names must be alpha-numeric characters (0-9, a-z, A-Z) or "/" underscore "_" 86 | // other ascii characters are stripped out by client, including / generates 87 | // sub-directories 88 | #define DEFAULT_FILENAME "tft_screenshots/screenshot" // In case none is specified 89 | #define FILE_TYPE "png" // jpg, bmp, png, tif are valid 90 | 91 | // Filename extension 92 | // '#' = add incrementing number, '@' = add timestamp, '%' add millis() timestamp, 93 | // '*' = add nothing 94 | // '@' and '%' will generate new unique filenames, so beware of cluttering up your 95 | // hard drive with lots of images! The PC client sketch is set to limit the number of 96 | // saved images to 1000 and will then prompt for a restart. 97 | #define FILE_EXT '@' 98 | 99 | // Number of pixels to send in a burst (minimum of 1), no benefit above 8 100 | // NPIXELS values and render times: 101 | // NPIXELS 1 = use readPixel() = >5s and 16 bit pixels only 102 | // NPIXELS >1 using rectRead() 2 = 1.75s, 4 = 1.68s, 8 = 1.67s 103 | #define NPIXELS 8 // Must be integer division of both TFT width and TFT height 104 | 105 | class ScreenServer 106 | { 107 | public: 108 | /** 109 | * @brief Start a screen dump server - no filename specified 110 | * 111 | * @param tft TFT_eSPI instance to print 112 | * @return true if image is sent properly otherwise it returns false 113 | */ 114 | static bool screenServer(TFT_eSPI& tft); 115 | 116 | /** 117 | * @brief Start a screen dump server - filename specified 118 | * 119 | * @param filename Name of the saved image 120 | * @param tft TFT_eSPI instance to print 121 | * @return true if image is sent properly otherwise it returns false 122 | */ 123 | static bool screenServer(String filename, TFT_eSPI& tft); 124 | 125 | /** 126 | * @brief Send screen size etc using a simple header with delimiters for client checks 127 | * 128 | * @param filename Name of the saved image 129 | * @param tft TFT_eSPI instance to print 130 | */ 131 | static void sendParameters(String filename, TFT_eSPI& tft); 132 | }; 133 | 134 | #define PRINT_SCR(tft) ScreenServer::screenServer(tft); 135 | #else 136 | #define PRINT_SCR(tft) 137 | #endif 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /partitions_two_ota_SPIFFS.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap 3 | nvs, data, nvs, , 0x4000, 4 | otadata, data, ota, , 0x2000, 5 | phy_init, data, phy, , 0x1000, 6 | factory, app, factory, , 1500K, 7 | ota_0, app, ota_0, , 1500K, 8 | ota_1, app, ota_1, , 1500K, 9 | storage, data, spiffs, , 500K, 10 | --------------------------------------------------------------------------------