178 Commits
1.4.1 ... 1.5.1

Author SHA1 Message Date
Knutwurst
e0bb686818 Add support for SD extender. 2023-06-13 13:39:30 +02:00
Knutwurst
ff3c981420 Add TODO for SD Extender support. 2023-06-13 12:45:35 +02:00
Knutwurst
f06a7a1454 Update build date. 2023-06-13 12:27:19 +02:00
Knutwurst
201a693283 Make sorting much faster and prevent it from using too much RAM. 2023-06-13 12:07:17 +02:00
Knutwurst
2a33df6da5 Remove unnecessary newlines in serial protocol 2023-06-13 08:54:19 +02:00
Knutwurst
05bd0da620 Add missing break; 2023-06-13 01:16:45 +02:00
Knutwurst
e4081fc7c3 Restructure A6 Get SD Card printing status 2023-06-13 01:12:13 +02:00
Knutwurst
1d2c42d994 A26 refresh SD routine refactoring to it is faster when no sd card is present. 2023-06-12 18:51:20 +02:00
Knutwurst
1be2be4b08 Update build date. 2023-06-12 09:36:27 +02:00
Knutwurst
afa7be67fa Add clang-format config file. 2023-06-11 18:53:37 +02:00
Knutwurst
72c57b37e6 Remove FilamentRunoutCheck on Startup. 2023-06-11 13:42:29 +02:00
Knutwurst
688cb03275 Update Wifi pin header documentation. 2023-06-11 11:52:17 +02:00
Knutwurst
b356da3f9b Update Bulddate. 2023-06-11 11:31:31 +02:00
Knutwurst
cb3848deaf Refactor printing status and time display for anycubic 1.0 tft. 2023-06-11 11:27:17 +02:00
Knutwurst
68a4857305 Revert "Remove thermalManager dependency from 4MAX AutoPowerOff."
This reverts commit de446f0520.
2023-06-11 08:57:12 +02:00
Knutwurst
000c489b63 Restructure fileList to load faster. 2023-06-10 17:32:34 +02:00
Knutwurst
556be8126b Enable Autosave after ABL on chiron models. 2023-06-10 00:29:27 +02:00
Knutwurst
b21b25ddf9 Add initialization to OutputString. You never know. 2023-06-09 22:50:42 +02:00
Knutwurst
2849d5afc3 Switch back from char* to const char* withyout copy routine for testing. 2023-06-09 22:36:30 +02:00
Knutwurst
c10a05b8dd Check for inserted flag from marlin instead of separate check. 2023-06-09 22:27:12 +02:00
Knutwurst
3225d0dad3 Revert File list refactoring a253776. 2023-06-09 22:07:34 +02:00
Knutwurst
d528646009 Remove duplicate sd card check 2023-06-09 13:46:36 +02:00
Knutwurst
a253776044 File list refactoring. 2023-06-09 13:16:27 +02:00
Oliver Köster
ecdbf477ec Merge pull request #462 from stklcode/marlin-2.1.2.1
Merge upstream changes from Marlin 2.1.2.1
2023-06-09 08:50:09 +02:00
Knutwurst
4335238131 Fix anycubics typos in laser implementation. 2023-06-08 22:03:08 +02:00
Knutwurst
dc28578f54 Disable Steppers after one Minute 2023-06-08 18:26:53 +02:00
Knutwurst
de446f0520 Remove thermalManager dependency from 4MAX AutoPowerOff. 2023-06-08 18:17:51 +02:00
Knutwurst
f89e25ce3e Remove debugging defines and auto save after BLTouch leveling. This is saved afterwards when closing the menu. 2023-06-08 18:07:49 +02:00
Knutwurst
4c0ed10367 Rework file counting and substitute probe.offset.z with setZOffset_mm which is an ExtUI function. Also increase build number. 2023-06-08 18:00:11 +02:00
Knutwurst
c77aacbbd9 Set build version for next release 2023-06-07 21:59:21 +02:00
Knutwurst
4206e3c4e8 Invert setSoftEndstopState logic on print stop 2023-06-07 21:39:14 +02:00
Knutwurst
dfc9cbe8b1 Change Chiron and 4MAX filament load length. 2023-06-07 18:55:48 +02:00
Knutwurst
9c7e330363 Fix AutoPowerOff menu selection. 2023-06-07 18:02:01 +02:00
Knutwurst
580d56bd37 Fix PowerOffFlag handling. 2023-06-07 16:16:06 +02:00
Knutwurst
588f703684 Add Special Menu BLTouch HighSpeed Mode selection 2023-06-07 12:39:56 +02:00
Knutwurst
c48395f801 Fix 4MAX build 2023-06-07 09:09:14 +02:00
Knutwurst
f7060d5524 Add more TFT debugging messages. 2023-06-07 09:03:20 +02:00
Knutwurst
acee1592c9 Add setSoftEndstopState to TFT print and stop functions. 2023-06-07 08:49:56 +02:00
Knutwurst
442f66c145 Disable soft endstops while printing, so that mesh points below 0 can be reached. 2023-06-07 08:48:05 +02:00
Knutwurst
b5b3da41f5 Disable software endstops when manual or auto leveling is activated, so the nozzle can be set to a lower point than the endstop. 2023-06-07 08:35:43 +02:00
Knutwurst
38edd9375b Revert "Disable automatic mesh adjustment when Z offset is altered."
This reverts commit fb7a29ce8e.
2023-06-07 08:14:28 +02:00
Knutwurst
fb7a29ce8e Disable automatic mesh adjustment when Z offset is altered. 2023-06-06 21:44:08 +02:00
Knutwurst
056dd71494 Substitute LCD_SERIAL.println() with LCD_SERIAL.print(,2) to ensure display compatibility. 2023-06-06 19:06:50 +02:00
Knutwurst
09b448773f Revert define, because it breaks the build. 2023-06-06 17:01:43 +02:00
Knutwurst
223df2956a Fix display of single mesh points 2023-06-06 17:01:06 +02:00
Knutwurst
9376b95148 Fix live Z offset. 2023-06-06 16:46:09 +02:00
Knutwurst
fbd1b7b9bf Fix PowerOff. 2023-06-03 21:15:52 +02:00
Knutwurst
61fba37678 Reenable auto power off on 4MAX Pro 2.0 2023-06-03 19:45:48 +02:00
Knutwurst
7b0aa6ec6a Code cleanup. 2023-06-03 19:45:21 +02:00
Knutwurst
70ccd6a957 Refactor Chiron A31 Adjust all Probe Points routine 2023-06-03 19:29:59 +02:00
Knutwurst
6bc410a0e3 Unify special menu defines for both display types. Also fix NoSD message and error, when no SD card is present. 2023-06-03 18:51:02 +02:00
Knutwurst
011752e02a Improve file list rendering speed. 2023-06-03 09:20:54 +02:00
Knutwurst
471d7f47a0 Remove unnecessary code from get-sd-list routine. 2023-06-03 00:20:25 +02:00
Knutwurst
0670fb9253 Revert from const char* to char* because it breaks Anycubic 1.0 without SD card. 2023-06-02 22:57:16 +02:00
Knutwurst
501ebfd159 Fix load fw defaults gcode in special menu. 2023-06-02 22:23:53 +02:00
Knutwurst
dedc00fb0d Reenable automatic filament feed on M600, because a little purge is needed to enable the continue button. 2023-06-02 19:42:13 +02:00
Knutwurst
acc3c74905 New load/unload values for chiron. 2023-06-02 19:02:36 +02:00
Knutwurst
d1f269d654 Fix build 2023-06-02 18:59:12 +02:00
Knutwurst
d4fe673b96 Add M600 config for CHIRON. 2023-06-02 18:54:52 +02:00
Knutwurst
862ac308c7 Clean dead code and disable debugging messages. 2023-06-02 18:18:49 +02:00
Knutwurst
75c541cafb Change preheat temperatures. 2023-06-02 18:02:17 +02:00
Knutwurst
bb4ee37676 Set release version and clean up some code snippets. 2023-06-02 17:42:29 +02:00
Knutwurst
bf80c9b8dd Suppress AUTO_ASSIGN_WARNING on Chiron and 4MAX builds. 2023-06-02 17:01:25 +02:00
Knutwurst
79eaf1a8b5 Allow manual probing on Chiron. 2023-06-02 16:57:27 +02:00
Knutwurst
ff5b808dea Add new mediaPrintingState for probing, which is needed by the chiron routine. 2023-06-02 16:48:10 +02:00
Knutwurst
37ef0ca742 Add more debug output. 2023-06-02 13:14:48 +02:00
Knutwurst
fd84ec3523 Add TODO in case A31 - Adjust all Probe Points 2023-06-02 11:16:11 +02:00
Knutwurst
afa411f065 Substitute settings() with command injection. 2023-06-02 08:52:05 +02:00
Knutwurst
d93ff45af6 Set build version and date. Also enable TFT debugging. 2023-06-02 08:48:41 +02:00
Knutwurst
8fb71f482e Fix build 2023-06-02 08:47:06 +02:00
Knutwurst
325bcb7e01 Rebuild Chiron leveling feature. 2023-06-02 08:38:28 +02:00
Knutwurst
0af71b9817 Rename CodeSeen to FindToken. 2023-06-01 22:13:43 +02:00
Knutwurst
8e828a48b9 Revert duplicate Z2 pin definitions on 4MAX and Chiron. 2023-06-01 22:01:17 +02:00
Knutwurst
a356788dc7 Add fix for .GCO files on DGUS2 Clone Display 2023-06-01 19:27:01 +02:00
Knutwurst
6499c6b7c3 Simplify non-printable char filter loop. 2023-06-01 18:42:30 +02:00
Knutwurst
fda51c1c46 Remove unneccessary code in the filename check. 2023-06-01 17:13:17 +02:00
Knutwurst
0c25c876d3 Some refactoring and cleanup. No breaking changes. 2023-06-01 09:14:14 +02:00
Knutwurst
067fe2f074 Bump version and date for next major release. 2023-05-31 21:21:39 +02:00
Knutwurst
e8d38ba955 Enable alphabetical SD card file sorting. 2023-05-31 21:19:37 +02:00
Knutwurst
6d257896c0 Beautify DGUS2 Clone file display. Might need some refactoring. 2023-05-31 16:57:20 +02:00
Knutwurst
2af4a2d4e6 Fix sanitization of directory names on Anycubic 1.0 Display. 2023-05-31 15:19:18 +02:00
Knutwurst
c83dad91f3 Z2 Stepper pin definitions for CHIRON and 4MAX. 2023-05-30 22:10:31 +02:00
Knutwurst
429b8cc1fa Fix warnings in 4MAX Build 2023-05-30 22:00:27 +02:00
Knutwurst
2e030524e2 Disable debug output. 2023-05-30 21:18:41 +02:00
Knutwurst
45cbc380d9 Update build date. 2023-05-30 19:26:27 +02:00
Knutwurst
cf0611a7d9 Use const char* because it's not altered past that point. 2023-05-30 17:33:39 +02:00
Knutwurst
9c4c58235b Fix compiler warnings for Chiron build and Directory selection on Anycubic 1.0 displays. 2023-05-30 16:46:30 +02:00
Knutwurst
75ffa32980 Use SENDLINE instead of SEND to create directory name on anycubic 1.0 display. 2023-05-30 16:07:26 +02:00
Knutwurst
e0d858d812 Fix misuse of const char pointer by creating a new string which represents the filename. 2023-05-30 15:09:46 +02:00
Knutwurst
ad86d96a31 Cleanup 2023-05-30 09:22:25 +02:00
Knutwurst
6c4a0a887a Remove old PrintList() implementation + some cleanup 2023-05-29 20:48:58 +02:00
Knutwurst
e940c218cd Do not remove current selection if Special Menu is enabled, so items can be tapped multiple times. 2023-05-29 20:40:27 +02:00
Knutwurst
1df0ee59d2 Set correct filament sensor pins for chiron in correspondig header and enable new file list implementation. 2023-05-29 20:34:08 +02:00
Knutwurst
9244ea5890 New file list render implementation - WIP! 2023-05-29 20:07:06 +02:00
Knutwurst
8e34d7dc7c Fix 4MAXP2 Build. 2023-05-29 19:27:55 +02:00
Knutwurst
7fbbbba752 Fix Typo 2023-05-29 14:20:28 +02:00
Knutwurst
2b5816037a Add custom M600 configuration for DirectExtruder 4MAX Pro 2.0. 2023-05-29 12:35:07 +02:00
Knutwurst
e008a96269 Fix Chiron and 4MAX Pro 2.0 Filament rundout sensor. 2023-05-29 11:39:00 +02:00
Knutwurst
952e0db31e Fix that you could not get out of a selected directory. Refactor Touchscreen file handling. 2023-05-29 11:20:22 +02:00
Knutwurst
69efa3376a Set lowest point for BLTouch from 2 to 10 mm. 2023-05-28 22:57:50 +02:00
Knutwurst
b3f22b2b11 Bump builddate. 2023-05-28 17:29:59 +02:00
Knutwurst
bb8d41c0e1 Disable BLTouch Highspeed Mode by default (can be enabled via M401 S1) 2023-05-28 17:28:12 +02:00
Stefan Kalscheuer
bdd6e0c7fe lower the maximum hotend temperature to stay within the thermistor range
The default thermistor type 1 supports a maximum value of 300°C. The
maximum heater temperature plus overshoot value must stay within that
range. For all targets but 4MAXP2 we use type 1 with a default overshoot
value of 15°C, so let's lower the maximum heater temperature to 285.
2023-05-28 17:18:03 +02:00
Knutwurst
ae82913d1f Fix special menu not shown, when SD card is not inserted (Fix for #463) 2023-05-28 17:13:20 +02:00
Stefan Kalscheuer
f92a587638 Merge upstream changes from Marlin 2.1.2.1 2023-05-26 18:50:47 +02:00
Knutwurst
22dedaeb81 Use M600 for FilamentChange instead of regular pause() 2023-05-26 18:39:22 +02:00
Knutwurst
2b57ebccaa Add Heater Error Check. 2023-05-26 10:08:06 +02:00
Knutwurst
4a3071aa56 Some thermalManager substitutions. 2023-05-26 10:03:24 +02:00
Knutwurst
595bdd00cc Use ExtUI injectCommands() instead of queue.inject_P for PSTR. 2023-05-26 09:50:26 +02:00
Knutwurst
d5aa1e1823 Massive code cleanup by using internal ExtUI methods. 2023-05-25 21:06:45 +02:00
Knutwurst
570c419165 Use toolhead/nozzle paring position when aborting the SD print, instead of G28 homing. 2023-05-24 23:06:13 +02:00
Knutwurst
05a706dfb6 Fix print time display. 2023-05-24 22:38:14 +02:00
Knutwurst
7cc485ae3e Fix host action commands conflicting with integrated filament sensor 2023-05-24 19:36:20 +02:00
Knutwurst
5fbd3337b6 Disable Touchscreen debugging messages 2023-05-24 19:27:45 +02:00
Knutwurst
62fcc2ff35 Fix filament sensor, but disable host action commands. 2023-05-24 19:22:58 +02:00
Knutwurst
c01193bf40 Finally fix print/pause/resume and M600 filament change. 2023-05-24 14:42:09 +02:00
Knutwurst
a019c471d1 Code cleanup. 2023-05-23 22:18:21 +02:00
Knutwurst
a2137565e5 Fix Chiron build errors. 2023-05-23 15:43:23 +02:00
Knutwurst
52dc811774 Lots of changes regadring the ExtUI implementation, Filament runout, Start, Stop, Pause and Resume. 2023-05-23 15:22:25 +02:00
Knutwurst
4d6715761d Revert c2c950b and 41c1600 and put changes into 36c8aee to recreate the 1.4.x filane behaviour. This should fix #453 and #455. It's untested atm and can include bugs. 2023-04-23 22:11:42 +02:00
Knutwurst
9f93a2cc5d Streamline Github workflows so tickets stay open longer. 2023-04-23 21:43:36 +02:00
Knutwurst
fb281baa27 Update builddate and Version 2023-01-03 13:47:14 +01:00
Oliver Köster
640fce0c02 Merge pull request #409 from stklcode/feature/extui
make custom Anycubic touchscreen implementation an ExtUI module
2023-01-03 13:00:29 +01:00
Knutwurst
33a8c67631 Update builddate 2022-12-23 18:53:05 +01:00
Stefan Kalscheuer
b115276fee move display notification after leveling for Chiron into ExtUI hook 2022-12-23 17:51:20 +01:00
Stefan Kalscheuer
36c8aee75b make custom Anycubic touchscreen implementation an ExtUI module
Start migration to ExtUI module. We do not yet change much of the custom
logic, but this brings us closer to upstream and allows use of some
integration hooks with less patching required.
2022-12-23 17:29:38 +01:00
Oliver Köster
a9513299c0 Merge pull request #408 from stklcode/fix/beeper
re-enable beeper pin for custom Anycubic touchscreen implementation
2022-12-23 17:16:03 +01:00
Stefan Kalscheuer
9e5248e65d re-enable beeper pin for custom Anycubic touchscreen implementation 2022-12-23 16:56:51 +01:00
Knutwurst
c9f1b91bbe Set correct default baudrate and port number for ESP wifi module. This fixes #406. 2022-12-22 12:48:16 +01:00
Oliver Köster
029b37077a Merge pull request #405 from stklcode/fix/marlin-212-missing
add missing files from 2.1.2 merge
2022-12-22 09:55:24 +01:00
Stefan Kalscheuer
4885c082fe add missing files from 2.1.2 merge
fixes 67c7ce7b79
2022-12-22 09:48:39 +01:00
Oliver Köster
0f75d5be1d Merge pull request #404 from stklcode/fix/chiron-regression
fix regression from LCD_SERIAL migration for CHIRON targets
2022-12-22 09:41:35 +01:00
Stefan Kalscheuer
affad24f74 fix regression from LCD_SERIAL migration for CHIRON targets
fixes fd58245bd2

There is an extension to the G29 implementation that sends a J25
notification to the external display. This must not use the
HardwareSerial implementation anymore.

there are also two leftover opening parenthesis in the command scaning
loop within the Chiron block that must be removed.
2022-12-22 09:20:12 +01:00
Oliver Köster
bd5eba2a0c Merge pull request #403 from stklcode/fix/filename-padding
fill the output buffer with blanks on DGUS2 clone displays
2022-12-21 21:42:04 +01:00
Oliver Köster
b750daf391 Merge pull request #401 from stklcode/fix/z-mapping
swap Z motors for all targets and use predefined mappings
2022-12-21 21:40:29 +01:00
Oliver Köster
4fc8948e0b Merge pull request #400 from stklcode/feature/lcd-serial
use LCD_SERIAL for Anycubic touchscreen communication
2022-12-21 21:40:05 +01:00
Stefan Kalscheuer
41c16006a1 fill the output buffer with blanks on DGUS2 clone displays
The intention behind the original logic was to fill the entire line with
blanks, so that the output buffer of the display gets "flushed". Restore
this behavior.
2022-12-21 20:15:37 +01:00
Stefan Kalscheuer
d43d99bead swap Z motors for all targets and use predefined mappings
Z endstop mapping has changed as side effect of the upstream merge, so
it does no longer match the motor mapping.
Define SWAP_Z_MOTORS to resolve this issue without manipulation of the
upstream pin mapping.

Also use predefined mapping instead of custom overrides.
2022-12-21 19:56:55 +01:00
Stefan Kalscheuer
fd58245bd2 use LCD_SERIAL for Anycubic touchscreen communication
Replace our implementation of HardwareSerial with LCD_SERIAL from AVR
HAL and copy helper methods and macros from Anycubic i3 ExtUI.
2022-12-21 12:26:45 +01:00
Oliver Köster
bd0f3a9aa5 Merge pull request #399 from stklcode/fix/cleanup-filename
simplify file name sanitization
2022-12-21 09:14:16 +01:00
Knutwurst
55170f9fc8 Update build version 2022-12-21 09:09:55 +01:00
Stefan Kalscheuer
c2c950bbca simplify file name sanitization
The routine copies "fileNameLen" characters from the original filename
plus one additional character or a trailing blank. This additional char
is overwritten by a terminating null-byte afterwards anyway.

Remove the redundant check and simplify the loop.
2022-12-21 09:07:05 +01:00
Knutwurst
c03aa9d5a4 Fix Z home position not touching the buildplate (see #396) by removing the 2mm HOMING_BACKOFF_POST_MM on z. 2022-12-21 08:58:53 +01:00
Oliver Köster
8877ad534d Merge pull request #398 from stklcode/fix/393-sd-filenames
use longest_filename() for SD card files instead of longFilename
2022-12-20 09:16:59 +01:00
Stefan Kalscheuer
3a19d9ef69 use longest_filename() for SD card files instead of longFilename
The long filename is not always filled, so files like "test.gco" may not
be shown in the file list. Use the built-in fallback to the longest name
available to overcome that issue and print the 8.3 name if no other is
available.
2022-12-20 09:03:22 +01:00
Oliver Köster
3be0c7e7a6 Merge pull request #397 from stklcode/marlin-212
Merge upstream changes from Marlin 2.1.2
2022-12-19 16:03:54 +01:00
Stefan Kalscheuer
67c7ce7b79 Merge upstream changes from Marlin 2.1.2 2022-12-19 15:31:22 +01:00
Oliver Köster
fe9ea826a5 Merge pull request #394 from KemalErtas/patch-1
Update mesh_bed_leveling.h
2022-12-19 15:16:24 +01:00
KemalErtas
24d306ccb0 Update mesh_bed_leveling.h
Bedleveling should run on 4MAXP2 rectangular shape beds. It has no problem with square shape.
2022-12-01 13:13:12 +03:00
Knutwurst
ac7c272403 Update Version and release date 2022-09-13 09:27:36 +02:00
Oliver Köster
38f15215f8 Merge pull request #364 from stklcode/marlin-2.1.1
update code base to Marlin 2.1.1
2022-09-12 16:21:58 +02:00
Stefan Kalscheuer
bd49cc3d48 config: use soft PWM for fans
The hardware PWM for fan control conflicts with the speaker setup. While
this has always been an issue, sanity checks now fail because of this.

We've used soft PWM in 1.4.0 and reverted back to hardware PWM in 1.4.1,
so we probably need some additional investigation and testing here.
2022-09-12 16:18:18 +02:00
Stefan Kalscheuer
867ba6abc4 README++ 2022-09-12 16:18:04 +02:00
Stefan Kalscheuer
db27202614 update leveling implementation and pin config for Chiron 2022-09-12 16:18:03 +02:00
Stefan Kalscheuer
6368552ced clean up HardwareSerial code
Remove unused variables, sanitize declarations and apply uncrust.
2022-09-12 16:18:02 +02:00
Stefan Kalscheuer
afee7b10c2 apply uncrust to anycubic_touchscreen 2022-09-03 09:26:38 +02:00
Stefan Kalscheuer
031c095019 remove explicit ABL inclusion from Anycubit Touchscreen code 2022-09-03 09:26:05 +02:00
Stefan Kalscheuer
bf2795c51e add some directives to support custom target pinout 2022-09-03 09:25:33 +02:00
Stefan Kalscheuer
986e416c7f Merge upstream changes from Marlin 2.1.1 2022-09-03 09:23:32 +02:00
Knutwurst
626283aadb Set Z_PROBE_LOW_POINT to -2 to fix #346 2022-07-29 08:59:58 +02:00
Oliver Köster
84c181d4cf Merge pull request #311 from ignotus666/neo-fix
Comment out M150.cpp
2022-06-01 15:13:24 +02:00
Knutwurst
41d069464e Update build version 2022-05-12 13:16:27 +02:00
Knutwurst
4f459362c2 Enable Software-Endstop for Z_MIN which was disabled for BLTouch in the past. 2022-05-12 13:05:22 +02:00
Oliver Köster
4fcbe2afd0 Merge pull request #326 from stklcode/feature/325-m808
config: enable g-code M808 for repeat markers (#325)
2022-05-10 18:55:04 +02:00
Stefan Kalscheuer
465f4cbf60 config: enable g-code M808 for repeat markers (#325) 2022-05-09 19:45:56 +02:00
Knutwurst
e3a2aeb4cf Revert pause response to reenable M600 pause for use with octorptint. 2022-03-27 12:39:07 +02:00
ignotus
51da7acc6c Comment out M150.cpp
This line needs commenting out to successfully compile with Neopixel support.
2022-03-25 08:52:13 +01:00
Knutwurst
cbc02f7f3d Fix missing TMC26XStepper Lib build error. 2022-03-18 19:09:01 +01:00
Knutwurst
4985c9abf5 Only enable babystepping and probe offset change when BLTouch is enabled. 2022-02-23 10:08:45 +01:00
Knutwurst
0eaa8f902f Combine M851 and Z babystepping 2022-02-23 10:03:44 +01:00
Knutwurst
7444f4bb45 Add reset to 4Max Pro routine 2022-02-21 13:06:24 +01:00
Knutwurst
0440770618 Bump version for next release 2022-02-18 10:32:20 +01:00
Knutwurst
c66f3559d7 Reenable Mesh after 4 point easy level. 2022-02-18 09:57:27 +01:00
Knutwurst
1183a5b51c Fix bug, where Mesh was always applied when using 4 point easy leveling. 2022-02-18 09:53:43 +01:00
Knutwurst
2bc946edab Fix StopPrint when used before the actual print starts. 2022-02-13 12:43:34 +01:00
Knutwurst
3afc5c0dc1 Automatically disable steppers after stopping the print. 2022-02-13 12:34:32 +01:00
Knutwurst
f03df0b280 Add MEGA_P feature toggle (just in case, the implementation is used by another printer) 2022-02-10 09:37:08 +01:00
Knutwurst
b035c464dd Implement MEGA PRO inbuilt 4 point leveling 2022-02-10 09:25:13 +01:00
1968 changed files with 135435 additions and 75192 deletions

225
.clang-format Normal file
View File

@@ -0,0 +1,225 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignCompound: true
PadOperators: true
AlignConsecutiveBitFields:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignCompound: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: false
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Leave
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
...

29
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/python-3/.devcontainer/base.Dockerfile
# [Choice] Python version: 3, 3.9, 3.8, 3.7, 3.6
ARG VARIANT="3.9.0-buster"
FROM python:${VARIANT}
# [Option] Install Node.js
ARG INSTALL_NODE="true"
ARG NODE_VERSION="lts/*"
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.
# COPY requirements.txt /tmp/pip-tmp/
# RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
# && rm -rf /tmp/pip-tmp
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
RUN pip install -U https://github.com/platformio/platformio-core/archive/develop.zip
RUN platformio update
# To get the test platforms
RUN pip install PyYaml
#ENV PATH /code/buildroot/bin/:/code/buildroot/tests/:${PATH}

View File

@@ -0,0 +1,51 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/python-3
{
"name": "Python 3",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
// Update 'VARIANT' to pick a Python version: 3, 3.6, 3.7, 3.8, 3.9
"VARIANT": "3.9.0-buster",
// Options
"INSTALL_NODE": "false",
"NODE_VERSION": "lts/*"
}
},
// Set *default* container specific settings.json values on container create.
"settings": {
"python.pythonPath": "/usr/local/bin/python",
"python.languageServer": "Pylance",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"platformio.platformio-ide",
"marlinfirmware.auto-build",
"editorconfig.editorconfig"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
// "remoteUser": "vscode"
}

View File

@@ -14,6 +14,10 @@ end_of_line = lf
indent_style = space
indent_size = 2
[{*.py,*.conf,*.sublime-project}]
[{*.py}]
indent_style = space
indent_size = 4
[{*.conf,*.sublime-project}]
indent_style = tab
indent_size = 4

0
.github/ISSUE_TEMPLATE/bug_report.md vendored Executable file → Normal file
View File

0
.github/ISSUE_TEMPLATE/config.yml vendored Executable file → Normal file
View File

0
.github/ISSUE_TEMPLATE/feature_request.md vendored Executable file → Normal file
View File

46
.github/code_of_conduct.md vendored Normal file
View File

@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [marlinfirmware@github.com](mailto:marlinfirmware@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/

146
.github/contributing.md vendored Normal file
View File

@@ -0,0 +1,146 @@
# Contributing to Marlin
Thanks for your interest in contributing to Marlin Firmware!
The following is a set of guidelines for contributing to Marlin, hosted by the [MarlinFirmware Organization](https://github.com/MarlinFirmware) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a Pull Request.
#### Table Of Contents
[Code of Conduct](#code-of-conduct)
[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Features or Changes](#suggesting-features-or-changes)
* [Your First Code Contribution](#your-first-code-contribution)
* [Pull Requests](#pull-requests)
[Styleguides](#styleguides)
* [Git Commit Messages](#git-commit-messages)
* [C++ Coding Standards](#c++-coding-standards)
* [Documentation Styleguide](#documentation)
[Additional Notes](#additional-notes)
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
## Code of Conduct
This project and everyone participating in it is governed by the [Marlin Code of Conduct](code_of_conduct.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [marlinfirmware@github.com](mailto:marlinfirmware@github.com).
## I don't want to read this whole thing I just have a question!!!
> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below.
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation
- Facebook Group ["Marlin Firmware"](https://www.facebook.com/groups/1049718498464482/)
- RepRap.org [Marlin Forum](https://forums.reprap.org/list.php?415)
- Facebook Group ["Marlin Firmware for 3D Printers"](https://www.facebook.com/groups/3Dtechtalk/)
- [Marlin Configuration](https://www.youtube.com/results?search_query=marlin+configuration) on YouTube
If chat is more your speed, you can join the MarlinFirmware Discord server:
* Use the link https://discord.gg/n5NJ59y to join up as a General User.
* Even though our Discord is pretty active, it may take a while for community members to respond &mdash; please be patient!
* Use the `#general` channel for general questions or discussion about Marlin.
* Other channels exist for certain topics or are limited to Patrons. Check the channel list.
## How Can I Contribute?
### Reporting Bugs
This section guides you through submitting a Bug Report for Marlin. Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.
Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE/bug_report.yml), the information it asks for helps us resolve issues faster.
> **Note:** Regressions can happen. If you find a **Closed** issue that seems like your issue, go ahead and open a new issue and include a link to the original issue in the body of your new one. All you need to create a link is the issue number, preceded by #. For example, #8888.
#### How Do I Submit A (Good) Bug Report?
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Use the New Issue button to create an issue and provide the following information by filling in [the template](ISSUE_TEMPLATE/bug_report.yml).
Explain the problem and include additional details to help maintainers reproduce the problem:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started Marlin, e.g. which command exactly you used in the terminal, or how you started Marlin otherwise. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you moved the cursor to the end of a line, explain if you used the mouse, or a keyboard shortcut or an Marlin command, and if so which one?
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets or log output in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Include detailed log output** especially for probing and leveling. See below for usage of `DEBUG_LEVELING_FEATURE`.
* **Include screenshots, links to videos, etc.** which clearly demonstrate the problem.
* **Include G-code** (if relevant) that reliably causes the problem to show itself.
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
Provide more context:
* **Can you reproduce the problem with a minimum of options enabled?**
* **Did the problem start happening recently** (e.g. after updating to a new version of Marlin) or was this always a problem?
* If the problem started happening recently, **can you reproduce the problem in an older version of Marlin?** What's the most recent version in which the problem doesn't happen? You can download older versions of Marlin from [the releases page](https://github.com/MarlinFirmware/Marlin/releases).
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
Include details about your configuration and environment:
* **Which version of Marlin are you using?** Marlin's exact version and build date can be seen in the startup message when a host connects to Marlin, or in the LCD Info menu (if enabled).
* **What kind of 3D Printer and electronics are you using**?
* **What kind of add-ons (probe, filament sensor) do you have**?
* **Include your Configuration files.** Make a ZIP file containing `Configuration.h` and `Configuration_adv.h` and drop it on your reply.
### Suggesting Features or Changes
This section guides you through submitting a suggestion for Marlin, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related suggestions.
Before creating a suggestion, please check [this list](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-feature-request). Fill in [the template](ISSUE_TEMPLATE/feature_request.yml), including the steps that you imagine you would take if the feature you're requesting existed.
#### Before Submitting a Feature Request
* **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html).
* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Feature Request?
Feature Requests are tracked as [GitHub issues](https://guides.github.com/features/issues/). Please follow these guidelines in your request:
* **Use a clear and descriptive title** for the issue to identify the suggestion.
* **Provide a step-by-step description of the requested feature** in as much detail as possible.
* **Provide specific examples to demonstrate the steps**.
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
* **Include screenshots and links to videos** which demonstrate the feature or point out the part of Marlin to which the request is related.
* **Explain why this feature would be useful** to most Marlin users.
* **Name other firmwares that have this feature, if any.**
### Your First Code Contribution
Unsure where to begin contributing to Marlin? You can start by looking through these `good-first-issue` and `help-wanted` issues:
* [Beginner issues][good-first-issue] - issues which should only require a few lines of code, and a test or two.
* [Help Wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues.
### Pull Requests
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
* Fill in [the required template](pull_request_template.md).
* Don't include issue numbers in the PR title.
* Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed.
* Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website.
* Document new code with clear and concise comments.
* End all files with a newline.
## Styleguides
### Git Commit Messages
* Use the present tense ("Add feature" not "Added feature").
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...").
* Limit the first line to 72 characters or fewer.
* Reference issues and Pull Requests liberally after the first line.
### C++ Coding Standards
* Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
### Documentation
* Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point.

View File

@@ -1,18 +1,32 @@
### Requirements
<!--
* Filling out this template is required. Pull Requests without a clear description may be closed at the maintainers' discretion.
Submitting a Pull Request
- Please fill out all sections of this form. You can delete the helpful comments.
- Pull Requests without clear information will take longer and may even be rejected.
- We get a high volume of submissions so please be patient during review.
-->
### Description
<!--
We must be able to understand your proposed change from this description. If we can't understand what the code will do from this description, the Pull Request may be closed at the maintainers' discretion. Keep in mind that the maintainer reviewing this PR may not be familiar with or have worked with the code recently, so please walk us through the concepts.
Clearly describe the submitted changes with lots of details. Include images where helpful. Initial reviewers may not be familiar with the subject, so be as thorough as possible. You can use MarkDown syntax to improve readability with bullet lists, code blocks, and so on. PREVIEW and fix up formatting before submitting.
-->
### Requirements
<!-- Does this PR require a specific board, LCD, etc.? -->
### Benefits
<!-- What does this fix or improve? -->
<!-- What does this PR fix or improve? -->
### Configurations
<!-- Attach Configurations ZIP and any other files needed to test this PR. -->
### Configurations
@@ -20,4 +34,4 @@ We must be able to understand your proposed change from this description. If we
### Related Issues
<!-- Whether this fixes a bug or fulfills a feature request, please list any related Issues here. -->
<!-- Does this PR fix a bug or fulfill a Feature Request? Link related Issues here. -->

View File

@@ -21,7 +21,7 @@ jobs:
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label / comment or this will be closed in 5 days.'
days-before-stale: 30
days-before-close: 5
days-before-stale: 300
days-before-close: 30
stale-issue-label: 'stale-closing-soon'
exempt-issue-labels: 'T: Feature Request'

View File

@@ -21,7 +21,7 @@ jobs:
with:
github-token: ${{ github.token }}
process-only: 'issues'
issue-lock-inactive-days: '60'
issue-lock-inactive-days: '300'
issue-exclude-created-before: ''
issue-exclude-labels: 'no-locking'
issue-lock-labels: ''

64
.gitignore vendored
View File

@@ -21,32 +21,18 @@
# Generated files
_Version.h
bdf2u8g
bdf2u8g.exe
genpages.exe
marlin_config.json
mczip.h
*.gen
*.sublime-workspace
#
# OS
#
applet/
*.DS_Store
.DS_Store
#
# Misc
#
*~
*.orig
*.rej
*.bak
*.idea
*.s
*.i
*.ii
*.swp
tags
#
# C++
#
# Compiled Object files
# Compiled C++ Object files
*.slo
*.lo
*.o
@@ -77,10 +63,7 @@ tags
*.out
*.app
#
# C
#
# Object files
# Compiled C Object files
*.o
*.ko
*.obj
@@ -137,20 +120,20 @@ __vm/
vc-fileutils.settings
# Visual Studio Code
.vscode
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/*.db
.vscode/*
!.vscode/extensions.json
#Simulation
# Simulation files
imgui.ini
eeprom.dat
spi_flash.bin
fs.img
#cmake
# CMake
CMakeLists.txt
src/CMakeLists.txt
CMakeListsPrivate.txt
build/
# CLion
cmake-build-*
@@ -168,6 +151,15 @@ __pycache__
# IOLogger logs
*_log.csv
# Simulation / Native
eeprom.dat
imgui.ini
# Misc.
*~
*.orig
*.rej
*.bak
*.idea
*.i
*.ii
*.swp
tags
*.logs
*.bak

11
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"marlinfirmware.auto-build",
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

0
LICENSE Executable file → Normal file
View File

59
Makefile Normal file
View File

@@ -0,0 +1,59 @@
SCRIPTS_DIR := buildroot/share/scripts
CONTAINER_RT_BIN := docker
CONTAINER_RT_OPTS := --rm -v $(PWD):/code -v platformio-cache:/root/.platformio
CONTAINER_IMAGE := marlin-dev
help:
@echo "Tasks for local development:"
@echo "* tests-single-ci: Run a single test from inside the CI"
@echo "* tests-single-local: Run a single test locally"
@echo "* tests-single-local-docker: Run a single test locally, using docker"
@echo "* tests-all-local: Run all tests locally"
@echo "* tests-all-local-docker: Run all tests locally, using docker"
@echo "* setup-local-docker: Build the local docker image"
@echo ""
@echo "Options for testing:"
@echo " TEST_TARGET Set when running tests-single-*, to select the"
@echo " test. If you set it to ALL it will run all "
@echo " tests, but some of them are broken: use "
@echo " tests-all-* instead to run only the ones that "
@echo " run on GitHub CI"
@echo " ONLY_TEST Limit tests to only those that contain this, or"
@echo " the index of the test (1-based)"
@echo " VERBOSE_PLATFORMIO If you want the full PIO output, set any value"
@echo " GIT_RESET_HARD Used by CI: reset all local changes. WARNING:"
@echo " THIS WILL UNDO ANY CHANGES YOU'VE MADE!"
.PHONY: help
tests-single-ci:
export GIT_RESET_HARD=true
$(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET)
.PHONY: tests-single-ci
tests-single-local:
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local" ; return 1; fi
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
.PHONY: tests-single-local
tests-single-local-docker:
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local-docker" ; return 1; fi
@if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
.PHONY: tests-single-local-docker
tests-all-local:
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& for TEST_TARGET in $$($(SCRIPTS_DIR)/get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done
.PHONY: tests-all-local
tests-all-local-docker:
@if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) $(MAKE) tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
.PHONY: tests-all-local-docker
setup-local-docker:
$(CONTAINER_RT_BIN) build -t $(CONTAINER_IMAGE) -f docker/Dockerfile .
.PHONY: setup-local-docker

2075
Marlin/Configuration.h Executable file → Normal file

File diff suppressed because it is too large Load Diff

2615
Marlin/Configuration_adv.h Executable file → Normal file

File diff suppressed because it is too large Load Diff

1037
Marlin/Makefile Normal file

File diff suppressed because it is too large Load Diff

0
Marlin/Marlin.ino Executable file → Normal file
View File

4
Marlin/Version.h Executable file → Normal file
View File

@@ -28,7 +28,7 @@
/**
* Marlin release version identifier
*/
//#define SHORT_BUILD_VERSION "2.0.9.2"
//#define SHORT_BUILD_VERSION "2.1.2.1"
/**
* Verbose version identifier which should contain a reference to the location
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2021-09-03"
//#define STRING_DISTRIBUTION_DATE "2023-05-16"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.

211
Marlin/config.ini Normal file
View File

@@ -0,0 +1,211 @@
#
# Marlin Firmware
# config.ini - Options to apply before the build
#
[config:base]
ini_use_config = none
# Load all config: sections in this file
;ini_use_config = all
# Load config file relative to Marlin/
;ini_use_config = another.ini
# Download configurations from GitHub
;ini_use_config = example/Creality/Ender-5 Plus @ bugfix-2.1.x
# Download configurations from your server
;ini_use_config = https://me.myserver.com/path/to/configs
# Evaluate config:base and do a config dump
;ini_use_config = base
;config_export = 2
[config:minimal]
motherboard = BOARD_RAMPS_14_EFB
serial_port = 0
baudrate = 250000
use_watchdog = on
thermal_protection_hotends = on
thermal_protection_hysteresis = 4
thermal_protection_period = 40
bufsize = 4
block_buffer_size = 16
max_cmd_size = 96
extruders = 1
temp_sensor_0 = 1
temp_hysteresis = 3
heater_0_mintemp = 5
heater_0_maxtemp = 275
preheat_1_temp_hotend = 180
bang_max = 255
pidtemp = on
pid_k1 = 0.95
pid_max = BANG_MAX
pid_functional_range = 10
default_kp = 22.20
default_ki = 1.08
default_kd = 114.00
x_driver_type = A4988
y_driver_type = A4988
z_driver_type = A4988
e0_driver_type = A4988
x_bed_size = 200
x_min_pos = 0
x_max_pos = X_BED_SIZE
y_bed_size = 200
y_min_pos = 0
y_max_pos = Y_BED_SIZE
z_min_pos = 0
z_max_pos = 200
x_home_dir = -1
y_home_dir = -1
z_home_dir = -1
use_xmin_plug = on
use_ymin_plug = on
use_zmin_plug = on
x_min_endstop_inverting = false
y_min_endstop_inverting = false
z_min_endstop_inverting = false
default_axis_steps_per_unit = { 80, 80, 400, 500 }
axis_relative_modes = { false, false, false, false }
default_max_feedrate = { 300, 300, 5, 25 }
default_max_acceleration = { 3000, 3000, 100, 10000 }
homing_feedrate_mm_m = { (50*60), (50*60), (4*60) }
homing_bump_divisor = { 2, 2, 4 }
x_enable_on = 0
y_enable_on = 0
z_enable_on = 0
e_enable_on = 0
invert_x_dir = false
invert_y_dir = true
invert_z_dir = false
invert_e0_dir = false
invert_e_step_pin = false
invert_x_step_pin = false
invert_y_step_pin = false
invert_z_step_pin = false
disable_x = false
disable_y = false
disable_z = false
disable_e = false
proportional_font_ratio = 1.0
default_nominal_filament_dia = 1.75
junction_deviation_mm = 0.013
default_acceleration = 3000
default_travel_acceleration = 3000
default_retract_acceleration = 3000
default_minimumfeedrate = 0.0
default_mintravelfeedrate = 0.0
minimum_planner_speed = 0.05
min_steps_per_segment = 6
default_minsegmenttime = 20000
[config:basic]
bed_overshoot = 10
busy_while_heating = on
default_ejerk = 5.0
default_keepalive_interval = 2
default_leveling_fade_height = 0.0
disable_inactive_extruder = on
display_charset_hd44780 = JAPANESE
eeprom_boot_silent = on
eeprom_chitchat = on
endstoppullups = on
extrude_maxlength = 200
extrude_mintemp = 170
host_keepalive_feature = on
hotend_overshoot = 15
jd_handle_small_segments = on
lcd_info_screen_style = 0
lcd_language = en
max_bed_power = 255
mesh_inset = 0
min_software_endstops = on
max_software_endstops = on
min_software_endstop_x = on
min_software_endstop_y = on
min_software_endstop_z = on
max_software_endstop_x = on
max_software_endstop_y = on
max_software_endstop_z = on
preheat_1_fan_speed = 0
preheat_1_label = "PLA"
preheat_1_temp_bed = 70
prevent_cold_extrusion = on
prevent_lengthy_extrude = on
printjob_timer_autostart = on
probing_margin = 10
show_bootscreen = on
soft_pwm_scale = 0
string_config_h_author = "(none, default config)"
temp_bed_hysteresis = 3
temp_bed_residency_time = 10
temp_bed_window = 1
temp_residency_time = 10
temp_window = 1
validate_homing_endstops = on
xy_probe_feedrate = (133*60)
z_clearance_between_probes = 5
z_clearance_deploy_probe = 10
z_clearance_multi_probe = 5
[config:advanced]
arc_support = on
auto_report_temperatures = on
autotemp = on
autotemp_oldweight = 0.98
bed_check_interval = 5000
default_stepper_deactive_time = 120
default_volumetric_extruder_limit = 0.00
disable_inactive_e = true
disable_inactive_x = true
disable_inactive_y = true
disable_inactive_z = true
e0_auto_fan_pin = -1
encoder_100x_steps_per_sec = 80
encoder_10x_steps_per_sec = 30
encoder_rate_multiplier = on
extended_capabilities_report = on
extruder_auto_fan_speed = 255
extruder_auto_fan_temperature = 50
fanmux0_pin = -1
fanmux1_pin = -1
fanmux2_pin = -1
faster_gcode_parser = on
homing_bump_mm = { 5, 5, 2 }
max_arc_segment_mm = 1.0
min_arc_segment_mm = 0.1
min_circle_segments = 72
n_arc_correction = 25
serial_overrun_protection = on
slowdown = on
slowdown_divisor = 2
temp_sensor_bed = 0
thermal_protection_bed_hysteresis = 2
thermocouple_max_errors = 15
tx_buffer_size = 0
watch_bed_temp_increase = 2
watch_bed_temp_period = 60
watch_temp_increase = 2
watch_temp_period = 20

0
Marlin/lib/readme.txt Executable file → Normal file
View File

View File

@@ -23,6 +23,7 @@
#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#include <avr/wdt.h>
#ifdef USBCON
DefaultSerial1 MSerial0(false, Serial);
@@ -35,13 +36,32 @@
// Public Variables
// ------------------------
//uint8_t MCUSR;
// Don't initialize/override variable (which would happen in .init4)
uint8_t MarlinHAL::reset_reason __attribute__((section(".noinit")));
// ------------------------
// Public functions
// ------------------------
void HAL_init() {
__attribute__((naked)) // Don't output function pro- and epilogue
__attribute__((used)) // Output the function, even if "not used"
__attribute__((section(".init3"))) // Put in an early user definable section
void save_reset_reason() {
#if ENABLED(OPTIBOOT_RESET_REASON)
__asm__ __volatile__(
A("STS %0, r2")
: "=m"(hal.reset_reason)
);
#else
hal.reset_reason = MCUSR;
#endif
// Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
hal.clear_reset_source();
wdt_disable();
}
void MarlinHAL::init() {
// Init Servo Pins
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
#if HAS_SERVO_0
@@ -56,9 +76,11 @@ void HAL_init() {
#if HAS_SERVO_3
INIT_SERVO(3);
#endif
init_pwm_timers(); // Init user timers to default frequency - 1000HZ
}
void HAL_reboot() {
void MarlinHAL::reboot() {
#if ENABLED(USE_WATCHDOG)
while (1) { /* run out the watchdog */ }
#else
@@ -67,6 +89,62 @@ void HAL_reboot() {
#endif
}
// ------------------------
// Watchdog Timer
// ------------------------
#if ENABLED(USE_WATCHDOG)
#include <avr/wdt.h>
#include "../../MarlinCore.h"
// Initialize watchdog with 8s timeout, if possible. Otherwise, make it 4s.
void MarlinHAL::watchdog_init() {
#if ENABLED(WATCHDOG_DURATION_8S) && defined(WDTO_8S)
#define WDTO_NS WDTO_8S
#else
#define WDTO_NS WDTO_4S
#endif
#if ENABLED(WATCHDOG_RESET_MANUAL)
// Enable the watchdog timer, but only for the interrupt.
// Take care, as this requires the correct order of operation, with interrupts disabled.
// See the datasheet of any AVR chip for details.
wdt_reset();
cli();
_WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
_WD_CONTROL_REG = _BV(WDIE) | (WDTO_NS & 0x07) | ((WDTO_NS & 0x08) << 2); // WDTO_NS directly does not work. bit 0-2 are consecutive in the register but the highest value bit is at bit 5
// So worked for up to WDTO_2S
sei();
wdt_reset();
#else
wdt_enable(WDTO_NS); // The function handles the upper bit correct.
#endif
//delay(10000); // test it!
}
//===========================================================================
//=================================== ISR ===================================
//===========================================================================
// Watchdog timer interrupt, called if main program blocks >4sec and manual reset is enabled.
#if ENABLED(WATCHDOG_RESET_MANUAL)
ISR(WDT_vect) {
sei(); // With the interrupt driven serial we need to allow interrupts.
SERIAL_ERROR_MSG(STR_WATCHDOG_FIRED);
minkill(); // interrupt-safe final kill and infinite loop
}
#endif
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or AVR will go into emergency procedures.
void MarlinHAL::watchdog_refresh() { wdt_reset(); }
#endif // USE_WATCHDOG
// ------------------------
// Free Memory Accessor
// ------------------------
#if ENABLED(SDSUPPORT)
#include "../../sd/SdFatUtil.h"
@@ -74,20 +152,20 @@ void HAL_reboot() {
#else // !SDSUPPORT
extern "C" {
extern char __bss_end;
extern char __heap_start;
extern void* __brkval;
extern "C" {
extern char __bss_end;
extern char __heap_start;
extern void* __brkval;
int freeMemory() {
int free_memory;
if ((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end);
else
free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory;
int freeMemory() {
int free_memory;
if ((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end);
else
free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory;
}
}
}
#endif // !SDSUPPORT

View File

@@ -19,17 +19,20 @@
*/
#pragma once
/**
* HAL for Arduino AVR
*/
#include "../shared/Marduino.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#include "math.h"
#ifdef USBCON
#include <HardwareSerial.h>
#else
#define HardwareSerial_h // Hack to prevent HardwareSerial.h header inclusion
#include "MarlinSerial.h"
#define BOARD_NO_NATIVE_USB
#endif
#include <stdint.h>
@@ -74,9 +77,9 @@
#define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli()
#define CRITICAL_SECTION_END() SREG = _sreg
#endif
#define ISRS_ENABLED() TEST(SREG, SREG_I)
#define ENABLE_ISRS() sei()
#define DISABLE_ISRS() cli()
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
#define PWM_FREQUENCY 1000 // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
// ------------------------
// Types
@@ -84,16 +87,15 @@
typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS
#define HAL_SERVO_LIB Servo
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
class Servo;
typedef Servo hal_servo_t;
// ------------------------
// Public Variables
// ------------------------
//extern uint8_t MCUSR;
// Serial ports
// ------------------------
#ifdef USBCON
#include "../../core/serial_hook.h"
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
@@ -105,36 +107,36 @@ typedef int8_t pin_t;
#define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
#else
#if !WITHIN(SERIAL_PORT, -1, 3)
#error "SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#if !WITHIN(SERIAL_PORT, 0, 3)
#error "SERIAL_PORT must be from 0 to 3."
#endif
#define MYSERIAL1 customizedSerial1
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3)
#error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial."
#if !WITHIN(SERIAL_PORT_2, 0, 3)
#error "SERIAL_PORT_2 must be from 0 to 3."
#endif
#define MYSERIAL2 customizedSerial2
#endif
#ifdef SERIAL_PORT_3
#if !WITHIN(SERIAL_PORT_3, -1, 3)
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
#if !WITHIN(SERIAL_PORT_3, 0, 3)
#error "SERIAL_PORT_3 must be from 0 to 3."
#endif
#define MYSERIAL3 customizedSerial3
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if !WITHIN(MMU2_SERIAL_PORT, -1, 3)
#error "MMU2_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#if !WITHIN(MMU2_SERIAL_PORT, 0, 3)
#error "MMU2_SERIAL_PORT must be from 0 to 3"
#endif
#define MMU2_SERIAL mmuSerial
#endif
#ifdef LCD_SERIAL_PORT
#if !WITHIN(LCD_SERIAL_PORT, -1, 3)
#error "LCD_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#if !WITHIN(LCD_SERIAL_PORT, 0, 3)
#error "LCD_SERIAL_PORT must be from 0 to 3."
#endif
#define LCD_SERIAL lcdSerial
#if HAS_DGUS_LCD
@@ -142,59 +144,15 @@ typedef int8_t pin_t;
#endif
#endif
// ------------------------
// Public functions
// ------------------------
void HAL_init();
//void cli();
//void _delay_ms(const int delay);
inline void HAL_clear_reset_source() { MCUSR = 0; }
inline uint8_t HAL_get_reset_source() { return MCUSR; }
void HAL_reboot();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
extern "C" int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
//
// ADC
#ifdef DIDR2
#define HAL_ANALOG_SELECT(ind) do{ if (ind < 8) SBI(DIDR0, ind); else SBI(DIDR2, ind & 0x07); }while(0)
#else
#define HAL_ANALOG_SELECT(ind) SBI(DIDR0, ind);
#endif
inline void HAL_adc_init() {
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
#define SET_ADMUX_ADCSRA(ch) ADMUX = _BV(REFS0) | (ch & 0x07); SBI(ADCSRA, ADSC)
#ifdef MUX5
#define HAL_START_ADC(ch) if (ch > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
#else
#define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
#endif
//
#define HAL_ADC_VREF 5.0
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() ADC
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
//
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
@@ -208,23 +166,113 @@ inline void HAL_adc_init() {
// AVR compatibility
#define strtof strtod
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
// ------------------------
// Free Memory Accessor
// ------------------------
/**
* set_pwm_frequency
* Sets the frequency of the timer corresponding to the provided pin
* as close as possible to the provided desired frequency. Internally
* calculates the required waveform generation mode, prescaler and
* resolution values required and sets the timer registers accordingly.
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST FAN PWM Settings)
*/
void set_pwm_frequency(const pin_t pin, int f_desired);
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
/**
* set_pwm_duty
* Sets the PWM duty cycle of the provided pin to the provided value
* Optionally allows inverting the duty cycle [default = false]
* Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
*/
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
extern "C" int freeMemory();
#pragma GCC diagnostic pop
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup()
static void init_board() {} // Called less early in setup()
static void reboot(); // Restart the firmware from 0x0
// Interrupts
static bool isr_state() { return TEST(SREG, SREG_I); }
static void isr_on() { sei(); }
static void isr_off() { cli(); }
static void delay_ms(const int ms) { _delay_ms(ms); }
// Tasks, called from idle()
static void idletask() {}
// Reset
static uint8_t reset_reason;
static uint8_t get_reset_source() { return reset_reason; }
static void clear_reset_source() { MCUSR = 0; }
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
// Called by Temperature::init once at startup
static void adc_init() {
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t ch) {
#ifdef DIDR2
if (ch > 7) { SBI(DIDR2, ch & 0x07); return; }
#endif
SBI(DIDR0, ch);
}
// Begin ADC sampling on the given channel. Called from Temperature::isr!
static void adc_start(const uint8_t ch) {
#ifdef MUX5
ADCSRB = ch > 7 ? _BV(MUX5) : 0;
#else
ADCSRB = 0;
#endif
ADMUX = _BV(REFS0) | (ch & 0x07);
SBI(ADCSRA, ADSC);
}
// Is the ADC ready for reading?
static bool adc_ready() { return !TEST(ADCSRA, ADSC); }
// The current value of the ADC register
static __typeof__(ADC) adc_value() { return ADC; }
/**
* init_pwm_timers
* Set the default frequency for timers 2-5 to 1000HZ
*/
static void init_pwm_timers();
/**
* Set the PWM duty cycle for the pin to the given value.
* Optionally invert the duty cycle [default = false]
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
/**
* Set the frequency of the timer for the given pin as close as
* possible to the provided desired frequency. Internally calculate
* the required waveform generation mode, prescaler, and resolution
* values and set timer registers accordingly.
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST_PWM_FAN Settings)
*/
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
};

View File

@@ -34,21 +34,21 @@
#include "../../inc/MarlinConfig.h"
void spiBegin() {
OUT_WRITE(SD_SS_PIN, HIGH);
#if PIN_EXISTS(SD_SS)
// Do not init HIGH for boards with pin 4 used as Fans or Heaters or otherwise, not likely to have multiple SPI devices anyway.
#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
// SS must be in output mode even it is not chip select
SET_OUTPUT(SD_SS_PIN);
#else
// set SS high - may be chip select for another SPI device
OUT_WRITE(SD_SS_PIN, HIGH);
#endif
#endif
SET_OUTPUT(SD_SCK_PIN);
SET_INPUT(SD_MISO_PIN);
SET_OUTPUT(SD_MOSI_PIN);
#if DISABLED(SOFTWARE_SPI)
// SS must be in output mode even it is not chip select
//SET_OUTPUT(SD_SS_PIN);
// set SS high - may be chip select for another SPI device
//#if SET_SPI_SS_HIGH
//WRITE(SD_SS_PIN, HIGH);
//#endif
// set a default rate
spiInit(1);
#endif
IF_DISABLED(SOFTWARE_SPI, spiInit(SPI_HALF_SPEED));
}
#if NONE(SOFTWARE_SPI, FORCE_SOFT_SPI)

View File

@@ -486,7 +486,7 @@ void MarlinSerial<Cfg>::write(const uint8_t c) {
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) {
if (!hal.isr_state()) {
// Make room by polling if it is possible to transmit, and do so!
while (i == tx_buffer.tail) {
@@ -534,7 +534,7 @@ void MarlinSerial<Cfg>::flushTX() {
if (!_written) return;
// If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) {
if (!hal.isr_state()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !B_TXC) {

View File

@@ -191,13 +191,13 @@
rx_framing_errors;
static ring_buffer_pos_t rx_max_enqueued;
static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head();
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_head();
static volatile bool rx_tail_value_not_stable;
static volatile uint16_t rx_tail_value_backup;
static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value);
static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail();
FORCE_INLINE static void atomic_set_rx_tail(ring_buffer_pos_t value);
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_tail();
public:
FORCE_INLINE static void store_rxd_char();
@@ -217,7 +217,7 @@
#endif
enum { HasEmergencyParser = Cfg::EMERGENCYPARSER };
static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }

View File

@@ -66,27 +66,26 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
/************ static functions common to all instances ***********************/
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
if (Channel[timer] < 0)
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
else {
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
}
static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
if (cho < 0) // Channel -1 indicates the refresh interval completed...
*TCNTn = 0; // ...so reset the timer
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
Channel[timer]++; // increment to the next channel
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
*OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
Channel[timer] = ++cho; // Handle the next channel (or 0)
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
*OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
if (SERVO(timer, cho).Pin.isActive) // activated?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
}
else {
// finished all channels so wait for the refresh period to expire before starting over
if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
else
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
*OCRnA = max(cval, ival);
Channel[timer] = -1; // reset the timer counter to 0 on the next call
}
}
@@ -123,91 +122,102 @@ static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t
/****************** end of static functions ******************************/
void initISR(timer16_Sequence_t timer) {
#ifdef _useTimer1
if (timer == _timer1) {
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
SBI(TIFR, OCF1A); // clear any pending interrupts;
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
SBI(TIFR1, OCF1A); // clear any pending interrupts;
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif
void initISR(const timer16_Sequence_t timer_index) {
switch (timer_index) {
default: break;
#ifdef _useTimer3
if (timer == _timer3) {
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#ifdef __AVR_ATmega128__
SBI(TIFR, OCF3A); // clear any pending interrupts;
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else
SBI(TIFR3, OCF3A); // clear any pending interrupts;
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
}
#endif
#ifdef _useTimer1
case _timer1:
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
SBI(TIFR, OCF1A); // clear any pending interrupts;
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
SBI(TIFR1, OCF1A); // clear any pending interrupts;
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
break;
#endif
#ifdef _useTimer4
if (timer == _timer4) {
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
}
#endif
#ifdef _useTimer3
case _timer3:
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#ifdef __AVR_ATmega128__
SBI(TIFR, OCF3A); // clear any pending interrupts;
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else
SBI(TIFR3, OCF3A); // clear any pending interrupts;
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
break;
#endif
#ifdef _useTimer5
if (timer == _timer5) {
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
}
#endif
#ifdef _useTimer4
case _timer4:
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
break;
#endif
#ifdef _useTimer5
case _timer5:
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
break;
#endif
}
}
void finISR(timer16_Sequence_t timer) {
void finISR(const timer16_Sequence_t timer_index) {
// Disable use of the given timer
#ifdef WIRING
if (timer == _timer1) {
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK1
#else
TIMSK
#endif
, OCIE1A); // disable timer 1 output compare interrupt
timerDetach(TIMER1OUTCOMPAREA_INT);
}
else if (timer == _timer3) {
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK3
#else
ETIMSK
#endif
, OCIE3A); // disable the timer3 output compare A interrupt
timerDetach(TIMER3OUTCOMPAREA_INT);
switch (timer_index) {
default: break;
case _timer1:
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK1
#else
TIMSK
#endif
, OCIE1A // disable timer 1 output compare interrupt
);
timerDetach(TIMER1OUTCOMPAREA_INT);
break;
case _timer3:
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK3
#else
ETIMSK
#endif
, OCIE3A // disable the timer3 output compare A interrupt
);
timerDetach(TIMER3OUTCOMPAREA_INT);
break;
}
#else // !WIRING
// For arduino - in future: call here to a currently undefined function to reset the timer
UNUSED(timer);
UNUSED(timer_index);
#endif
}

View File

@@ -213,6 +213,51 @@ void setup_endstop_interrupts() {
pciSetup(K_MIN_PIN);
#endif
#endif
#if HAS_U_MAX
#if (digitalPinToInterrupt(U_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(U_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(U_MAX_PIN), "U_MAX_PIN is not interrupt-capable");
pciSetup(U_MAX_PIN);
#endif
#elif HAS_U_MIN
#if (digitalPinToInterrupt(U_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(U_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(U_MIN_PIN), "U_MIN_PIN is not interrupt-capable");
pciSetup(U_MIN_PIN);
#endif
#endif
#if HAS_V_MAX
#if (digitalPinToInterrupt(V_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(V_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(V_MAX_PIN), "V_MAX_PIN is not interrupt-capable");
pciSetup(V_MAX_PIN);
#endif
#elif HAS_V_MIN
#if (digitalPinToInterrupt(V_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(V_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(V_MIN_PIN), "V_MIN_PIN is not interrupt-capable");
pciSetup(V_MIN_PIN);
#endif
#endif
#if HAS_W_MAX
#if (digitalPinToInterrupt(W_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(W_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(W_MAX_PIN), "W_MAX_PIN is not interrupt-capable");
pciSetup(W_MAX_PIN);
#endif
#elif HAS_W_MIN
#if (digitalPinToInterrupt(W_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(W_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(W_MIN_PIN), "W_MIN_PIN is not interrupt-capable");
pciSetup(W_MIN_PIN);
#endif
#endif
#if HAS_X2_MAX
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN);
@@ -301,5 +346,6 @@ void setup_endstop_interrupts() {
pciSetup(Z_MIN_PROBE_PIN);
#endif
#endif
// If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
}

View File

@@ -21,11 +21,11 @@
*/
#ifdef __AVR__
#include "../../inc/MarlinConfigPre.h"
#include "../../inc/MarlinConfig.h"
#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
#include "HAL.h"
//#define DEBUG_AVR_FAST_PWM
#define DEBUG_OUT ENABLED(DEBUG_AVR_FAST_PWM)
#include "../../core/debug_out.h"
struct Timer {
volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
@@ -33,250 +33,207 @@ struct Timer {
volatile uint16_t* ICRn; // max 1 ICR register per timer
uint8_t n; // the timer number [0->5]
uint8_t q; // the timer output [0->2] (A->C)
bool isPWM; // True if pin is a "hardware timer"
bool isProtected; // True if timer is protected
};
// Macros for the Timer structure
#define _SET_WGMnQ(T, V) do{ \
*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
*(T.TCCRnQ)[1] = (*(T.TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
}while(0)
// Set TCCR CS bits
#define _SET_CSn(T, V) (*(T.TCCRnQ)[1] = (*(T.TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0))
// Set TCCR COM bits
#define _SET_COMnQ(T, Q, V) (*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q))))
// Set OCRnQ register
#define _SET_OCRnQ(T, Q, V) (*(T.OCRnQ)[Q] = int(V) & 0xFFFF)
// Set ICRn register (one per timer)
#define _SET_ICRn(T, V) (*(T.ICRn) = int(V) & 0xFFFF)
/**
* get_pwm_timer
* Get the timer information and register of the provided pin.
* Return a Timer struct containing this information.
* Used by set_pwm_frequency, set_pwm_duty
* Return a Timer struct describing a pin's timer.
*/
Timer get_pwm_timer(const pin_t pin) {
const Timer get_pwm_timer(const pin_t pin) {
uint8_t q = 0;
switch (digitalPinToTimer(pin)) {
// Protect reserved timers (TIMER0 & TIMER1)
#ifdef TCCR0A
#if !AVR_AT90USB1286_FAMILY
case TIMER0A:
#endif
case TIMER0B:
IF_DISABLED(AVR_AT90USB1286_FAMILY, case TIMER0A:)
#endif
#ifdef TCCR1A
case TIMER1A: case TIMER1B:
#endif
break;
#if defined(TCCR2) || defined(TCCR2A)
#ifdef TCCR2
case TIMER2: {
Timer timer = {
/*TCCRnQ*/ { &TCCR2, nullptr, nullptr },
/*OCRnQ*/ { (uint16_t*)&OCR2, nullptr, nullptr },
/*ICRn*/ nullptr,
/*n, q*/ 2, 0
};
}
#elif defined(TCCR2A)
#if ENABLED(USE_OCR2A_AS_TOP)
case TIMER2A: break; // protect TIMER2A
case TIMER2B: {
Timer timer = {
/*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
/*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
/*ICRn*/ nullptr,
/*n, q*/ 2, 1
};
return timer;
}
#else
case TIMER2B: ++q;
case TIMER2A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
/*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
/*ICRn*/ nullptr,
2, q
};
return timer;
}
#endif
#endif
break; // Protect reserved timers (TIMER0 & TIMER1)
#ifdef TCCR0A
case TIMER0B: // Protected timer, but allow setting the duty cycle on OCR0B for pin D4 only
return Timer({ { &TCCR0A, nullptr, nullptr }, { (uint16_t*)&OCR0A, (uint16_t*)&OCR0B, nullptr }, nullptr, 0, 1, true, true });
#endif
#if HAS_TCCR2
case TIMER2:
return Timer({ { &TCCR2, nullptr, nullptr }, { (uint16_t*)&OCR2, nullptr, nullptr }, nullptr, 2, 0, true, false });
#elif ENABLED(USE_OCR2A_AS_TOP)
case TIMER2A: break; // Protect TIMER2A since its OCR is used by TIMER2B
case TIMER2B:
return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, 1, true, false });
#elif defined(TCCR2A)
case TIMER2B: ++q; case TIMER2A:
return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, q, true, false });
#endif
#ifdef OCR3C
case TIMER3C: ++q;
case TIMER3B: ++q;
case TIMER3A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR3A, &TCCR3B, &TCCR3C },
/*OCRnQ*/ { &OCR3A, &OCR3B, &OCR3C },
/*ICRn*/ &ICR3,
/*n, q*/ 3, q
};
return timer;
}
case TIMER3C: ++q; case TIMER3B: ++q; case TIMER3A:
return Timer({ { &TCCR3A, &TCCR3B, &TCCR3C }, { &OCR3A, &OCR3B, &OCR3C }, &ICR3, 3, q, true, false });
#elif defined(OCR3B)
case TIMER3B: ++q;
case TIMER3A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR3A, &TCCR3B, nullptr },
/*OCRnQ*/ { &OCR3A, &OCR3B, nullptr },
/*ICRn*/ &ICR3,
/*n, q*/ 3, q
};
return timer;
}
case TIMER3B: ++q; case TIMER3A:
return Timer({ { &TCCR3A, &TCCR3B, nullptr }, { &OCR3A, &OCR3B, nullptr }, &ICR3, 3, q, true, false });
#endif
#ifdef TCCR4A
case TIMER4C: ++q;
case TIMER4B: ++q;
case TIMER4A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR4A, &TCCR4B, &TCCR4C },
/*OCRnQ*/ { &OCR4A, &OCR4B, &OCR4C },
/*ICRn*/ &ICR4,
/*n, q*/ 4, q
};
return timer;
}
case TIMER4C: ++q; case TIMER4B: ++q; case TIMER4A:
return Timer({ { &TCCR4A, &TCCR4B, &TCCR4C }, { &OCR4A, &OCR4B, &OCR4C }, &ICR4, 4, q, true, false });
#endif
#ifdef TCCR5A
case TIMER5C: ++q;
case TIMER5B: ++q;
case TIMER5A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR5A, &TCCR5B, &TCCR5C },
/*OCRnQ*/ { &OCR5A, &OCR5B, &OCR5C },
/*ICRn*/ &ICR5,
/*n, q*/ 5, q
};
return timer;
}
case TIMER5C: ++q; case TIMER5B: ++q; case TIMER5A:
return Timer({ { &TCCR5A, &TCCR5B, &TCCR5C }, { &OCR5A, &OCR5B, &OCR5C }, &ICR5, 5, q, true, false });
#endif
}
Timer timer = {
/*TCCRnQ*/ { nullptr, nullptr, nullptr },
/*OCRnQ*/ { nullptr, nullptr, nullptr },
/*ICRn*/ nullptr,
0, 0
};
return timer;
return Timer();
}
void set_pwm_frequency(const pin_t pin, int f_desired) {
Timer timer = get_pwm_timer(pin);
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
uint16_t size;
if (timer.n == 2) size = 255; else size = 65535;
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
DEBUG_ECHOLNPGM("set_pwm_frequency(pin=", pin, ", freq=", f_desired, ")");
const Timer timer = get_pwm_timer(pin);
if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized
uint16_t res = 255; // resolution (TOP value)
uint8_t j = 0; // prescaler index
uint8_t wgm = 1; // waveform generation mode
const bool is_timer2 = timer.n == 2;
const uint16_t maxtop = is_timer2 ? 0xFF : 0xFFFF;
DEBUG_ECHOLNPGM("maxtop=", maxtop);
uint16_t res = 0xFF; // resolution (TOP value)
uint8_t j = CS_NONE; // prescaler index
uint8_t wgm = WGM_PWM_PC_8; // waveform generation mode
// Calculating the prescaler and resolution to use to achieve closest frequency
if (f_desired != 0) {
int f = (F_CPU) / (2 * 1024 * size) + 1; // Initialize frequency as lowest (non-zero) achievable
uint16_t prescaler[] = { 0, 1, 8, /*TIMER2 ONLY*/32, 64, /*TIMER2 ONLY*/128, 256, 1024 };
constexpr uint16_t prescaler[] = { 1, 8, (32), 64, (128), 256, 1024 }; // (*) are Timer 2 only
uint16_t f = (F_CPU) / (uint32_t(maxtop) << 11) + 1; // Start with the lowest non-zero frequency achievable (for 16MHz, 1 or 31)
// loop over prescaler values
LOOP_S_L_N(i, 1, 8) {
uint16_t res_temp_fast = 255, res_temp_phase_correct = 255;
if (timer.n == 2) {
// No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
#if ENABLED(USE_OCR2A_AS_TOP)
const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
res_temp_fast = rtf - 1;
res_temp_phase_correct = rtf / 2;
DEBUG_ECHOLNPGM("f=", f);
DEBUG_ECHOLNPGM("(prescaler loop)");
LOOP_L_N(i, COUNT(prescaler)) { // Loop through all prescaler values
const uint32_t p = prescaler[i]; // Extend to 32 bits for calculations
DEBUG_ECHOLNPGM("prescaler[", i, "]=", p);
uint16_t res_fast_temp, res_pc_temp;
if (is_timer2) {
#if ENABLED(USE_OCR2A_AS_TOP) // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
const uint16_t rft = (F_CPU) / (p * f_desired);
res_fast_temp = rft - 1;
res_pc_temp = rft / 2;
DEBUG_ECHOLNPGM("(Timer2) res_fast_temp=", res_fast_temp, " res_pc_temp=", res_pc_temp);
#else
res_fast_temp = res_pc_temp = maxtop;
DEBUG_ECHOLNPGM("(Timer2) res_fast_temp=", maxtop, " res_pc_temp=", maxtop);
#endif
}
else {
// Skip TIMER2 specific prescalers when not TIMER2
if (i == 3 || i == 5) continue;
const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
res_temp_fast = rtf - 1;
res_temp_phase_correct = rtf / 2;
if (p == 32 || p == 128) continue; // Skip TIMER2 specific prescalers when not TIMER2
const uint16_t rft = (F_CPU) / (p * f_desired);
DEBUG_ECHOLNPGM("(Not Timer 2) F_CPU=" STRINGIFY(F_CPU), " prescaler=", p, " f_desired=", f_desired);
res_fast_temp = rft - 1;
res_pc_temp = rft / 2;
}
LIMIT(res_temp_fast, 1U, size);
LIMIT(res_temp_phase_correct, 1U, size);
LIMIT(res_fast_temp, 1U, maxtop);
LIMIT(res_pc_temp, 1U, maxtop);
// Calculate frequencies of test prescaler and resolution values
const int f_temp_fast = (F_CPU) / (prescaler[i] * (1 + res_temp_fast)),
f_temp_phase_correct = (F_CPU) / (2 * prescaler[i] * res_temp_phase_correct),
f_diff = ABS(f - f_desired),
f_fast_diff = ABS(f_temp_fast - f_desired),
f_phase_diff = ABS(f_temp_phase_correct - f_desired);
const uint16_t f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)),
f_pc_temp = (F_CPU) / ((p * res_pc_temp) << 1),
f_diff = _MAX(f, f_desired) - _MIN(f, f_desired),
f_fast_diff = _MAX(f_fast_temp, f_desired) - _MIN(f_fast_temp, f_desired),
f_pc_diff = _MAX(f_pc_temp, f_desired) - _MIN(f_pc_temp, f_desired);
// If FAST values are closest to desired f
if (f_fast_diff < f_diff && f_fast_diff <= f_phase_diff) {
// Remember this combination
f = f_temp_fast;
res = res_temp_fast;
j = i;
DEBUG_ECHOLNPGM("f_fast_temp=", f_fast_temp, " f_pc_temp=", f_pc_temp, " f_diff=", f_diff, " f_fast_diff=", f_fast_diff, " f_pc_diff=", f_pc_diff);
if (f_fast_diff < f_diff && f_fast_diff <= f_pc_diff) { // FAST values are closest to desired f
// Set the Wave Generation Mode to FAST PWM
if (timer.n == 2) {
wgm = (
#if ENABLED(USE_OCR2A_AS_TOP)
WGM2_FAST_PWM_OCR2A
#else
WGM2_FAST_PWM
#endif
);
}
else wgm = WGM_FAST_PWM_ICRn;
wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM)) : uint8_t(WGM_FAST_PWM_ICRn);
// Remember this combination
f = f_fast_temp; res = res_fast_temp; j = i + 1;
DEBUG_ECHOLNPGM("(FAST) updated f=", f);
}
// If PHASE CORRECT values are closes to desired f
else if (f_phase_diff < f_diff) {
f = f_temp_phase_correct;
res = res_temp_phase_correct;
j = i;
else if (f_pc_diff < f_diff) { // PHASE CORRECT values are closes to desired f
// Set the Wave Generation Mode to PWM PHASE CORRECT
if (timer.n == 2) {
wgm = (
#if ENABLED(USE_OCR2A_AS_TOP)
WGM2_PWM_PC_OCR2A
#else
WGM2_PWM_PC
#endif
);
}
else wgm = WGM_PWM_PC_ICRn;
wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_PWM_PC)) : uint8_t(WGM_PWM_PC_ICRn);
f = f_pc_temp; res = res_pc_temp; j = i + 1;
DEBUG_ECHOLNPGM("(PHASE) updated f=", f);
}
}
} // prescaler loop
}
_SET_WGMnQ(timer.TCCRnQ, wgm);
_SET_CSn(timer.TCCRnQ, j);
if (timer.n == 2) {
#if ENABLED(USE_OCR2A_AS_TOP)
_SET_OCRnQ(timer.OCRnQ, 0, res); // Set OCR2A value (TOP) = res
#endif
_SET_WGMnQ(timer, wgm);
_SET_CSn(timer, j);
if (is_timer2) {
TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer, 0, res)); // Set OCR2A value (TOP) = res
}
else
_SET_ICRn(timer.ICRn, res); // Set ICRn value (TOP) = res
_SET_ICRn(timer, res); // Set ICRn value (TOP) = res
}
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
// Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
// Note that digitalWrite also disables PWM output for us (sets COM bit to 0)
if (v == 0)
digitalWrite(pin, invert);
else if (v == v_size)
digitalWrite(pin, !invert);
else {
Timer timer = get_pwm_timer(pin);
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
// Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
_SET_COMnQ(timer.TCCRnQ, (timer.q
#ifdef TCCR2
+ (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro
#endif
), COM_CLEAR_SET + invert
);
uint16_t top;
if (timer.n == 2) { // if TIMER2
top = (
#if ENABLED(USE_OCR2A_AS_TOP)
*timer.OCRnQ[0] // top = OCR2A
#else
255 // top = 0xFF (max)
#endif
);
const Timer timer = get_pwm_timer(pin);
if (timer.isPWM) {
if (timer.n == 0) {
_SET_COMnQ(timer, timer.q, COM_CLEAR_SET); // Only allow a TIMER0B select...
_SET_OCRnQ(timer, timer.q, v); // ...and OCR0B duty update. For output pin D4 no frequency changes are permitted.
}
else if (!timer.isProtected) {
const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
_SET_COMnQ(timer, SUM_TERN(HAS_TCCR2, timer.q, timer.q == 2), COM_CLEAR_SET + invert); // COM20 is on bit 4 of TCCR2, so +1 for q==2
_SET_OCRnQ(timer, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value
}
}
else
top = *timer.ICRn; // top = ICRn
_SET_OCRnQ(timer.OCRnQ, timer.q, v * float(top) / float(v_size)); // Scale 8/16-bit v to top value
digitalWrite(pin, v < v_size / 2 ? LOW : HIGH);
}
}
#endif // NEEDS_HARDWARE_PWM
void MarlinHAL::init_pwm_timers() {
// Init some timer frequencies to a default 1KHz
const pin_t pwm_pin[] = {
#ifdef __AVR_ATmega2560__
10, 5, 6, 46
#elif defined(__AVR_ATmega1280__)
12, 31
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__)
15, 6
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_mega64) || defined(__AVR_mega128)
16, 24
#endif
};
LOOP_L_N(i, COUNT(pwm_pin))
set_pwm_frequency(pwm_pin[i], 1000);
}
#endif // __AVR__

View File

@@ -245,7 +245,7 @@ uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb
float count = 0;
if (hz > 0 && (dca || dcb || dcc)) {
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.
uint16_t prescaler; // Range of 30.5Hz (65535) 64.5KHz (>31)
uint16_t prescaler; // Range of 30.5Hz (65535) 64.5kHz (>31)
if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); }
else if (count >= 255. * 64.) { prescaler = 256; SET_CS(5, PRESCALER_256); }
@@ -257,7 +257,7 @@ uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb
const float pwm_top = round(count); // Get the rounded count
ICR5 = (uint16_t)pwm_top - 1; // Subtract 1 for TOP
OCR5A = pwm_top * ABS(dca); // Update and scale DCs
OCR5A = pwm_top * ABS(dca); // Update and scale DCs
OCR5B = pwm_top * ABS(dcb);
OCR5C = pwm_top * ABS(dcc);
_SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes
@@ -277,7 +277,7 @@ uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb
// Restore the default for Timer 5
SET_WGM(5, PWM_PC_8); // PWM 8-bit (Phase Correct)
SET_COMS(5, NORMAL, NORMAL, NORMAL); // Do nothing
SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250KHz
SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250kHz
OCR5A = OCR5B = OCR5C = 0;
}
return round(count);

View File

@@ -118,7 +118,7 @@
*/
// Waveform Generation Modes
enum WaveGenMode : char {
enum WaveGenMode : uint8_t {
WGM_NORMAL, // 0
WGM_PWM_PC_8, // 1
WGM_PWM_PC_9, // 2
@@ -138,19 +138,19 @@ enum WaveGenMode : char {
};
// Wavefore Generation Modes (Timer 2 only)
enum WaveGenMode2 : char {
WGM2_NORMAL, // 0
WGM2_PWM_PC, // 1
WGM2_CTC_OCR2A, // 2
WGM2_FAST_PWM, // 3
WGM2_reserved_1, // 4
WGM2_PWM_PC_OCR2A, // 5
WGM2_reserved_2, // 6
WGM2_FAST_PWM_OCR2A, // 7
enum WaveGenMode2 : uint8_t {
WGM2_NORMAL, // 0
WGM2_PWM_PC, // 1
WGM2_CTC_OCR2A, // 2
WGM2_FAST_PWM, // 3
WGM2_reserved_1, // 4
WGM2_PWM_PC_OCR2A, // 5
WGM2_reserved_2, // 6
WGM2_FAST_PWM_OCR2A, // 7
};
// Compare Modes
enum CompareMode : char {
enum CompareMode : uint8_t {
COM_NORMAL, // 0
COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL
COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
@@ -158,7 +158,7 @@ enum CompareMode : char {
};
// Clock Sources
enum ClockSource : char {
enum ClockSource : uint8_t {
CS_NONE, // 0
CS_PRESCALER_1, // 1
CS_PRESCALER_8, // 2
@@ -170,7 +170,7 @@ enum ClockSource : char {
};
// Clock Sources (Timer 2 only)
enum ClockSource2 : char {
enum ClockSource2 : uint8_t {
CS2_NONE, // 0
CS2_PRESCALER_1, // 1
CS2_PRESCALER_8, // 2
@@ -203,40 +203,33 @@ enum ClockSource2 : char {
TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \
}while(0)
#define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
// Runtime (see set_pwm_frequency):
#define _SET_WGMnQ(TCCRnQ, V) do{ \
*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
*(TCCRnQ)[1] = (*(TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
}while(0)
// Set Clock Select bits
// Ex: SET_CS3(PRESCALER_64);
#ifdef TCCR2
#define HAS_TCCR2 1
#endif
#define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
#define _SET_CS0(V) _SET_CS(0,V)
#define _SET_CS1(V) _SET_CS(1,V)
#ifdef TCCR2
#define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
#else
#define _SET_CS2(V) _SET_CS(2,V)
#endif
#define _SET_CS3(V) _SET_CS(3,V)
#define _SET_CS4(V) _SET_CS(4,V)
#define _SET_CS5(V) _SET_CS(5,V)
#define SET_CS0(V) _SET_CS0(CS_##V)
#define SET_CS1(V) _SET_CS1(CS_##V)
#ifdef TCCR2
#if HAS_TCCR2
#define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
#define SET_CS2(V) _SET_CS2(CS2_##V)
#else
#define _SET_CS2(V) _SET_CS(2,V)
#define SET_CS2(V) _SET_CS2(CS_##V)
#endif
#define SET_CS3(V) _SET_CS3(CS_##V)
#define SET_CS4(V) _SET_CS4(CS_##V)
#define SET_CS5(V) _SET_CS5(CS_##V)
#define SET_CS(T,V) SET_CS##T(V)
// Runtime (see set_pwm_frequency)
#define _SET_CSn(TCCRnQ, V) do{ \
(*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)); \
}while(0)
// Set Compare Mode bits
// Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
@@ -246,22 +239,6 @@ enum ClockSource2 : char {
#define SET_COMB(T,V) SET_COM(T,B,V)
#define SET_COMC(T,V) SET_COM(T,C,V)
#define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
// Runtime (see set_pwm_duty)
#define _SET_COMnQ(TCCRnQ, Q, V) do{ \
(*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))); \
}while(0)
// Set OCRnQ register
// Runtime (see set_pwm_duty):
#define _SET_OCRnQ(OCRnQ, Q, V) do{ \
(*(OCRnQ)[(Q)] = (0x0000) | (int(V) & 0xFFFF)); \
}while(0)
// Set ICRn register (one per timer)
// Runtime (see set_pwm_frequency)
#define _SET_ICRn(ICRn, V) do{ \
(*(ICRn) = (0x0000) | (int(V) & 0xFFFF)); \
}while(0)
// Set Noise Canceler bit
// Ex: SET_ICNC(2,1)
@@ -316,11 +293,11 @@ enum ClockSource2 : char {
#if HAS_MOTOR_CURRENT_PWM
#if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z || P == MOTOR_CURRENT_PWM_XY)
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E_PIN || P == MOTOR_CURRENT_PWM_E0_PIN || P == MOTOR_CURRENT_PWM_E1_PIN || P == MOTOR_CURRENT_PWM_Z_PIN || P == MOTOR_CURRENT_PWM_XY_PIN)
#elif PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z)
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E_PIN || P == MOTOR_CURRENT_PWM_E0_PIN || P == MOTOR_CURRENT_PWM_E1_PIN || P == MOTOR_CURRENT_PWM_Z_PIN)
#else
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E)
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E_PIN || P == MOTOR_CURRENT_PWM_E0_PIN || P == MOTOR_CURRENT_PWM_E1_PIN)
#endif
#else
#define PWM_CHK_MOTOR_CURRENT(P) false

View File

@@ -27,6 +27,9 @@
* Hardware Pin : 02 03 06 07 01 05 15 16 17 18 23 24 25 26 64 63 13 12 46 45 44 43 78 77 76 75 74 73 72 71 60 59 58 57 56 55 54 53 50 70 52 51 42 41 40 39 38 37 36 35 22 21 20 19 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 | 04 08 09 10 11 14 27 28 29 30 31 32 33 34 47 48 49 61 62 65 66 67 68 69 79 80 81 98 99 100
* Port : E0 E1 E4 E5 G5 E3 H3 H4 H5 H6 B4 B5 B6 B7 J1 J0 H1 H0 D3 D2 D1 D0 A0 A1 A2 A3 A4 A5 A6 A7 C7 C6 C5 C4 C3 C2 C1 C0 D7 G2 G1 G0 L7 L6 L5 L4 L3 L2 L1 L0 B3 B2 B1 B0 F0 F1 F2 F3 F4 F5 F6 F7 K0 K1 K2 K3 K4 K5 K6 K7 | E2 E6 E7 xx xx H2 H7 G3 G4 xx xx xx xx xx D4 D5 D6 xx xx J2 J3 J4 J5 J6 J7 xx xx xx xx xx
* Logical Pin : 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 78 79 80 xx xx 84 85 71 70 xx xx xx xx xx 81 82 83 xx xx 72 73 75 76 77 74 xx xx xx xx xx
*
* Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA
* AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg
*/
#include "../fastio.h"

View File

@@ -26,6 +26,9 @@
*
* Logical Pin: 38 39 40 41 42 43 44 45 16 10 11 12 06 07 08 09 30 31 32 33 34 35 36 37 17 18 19 20 21 22 23 24 00 01 13 05 02 03 14 15 46 47 48 49 50 51 52 53 25 26 27 28 29 04
* Port: A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7 G0 G1 G2 G3 G4 G5
*
* Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA
* AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg
*/
#include "../fastio.h"

View File

@@ -26,6 +26,9 @@
*
* Logical Pin: 08 09 10 11 12 13 14 15 16 17 18 19 20 21 00 01 02 03 04 05 06 07
* Port: B0 B1 B2 B3 B4 B5 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7
*
* Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA
* AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg
*/
#include "../fastio.h"

View File

@@ -26,6 +26,9 @@
*
* Logical Pin: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
* Port: B0 B1 B2 B3 B4 B5 B6 B7 D0 D1 D2 D3 D4 D5 D6 D7 C0 C1 C2 C3 C4 C5 C6 C7 A7 A6 A5 A4 A3 A2 A1 A0
*
* Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA
* AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg
*/
/** ATMega644

View File

@@ -27,6 +27,9 @@
* Logical Pin: 28 29 30 31 32 33 34 35 20 21 22 23 24 25 26 27 10 11 12 13 14 15 16 17 00 01 02 03 04 05 06 07 08 09(46*47)36 37 18 19 38 39 40 41 42 43 44 45
* Port: A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7
* The logical pins 46 and 47 are not supported by Teensyduino, but are supported below as E2 and E3
*
* Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA
* AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg
*/
#include "../fastio.h"

View File

@@ -20,7 +20,3 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/AVR."
#endif

View File

@@ -25,11 +25,57 @@
* Test AVR-specific configuration values for errors at compile-time.
*/
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/AVR."
#endif
/**
* Check for common serial pin conflicts
*/
#define CHECK_SERIAL_PIN(N) ( \
X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
|| X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
|| X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
|| X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
|| X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
|| BTN_EN1 == N || BTN_EN2 == N \
)
#if SERIAL_IN_USE(0)
// D0-D1. No known conflicts.
#endif
#if SERIAL_IN_USE(1)
#if NOT_TARGET(__AVR_ATmega644P__, __AVR_ATmega1284P__)
#if CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19)
#error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
#endif
#else
#if CHECK_SERIAL_PIN(10) || CHECK_SERIAL_PIN(11)
#error "Serial Port 1 pin D10 and/or D11 conflicts with another pin on the board."
#endif
#endif
#endif
#if SERIAL_IN_USE(2) && (CHECK_SERIAL_PIN(16) || CHECK_SERIAL_PIN(17))
#error "Serial Port 2 pin D16 and/or D17 conflicts with another pin on the board."
#endif
#if SERIAL_IN_USE(3) && (CHECK_SERIAL_PIN(14) || CHECK_SERIAL_PIN(15))
#error "Serial Port 3 pin D14 and/or D15 conflicts with another pin on the board."
#endif
#undef CHECK_SERIAL_PIN
/**
* Checks for FAST PWM
*/
#if ENABLED(FAST_PWM_FAN) && (ENABLED(USE_OCR2A_AS_TOP) && defined(TCCR2))
#error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2"
#if ALL(FAST_PWM_FAN, USE_OCR2A_AS_TOP, HAS_TCCR2)
#error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2."
#endif
/**
* Checks for SOFT PWM
*/
#if HAS_FAN0 && FAN_PIN == 9 && DISABLED(FAN_SOFT_PWM) && ENABLED(SPEAKER)
#error "FAN_PIN 9 Hardware PWM uses Timer 2 which conflicts with Arduino AVR Tone Timer (for SPEAKER)."
#error "Disable SPEAKER or enable FAN_SOFT_PWM."
#endif
/**
@@ -42,7 +88,7 @@
#elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system."
#endif
#elif defined(SPINDLE_LASER_FREQUENCY)
#elif SPINDLE_LASER_FREQUENCY
#error "SPINDLE_LASER_FREQUENCY requires SPINDLE_LASER_USE_PWM."
#endif
@@ -63,3 +109,7 @@
#if ENABLED(POSTMORTEM_DEBUGGING)
#error "POSTMORTEM_DEBUGGING is not supported on AVR boards."
#endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on AVR boards."
#endif

View File

@@ -27,15 +27,16 @@
// intRes = longIn1 * longIn2 >> 24
// uses:
// A[tmp] to store 0
// B[tmp] to store bits 16-23 of the 48bit result. The top bit is used to round the two byte result.
// note that the lower two bytes and the upper byte of the 48bit result are not calculated.
// this can cause the result to be out by one as the lower bytes may cause carries into the upper ones.
// B A are bits 24-39 and are the returned value
// C B A is longIn1
// D C B A is longIn2
// r1, r0 for the result of mul.
// [tmp1] to store 0.
// [tmp2] to store bits 16-23 of the 56 bit result. The top bit of [tmp2] is used for rounding.
// Note that the lower two bytes and the upper two bytes of the 56 bit result are not calculated.
// This can cause the result to be out by one as the lower bytes may cause carries into the upper ones.
// [intRes] (A B) is bits 24-39 and is the returned value.
// [longIn1] (C B A) is a 24 bit parameter.
// [longIn2] (D C B A) is a 32 bit parameter.
//
static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
uint8_t tmp1;
uint8_t tmp2;
uint16_t intRes;
@@ -66,11 +67,9 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
A("add %[tmp2], r1")
A("adc %A[intRes], %[tmp1]")
A("adc %B[intRes], %[tmp1]")
A("lsr %[tmp2]")
A("adc %A[intRes], %[tmp1]")
A("adc %B[intRes], %[tmp1]")
A("mul %D[longIn2], %A[longIn1]")
A("add %A[intRes], r0")
A("lsl %[tmp2]")
A("adc %A[intRes], r0")
A("adc %B[intRes], r1")
A("mul %D[longIn2], %B[longIn1]")
A("add %B[intRes], r0")
@@ -85,11 +84,16 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
return intRes;
}
// intRes = intIn1 * intIn2 >> 16
// intRes = intIn1 * intIn2 >> 8
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 24 bit result
static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
// r1, r0 for the result of mul. After the second mul, r0 holds bits 0-7 of the 24 bit result and
// the top bit of r0 is used for rounding.
// [tmp] to store 0.
// [intRes] (A B) is bits 8-15 and is the returned value.
// [charIn1] is an 8 bit parameter.
// [intIn2] (B A) is a 16 bit parameter.
//
FORCE_INLINE static uint16_t MultiU8X16toH16(uint8_t charIn1, uint16_t intIn2) {
uint8_t tmp;
uint16_t intRes;
__asm__ __volatile__ (
@@ -97,10 +101,8 @@ static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
A("mul %[charIn1], %B[intIn2]")
A("movw %A[intRes], r0")
A("mul %[charIn1], %A[intIn2]")
A("add %A[intRes], r1")
A("adc %B[intRes], %[tmp]")
A("lsr r0")
A("adc %A[intRes], %[tmp]")
A("lsl r0")
A("adc %A[intRes], r1")
A("adc %B[intRes], %[tmp]")
A("clr r1")
: [intRes] "=&r" (intRes),

View File

@@ -64,17 +64,19 @@
#define VALID_PIN(pin) (pin >= 0 && pin < NUM_DIGITAL_PINS ? 1 : 0)
#if AVR_ATmega1284_FAMILY
#define DIGITAL_PIN_TO_ANALOG_PIN(P) int(analogInputToDigitalPin(0) - (P))
#define IS_ANALOG(P) ((P) >= analogInputToDigitalPin(7) && (P) <= analogInputToDigitalPin(0))
#define IS_ANALOG(P) WITHIN(P, analogInputToDigitalPin(7), analogInputToDigitalPin(0))
#define DIGITAL_PIN_TO_ANALOG_PIN(P) int(IS_ANALOG(P) ? (P) - analogInputToDigitalPin(7) : -1)
#else
#define DIGITAL_PIN_TO_ANALOG_PIN(P) int((P) - analogInputToDigitalPin(0))
#define IS_ANALOG(P) ((P) >= analogInputToDigitalPin(0) && ((P) <= analogInputToDigitalPin(15) || (P) <= analogInputToDigitalPin(7)))
#define _ANALOG1(P) WITHIN(P, analogInputToDigitalPin(0), analogInputToDigitalPin(7))
#define _ANALOG2(P) WITHIN(P, analogInputToDigitalPin(8), analogInputToDigitalPin(15))
#define IS_ANALOG(P) (_ANALOG1(P) || _ANALOG2(P))
#define DIGITAL_PIN_TO_ANALOG_PIN(P) int(_ANALOG1(P) ? (P) - analogInputToDigitalPin(0) : _ANALOG2(P) ? (P) - analogInputToDigitalPin(8) + 8 : -1)
#endif
#define GET_ARRAY_PIN(p) pgm_read_byte(&pin_array[p].pin)
#define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin
void PRINT_ARRAY_NAME(uint8_t x) {
char *name_mem_pointer = (char*)pgm_read_ptr(&pin_array[x].name);
PGM_P const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
LOOP_L_N(y, MAX_NAME_LENGTH) {
char temp_char = pgm_read_byte(name_mem_pointer + y);
if (temp_char != 0)
@@ -102,7 +104,7 @@ void PRINT_ARRAY_NAME(uint8_t x) {
return true; \
} else return false
#define ABTEST(N) defined(TCCR##N##A) && defined(COM##N##A1)
/**
* Print a pin's PWM status.
@@ -113,7 +115,7 @@ static bool pwm_status(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) {
#if defined(TCCR0A) && defined(COM0A1)
#if ABTEST(0)
#ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
PWM_CASE(0, A);
@@ -122,20 +124,20 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(0, B);
#endif
#if defined(TCCR1A) && defined(COM1A1)
#if ABTEST(1)
PWM_CASE(1, A);
PWM_CASE(1, B);
#if defined(COM1C1) && defined(TIMER1C)
PWM_CASE(1, C);
#endif
#if defined(COM1C1) && defined(TIMER1C)
PWM_CASE(1, C);
#endif
#endif
#if defined(TCCR2A) && defined(COM2A1)
#if ABTEST(2)
PWM_CASE(2, A);
PWM_CASE(2, B);
#endif
#if defined(TCCR3A) && defined(COM3A1)
#if ABTEST(3)
PWM_CASE(3, A);
PWM_CASE(3, B);
#ifdef COM3C1
@@ -149,7 +151,7 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(4, C);
#endif
#if defined(TCCR5A) && defined(COM5A1)
#if ABTEST(5)
PWM_CASE(5, A);
PWM_CASE(5, B);
PWM_CASE(5, C);
@@ -166,16 +168,16 @@ static bool pwm_status(uint8_t pin) {
const volatile uint8_t* const PWM_other[][3] PROGMEM = {
{ &TCCR0A, &TCCR0B, &TIMSK0 },
{ &TCCR1A, &TCCR1B, &TIMSK1 },
#if defined(TCCR2A) && defined(COM2A1)
#if ABTEST(2)
{ &TCCR2A, &TCCR2B, &TIMSK2 },
#endif
#if defined(TCCR3A) && defined(COM3A1)
#if ABTEST(3)
{ &TCCR3A, &TCCR3B, &TIMSK3 },
#endif
#ifdef TCCR4A
{ &TCCR4A, &TCCR4B, &TIMSK4 },
#endif
#if defined(TCCR5A) && defined(COM5A1)
#if ABTEST(5)
{ &TCCR5A, &TCCR5B, &TIMSK5 },
#endif
};
@@ -195,11 +197,11 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 },
#endif
#if defined(TCCR2A) && defined(COM2A1)
#if ABTEST(2)
{ &OCR2A, &OCR2B, 0 },
#endif
#if defined(TCCR3A) && defined(COM3A1)
#if ABTEST(3)
#ifdef COM3C1
{ (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C },
#else
@@ -211,7 +213,7 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C },
#endif
#if defined(TCCR5A) && defined(COM5A1)
#if ABTEST(5)
{ (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C },
#endif
};
@@ -281,7 +283,7 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
static void pwm_details(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) {
#if defined(TCCR0A) && defined(COM0A1)
#if ABTEST(0)
#ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
case TIMER0A: timer_prefix(0, 'A', 3); break;
@@ -290,7 +292,7 @@ static void pwm_details(uint8_t pin) {
case TIMER0B: timer_prefix(0, 'B', 3); break;
#endif
#if defined(TCCR1A) && defined(COM1A1)
#if ABTEST(1)
case TIMER1A: timer_prefix(1, 'A', 4); break;
case TIMER1B: timer_prefix(1, 'B', 4); break;
#if defined(COM1C1) && defined(TIMER1C)
@@ -298,12 +300,12 @@ static void pwm_details(uint8_t pin) {
#endif
#endif
#if defined(TCCR2A) && defined(COM2A1)
#if ABTEST(2)
case TIMER2A: timer_prefix(2, 'A', 3); break;
case TIMER2B: timer_prefix(2, 'B', 3); break;
#endif
#if defined(TCCR3A) && defined(COM3A1)
#if ABTEST(3)
case TIMER3A: timer_prefix(3, 'A', 4); break;
case TIMER3B: timer_prefix(3, 'B', 4); break;
#ifdef COM3C1
@@ -317,7 +319,7 @@ static void pwm_details(uint8_t pin) {
case TIMER4C: timer_prefix(4, 'C', 4); break;
#endif
#if defined(TCCR5A) && defined(COM5A1)
#if ABTEST(5)
case TIMER5A: timer_prefix(5, 'A', 4); break;
case TIMER5B: timer_prefix(5, 'B', 4); break;
case TIMER5C: timer_prefix(5, 'C', 4); break;
@@ -351,7 +353,6 @@ static void pwm_details(uint8_t pin) {
#endif
} // pwm_details
#ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs
int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed
const uint8_t port = digitalPinToPort_DEBUG(pin);
@@ -397,3 +398,5 @@ static void pwm_details(uint8_t pin) {
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#undef ABTEST

View File

@@ -34,37 +34,37 @@ typedef uint16_t hal_timer_t;
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
#ifndef STEP_TIMER_NUM
#define STEP_TIMER_NUM 1
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 1
#endif
#ifndef PULSE_TIMER_NUM
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef TEMP_TIMER_NUM
#define TEMP_TIMER_NUM 0
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP 0
#endif
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
#define TEMP_TIMER_FREQUENCY (((F_CPU) + 0x2000) / 0x4000)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0B)
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B)
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0A)
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0A)
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0A)
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
switch (timer_num) {
case STEP_TIMER_NUM:
case MF_TIMER_STEP:
// waveform generation = 0100 = CTC
SET_WGM(1, CTC_OCRnA);
@@ -84,10 +84,10 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
TCNT1 = 0;
break;
case TEMP_TIMER_NUM:
case MF_TIMER_TEMP:
// Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt
OCR0B = 128;
OCR0A = 128;
break;
}
}
@@ -109,12 +109,12 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
* (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others.
*/
#define HAL_timer_isr_prologue(TIMER_NUM)
#define HAL_timer_isr_epilogue(TIMER_NUM)
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP
/* 18 cycles maximum latency */
#ifndef HAL_STEP_TIMER_ISR
/* 18 cycles maximum latency */
#define HAL_STEP_TIMER_ISR() \
extern "C" void TIMER1_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER1_COMPA_vect_bottom() asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
@@ -180,7 +180,7 @@ void TIMER1_COMPA_vect() { \
: \
: [timsk0] "i" ((uint16_t)&TIMSK0), \
[timsk1] "i" ((uint16_t)&TIMSK1), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)),\
[msk0] "M" ((uint8_t)(1<<OCIE0A)),\
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \
: \
); \
@@ -193,9 +193,9 @@ void TIMER1_COMPA_vect_bottom()
/* 14 cycles maximum latency */
#define HAL_TEMP_TIMER_ISR() \
extern "C" void TIMER0_COMPB_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER0_COMPB_vect_bottom() asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER0_COMPB_vect() { \
extern "C" void TIMER0_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER0_COMPA_vect_bottom() asm ("TIMER0_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER0_COMPA_vect() { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
@@ -223,7 +223,7 @@ void TIMER0_COMPB_vect() { \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER0_COMPB_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("call TIMER0_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
@@ -251,10 +251,10 @@ void TIMER0_COMPB_vect() { \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i"((uint16_t)&TIMSK0), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)) \
[msk0] "M" ((uint8_t)(1<<OCIE0A)) \
: \
); \
} \
void TIMER0_COMPB_vect_bottom()
void TIMER0_COMPA_vect_bottom()
#endif // HAL_TEMP_TIMER_ISR

View File

@@ -1,70 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef __AVR__
#include "../../inc/MarlinConfig.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#include "../../MarlinCore.h"
// Initialize watchdog with 8s timeout, if possible. Otherwise, make it 4s.
void watchdog_init() {
#if ENABLED(WATCHDOG_DURATION_8S) && defined(WDTO_8S)
#define WDTO_NS WDTO_8S
#else
#define WDTO_NS WDTO_4S
#endif
#if ENABLED(WATCHDOG_RESET_MANUAL)
// Enable the watchdog timer, but only for the interrupt.
// Take care, as this requires the correct order of operation, with interrupts disabled.
// See the datasheet of any AVR chip for details.
wdt_reset();
cli();
_WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
_WD_CONTROL_REG = _BV(WDIE) | (WDTO_NS & 0x07) | ((WDTO_NS & 0x08) << 2); // WDTO_NS directly does not work. bit 0-2 are consecutive in the register but the highest value bit is at bit 5
// So worked for up to WDTO_2S
sei();
wdt_reset();
#else
wdt_enable(WDTO_NS); // The function handles the upper bit correct.
#endif
//delay(10000); // test it!
}
//===========================================================================
//=================================== ISR ===================================
//===========================================================================
// Watchdog timer interrupt, called if main program blocks >4sec and manual reset is enabled.
#if ENABLED(WATCHDOG_RESET_MANUAL)
ISR(WDT_vect) {
sei(); // With the interrupt driven serial we need to allow interrupts.
SERIAL_ERROR_MSG(STR_WATCHDOG_FIRED);
minkill(); // interrupt-safe final kill and infinite loop
}
#endif
#endif // USE_WATCHDOG
#endif // __AVR__

View File

@@ -25,7 +25,7 @@
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#include "../../MarlinCore.h"
#include <Wire.h>
#include "usb/usb_task.h"
@@ -34,39 +34,33 @@
// Public Variables
// ------------------------
uint16_t HAL_adc_result;
uint16_t MarlinHAL::adc_result;
// ------------------------
// Public functions
// ------------------------
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
#if ENABLED(POSTMORTEM_DEBUGGING)
extern void install_min_serial();
#endif
// HAL initialization task
void HAL_init() {
// Initialize the USB stack
void MarlinHAL::init() {
#if ENABLED(SDSUPPORT)
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif
usb_task_init();
usb_task_init(); // Initialize the USB stack
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
}
// HAL idle task
void HAL_idletask() {
// Perform USB stack housekeeping
usb_task_idle();
void MarlinHAL::init_board() {
#ifdef BOARD_INIT
BOARD_INIT();
#endif
}
// Disable interrupts
void cli() { noInterrupts(); }
void MarlinHAL::idletask() { usb_task_idle(); } // Perform USB stack housekeeping
// Enable interrupts
void sei() { interrupts(); }
void HAL_clear_reset_source() { }
uint8_t HAL_get_reset_source() {
uint8_t MarlinHAL::get_reset_source() {
switch ((RSTC->RSTC_SR >> 8) & 0x07) {
case 0: return RST_POWER_ON;
case 1: return RST_BACKUP;
@@ -77,13 +71,105 @@ uint8_t HAL_get_reset_source() {
}
}
void HAL_reboot() { rstc_start_software_reset(RSTC); }
void MarlinHAL::reboot() { rstc_start_software_reset(RSTC); }
void _delay_ms(const int delay_ms) {
// Todo: port for Due?
delay(delay_ms);
// ------------------------
// Watchdog Timer
// ------------------------
#if ENABLED(USE_WATCHDOG)
// Initialize watchdog - On SAM3X, Watchdog was already configured
// and enabled or disabled at startup, so no need to reconfigure it
// here.
void MarlinHAL::watchdog_init() { WDT_Restart(WDT); } // Reset watchdog to start clean
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or AVR will go into emergency procedures.
void MarlinHAL::watchdog_refresh() { watchdogReset(); }
#endif
// Override Arduino runtime to either config or disable the watchdog
//
// We need to configure the watchdog as soon as possible in the boot
// process, because watchdog initialization at hardware reset on SAM3X8E
// is unreliable, and there is risk of unintended resets if we delay
// that initialization to a later time.
void watchdogSetup() {
#if ENABLED(USE_WATCHDOG)
// 4 seconds timeout
uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
// Calculate timeout value in WDT counter ticks: This assumes
// the slow clock is running at 32.768 kHz watchdog
// frequency is therefore 32768 / 128 = 256 Hz
timeout = (timeout << 8) / 1000;
if (timeout == 0)
timeout = 1;
else if (timeout > 0xFFF)
timeout = 0xFFF;
// We want to enable the watchdog with the specified timeout
uint32_t value =
WDT_MR_WDV(timeout) | // With the specified timeout
WDT_MR_WDD(timeout) | // and no invalid write window
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
// to keep PIO controller state
#endif
WDT_MR_WDDBGHLT | // WDT stops in debug state.
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
// Configure WDT to only trigger an interrupt
value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
// Disable WDT interrupt (just in case, to avoid triggering it!)
NVIC_DisableIRQ(WDT_IRQn);
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
// Configure and enable WDT interrupt.
NVIC_ClearPendingIRQ(WDT_IRQn);
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
NVIC_EnableIRQ(WDT_IRQn);
#else
// a WDT fault triggers a reset
value |= WDT_MR_WDRSTEN;
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
#endif
// Reset the watchdog
WDT_Restart(WDT);
#else
// Make sure to completely disable the Watchdog
WDT_Disable(WDT);
#endif
}
// ------------------------
// Free Memory Accessor
// ------------------------
extern "C" {
extern unsigned int _ebss; // end of bss section
}
@@ -95,18 +181,9 @@ int freeMemory() {
}
// ------------------------
// ADC
// Serial Ports
// ------------------------
void HAL_adc_start_conversion(const uint8_t ch) {
HAL_adc_result = analogRead(ch);
}
uint16_t HAL_adc_get_result() {
// nop
return HAL_adc_result;
}
// Forward the default serial ports
#if USING_HW_SERIAL0
DefaultSerial1 MSerial0(false, Serial);

View File

@@ -32,12 +32,15 @@
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#include <stdint.h>
#include "../../core/serial_hook.h"
// ------------------------
// Serial ports
// ------------------------
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
@@ -97,55 +100,38 @@ extern DefaultSerial4 MSerial3;
#include "MarlinSerial.h"
#include "MarlinSerialUSB.h"
// On AVR this is in math.h?
#define square(x) ((x)*(x))
// ------------------------
// Types
// ------------------------
typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS
#define HAL_SERVO_LIB Servo
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
class Servo;
typedef Servo hal_servo_t;
//
// Interrupts
//
#define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq()
#define CRITICAL_SECTION_END() if (!primask) __enable_irq()
#define ISRS_ENABLED() (!__get_PRIMASK())
#define ENABLE_ISRS() __enable_irq()
#define DISABLE_ISRS() __disable_irq()
#define sei() interrupts()
#define cli() noInterrupts()
void cli(); // Disable interrupts
void sei(); // Enable interrupts
void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason
void HAL_reboot();
#define CRITICAL_SECTION_START() const bool _irqon = hal.isr_state(); hal.isr_off()
#define CRITICAL_SECTION_END() if (_irqon) hal.isr_on()
//
// ADC
//
extern uint16_t HAL_adc_result; // result of last ADC conversion
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
#ifndef analogInputToDigitalPin
#define analogInputToDigitalPin(p) ((p < 12U) ? (p) + 54U : -1)
#endif
#define HAL_ANALOG_SELECT(ch)
inline void HAL_adc_init() {}//todo
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
void HAL_adc_start_conversion(const uint8_t ch);
uint16_t HAL_adc_get_result();
//
// Pin Map
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
@@ -154,30 +140,19 @@ uint16_t HAL_adc_get_result();
//
// Tone
//
void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin);
// Enable hooks into idle and setup for HAL
#define HAL_IDLETASK 1
void HAL_idletask();
void HAL_init();
//
// Utility functions
//
void _delay_ms(const int delay);
// ------------------------
// Class Utilities
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
#ifdef __cplusplus
extern "C" {
@@ -186,3 +161,73 @@ char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s
#ifdef __cplusplus
}
#endif
// Return free RAM between end of heap (or end bss) and whatever is current
int freeMemory();
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup()
static void init_board(); // Called less early in setup()
static void reboot(); // Restart the firmware
// Interrupts
static bool isr_state() { return !__get_PRIMASK(); }
static void isr_on() { __enable_irq(); }
static void isr_off() { __disable_irq(); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source();
static void clear_reset_source() {}
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
static uint16_t adc_result;
// Called by Temperature::init once at startup
static void adc_init() {}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t /*ch*/) {}
// Begin ADC sampling on the given channel. Called from Temperature::isr!
static void adc_start(const uint8_t ch) { adc_result = analogRead(ch); }
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return adc_result; }
/**
* Set the PWM duty cycle for the pin to the given value.
* No inverting the duty cycle in this HAL.
* No changing the maximum size of the provided value to enable finer PWM duty control in this HAL.
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
}
};

View File

@@ -31,8 +31,6 @@
/**
* HAL for Arduino Due and compatible (SAM3X8E)
*
* For ARDUINO_ARCH_SAM
*/
#ifdef ARDUINO_ARCH_SAM
@@ -249,12 +247,12 @@
b <<= 1; // little setup time
WRITE(SD_SCK_PIN, HIGH);
DELAY_NS(spiDelayNS);
DELAY_NS_VAR(spiDelayNS);
b |= (READ(SD_MISO_PIN) != 0);
WRITE(SD_SCK_PIN, LOW);
DELAY_NS(spiDelayNS);
DELAY_NS_VAR(spiDelayNS);
} while (--bits);
return b;
}

View File

@@ -41,7 +41,7 @@
practice, we need alignment to 256 bytes to make this work in all
cases */
__attribute__ ((aligned(256)))
static DeviceVectors ram_tab = { nullptr };
static DeviceVectors ram_tab[61] = { nullptr };
/**
* This function checks if the exception/interrupt table is already in SRAM or not.

View File

@@ -406,7 +406,7 @@ size_t MarlinSerial<Cfg>::write(const uint8_t c) {
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) {
if (!hal.isr_state()) {
// Make room by polling if it is possible to transmit, and do so!
while (i == tx_buffer.tail) {
@@ -454,7 +454,7 @@ void MarlinSerial<Cfg>::flushTX() {
if (!_written) return;
// If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) {
if (!hal.isr_state()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {

View File

@@ -118,7 +118,7 @@ public:
static size_t write(const uint8_t c);
static void flushTX();
static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }

View File

@@ -41,7 +41,7 @@ extern "C" {
int udi_cdc_getc();
bool udi_cdc_is_tx_ready();
int udi_cdc_putc(int value);
};
}
// Pending character
static int pending_char = -1;

View File

@@ -25,7 +25,7 @@
#if ENABLED(POSTMORTEM_DEBUGGING)
#include "../shared/HAL_MinSerial.h"
#include "../shared/MinSerial.h"
#include <stdarg.h>

View File

@@ -47,12 +47,12 @@
#include "../shared/servo.h"
#include "../shared/servo_private.h"
static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
// ------------------------
/// Interrupt handler for the TC0 channel 1.
// ------------------------
void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
#ifdef _useTimer1
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
@@ -70,88 +70,92 @@ void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
#endif
void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
// clear interrupt
tc->TC_CHANNEL[channel].TC_SR;
if (Channel[timer] < 0)
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
if (cho < 0) { // Channel -1 indicates the refresh interval completed...
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
if (DisablePending[timer]) {
// Disabling only after the full servo period expires prevents
// pulses being too close together if immediately re-enabled.
DisablePending.clear(timer);
TC_Stop(tc, channel);
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
return;
}
}
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
Channel[timer]++; // increment to the next channel
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
Channel[timer] = ++cho; // go to the next channel (or 0)
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
if (SERVO(timer, cho).Pin.isActive) // activated?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
}
else {
// finished all channels so wait for the refresh period to expire before starting over
tc->TC_CHANNEL[channel].TC_RA =
tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed
: tc->TC_CHANNEL[channel].TC_CV + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
Channel[timer] = -1; // reset the timer CCR on the next call
}
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
}
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
pmc_enable_periph_clk(id);
TC_Configure(tc, channel,
TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC
TC_CMR_WAVE // Waveform mode
| TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
| (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
| (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
| (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
| (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
);
/* 84MHz, MCK/32, for 1.5ms: 3937 */
TC_SetRA(tc, channel, 2625); // 1ms
// Wait 1ms before the first ISR
TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
/* Configure and enable interrupt */
// Configure and enable interrupt
NVIC_EnableIRQ(irqn);
// TC_IER_CPAS: RA Compare
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare
// Enables the timer clock and performs a software reset to start the counting
TC_Start(tc, channel);
}
void initISR(timer16_Sequence_t timer) {
#ifdef _useTimer1
if (timer == _timer1)
_initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
#endif
#ifdef _useTimer2
if (timer == _timer2)
_initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
#endif
#ifdef _useTimer3
if (timer == _timer3)
_initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
#endif
#ifdef _useTimer4
if (timer == _timer4)
_initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
#endif
#ifdef _useTimer5
if (timer == _timer5)
_initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#endif
void initISR(const timer16_Sequence_t timer_index) {
CRITICAL_SECTION_START();
const bool disable_soon = DisablePending[timer_index];
DisablePending.clear(timer_index);
CRITICAL_SECTION_END();
if (!disable_soon) switch (timer_index) {
default: break;
#ifdef _useTimer1
case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
#endif
#ifdef _useTimer2
case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
#endif
#ifdef _useTimer3
case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
#endif
#ifdef _useTimer4
case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
#endif
#ifdef _useTimer5
case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#endif
}
}
void finISR(timer16_Sequence_t) {
#ifdef _useTimer1
TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
#endif
#ifdef _useTimer2
TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
#endif
#ifdef _useTimer3
TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
#endif
#ifdef _useTimer4
TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
#endif
#ifdef _useTimer5
TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
#endif
void finISR(const timer16_Sequence_t timer_index) {
// Timer is disabled from the ISR, to ensure proper final pulse length.
DisablePending.set(timer_index);
}
#endif // HAS_SERVOS

View File

@@ -37,7 +37,7 @@
#define _useTimer5
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
#define SERVO_TIMER_PRESCALER 32 // timer prescaler
#define SERVO_TIMER_PRESCALER 2 // timer prescaler
/*
TC0, chan 0 => TC0_Handler

View File

@@ -35,20 +35,20 @@
static pin_t tone_pin;
volatile static int32_t toggles;
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) {
tone_pin = _pin;
toggles = 2 * frequency * duration / 1000;
HAL_timer_start(TONE_TIMER_NUM, 2 * frequency);
HAL_timer_start(MF_TIMER_TONE, 2 * frequency);
}
void noTone(const pin_t _pin) {
HAL_timer_disable_interrupt(TONE_TIMER_NUM);
HAL_timer_disable_interrupt(MF_TIMER_TONE);
extDigitalWrite(_pin, LOW);
}
HAL_TONE_TIMER_ISR() {
static uint8_t pin_state = 0;
HAL_timer_isr_prologue(TONE_TIMER_NUM);
HAL_timer_isr_prologue(MF_TIMER_TONE);
if (toggles) {
toggles--;

View File

@@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(U8GLIB_ST7920)
#if IS_U8GLIB_ST7920
#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h"
@@ -182,5 +182,5 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
}
#endif // LIGHTWEIGHT_UI
#endif // U8GLIB_ST7920
#endif // IS_U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM

View File

@@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920)
#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
@@ -141,5 +141,5 @@ uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
return 1;
}
#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920
#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM

View File

@@ -199,8 +199,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
for (i = 0; i <PageSize >> 2; i++)
pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i]));
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM PageWrite ", page);
DEBUG_ECHO_MSG("EEPROM PageWrite ", page);
DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_FLUSH();
@@ -245,8 +244,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
// Reenable interrupts
__enable_irq();
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Unlock failure for page ", page);
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ", page);
return false;
}
@@ -270,8 +268,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
// Reenable interrupts
__enable_irq();
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Write failure for page ", page);
DEBUG_ECHO_MSG("EEPROM Write failure for page ", page);
return false;
}
@@ -286,8 +283,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
if (memcmp(getFlashStorage(page),data,PageSize)) {
#ifdef EE_EMU_DEBUG
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Verify Write failure for page ", page);
DEBUG_ECHO_MSG("EEPROM Verify Write failure for page ", page);
ee_Dump( page, (uint32_t *)addrflash);
ee_Dump(-page, data);
@@ -325,8 +321,7 @@ static bool ee_PageErase(uint16_t page) {
uint16_t i;
uint32_t addrflash = uint32_t(getFlashStorage(page));
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM PageErase ", page);
DEBUG_ECHO_MSG("EEPROM PageErase ", page);
DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_FLUSH();
@@ -370,8 +365,7 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts
__enable_irq();
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Unlock failure for page ",page);
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ",page);
return false;
}
@@ -394,8 +388,7 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts
__enable_irq();
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Erase failure for page ",page);
DEBUG_ECHO_MSG("EEPROM Erase failure for page ",page);
return false;
}
@@ -410,8 +403,7 @@ static bool ee_PageErase(uint16_t page) {
uint32_t * aligned_src = (uint32_t *) addrflash;
for (i = 0; i < PageSize >> 2; i++) {
if (*aligned_src++ != 0xFFFFFFFF) {
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Verify Erase failure for page ",page);
DEBUG_ECHO_MSG("EEPROM Verify Erase failure for page ",page);
ee_Dump(page, (uint32_t *)addrflash);
return false;
}
@@ -921,8 +913,7 @@ static void ee_Init() {
// If all groups seem to be used, default to first group
if (curGroup >= GroupCount) curGroup = 0;
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Current Group: ",curGroup);
DEBUG_ECHO_MSG("EEPROM Current Group: ",curGroup);
DEBUG_FLUSH();
// Now, validate that all the other group pages are empty
@@ -931,8 +922,7 @@ static void ee_Init() {
for (int page = 0; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(grp * PagesPerGroup + page)) {
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Page ", page, " not clean on group ", grp);
DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on group ", grp);
DEBUG_FLUSH();
ee_PageErase(grp * PagesPerGroup + page);
}
@@ -948,15 +938,13 @@ static void ee_Init() {
}
}
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Active page: ", curPage);
DEBUG_ECHO_MSG("EEPROM Active page: ", curPage);
DEBUG_FLUSH();
// Make sure the pages following the first clean one are also clean
for (int page = curPage + 1; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) {
DEBUG_ECHO_START();
DEBUG_ECHOLNPGM("EEPROM Page ", page, " not clean on active group ", curGroup);
DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on active group ", curGroup);
DEBUG_FLUSH();
ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page));
ee_PageErase(curGroup * PagesPerGroup + page);

View File

@@ -70,4 +70,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN));
TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN));
TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN));
TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN));
TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN));
TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN));
}

View File

@@ -25,7 +25,7 @@
* is NOT used to directly toggle pins. The ISR writes to the pin assigned to
* that interrupt.
*
* All PWMs use the same repetition rate. The G2 needs about 10KHz min in order to
* All PWMs use the same repetition rate. The G2 needs about 10kHz min in order to
* not have obvious ripple on the Vref signals.
*
* The data structures are setup to minimize the computation done by the ISR which

View File

@@ -20,7 +20,3 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/DUE."
#endif

View File

@@ -25,6 +25,34 @@
* Test Arduino Due specific configuration values for errors at compile-time.
*/
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/DUE."
#endif
/**
* Check for common serial pin conflicts
*/
#define CHECK_SERIAL_PIN(N) ( \
X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
|| X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
|| X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
|| X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
|| X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
)
#if SERIAL_IN_USE(0) // D0-D1. No known conflicts.
#endif
#if SERIAL_IN_USE(1) && (CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19))
#error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
#endif
#if SERIAL_IN_USE(2) && (CHECK_SERIAL_PIN(16) || CHECK_SERIAL_PIN(17))
#error "Serial Port 2 pin D16 and/or D17 conflicts with another pin on the board."
#endif
#if SERIAL_IN_USE(3) && (CHECK_SERIAL_PIN(14) || CHECK_SERIAL_PIN(15))
#error "Serial Port 3 pin D14 and/or D15 conflicts with another pin on the board."
#endif
#undef CHECK_SERIAL_PIN
/**
* HARDWARE VS. SOFTWARE SPI COMPATIBILITY
*
@@ -53,9 +81,13 @@
#endif
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on DUE."
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported for HAL/DUE."
#endif
#if HAS_TMC_SW_SERIAL
#error "TMC220x Software Serial is not supported on the DUE platform."
#endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on DUE boards."
#endif

View File

@@ -53,7 +53,7 @@
* The net result is that both the g_pinStatus[pin] array and the PIO_OSR register
* needs to be looked at when determining if a pin is an input or an output.
*
* b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1KHz
* b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1kHz
*
* c) NUM_DIGITAL_PINS does not include the analog pins
*
@@ -70,7 +70,7 @@
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0)
#define VALID_PIN(pin) (pin >= 0 && pin < int8_t(NUMBER_PINS_TOTAL))
#define DIGITAL_PIN_TO_ANALOG_PIN(p) int(p - analogInputToDigitalPin(0))
#define IS_ANALOG(P) WITHIN(P, char(analogInputToDigitalPin(0)), char(analogInputToDigitalPin(NUM_ANALOG_INPUTS - 1)))
#define pwm_status(pin) (((g_pinStatus[pin] & 0xF) == PIN_STATUS_PWM) && \
@@ -86,7 +86,6 @@ bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|| pwm_status(pin));
}
void pwm_details(int32_t pin) {
if (pwm_status(pin)) {
uint32_t chan = g_APinDescription[pin].ulPWMChannel;

View File

@@ -42,7 +42,7 @@
// Private Variables
// ------------------------
const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
{ TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5]
{ TC0, 1, TC1_IRQn, 0}, // 1
{ TC0, 2, TC2_IRQn, 2}, // 2 - stepper
@@ -66,9 +66,9 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
*/
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
Tc *tc = TimerConfig[timer_num].pTimerRegs;
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
uint32_t channel = TimerConfig[timer_num].channel;
Tc *tc = timer_config[timer_num].pTimerRegs;
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
uint32_t channel = timer_config[timer_num].channel;
// Disable interrupt, just in case it was already enabled
NVIC_DisableIRQ(irq);
@@ -86,13 +86,20 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
NVIC_SetPriority(irq, TimerConfig [timer_num].priority);
NVIC_SetPriority(irq, timer_config[timer_num].priority);
// wave mode, reset counter on match with RC,
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
TC_Configure(tc, channel,
TC_CMR_WAVE
| TC_CMR_WAVSEL_UP_RC
| (HAL_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0)
| (HAL_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0)
| (HAL_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0)
| (HAL_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0)
);
// Set compare value
TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency);
// And start timer
TC_Start(tc, channel);
@@ -105,12 +112,12 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
}
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
NVIC_EnableIRQ(irq);
}
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
NVIC_DisableIRQ(irq);
// We NEED memory barriers to ensure Interrupts are actually disabled!
@@ -125,7 +132,7 @@ static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
return NVIC_GetEnabledIRQ(irq);
}

View File

@@ -35,37 +35,38 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
#define HAL_TIMER_PRESCALER 2
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
#ifndef STEP_TIMER_NUM
#define STEP_TIMER_NUM 2 // Timer Index for Stepper
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 2 // Timer Index for Stepper
#endif
#ifndef PULSE_TIMER_NUM
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef TEMP_TIMER_NUM
#define TEMP_TIMER_NUM 4 // Timer Index for Temperature
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP 4 // Timer Index for Temperature
#endif
#ifndef TONE_TIMER_NUM
#define TONE_TIMER_NUM 6 // index of timer to use for beeper tones
#ifndef MF_TIMER_TONE
#define MF_TIMER_TONE 6 // index of timer to use for beeper tones
#endif
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() void TC2_Handler()
@@ -92,7 +93,7 @@ typedef struct {
// Public Variables
// ------------------------
extern const tTimerConfig TimerConfig[];
extern const tTimerConfig timer_config[];
// ------------------------
// Public functions
@@ -101,17 +102,17 @@ extern const tTimerConfig TimerConfig[];
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num];
const tTimerConfig * const pConfig = &timer_config[timer_num];
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num];
const tTimerConfig * const pConfig = &timer_config[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num];
const tTimerConfig * const pConfig = &timer_config[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV;
}
@@ -120,9 +121,9 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num];
const tTimerConfig * const pConfig = &timer_config[timer_num];
// Reading the status register clears the interrupt flag
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR;
}
#define HAL_timer_isr_epilogue(TIMER_NUM)
#define HAL_timer_isr_epilogue(T) NOOP

View File

@@ -4,15 +4,16 @@
# Windows: bossac.exe
# Other: leave unchanged
#
import pioutil
if pioutil.is_pio_build():
import platform
current_OS = platform.system()
import platform
current_OS = platform.system()
if current_OS == 'Windows':
if current_OS == 'Windows':
Import("env")
Import("env")
# Use bossac.exe on Windows
env.Replace(
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)
# Use bossac.exe on Windows
env.Replace(
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)

View File

@@ -1059,7 +1059,7 @@ static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
while (val_index < 8)
{
data[val_index++] = value & 0xFF;
value = value >> 8;
value >>= 8;
}
}

View File

@@ -10,7 +10,7 @@
#include "../../../sd/cardreader.h"
extern "C" {
#include "sd_mmc_spi_mem.h"
#include "sd_mmc_spi_mem.h"
}
#define SD_MMC_BLOCK_SIZE 512

View File

@@ -62,7 +62,7 @@ void usb_task_idle(void) {
// Attend SD card access from the USB MSD -- Prioritize access to improve speed
int delay = 2;
while (main_b_msc_enable && --delay > 0) {
if (udi_msc_process_trans()) delay = 10000;
if (udi_msc_process_trans()) delay = 20;
// Reset the watchdog, just to be sure
REG_WDT_CR = WDT_CR_WDRSTT | WDT_CR_KEY(0xA5);

View File

@@ -1,114 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#include "../../MarlinCore.h"
#include "watchdog.h"
// Override Arduino runtime to either config or disable the watchdog
//
// We need to configure the watchdog as soon as possible in the boot
// process, because watchdog initialization at hardware reset on SAM3X8E
// is unreliable, and there is risk of unintended resets if we delay
// that initialization to a later time.
void watchdogSetup() {
#if ENABLED(USE_WATCHDOG)
// 4 seconds timeout
uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
// Calculate timeout value in WDT counter ticks: This assumes
// the slow clock is running at 32.768 kHz watchdog
// frequency is therefore 32768 / 128 = 256 Hz
timeout = (timeout << 8) / 1000;
if (timeout == 0)
timeout = 1;
else if (timeout > 0xFFF)
timeout = 0xFFF;
// We want to enable the watchdog with the specified timeout
uint32_t value =
WDT_MR_WDV(timeout) | // With the specified timeout
WDT_MR_WDD(timeout) | // and no invalid write window
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
// to keep PIO controller state
#endif
WDT_MR_WDDBGHLT | // WDT stops in debug state.
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
// Configure WDT to only trigger an interrupt
value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
// Disable WDT interrupt (just in case, to avoid triggering it!)
NVIC_DisableIRQ(WDT_IRQn);
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
// Configure and enable WDT interrupt.
NVIC_ClearPendingIRQ(WDT_IRQn);
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
NVIC_EnableIRQ(WDT_IRQn);
#else
// a WDT fault triggers a reset
value |= WDT_MR_WDRSTEN;
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
#endif
// Reset the watchdog
WDT_Restart(WDT);
#else
// Make sure to completely disable the Watchdog
WDT_Disable(WDT);
#endif
}
#if ENABLED(USE_WATCHDOG)
// Initialize watchdog - On SAM3X, Watchdog was already configured
// and enabled or disabled at startup, so no need to reconfigure it
// here.
void watchdog_init() {
// Reset watchdog to start clean
WDT_Restart(WDT);
}
#endif // USE_WATCHDOG
#endif

View File

@@ -28,6 +28,10 @@
#include <esp_adc_cal.h>
#include <HardwareSerial.h>
#if ENABLED(USE_ESP32_TASK_WDT)
#include <esp_task_wdt.h>
#endif
#if ENABLED(WIFISUPPORT)
#include <ESPAsyncWebServer.h>
#include "wifi.h"
@@ -48,7 +52,7 @@
// Externs
// ------------------------
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE MarlinHAL::spinlock = portMUX_INITIALIZER_UNLOCKED;
// ------------------------
// Local defines
@@ -60,7 +64,8 @@ portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
// Public Variables
// ------------------------
uint16_t HAL_adc_result;
uint16_t MarlinHAL::adc_result;
pwm_pin_t MarlinHAL::pwm_pin_data[MAX_EXPANDER_BITS];
// ------------------------
// Private Variables
@@ -69,9 +74,16 @@ uint16_t HAL_adc_result;
esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX];
adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {};
uint32_t thresholds[ADC_ATTEN_MAX];
volatile int numPWMUsed = 0,
pwmPins[MAX_PWM_PINS],
pwmValues[MAX_PWM_PINS];
volatile int numPWMUsed = 0;
volatile struct { pin_t pin; int value; } pwmState[MAX_PWM_PINS];
pin_t chan_pin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32
struct {
uint32_t freq; // ledcReadFreq doesn't work if a duty hasn't been set yet!
uint16_t res;
} pwmInfo[(CHANNEL_MAX_NUM + 1) / 2];
// ------------------------
// Public functions
@@ -90,8 +102,26 @@ volatile int numPWMUsed = 0,
#endif
void HAL_init_board() {
#if ENABLED(USE_ESP32_EXIO)
HardwareSerial YSerial2(2);
void Write_EXIO(uint8_t IO, uint8_t v) {
if (hal.isr_state()) {
hal.isr_off();
YSerial2.write(0x80 | (((char)v) << 5) | (IO - 100));
hal.isr_on();
}
else
YSerial2.write(0x80 | (((char)v) << 5) | (IO - 100));
}
#endif
void MarlinHAL::init_board() {
#if ENABLED(USE_ESP32_TASK_WDT)
esp_task_wdt_init(10, true);
#endif
#if ENABLED(ESP3D_WIFISUPPORT)
esp3dlib.init();
#elif ENABLED(WIFISUPPORT)
@@ -127,30 +157,58 @@ void HAL_init_board() {
// Initialize the i2s peripheral only if the I2S stepper stream is enabled.
// The following initialization is performed after Serial1 and Serial2 are defined as
// their native pins might conflict with the i2s stream even when they are remapped.
TERN_(I2S_STEPPER_STREAM, i2s_init());
#if ENABLED(USE_ESP32_EXIO)
YSerial2.begin(460800 * 3, SERIAL_8N1, 16, 17);
#elif ENABLED(I2S_STEPPER_STREAM)
i2s_init();
#endif
}
void HAL_idletask() {
void MarlinHAL::idletask() {
#if BOTH(WIFISUPPORT, OTASUPPORT)
OTA_handle();
#endif
TERN_(ESP3D_WIFISUPPORT, esp3dlib.idletask());
}
void HAL_clear_reset_source() { }
uint8_t MarlinHAL::get_reset_source() { return rtc_get_reset_reason(1); }
uint8_t HAL_get_reset_source() { return rtc_get_reset_reason(1); }
void HAL_reboot() { ESP.restart(); }
void MarlinHAL::reboot() { ESP.restart(); }
void _delay_ms(int delay_ms) { delay(delay_ms); }
// return free memory between end of heap (or end bss) and whatever is current
int freeMemory() { return ESP.getFreeHeap(); }
int MarlinHAL::freeMemory() { return ESP.getFreeHeap(); }
// ------------------------
// Watchdog Timer
// ------------------------
#if ENABLED(USE_WATCHDOG)
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
extern "C" {
esp_err_t esp_task_wdt_reset();
}
void watchdogSetup() {
// do whatever. don't remove this function.
}
void MarlinHAL::watchdog_init() {
// TODO
}
// Reset watchdog.
void MarlinHAL::watchdog_refresh() { esp_task_wdt_reset(); }
#endif
// ------------------------
// ADC
// ------------------------
#define ADC1_CHANNEL(pin) ADC1_GPIO ## pin ## _CHANNEL
adc1_channel_t get_channel(int pin) {
@@ -172,22 +230,24 @@ void adc1_set_attenuation(adc1_channel_t chan, adc_atten_t atten) {
}
}
void HAL_adc_init() {
void MarlinHAL::adc_init() {
// Configure ADC
adc1_config_width(ADC_WIDTH_12Bit);
// Configure channels only if used as (re-)configuring a pin for ADC that is used elsewhere might have adverse effects
TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_PROBE, adc1_set_attenuation(get_channel(TEMP_PROBE_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_BOARD, adc1_set_attenuation(get_channel(TEMP_BOARD_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.
@@ -202,11 +262,16 @@ void HAL_adc_init() {
}
}
void HAL_adc_start_conversion(const uint8_t adc_pin) {
const adc1_channel_t chan = get_channel(adc_pin);
#ifndef ADC_REFERENCE_VOLTAGE
#define ADC_REFERENCE_VOLTAGE 3.3
#endif
void MarlinHAL::adc_start(const pin_t pin) {
const adc1_channel_t chan = get_channel(pin);
uint32_t mv;
esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv);
HAL_adc_result = mv * 1023.0 / 3300.0;
adc_result = mv * isr_float_t(1023) / isr_float_t(ADC_REFERENCE_VOLTAGE) / isr_float_t(1000);
// Change the attenuation level based on the new reading
adc_atten_t atten;
@@ -223,25 +288,104 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
adc1_set_attenuation(chan, atten);
}
void analogWrite(pin_t pin, int value) {
// Use ledc hardware for internal pins
if (pin < 34) {
static int cnt_channel = 1, pin_to_channel[40] = { 0 };
if (pin_to_channel[pin] == 0) {
ledcAttachPin(pin, cnt_channel);
ledcSetup(cnt_channel, 490, 8);
ledcWrite(cnt_channel, value);
pin_to_channel[pin] = cnt_channel++;
// ------------------------
// PWM
// ------------------------
int8_t channel_for_pin(const uint8_t pin) {
for (int i = 0; i <= CHANNEL_MAX_NUM; i++)
if (chan_pin[i] == pin) return i;
return -1;
}
// get PWM channel for pin - if none then attach a new one
// return -1 if fail or invalid pin#, channel # (0-15) if success
int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) {
if (!WITHIN(pin, 1, MAX_PWM_IOPIN)) return -1; // Not a hardware PWM pin!
int8_t cid = channel_for_pin(pin);
if (cid >= 0) return cid;
// Find an empty adjacent channel (same timer & freq/res)
for (int i = 0; i <= CHANNEL_MAX_NUM; i++) {
if (chan_pin[i] == 0) {
if (chan_pin[i ^ 0x1] != 0) {
if (pwmInfo[i / 2].freq == freq && pwmInfo[i / 2].res == res) {
chan_pin[i] = pin; // Allocate PWM to this channel
ledcAttachPin(pin, i);
return i;
}
}
else if (cid == -1) // Pair of empty channels?
cid = i & 0xFE; // Save lower channel number
}
ledcWrite(pin_to_channel[pin], value);
}
// not attached, is an empty timer slot avail?
if (cid >= 0) {
chan_pin[cid] = pin;
pwmInfo[cid / 2].freq = freq;
pwmInfo[cid / 2].res = res;
ledcSetup(cid, freq, res);
ledcAttachPin(pin, cid);
}
return cid; // -1 if no channel avail
}
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) {
#if ENABLED(I2S_STEPPER_STREAM)
if (pin > 127) {
const uint8_t pinlo = pin & 0x7F;
pwm_pin_t &pindata = pwm_pin_data[pinlo];
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, pindata.pwm_cycle_ticks);
if (duty == 0 || duty == pindata.pwm_cycle_ticks) { // max or min (i.e., on/off)
pindata.pwm_duty_ticks = 0; // turn off PWM for this pin
duty ? SBI32(i2s_port_data, pinlo) : CBI32(i2s_port_data, pinlo); // set pin level
}
else
pindata.pwm_duty_ticks = duty; // PWM duty count = # of 4µs ticks per full PWM cycle
return;
}
#endif
const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION);
if (cid >= 0) {
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
ledcWrite(cid, duty);
}
}
int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) {
#if ENABLED(I2S_STEPPER_STREAM)
if (pin > 127) {
pwm_pin_data[pin & 0x7F].pwm_cycle_ticks = 1000000UL / f_desired / 4; // # of 4µs ticks per full PWM cycle
return 0;
}
#endif
const int8_t cid = channel_for_pin(pin);
if (cid >= 0) {
if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
ledcDetachPin(chan_pin[cid]);
chan_pin[cid] = 0; // remove old freq channel
}
return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one
}
// use hardware PWM if avail, if not then ISR
void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution!
// Use ledc hardware for internal pins
const int8_t cid = get_pwm_channel(pin, freq, res);
if (cid >= 0) {
ledcWrite(cid, value); // set duty value
return;
}
// not a hardware PWM pin OR no PWM channels available
int idx = -1;
// Search Pin
for (int i = 0; i < numPWMUsed; ++i)
if (pwmPins[i] == pin) { idx = i; break; }
if (pwmState[i].pin == pin) { idx = i; break; }
// not found ?
if (idx < 0) {
@@ -250,34 +394,34 @@ void analogWrite(pin_t pin, int value) {
// Take new slot for pin
idx = numPWMUsed;
pwmPins[idx] = pin;
pwmState[idx].pin = pin;
// Start timer on first use
if (idx == 0) HAL_timer_start(PWM_TIMER_NUM, PWM_TIMER_FREQUENCY);
if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY);
++numPWMUsed;
}
// Use 7bit internal value - add 1 to have 100% high at 255
pwmValues[idx] = (value + 1) / 2;
pwmState[idx].value = (value + 1) / 2;
}
// Handle PWM timer interrupt
HAL_PWM_TIMER_ISR() {
HAL_timer_isr_prologue(PWM_TIMER_NUM);
HAL_timer_isr_prologue(MF_TIMER_PWM);
static uint8_t count = 0;
for (int i = 0; i < numPWMUsed; ++i) {
if (count == 0) // Start of interval
WRITE(pwmPins[i], pwmValues[i] ? HIGH : LOW);
else if (pwmValues[i] == count) // End of duration
WRITE(pwmPins[i], LOW);
digitalWrite(pwmState[i].pin, pwmState[i].value ? HIGH : LOW);
else if (pwmState[i].value == count) // End of duration
digitalWrite(pwmState[i].pin, LOW);
}
// 128 for 7 Bit resolution
count = (count + 1) & 0x7F;
HAL_timer_isr_epilogue(PWM_TIMER_NUM);
HAL_timer_isr_epilogue(MF_TIMER_PWM);
}
#endif // ARDUINO_ARCH_ESP32

View File

@@ -32,7 +32,6 @@
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#include "i2s.h"
#if ENABLED(WIFISUPPORT)
@@ -49,40 +48,43 @@
// Defines
// ------------------------
extern portMUX_TYPE spinlock;
#define MYSERIAL1 flushableSerial
#if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT)
#if ENABLED(ESP3D_WIFISUPPORT)
typedef ForwardSerial1Class< decltype(Serial2Socket) > DefaultSerial1;
extern DefaultSerial1 MSerial0;
#define MYSERIAL2 MSerial0
#else
#define MYSERIAL2 webSocketSerial
#endif
#if ENABLED(ESP3D_WIFISUPPORT)
typedef ForwardSerial1Class< decltype(Serial2Socket) > DefaultSerial1;
extern DefaultSerial1 MSerial0;
#define MYSERIAL2 MSerial0
#elif ENABLED(WIFISUPPORT)
#define MYSERIAL2 webSocketSerial
#endif
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock)
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock)
#define ISRS_ENABLED() (spinlock.owner == portMUX_FREE_VAL)
#define ENABLE_ISRS() if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock)
#define DISABLE_ISRS() portENTER_CRITICAL(&spinlock)
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&hal.spinlock)
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&hal.spinlock)
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
#define PWM_RESOLUTION 10u // Default PWM bit resolution
#define CHANNEL_MAX_NUM 15u // max PWM channel # to allocate (7 to only use low speed, 15 to use low & high)
#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34
#ifndef MAX_EXPANDER_BITS
#define MAX_EXPANDER_BITS 32 // I2S expander bit width (max 32)
#endif
// ------------------------
// Types
// ------------------------
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int16_t pin_t;
#define HAL_SERVO_LIB Servo
typedef struct pwm_pin {
uint32_t pwm_cycle_ticks = 1000000UL / (PWM_FREQUENCY) / 4; // # ticks per pwm cycle
uint32_t pwm_tick_count = 0; // current tick count
uint32_t pwm_duty_ticks = 0; // # of ticks for current duty cycle
} pwm_pin_t;
// ------------------------
// Public Variables
// ------------------------
/** result of last ADC conversion */
extern uint16_t HAL_adc_result;
class Servo;
typedef Servo hal_servo_t;
// ------------------------
// Public functions
@@ -91,56 +93,21 @@ extern uint16_t HAL_adc_result;
//
// Tone
//
void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin);
int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res);
void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq=PWM_FREQUENCY, const uint16_t res=8);
// clear reset reason
void HAL_clear_reset_source();
// reset reason
uint8_t HAL_get_reset_source();
void HAL_reboot();
void _delay_ms(int delay);
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
void analogWrite(pin_t pin, int value);
// ADC
#define HAL_ANALOG_SELECT(pin)
void HAL_adc_init();
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
void HAL_adc_start_conversion(const uint8_t adc_pin);
//
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
// Enable hooks into idle and setup for HAL
#define HAL_IDLETASK 1
#define BOARD_INIT() HAL_init_board();
void HAL_idletask();
inline void HAL_init() {}
void HAL_init_board();
#if ENABLED(USE_ESP32_EXIO)
void Write_EXIO(uint8_t IO, uint8_t v);
#endif
//
// Delay in cycles (used by DELAY_NS / DELAY_US)
@@ -182,3 +149,96 @@ FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
}
}
// ------------------------
// Class Utilities
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#pragma GCC diagnostic pop
void _delay_ms(const int ms);
// ------------------------
// MarlinHAL Class
// ------------------------
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init() {} // Called early in setup()
static void init_board(); // Called less early in setup()
static void reboot(); // Restart the firmware
// Interrupts
static portMUX_TYPE spinlock;
static bool isr_state() { return spinlock.owner == portMUX_FREE_VAL; }
static void isr_on() { if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock); }
static void isr_off() { portENTER_CRITICAL(&spinlock); }
static void delay_ms(const int ms) { _delay_ms(ms); }
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source();
static void clear_reset_source() {}
// Free SRAM
static int freeMemory();
static pwm_pin_t pwm_pin_data[MAX_EXPANDER_BITS];
//
// ADC Methods
//
static uint16_t adc_result;
// Called by Temperature::init once at startup
static void adc_init();
// Called by Temperature::init for each sensor at startup
static void adc_enable(const pin_t pin) {}
// Begin ADC sampling on the given pin. Called from Temperature::isr!
static void adc_start(const pin_t pin);
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return adc_result; }
/**
* If not already allocated, allocate a hardware PWM channel
* to the pin and set the duty cycle..
* Optionally invert the duty cycle [default = false]
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
/**
* Allocate and set the frequency of a hardware PWM pin
* Returns -1 if no pin available.
*/
static int8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired);
};

View File

@@ -53,11 +53,9 @@ static SPISettings spiConfig;
// ------------------------
void spiBegin() {
#if !PIN_EXISTS(SD_SS)
#error "SD_SS_PIN not defined!"
#if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_SS)
OUT_WRITE(SD_SS_PIN, HIGH);
#endif
OUT_WRITE(SD_SS_PIN, HIGH);
}
void spiInit(uint8_t spiRate) {

View File

@@ -31,20 +31,18 @@
// so we only allocate servo channels up high to avoid side effects with regards to analogWrite (fans, leds, laser pwm etc.)
int Servo::channel_next_free = 12;
Servo::Servo() {
channel = channel_next_free++;
}
Servo::Servo() {}
int8_t Servo::attach(const int inPin) {
if (channel >= CHANNEL_MAX_NUM) return -1;
if (inPin > 0) pin = inPin;
ledcSetup(channel, 50, 16); // channel X, 50 Hz, 16-bit depth
ledcAttachPin(pin, channel);
return true;
channel = get_pwm_channel(pin, 50u, 16u);
return channel; // -1 if no PWM avail.
}
void Servo::detach() { ledcDetachPin(pin); }
// leave channel connected to servo - set duty to zero
void Servo::detach() {
if (channel >= 0) ledcWrite(channel, 0);
}
int Servo::read() { return degrees; }
@@ -52,7 +50,7 @@ void Servo::write(int inDegrees) {
degrees = constrain(inDegrees, MIN_ANGLE, MAX_ANGLE);
int us = map(degrees, MIN_ANGLE, MAX_ANGLE, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
int duty = map(us, 0, TAU_USEC, 0, MAX_COMPARE);
ledcWrite(channel, duty);
if (channel >= 0) ledcWrite(channel, duty); // don't save duty for servos!
}
void Servo::move(const int value) {

View File

@@ -30,8 +30,7 @@ class Servo {
MAX_PULSE_WIDTH = 2400, // Longest pulse sent to a servo
TAU_MSEC = 20,
TAU_USEC = (TAU_MSEC * 1000),
MAX_COMPARE = _BV(16) - 1, // 65535
CHANNEL_MAX_NUM = 16;
MAX_COMPARE = _BV(16) - 1; // 65535
public:
Servo();

View File

@@ -35,19 +35,19 @@
static pin_t tone_pin;
volatile static int32_t toggles;
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) {
tone_pin = _pin;
toggles = 2 * frequency * duration / 1000;
HAL_timer_start(TONE_TIMER_NUM, 2 * frequency);
HAL_timer_start(MF_TIMER_TONE, 2 * frequency);
}
void noTone(const pin_t _pin) {
HAL_timer_disable_interrupt(TONE_TIMER_NUM);
HAL_timer_disable_interrupt(MF_TIMER_TONE);
WRITE(_pin, LOW);
}
HAL_TONE_TIMER_ISR() {
HAL_timer_isr_prologue(TONE_TIMER_NUM);
HAL_timer_isr_prologue(MF_TIMER_TONE);
if (toggles) {
toggles--;

View File

@@ -65,4 +65,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN));
TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN));
TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN));
TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN));
TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN));
TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN));
}

View File

@@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x180000,
app1, app, ota_1, 0x190000, 0x180000,
spiffs, data, spiffs, 0x310000, 0xF0000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x180000
5 app1 app ota_1 0x190000 0x180000
6 spiffs data spiffs 0x310000 0xF0000

View File

@@ -40,13 +40,19 @@
// Set pin as input with pullup mode
#define _PULLUP(IO, v) pinMode(IO, v ? INPUT_PULLUP : INPUT)
// Read a pin wrapper
#define READ(IO) (IS_I2S_EXPANDER_PIN(IO) ? i2s_state(I2S_EXPANDER_PIN_INDEX(IO)) : digitalRead(IO))
#if ENABLED(USE_ESP32_EXIO)
// Read a pin wrapper
#define READ(IO) digitalRead(IO)
// Write to a pin wrapper
#define WRITE(IO, v) (IO >= 100 ? Write_EXIO(IO, v) : digitalWrite(IO, v))
#else
// Read a pin wrapper
#define READ(IO) (IS_I2S_EXPANDER_PIN(IO) ? i2s_state(I2S_EXPANDER_PIN_INDEX(IO)) : digitalRead(IO))
// Write to a pin wrapper
#define WRITE(IO, v) (IS_I2S_EXPANDER_PIN(IO) ? i2s_write(I2S_EXPANDER_PIN_INDEX(IO), v) : digitalWrite(IO, v))
#endif
// Write to a pin wrapper
#define WRITE(IO, v) (IS_I2S_EXPANDER_PIN(IO) ? i2s_write(I2S_EXPANDER_PIN_INDEX(IO), v) : digitalWrite(IO, v))
// Set pin as input wrapper
// Set pin as input wrapper (0x80 | (v << 5) | (IO - 100))
#define SET_INPUT(IO) _SET_INPUT(IO)
// Set pin as input with pullup wrapper

View File

@@ -23,6 +23,8 @@
#include "../../inc/MarlinConfigPre.h"
#if DISABLED(USE_ESP32_EXIO)
#include "i2s.h"
#include "../shared/Marduino.h"
@@ -62,12 +64,9 @@ uint32_t i2s_port_data = 0;
#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
static inline void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) {
//if pin = -1, do not need to configure
if (gpio != -1) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
}
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
}
static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) {
@@ -140,22 +139,38 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
}
void stepperTask(void *parameter) {
uint32_t remaining = 0;
uint32_t nextMainISR = 0;
#if ENABLED(LIN_ADVANCE)
uint32_t nextAdvanceISR = Stepper::LA_ADV_NEVER;
#endif
while (1) {
for (;;) {
xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
dma.rw_pos = 0;
while (dma.rw_pos < DMA_SAMPLE_COUNT) {
// Fill with the port data post pulse_phase until the next step
if (remaining) {
i2s_push_sample();
remaining--;
}
else {
if (!nextMainISR) {
Stepper::pulse_phase_isr();
remaining = Stepper::block_phase_isr();
nextMainISR = Stepper::block_phase_isr();
}
#if ENABLED(LIN_ADVANCE)
else if (!nextAdvanceISR) {
Stepper::advance_isr();
nextAdvanceISR = Stepper::la_interval;
}
#endif
else
i2s_push_sample();
nextMainISR--;
#if ENABLED(LIN_ADVANCE)
if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
nextAdvanceISR = Stepper::la_interval;
if (nextAdvanceISR && nextAdvanceISR != Stepper::LA_ADV_NEVER)
nextAdvanceISR--;
#endif
}
}
}
@@ -254,13 +269,7 @@ int i2s_init() {
I2S0.fifo_conf.dscr_en = 0;
I2S0.conf_chan.tx_chan_mod = (
#if ENABLED(I2S_STEPPER_SPLIT_STREAM)
4
#else
0
#endif
);
I2S0.conf_chan.tx_chan_mod = TERN(I2S_STEPPER_SPLIT_STREAM, 4, 0);
I2S0.fifo_conf.tx_fifo_mod = 0;
I2S0.conf.tx_mono = 0;
@@ -311,9 +320,16 @@ int i2s_init() {
xTaskCreatePinnedToCore(stepperTask, "StepperTask", 10000, nullptr, 1, nullptr, CONFIG_ARDUINO_RUNNING_CORE); // run I2S stepper task on same core as rest of Marlin
// Route the i2s pins to the appropriate GPIO
gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0);
gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0);
gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0);
// If a pin is not defined, no need to configure
#if defined(I2S_DATA) && I2S_DATA >= 0
gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0);
#endif
#if defined(I2S_BCK) && I2S_BCK >= 0
gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0);
#endif
#if defined(I2S_WS) && I2S_WS >= 0
gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0);
#endif
// Start the I2S peripheral
return i2s_start(I2S_NUM_0);
@@ -337,7 +353,28 @@ uint8_t i2s_state(uint8_t pin) {
}
void i2s_push_sample() {
// Every 4µs (when space in DMA buffer) toggle each expander PWM output using
// the current duty cycle/frequency so they sync with any steps (once
// through the DMA/FIFO buffers). PWM signal inversion handled by other functions
LOOP_L_N(p, MAX_EXPANDER_BITS) {
if (hal.pwm_pin_data[p].pwm_duty_ticks > 0) { // pin has active pwm?
if (hal.pwm_pin_data[p].pwm_tick_count == 0) {
if (TEST32(i2s_port_data, p)) { // hi->lo
CBI32(i2s_port_data, p);
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_cycle_ticks - hal.pwm_pin_data[p].pwm_duty_ticks;
}
else { // lo->hi
SBI32(i2s_port_data, p);
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_duty_ticks;
}
}
else
hal.pwm_pin_data[p].pwm_tick_count--;
}
}
dma.current[dma.rw_pos++] = i2s_port_data;
}
#endif // !USE_ESP32_EXIO
#endif // ARDUINO_ARCH_ESP32

View File

@@ -20,7 +20,3 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/ESP32."
#endif

View File

@@ -20,3 +20,10 @@
*
*/
#pragma once
//
// Board-specific options need to be defined before HAL.h
//
#if MB(MKS_TINYBEE)
#define MAX_EXPANDER_BITS 24 // TinyBee has 3 x HC595
#endif

View File

@@ -21,12 +21,19 @@
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/ESP32."
#endif
#if ENABLED(EMERGENCY_PARSER)
#error "EMERGENCY_PARSER is not yet implemented for ESP32. Disable EMERGENCY_PARSER to continue."
#endif
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on ESP32."
#if ENABLED(SPINDLE_LASER_USE_PWM) && SPINDLE_LASER_FREQUENCY > 78125
#error "SPINDLE_LASER_FREQUENCY maximum value is 78125Hz for ESP32."
#endif
#if ENABLED(FAST_PWM_FAN) && FAST_PWM_FAN_FREQUENCY > 78125
#error "FAST_PWM_FREQUENCY maximum value is 78125Hz for ESP32."
#endif
#if HAS_TMC_SW_SERIAL
@@ -40,3 +47,23 @@
#if ENABLED(POSTMORTEM_DEBUGGING)
#error "POSTMORTEM_DEBUGGING is not yet supported on ESP32."
#endif
#if MB(MKS_TINYBEE) && ENABLED(FAST_PWM_FAN)
#error "FAST_PWM_FAN is not available on TinyBee."
#endif
#if BOTH(I2S_STEPPER_STREAM, BABYSTEPPING) && DISABLED(INTEGRATED_BABYSTEPPING)
#error "BABYSTEPPING on I2S stream requires INTEGRATED_BABYSTEPPING."
#endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on ESP32 boards."
#endif
#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA)
#error "I2S stream is currently incompatible with LIN_ADVANCE."
#endif
#if BOTH(I2S_STEPPER_STREAM, PRINTCOUNTER) && PRINTCOUNTER_SAVE_INTERVAL > 0 && DISABLED(PRINTCOUNTER_SYNC)
#error "PRINTCOUNTER_SAVE_INTERVAL may cause issues on ESP32 with an I2S expander. Define PRINTCOUNTER_SYNC in Configuration.h for an imperfect solution."
#endif

View File

@@ -41,7 +41,7 @@
static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
{ TIMER_GROUP_0, TIMER_0, STEPPER_TIMER_PRESCALE, stepTC_Handler }, // 0 - Stepper
{ TIMER_GROUP_0, TIMER_1, TEMP_TIMER_PRESCALE, tempTC_Handler }, // 1 - Temperature
{ TIMER_GROUP_1, TIMER_0, PWM_TIMER_PRESCALE, pwmTC_Handler }, // 2 - PWM
@@ -53,7 +53,7 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
// ------------------------
void IRAM_ATTR timer_isr(void *para) {
const tTimerConfig& timer = TimerConfig[(int)para];
const tTimerConfig& timer = timer_config[(int)para];
// Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt
@@ -81,8 +81,8 @@ void IRAM_ATTR timer_isr(void *para) {
* @param timer_num timer number to initialize
* @param frequency frequency of the timer
*/
void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) {
const tTimerConfig timer = TimerConfig[timer_num];
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
const tTimerConfig timer = timer_config[timer_num];
timer_config_t config;
config.divider = timer.divider;
@@ -111,12 +111,12 @@ void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) {
/**
* Set the upper value of the timer, when the timer reaches this upper value the
* interrupt should be triggered and the counter reset
* @param timer_num timer number to set the count to
* @param count threshold at which the interrupt is triggered
* @param timer_num timer number to set the compare value to
* @param compare threshold at which the interrupt is triggered
*/
void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) {
const tTimerConfig timer = TimerConfig[timer_num];
timer_set_alarm_value(timer.group, timer.idx, count);
void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
const tTimerConfig timer = timer_config[timer_num];
timer_set_alarm_value(timer.group, timer.idx, compare);
}
/**
@@ -125,7 +125,7 @@ void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) {
* @return the timer current threshold for the alarm to be triggered
*/
hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
const tTimerConfig timer = TimerConfig[timer_num];
const tTimerConfig timer = timer_config[timer_num];
uint64_t alarm_value;
timer_get_alarm_value(timer.group, timer.idx, &alarm_value);
@@ -139,7 +139,7 @@ hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
* @return the current counter of the alarm
*/
hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
const tTimerConfig timer = TimerConfig[timer_num];
const tTimerConfig timer = timer_config[timer_num];
uint64_t counter_value;
timer_get_counter_value(timer.group, timer.idx, &counter_value);
return counter_value;
@@ -150,7 +150,7 @@ hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
* @param timer_num timer number to enable interrupts on
*/
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
//const tTimerConfig timer = TimerConfig[timer_num];
//const tTimerConfig timer = timer_config[timer_num];
//timer_enable_intr(timer.group, timer.idx);
}
@@ -159,12 +159,12 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num) {
* @param timer_num timer number to disable interrupts on
*/
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
//const tTimerConfig timer = TimerConfig[timer_num];
//const tTimerConfig timer = timer_config[timer_num];
//timer_disable_intr(timer.group, timer.idx);
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
const tTimerConfig timer = TimerConfig[timer_num];
const tTimerConfig timer = timer_config[timer_num];
return TG[timer.group]->int_ena.val | BIT(timer_num);
}

View File

@@ -32,20 +32,20 @@
typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFFFFFFFFFULL
#ifndef STEP_TIMER_NUM
#define STEP_TIMER_NUM 0 // Timer Index for Stepper
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 0 // Timer Index for Stepper
#endif
#ifndef PULSE_TIMER_NUM
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef TEMP_TIMER_NUM
#define TEMP_TIMER_NUM 1 // Timer Index for Temperature
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP 1 // Timer Index for Temperature
#endif
#ifndef PWM_TIMER_NUM
#define PWM_TIMER_NUM 2 // index of timer to use for PWM outputs
#ifndef MF_TIMER_PWM
#define MF_TIMER_PWM 2 // index of timer to use for PWM outputs
#endif
#ifndef TONE_TIMER_NUM
#define TONE_TIMER_NUM 3 // index of timer for beeper tones
#ifndef MF_TIMER_TONE
#define MF_TIMER_TONE 3 // index of timer for beeper tones
#endif
#define HAL_TIMER_RATE APB_CLK_FREQ // frequency of timer peripherals
@@ -79,12 +79,12 @@ typedef uint64_t hal_timer_t;
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_TEMP_TIMER_ISR
#define HAL_TEMP_TIMER_ISR() extern "C" void tempTC_Handler()
@@ -121,13 +121,13 @@ typedef struct {
// Public Variables
// ------------------------
extern const tTimerConfig TimerConfig[];
extern const tTimerConfig timer_config[];
// ------------------------
// Public functions
// ------------------------
void HAL_timer_start (const uint8_t timer_num, uint32_t frequency);
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t count);
hal_timer_t HAL_timer_get_compare(const uint8_t timer_num);
hal_timer_t HAL_timer_get_count(const uint8_t timer_num);
@@ -136,5 +136,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
#define HAL_timer_isr_prologue(TIMER_NUM)
#define HAL_timer_isr_epilogue(TIMER_NUM)
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP

View File

@@ -0,0 +1,106 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* Copypaste of SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfig.h"
#if EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
#include <U8glib-HAL.h>
#include "../shared/HAL_SPI.h"
#include "HAL.h"
#include "SPI.h"
#if ENABLED(SDSUPPORT)
#include "../../sd/cardreader.h"
#if ENABLED(ESP3D_WIFISUPPORT)
#include "sd_ESP32.h"
#endif
#endif
static SPISettings spiConfig;
#ifndef LCD_SPI_SPEED
#ifdef SD_SPI_SPEED
#define LCD_SPI_SPEED SD_SPI_SPEED // Assume SPI speed shared with SD
#else
#define LCD_SPI_SPEED SPI_FULL_SPEED // Use full speed if SD speed is not supplied
#endif
#endif
uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT
#if ENABLED(PAUSE_LCD_FOR_BUSY_SD)
if (card.flag.saving || card.flag.logging || TERN0(ESP3D_WIFISUPPORT, sd_busy_lock == true)) return 0;
#endif
if (msgInitCount) {
if (msg == U8G_COM_MSG_INIT) msgInitCount--;
if (msgInitCount) return -1;
}
switch (msg) {
case U8G_COM_MSG_STOP: break;
case U8G_COM_MSG_INIT:
OUT_WRITE(DOGLCD_CS, HIGH);
OUT_WRITE(DOGLCD_A0, HIGH);
OUT_WRITE(LCD_RESET_PIN, HIGH);
u8g_Delay(5);
spiBegin();
spiInit(LCD_SPI_SPEED);
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
WRITE(DOGLCD_A0, arg_val ? HIGH : LOW);
break;
case U8G_COM_MSG_CHIP_SELECT: /* arg_val == 0 means HIGH level of U8G_PI_CS */
WRITE(DOGLCD_CS, arg_val ? LOW : HIGH);
break;
case U8G_COM_MSG_RESET:
WRITE(LCD_RESET_PIN, arg_val);
break;
case U8G_COM_MSG_WRITE_BYTE:
spiSend((uint8_t)arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ:
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
spiSend(*ptr++);
arg_val--;
}
break;
}
return 1;
}
#endif // EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
#endif // ARDUINO_ARCH_ESP32

View File

@@ -27,7 +27,8 @@
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
#include HAL_PATH(.,HAL.h)
#include HAL_PATH(..,HAL.h)
extern MarlinHAL hal;
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
@@ -44,7 +45,3 @@
#ifndef PGMSTR
#define PGMSTR(NAM,STR) const char NAM[] = STR
#endif
inline void watchdog_refresh() {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
}

View File

@@ -24,6 +24,10 @@
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
// ------------------------
// Serial ports
// ------------------------
MSerialT usb_serial(TERN0(EMERGENCY_PARSER, true));
// U8glib required functions
@@ -37,42 +41,21 @@ extern "C" {
//************************//
// return free heap space
int freeMemory() {
return 0;
}
int freeMemory() { return 0; }
// ------------------------
// ADC
// ------------------------
void HAL_adc_init() {
uint8_t MarlinHAL::active_ch = 0;
}
void HAL_adc_enable_channel(const uint8_t ch) {
}
uint8_t active_ch = 0;
void HAL_adc_start_conversion(const uint8_t ch) {
active_ch = ch;
}
bool HAL_adc_finished() {
return true;
}
uint16_t HAL_adc_get_result() {
pin_t pin = analogInputToDigitalPin(active_ch);
uint16_t MarlinHAL::adc_value() {
const pin_t pin = analogInputToDigitalPin(active_ch);
if (!VALID_PIN(pin)) return 0;
uint16_t data = ((Gpio::get(pin) >> 2) & 0x3FF);
const uint16_t data = ((Gpio::get(pin) >> 2) & 0x3FF);
return data; // return 10bit value as Marlin expects
}
void HAL_pwm_init() {
}
void HAL_reboot() { /* Reset the application state and GPIO */ }
void MarlinHAL::reboot() { /* Reset the application state and GPIO */ }
#endif // __PLAT_LINUX__

View File

@@ -21,25 +21,42 @@
*/
#pragma once
#define CPU_32_BIT
#include "../../inc/MarlinConfigPre.h"
#define F_CPU 100000000UL
#define SystemCoreClock F_CPU
#include <iostream>
#include <stdint.h>
#include <stdarg.h>
#undef min
#undef max
#include <algorithm>
void _printf (const char *format, ...);
#include "hardware/Clock.h"
#include "../shared/Marduino.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "serial.h"
// ------------------------
// Defines
// ------------------------
#define CPU_32_BIT
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
#define F_CPU 100000000UL
#define SystemCoreClock F_CPU
#define DELAY_CYCLES(x) Clock::delayCycles(x)
#define CPU_ST7920_DELAY_1 600
#define CPU_ST7920_DELAY_2 750
#define CPU_ST7920_DELAY_3 750
void _printf(const char *format, ...);
void _putc(uint8_t c);
uint8_t _getc();
//extern "C" volatile uint32_t _millis;
//arduino: Print.h
#define DEC 10
#define HEX 16
@@ -49,67 +66,100 @@ uint8_t _getc();
#define B01 1
#define B10 2
#include "hardware/Clock.h"
#include "../shared/Marduino.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#include "serial.h"
#define SHARED_SERVOS HAS_SERVOS
// ------------------------
// Serial ports
// ------------------------
extern MSerialT usb_serial;
#define MYSERIAL1 usb_serial
#define CPU_ST7920_DELAY_1 600
#define CPU_ST7920_DELAY_2 750
#define CPU_ST7920_DELAY_3 750
//
// Interrupts
//
#define CRITICAL_SECTION_START()
#define CRITICAL_SECTION_END()
#define ISRS_ENABLED()
#define ENABLE_ISRS()
#define DISABLE_ISRS()
inline void HAL_init() {}
// ADC
#define HAL_ADC_VREF 5.0
#define HAL_ADC_RESOLUTION 10
// Utility functions
// ------------------------
// Class Utilities
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
// ADC
#define HAL_ADC_VREF 5.0
#define HAL_ADC_RESOLUTION 10
#define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch)
#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch)
#define HAL_READ_ADC() HAL_adc_get_result()
#define HAL_ADC_READY() true
// ------------------------
// MarlinHAL Class
// ------------------------
void HAL_adc_init();
void HAL_adc_enable_channel(const uint8_t ch);
void HAL_adc_start_conversion(const uint8_t ch);
uint16_t HAL_adc_get_result();
class MarlinHAL {
public:
// Reset source
inline void HAL_clear_reset_source(void) {}
inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; }
// Earliest possible init, before setup()
MarlinHAL() {}
void HAL_reboot(); // Reset the application state and GPIO
// Watchdog
static void watchdog_init() {}
static void watchdog_refresh() {}
/* ---------------- Delay in cycles */
FORCE_INLINE static void DELAY_CYCLES(uint64_t x) {
Clock::delayCycles(x);
}
static void init() {} // Called early in setup()
static void init_board() {} // Called less early in setup()
static void reboot(); // Reset the application state and GPIO
// Interrupts
static bool isr_state() { return true; }
static void isr_on() {}
static void isr_off() {}
static void delay_ms(const int ms) { _delay_ms(ms); }
// Tasks, called from idle()
static void idletask() {}
// Reset
static constexpr uint8_t reset_reason = RST_POWER_ON;
static uint8_t get_reset_source() { return reset_reason; }
static void clear_reset_source() {}
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
static uint8_t active_ch;
// Called by Temperature::init once at startup
static void adc_init() {}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t) {}
// Begin ADC sampling on the given channel
static void adc_start(const uint8_t ch) { active_ch = ch; }
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value();
/**
* Set the PWM duty cycle for the pin to the given value.
* No option to change the resolution or invert the duty cycle.
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
}
static void set_pwm_frequency(const pin_t, int) {}
};

View File

@@ -31,9 +31,7 @@ void cli() { } // Disable
void sei() { } // Enable
// Time functions
void _delay_ms(const int delay_ms) {
delay(delay_ms);
}
void _delay_ms(const int ms) { delay(ms); }
uint32_t millis() {
return (uint32_t)Clock::millis();

View File

@@ -69,12 +69,12 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
std::size_t bytes_written = 0;
for (std::size_t i = 0; i < size; i++) {
buffer[pos+i] = value[i];
bytes_written ++;
buffer[pos + i] = value[i];
bytes_written++;
}
crc16(crc, value, size);
pos = pos + size;
pos += size;
return (bytes_written != size); // return true for any error
}
@@ -82,21 +82,21 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uin
std::size_t bytes_read = 0;
if (writing) {
for (std::size_t i = 0; i < size; i++) {
value[i] = buffer[pos+i];
bytes_read ++;
value[i] = buffer[pos + i];
bytes_read++;
}
crc16(crc, value, size);
}
else {
uint8_t temp[size];
for (std::size_t i = 0; i < size; i++) {
temp[i] = buffer[pos+i];
bytes_read ++;
temp[i] = buffer[pos + i];
bytes_read++;
}
crc16(crc, temp, size);
}
pos = pos + size;
pos += size;
return bytes_read != size; // return true for any error
}

View File

@@ -26,8 +26,8 @@
struct LowpassFilter {
uint64_t data_delay = 0;
uint16_t update(uint16_t value) {
data_delay = data_delay - (data_delay >> 6) + value;
return (uint16_t)(data_delay >> 6);
data_delay += value - (data_delay >> 6);
return uint16_t(data_delay >> 6);
}
};

View File

@@ -20,7 +20,3 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/LINUX."
#endif

View File

@@ -31,13 +31,17 @@
#endif
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on LINUX."
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported for HAL/LINUX."
#endif
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/LINUX."
#endif
#if HAS_TMC_SW_SERIAL
#error "TMC220x Software Serial is not supported on LINUX."
#error "TMC220x Software Serial is not supported for HAL/LINUX."
#endif
#if ENABLED(POSTMORTEM_DEBUGGING)
#error "POSTMORTEM_DEBUGGING is not yet supported on LINUX."
#error "POSTMORTEM_DEBUGGING is not yet supported for HAL/LINUX."
#endif

View File

@@ -59,10 +59,9 @@ typedef uint8_t byte;
#endif
#define sq(v) ((v) * (v))
#define square(v) sq(v)
#define constrain(value, arg_min, arg_max) ((value) < (arg_min) ? (arg_min) :((value) > (arg_max) ? (arg_max) : (value)))
//Interrupts
// Interrupts
void cli(); // Disable
void sei(); // Enable
void attachInterrupt(uint32_t pin, void (*callback)(), uint32_t mode);
@@ -74,8 +73,8 @@ extern "C" {
}
// Time functions
extern "C" void delay(const int milis);
void _delay_ms(const int delay);
extern "C" void delay(const int ms);
void _delay_ms(const int ms);
void delayMicroseconds(unsigned long);
uint32_t millis();

View File

@@ -25,10 +25,10 @@
#include "../../inc/MarlinConfigPre.h"
#if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN)
#define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
// spiBeginTransaction.
#define SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
// spiBeginTransaction.
#endif
// Onboard SD

View File

@@ -37,14 +37,14 @@ typedef uint32_t hal_timer_t;
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
#ifndef STEP_TIMER_NUM
#define STEP_TIMER_NUM 0 // Timer Index for Stepper
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 0 // Timer Index for Stepper
#endif
#ifndef PULSE_TIMER_NUM
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef TEMP_TIMER_NUM
#define TEMP_TIMER_NUM 1 // Timer Index for Temperature
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP 1 // Timer Index for Temperature
#endif
#define TEMP_TIMER_RATE 1000000
@@ -58,12 +58,12 @@ typedef uint32_t hal_timer_t;
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() extern "C" void TIMER0_IRQHandler()
@@ -77,7 +77,6 @@ typedef uint32_t hal_timer_t;
#define HAL_PWM_TIMER_ISR() extern "C" void TIMER3_IRQHandler()
#define HAL_PWM_TIMER_IRQn
void HAL_timer_init();
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
@@ -93,5 +92,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
#define HAL_timer_isr_prologue(TIMER_NUM)
#define HAL_timer_isr_epilogue(TIMER_NUM)
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP

View File

@@ -1,37 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef __PLAT_LINUX__
#include "../../inc/MarlinConfig.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
void watchdog_init() {}
void HAL_watchdog_refresh() {}
#endif
#endif // __PLAT_LINUX__

View File

@@ -25,13 +25,9 @@
#include "../shared/Delay.h"
#include "../../../gcode/parser.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#endif
DefaultSerial1 USBSerial(false, UsbSerial);
uint32_t HAL_adc_reading = 0;
uint32_t MarlinHAL::adc_result = 0;
// U8glib required functions
extern "C" {
@@ -41,8 +37,6 @@ extern "C" {
void u8g_Delay(uint16_t val) { delay(val); }
}
//************************//
// return free heap space
int freeMemory() {
char stack_end;
@@ -54,7 +48,71 @@ int freeMemory() {
return result;
}
// scan command line for code
void MarlinHAL::reboot() { NVIC_SystemReset(); }
uint8_t MarlinHAL::get_reset_source() {
#if ENABLED(USE_WATCHDOG)
if (watchdog_timed_out()) return RST_WATCHDOG;
#endif
return RST_POWER_ON;
}
void MarlinHAL::clear_reset_source() { watchdog_clear_timeout_flag(); }
void flashFirmware(const int16_t) {
delay(500); // Give OS time to disconnect
USB_Connect(false); // USB clear connection
delay(1000); // Give OS time to notice
hal.reboot();
}
#if ENABLED(USE_WATCHDOG)
#include <lpc17xx_wdt.h>
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
void MarlinHAL::watchdog_init() {
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
// Configure WDT to only trigger an interrupt
// Disable WDT interrupt (just in case, to avoid triggering it!)
NVIC_DisableIRQ(WDT_IRQn);
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
// Configure WDT to only trigger an interrupt
// Initialize WDT with the given parameters
WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_INT_ONLY);
// Configure and enable WDT interrupt.
NVIC_ClearPendingIRQ(WDT_IRQn);
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
NVIC_EnableIRQ(WDT_IRQn);
#else
WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
#endif
WDT_Start(WDT_TIMEOUT_US);
}
void MarlinHAL::watchdog_refresh() {
WDT_Feed();
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
TOGGLE(LED_PIN); // heartbeat indicator
#endif
}
// Timeout state
bool MarlinHAL::watchdog_timed_out() { return TEST(WDT_ReadTimeOutFlag(), 0); }
void MarlinHAL::watchdog_clear_timeout_flag() { WDT_ClrTimeOutFlag(); }
#endif // USE_WATCHDOG
// For M42/M43, scan command line for pin code
// return index into pin map array if found and the pin is valid.
// return dval if not found or not a valid pin.
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
@@ -63,24 +121,4 @@ int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
return ind > -1 ? ind : dval;
}
void flashFirmware(const int16_t) {
delay(500); // Give OS time to disconnect
USB_Connect(false); // USB clear connection
delay(1000); // Give OS time to notice
HAL_reboot();
}
void HAL_clear_reset_source(void) {
TERN_(USE_WATCHDOG, watchdog_clear_timeout_flag());
}
uint8_t HAL_get_reset_source(void) {
#if ENABLED(USE_WATCHDOG)
if (watchdog_timed_out()) return RST_WATCHDOG;
#endif
return RST_POWER_ON;
}
void HAL_reboot() { NVIC_SystemReset(); }
#endif // TARGET_LPC1768

View File

@@ -28,8 +28,6 @@
#define CPU_32_BIT
void HAL_init();
#include <stdint.h>
#include <stdarg.h>
#include <algorithm>
@@ -40,19 +38,15 @@ extern "C" volatile uint32_t _millis;
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#include "MarlinSerial.h"
#include <adc.h>
#include <pinmapping.h>
#include <CDCSerial.h>
//
// Default graphical display delays
//
#define CPU_ST7920_DELAY_1 600
#define CPU_ST7920_DELAY_2 750
#define CPU_ST7920_DELAY_3 750
// ------------------------
// Serial ports
// ------------------------
typedef ForwardSerial1Class< decltype(UsbSerial) > DefaultSerial1;
extern DefaultSerial1 USBSerial;
@@ -114,28 +108,12 @@ extern DefaultSerial1 USBSerial;
//
// Interrupts
//
#define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq()
#define CRITICAL_SECTION_END() if (!primask) __enable_irq()
#define ISRS_ENABLED() (!__get_PRIMASK())
#define ENABLE_ISRS() __enable_irq()
#define DISABLE_ISRS() __disable_irq()
#define CRITICAL_SECTION_START() const bool irqon = !__get_PRIMASK(); __disable_irq()
#define CRITICAL_SECTION_END() if (irqon) __enable_irq()
//
// Utility functions
//
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
//
// ADC API
// ADC
//
#define ADC_MEDIAN_FILTER_SIZE (23) // Higher values increase step delay (phase shift),
@@ -154,20 +132,9 @@ int freeMemory();
#define HAL_ADC_RESOLUTION 12 // 15 bit maximum, raw temperature is stored as int16_t
#define HAL_ADC_FILTERED // Disable oversampling done in Marlin as ADC values already filtered in HAL
using FilteredADC = LPC176x::ADC<ADC_LOWPASS_K_VALUE, ADC_MEDIAN_FILTER_SIZE>;
extern uint32_t HAL_adc_reading;
[[gnu::always_inline]] inline void HAL_adc_start_conversion(const pin_t pin) {
HAL_adc_reading = FilteredADC::read(pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
}
[[gnu::always_inline]] inline uint16_t HAL_adc_get_result() {
return HAL_adc_reading;
}
#define HAL_adc_init()
#define HAL_ANALOG_SELECT(pin) FilteredADC::enable_channel(pin)
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_READ_ADC() HAL_adc_get_result()
#define HAL_ADC_READY() (true)
//
// Pin Mapping for M42, M43, M226
//
// Test whether the pin is valid
constexpr bool VALID_PIN(const pin_t pin) {
@@ -194,32 +161,107 @@ int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
// P0.6 thru P0.9 are for the onboard SD card
#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09,
#define HAL_IDLETASK 1
void HAL_idletask();
// ------------------------
// Defines
// ------------------------
#define PLATFORM_M997_SUPPORT
void flashFirmware(const int16_t);
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
/**
* set_pwm_frequency
* Set the frequency of the timer corresponding to the provided pin
* All Hardware PWM pins run at the same frequency and all
* Software PWM pins run at the same frequency
*/
void set_pwm_frequency(const pin_t pin, int f_desired);
// Default graphical display delays
#define CPU_ST7920_DELAY_1 600
#define CPU_ST7920_DELAY_2 750
#define CPU_ST7920_DELAY_3 750
/**
* set_pwm_duty
* Set the PWM duty cycle of the provided pin to the provided value
* Optionally allows inverting the duty cycle [default = false]
* Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
*/
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
// ------------------------
// Free Memory Accessor
// ------------------------
// Reset source
void HAL_clear_reset_source(void);
uint8_t HAL_get_reset_source(void);
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
void HAL_reboot();
int freeMemory();
#pragma GCC diagnostic pop
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
static void init(); // Called early in setup()
static void init_board() {} // Called less early in setup()
static void reboot(); // Restart the firmware from 0x0
// Interrupts
static bool isr_state() { return !__get_PRIMASK(); }
static void isr_on() { __enable_irq(); }
static void isr_off() { __disable_irq(); }
static void delay_ms(const int ms) { _delay_ms(ms); }
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static bool watchdog_timed_out() IF_DISABLED(USE_WATCHDOG, { return false; });
static void watchdog_clear_timeout_flag() IF_DISABLED(USE_WATCHDOG, {});
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source();
static void clear_reset_source();
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
using FilteredADC = LPC176x::ADC<ADC_LOWPASS_K_VALUE, ADC_MEDIAN_FILTER_SIZE>;
// Called by Temperature::init once at startup
static void adc_init() {}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const pin_t pin) {
FilteredADC::enable_channel(pin);
}
// Begin ADC sampling on the given pin. Called from Temperature::isr!
static uint32_t adc_result;
static void adc_start(const pin_t pin) {
adc_result = FilteredADC::read(pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
}
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return uint16_t(adc_result); }
/**
* Set the PWM duty cycle for the pin to the given value.
* Optionally invert the duty cycle [default = false]
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
/**
* Set the frequency of the timer corresponding to the provided pin
* All Hardware PWM pins will run at the same frequency and
* All Software PWM pins will run at the same frequency
*/
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
};

Some files were not shown because too many files have changed in this diff Show More