Bump to head with initial raptor2 support
This commit is contained in:
+69
-36
@@ -4,6 +4,10 @@
|
||||
// CUSTOMIZE FOR YOUR MACHINE BELOW
|
||||
// CUSTOMIZE FOR YOUR MACHINE BELOW
|
||||
|
||||
// Enable this is you have a raptor 2.
|
||||
// Selects pin file, runout sensor and stock TMC Drivers automatically
|
||||
//#define RAPTOR2
|
||||
|
||||
/**
|
||||
* Enable if you replace the stepper drivers with TMC 2208. Be sure to remove MS3 jumper
|
||||
* underneath the stepper driver! Plug and Play will result in Stealth Chop 2 Mode enabled
|
||||
@@ -14,7 +18,9 @@
|
||||
//#define X_2208
|
||||
//#define X_SpreadCycle
|
||||
//#define Y_2208
|
||||
//#define Y_SpreadCyclebed
|
||||
//#define Y_SpreadCycle
|
||||
//#define Z_2208
|
||||
//#define Z_SpreadCycle
|
||||
//#define E_2208
|
||||
//#define E_SpreadCycle
|
||||
|
||||
@@ -41,7 +47,13 @@
|
||||
//ONLY MAKE CHANGES ABOVE FOR RELIABLE FUNCTION
|
||||
//ONLY MAKE CHANGES ABOVE FOR RELIABLE FUNCTION
|
||||
|
||||
|
||||
#if ENABLED(RAPTOR2)
|
||||
#define X_2208
|
||||
#define Y_2208
|
||||
#define Z_2208
|
||||
#define E_2208
|
||||
#define RunoutSensor
|
||||
#endif
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
@@ -177,7 +189,11 @@
|
||||
// The following define selects which electronics board you have.
|
||||
// Please choose the name from boards.h that matches your setup
|
||||
#ifndef MOTHERBOARD
|
||||
#define MOTHERBOARD BOARD_FORMBOT_RAPTOR
|
||||
#if ENABLED(RAPTOR2)
|
||||
#define MOTHERBOARD BOARD_FORMBOT_RAPTOR2
|
||||
#else
|
||||
#define MOTHERBOARD BOARD_FORMBOT_RAPTOR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Optional custom name for your RepStrap or other custom machine
|
||||
@@ -490,9 +506,15 @@
|
||||
|
||||
//120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
|
||||
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
|
||||
#define DEFAULT_bedKp 100.0
|
||||
#define DEFAULT_bedKi 15.0
|
||||
#define DEFAULT_bedKd 200.0
|
||||
#if(ENABLED(BED_AC))
|
||||
#define DEFAULT_bedKp 100.0
|
||||
#define DEFAULT_bedKi 15.0
|
||||
#define DEFAULT_bedKd 200.0
|
||||
#else
|
||||
#define DEFAULT_bedKp 10.00
|
||||
#define DEFAULT_bedKi .023
|
||||
#define DEFAULT_bedKd 305.4
|
||||
#endif
|
||||
|
||||
//120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
|
||||
//from pidautotune
|
||||
@@ -681,16 +703,25 @@
|
||||
* X, Y, Z, E0 [, E1[, E2[, E3[, E4]]]]
|
||||
*/
|
||||
#if(ENABLED(Y_2208))
|
||||
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 1600, 96 }
|
||||
#define Y_STEPSMM 80
|
||||
#else
|
||||
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 160, 1600, 96 }
|
||||
#define Y_STEPSMM 160
|
||||
#endif
|
||||
|
||||
#if(ENABLED(Z_2208))
|
||||
#define Z_STEPSMM 800
|
||||
#else
|
||||
#define Z_STEPSMM 1600
|
||||
#endif
|
||||
|
||||
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80,Y_STEPSMM , Z_STEPSMM, 96 }
|
||||
|
||||
/**
|
||||
* Default Max Feed Rate (mm/s)
|
||||
* Override with M203
|
||||
* X, Y, Z, E0 [, E1[, E2[, E3[, E4]]]]
|
||||
*/
|
||||
#define DEFAULT_MAX_FEEDRATE { 250, 150, 5, 25 }
|
||||
#define DEFAULT_MAX_FEEDRATE { 250, 120, 5, 25 }
|
||||
|
||||
/**
|
||||
* Default Max Acceleration (change/s) change = mm/s
|
||||
@@ -950,27 +981,31 @@
|
||||
|
||||
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
|
||||
#if(ENABLED(X_2208))
|
||||
#define INVERT_X_DIR true
|
||||
#define INVERT_X_DIR true
|
||||
#else
|
||||
#define INVERT_X_DIR false
|
||||
#define INVERT_X_DIR false
|
||||
#endif
|
||||
#if(ENABLED(Y_2208))
|
||||
#define INVERT_Y_DIR true
|
||||
#if(ENABLED(Y_2208))
|
||||
#define INVERT_Y_DIR true
|
||||
#else
|
||||
#define INVERT_Y_DIR false
|
||||
#define INVERT_Y_DIR false
|
||||
#endif
|
||||
#if(ENABLED(Z_2208))
|
||||
#define INVERT_Z_DIR false
|
||||
#else
|
||||
#define INVERT_Z_DIR true
|
||||
#endif
|
||||
#define INVERT_Z_DIR true
|
||||
|
||||
|
||||
// @section extruder
|
||||
|
||||
// For direct drive extruder v9 set to true, for geared extruder set to false.
|
||||
#if(ENABLED(E_2208))
|
||||
#define INVERT_E0_DIR false
|
||||
#define INVERT_E1_DIR false
|
||||
#define INVERT_E0_DIR false
|
||||
#define INVERT_E1_DIR true
|
||||
#else
|
||||
#define INVERT_E0_DIR true
|
||||
#define INVERT_E1_DIR true
|
||||
#define INVERT_E0_DIR true
|
||||
#define INVERT_E1_DIR false
|
||||
#endif
|
||||
#define INVERT_E2_DIR false
|
||||
#define INVERT_E3_DIR false
|
||||
@@ -1047,8 +1082,12 @@
|
||||
#endif
|
||||
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
|
||||
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
|
||||
#define FIL_RUNOUT_PIN 57
|
||||
#define FIL_RUNOUT_INVERTING true // set to true to invert the logic of the sensor.
|
||||
#if DISABLED(RAPTOR2)
|
||||
#define FIL_RUNOUT_PIN 57
|
||||
#define FIL_RUNOUT_INVERTING true // set to true to invert the logic of the sensor.
|
||||
#else
|
||||
#define FIL_RUNOUT_INVERTING false // set to true to invert the logic of the sensor.
|
||||
#endif
|
||||
#define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins.
|
||||
//#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins.
|
||||
#define FILAMENT_RUNOUT_SCRIPT "M600"
|
||||
@@ -1188,13 +1227,6 @@
|
||||
#define GRID_MAX_POINTS_X 10 // Don't use more than 15 points per axis, implementation limited.
|
||||
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
|
||||
|
||||
#define PROBE_PT_1_X 50 // Probing points for 3-Point leveling of the mesh
|
||||
#define PROBE_PT_1_Y 350
|
||||
#define PROBE_PT_2_X 50
|
||||
#define PROBE_PT_2_Y 50
|
||||
#define PROBE_PT_3_X 350
|
||||
#define PROBE_PT_3_Y 50
|
||||
|
||||
#define UBL_MESH_EDIT_MOVES_Z // Sophisticated users prefer no movement of nozzle
|
||||
#define UBL_SAVE_ACTIVE_ON_M500 // Save the currently active mesh in the current slot on M500
|
||||
|
||||
@@ -1220,12 +1252,12 @@
|
||||
* Override if the automatically selected points are inadequate.
|
||||
*/
|
||||
#if ENABLED(AUTO_BED_LEVELING_3POINT) || ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
//#define PROBE_PT_1_X 15
|
||||
//#define PROBE_PT_1_Y 180
|
||||
//#define PROBE_PT_2_X 15
|
||||
//#define PROBE_PT_2_Y 20
|
||||
//#define PROBE_PT_3_X 170
|
||||
//#define PROBE_PT_3_Y 20
|
||||
#define PROBE_PT_1_X 50 // Probing points for 3-Point leveling of the mesh
|
||||
#define PROBE_PT_1_Y 350
|
||||
#define PROBE_PT_2_X 50
|
||||
#define PROBE_PT_2_Y 50
|
||||
#define PROBE_PT_3_X 350
|
||||
#define PROBE_PT_3_Y 50
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -1273,6 +1305,7 @@
|
||||
// - If stepper drivers time out, it will need X and Y homing again before Z homing.
|
||||
// - Move the Z probe (or nozzle) to a defined XY point before Z Homing when homing all axes (G28).
|
||||
// - Prevent Z homing when the Z probe is outside bed area.
|
||||
//
|
||||
#define Z_SAFE_HOMING
|
||||
|
||||
#if ENABLED(Z_SAFE_HOMING)
|
||||
@@ -1506,7 +1539,7 @@
|
||||
*
|
||||
* View the current statistics with M78.
|
||||
*/
|
||||
//#define PRINTCOUNTER
|
||||
#define PRINTCOUNTER
|
||||
|
||||
//=============================================================================
|
||||
//============================= LCD and SD support ============================
|
||||
@@ -2056,7 +2089,7 @@
|
||||
* Set this manually if there are extra servos needing manual control.
|
||||
* Leave undefined or set to 0 to entirely disable the servo subsystem.
|
||||
*/
|
||||
//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
|
||||
#define NUM_SERVOS 1 // Servo index starts with 0 for M280 command
|
||||
|
||||
// Delay (in milliseconds) before the next move will start, to give the servo time to reach its target angle.
|
||||
// 300ms is a good value but you can try less delay.
|
||||
|
||||
+40
-15
@@ -237,7 +237,11 @@
|
||||
* Multiple extruders can be assigned to the same pin in which case
|
||||
* the fan will turn on when any selected extruder is above the threshold.
|
||||
*/
|
||||
#define E0_AUTO_FAN_PIN -1
|
||||
#if ENABLED(RAPTOR2)
|
||||
#define E0_AUTO_FAN_PIN 9
|
||||
#else
|
||||
#define E0_AUTO_FAN_PIN -1
|
||||
#endif
|
||||
#define E1_AUTO_FAN_PIN -1
|
||||
#define E2_AUTO_FAN_PIN -1
|
||||
#define E3_AUTO_FAN_PIN -1
|
||||
@@ -776,7 +780,7 @@
|
||||
* Mention @Sebastianv650 on GitHub to alert the author of any issues.
|
||||
*/
|
||||
#if(DISABLED(E_2208))
|
||||
#define LIN_ADVANCE
|
||||
#define LIN_ADVANCE
|
||||
#endif
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
#define LIN_ADVANCE_K 0.22 // Unit: mm compression per 1mm/s extruder speed
|
||||
@@ -787,10 +791,29 @@
|
||||
|
||||
#if ENABLED(MESH_BED_LEVELING) || ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
// Override the mesh area if the automatic (max) area is too large
|
||||
//#define MESH_MIN_X MESH_INSET
|
||||
//#define MESH_MIN_Y MESH_INSET
|
||||
//#define MESH_MAX_X X_BED_SIZE - (MESH_INSET)
|
||||
//#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
|
||||
#if( (X_PROBE_OFFSET_FROM_EXTRUDER + 15) > 0 )
|
||||
#define MESH_MIN_X (X_PROBE_OFFSET_FROM_EXTRUDER + 5)
|
||||
#else
|
||||
#define MESH_MIN_X 5
|
||||
#endif
|
||||
|
||||
#if( (X_BED_SIZE + X_PROBE_OFFSET_FROM_EXTRUDER - 10) < X_BED_SIZE)
|
||||
#define MESH_MAX_X (X_BED_SIZE + X_PROBE_OFFSET_FROM_EXTRUDER - 5)
|
||||
#else
|
||||
#define MESH_MAX_X (X_BED_SIZE - 10)
|
||||
#endif
|
||||
|
||||
#if ( (Y_PROBE_OFFSET_FROM_EXTRUDER + 10) > 10 )
|
||||
#define MESH_MIN_Y (Y_PROBE_OFFSET_FROM_EXTRUDER + 10)
|
||||
#else
|
||||
#define MESH_MIN_Y 20
|
||||
#endif
|
||||
|
||||
#if( (Y_BED_SIZE + Y_PROBE_OFFSET_FROM_EXTRUDER - 10) < Y_BED_SIZE)
|
||||
#define MESH_MAX_Y (Y_BED_SIZE + Y_PROBE_OFFSET_FROM_EXTRUDER - 10)
|
||||
#else
|
||||
#define MESH_MAX_Y (Y_BED_SIZE - 25)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -979,7 +1002,7 @@
|
||||
#define RETRACT_LENGTH 3 // Default retract length (positive mm)
|
||||
#define RETRACT_LENGTH_SWAP 13 // Default swap retract length (positive mm), for extruder change
|
||||
#define RETRACT_FEEDRATE 45 // Default feedrate for retracting (mm/s)
|
||||
#define RETRACT_ZLIFT 0 // Default retract Z-lift
|
||||
#define RETRACT_ZRAISE 0 // Default retract Z-lift
|
||||
#define RETRACT_RECOVER_LENGTH 0 // Default additional recover length (mm, added to retract length when recovering)
|
||||
#define RETRACT_RECOVER_LENGTH_SWAP 0 // Default additional swap recover length (mm, added to retract length when recovering from extruder change)
|
||||
#define RETRACT_RECOVER_FEEDRATE 8 // Default feedrate for recovering from retraction (mm/s)
|
||||
@@ -1021,7 +1044,7 @@
|
||||
// 0 to disable start loading and skip to fast load only
|
||||
#define FILAMENT_CHANGE_FAST_LOAD_FEEDRATE 6 // (mm/s) Load filament feedrate. This can be pretty fast.
|
||||
#define FILAMENT_CHANGE_FAST_LOAD_ACCEL 25 // (mm/s^2) Lower acceleration may allow a faster feedrate.
|
||||
#define FILAMENT_CHANGE_FAST_LOAD_LENGTH 5 // (mm) Load length of filament, from extruder gear to nozzle.
|
||||
#define FILAMENT_CHANGE_FAST_LOAD_LENGTH 2 // (mm) Load length of filament, from extruder gear to nozzle.
|
||||
// For Bowden, the full length of the tube and nozzle.
|
||||
// For direct drive, the full length of the nozzle.
|
||||
//#define ADVANCED_PAUSE_CONTINUOUS_PURGE // Purge continuously up to the purge length until interrupted.
|
||||
@@ -1381,17 +1404,19 @@
|
||||
*
|
||||
* See http://marlinfw.org/docs/configuration/laser_spindle.html for more config details.
|
||||
*/
|
||||
//#define SPINDLE_LASER_ENABLE
|
||||
#if ENABLED(RAPTOR2)
|
||||
#define SPINDLE_LASER_ENABLE
|
||||
#endif
|
||||
#if ENABLED(SPINDLE_LASER_ENABLE)
|
||||
|
||||
#define SPINDLE_LASER_ENABLE_INVERT false // set to "true" if the on/off function is reversed
|
||||
#define SPINDLE_LASER_PWM true // set to true if your controller supports setting the speed/power
|
||||
#define SPINDLE_LASER_ENABLE_INVERT true // set to "true" if the on/off function is reversed
|
||||
#define SPINDLE_LASER_PWM false // set to true if your controller supports setting the speed/power
|
||||
#define SPINDLE_LASER_PWM_INVERT true // set to "true" if the speed/power goes up when you want it to go slower
|
||||
#define SPINDLE_LASER_POWERUP_DELAY 5000 // delay in milliseconds to allow the spindle/laser to come up to speed/power
|
||||
#define SPINDLE_LASER_POWERDOWN_DELAY 5000 // delay in milliseconds to allow the spindle to stop
|
||||
#define SPINDLE_DIR_CHANGE true // set to true if your spindle controller supports changing spindle direction
|
||||
#define SPINDLE_LASER_POWERUP_DELAY 1 // delay in milliseconds to allow the spindle/laser to come up to speed/power
|
||||
#define SPINDLE_LASER_POWERDOWN_DELAY 1 // delay in milliseconds to allow the spindle to stop
|
||||
#define SPINDLE_DIR_CHANGE false // set to true if your spindle controller supports changing spindle direction
|
||||
#define SPINDLE_INVERT_DIR false
|
||||
#define SPINDLE_STOP_ON_DIR_CHANGE true // set to true if Marlin should stop the spindle before changing rotation direction
|
||||
#define SPINDLE_STOP_ON_DIR_CHANGE false // set to true if Marlin should stop the spindle before changing rotation direction
|
||||
|
||||
/**
|
||||
* The M3 & M4 commands use the following equation to convert PWM duty cycle to speed/power
|
||||
|
||||
+231
-159
@@ -89,8 +89,8 @@ WIRE ?= 0
|
||||
# this defines if U8GLIB is needed (may require RELOC_WORKAROUND)
|
||||
U8GLIB ?= 1
|
||||
|
||||
# this defines whether to include the Trinamic TMC2630Stepper
|
||||
TMC2630 ?= 1
|
||||
# this defines whether to include the Trinamic TMCStepper library
|
||||
TMC ?= 1
|
||||
|
||||
############
|
||||
# Try to automatically determine whether RELOC_WORKAROUND is needed based
|
||||
@@ -103,7 +103,7 @@ CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | c
|
||||
CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) )))
|
||||
ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1)
|
||||
@echo This version of GCC is likely broken. Enabling relocation workaround.
|
||||
RELOC_WORKAROUND = 1
|
||||
RELOC_WORKAROUND = 1
|
||||
endif
|
||||
|
||||
############################################################################
|
||||
@@ -195,7 +195,7 @@ else ifeq ($(HARDWARE_MOTHERBOARD),49)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),7)
|
||||
# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),71)
|
||||
MCU ?= atmega1280
|
||||
MCU ?= atmega1280
|
||||
# Azteeg X3
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),67)
|
||||
# Azteeg X3 Pro
|
||||
@@ -265,9 +265,9 @@ else ifeq ($(HARDWARE_MOTHERBOARD),75)
|
||||
#
|
||||
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),702)
|
||||
MCU ?= atmega1281
|
||||
MCU ?= atmega1281
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),25)
|
||||
MCU ?= atmega1281
|
||||
MCU ?= atmega1281
|
||||
|
||||
#
|
||||
# Sanguinololu and Derivatives - ATmega644P, ATmega1284P
|
||||
@@ -275,44 +275,44 @@ MCU ?= atmega1281
|
||||
|
||||
# Sanguinololu < 1.2
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),6)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
# Sanguinololu 1.2 and above
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),62)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
# Melzi
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),63)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
# Melzi with ATmega1284 (MaKr3d version)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),66)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
# Melzi Creality3D board (for CR-10 etc)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),89)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
# Melzi Malyan M150 board
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),92)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
# Tronxy X5S
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),505)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
# STB V1.1
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),64)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
# Azteeg X1
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),65)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
# Anet 1.0 (Melzi clone)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),69)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega1284p
|
||||
|
||||
#
|
||||
# Other ATmega644P, ATmega644, ATmega1284P
|
||||
@@ -320,52 +320,52 @@ MCU ?= atmega1284p
|
||||
|
||||
# Gen3 Monolithic Electronics
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),22)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
# Gen3+
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),9)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
# Gen6
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),5)
|
||||
HARDWARE_VARIANT ?= Gen6
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Gen6
|
||||
MCU ?= atmega644p
|
||||
# Gen6 deluxe
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),51)
|
||||
HARDWARE_VARIANT ?= Gen6
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Gen6
|
||||
MCU ?= atmega644p
|
||||
# Gen7 custom (Alfons3 Version)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),10)
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega644
|
||||
F_CPU ?= 20000000
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega644
|
||||
F_CPU ?= 20000000
|
||||
# Gen7 v1.1, v1.2
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),11)
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega644p
|
||||
F_CPU ?= 20000000
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega644p
|
||||
F_CPU ?= 20000000
|
||||
# Gen7 v1.3
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),12)
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega644p
|
||||
F_CPU ?= 20000000
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega644p
|
||||
F_CPU ?= 20000000
|
||||
# Gen7 v1.4
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),13)
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega1284p
|
||||
F_CPU ?= 20000000
|
||||
HARDWARE_VARIANT ?= Gen7
|
||||
MCU ?= atmega1284p
|
||||
F_CPU ?= 20000000
|
||||
# Alpha OMCA board
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),90)
|
||||
HARDWARE_VARIANT ?= SanguinoA
|
||||
MCU ?= atmega644
|
||||
HARDWARE_VARIANT ?= SanguinoA
|
||||
MCU ?= atmega644
|
||||
# Final OMCA board
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),91)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
# Sethi 3D_1
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),20)
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
HARDWARE_VARIANT ?= Sanguino
|
||||
MCU ?= atmega644p
|
||||
|
||||
#
|
||||
# Teensyduino - AT90USB1286, AT90USB1286P
|
||||
@@ -373,37 +373,49 @@ MCU ?= atmega644p
|
||||
|
||||
# Teensylu
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),8)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
# Printrboard (AT90USB1286)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),81)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
# Printrboard Revision F (AT90USB1286)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),811)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
# Brainwave (AT90USB646)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),82)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb646
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb646
|
||||
# Brainwave Pro (AT90USB1286)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),83)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
# SAV Mk-I (AT90USB1286)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),84)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
# Teensy++2.0 (AT90USB1286)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),85)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
# 5DPrint D8 Driver Board
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),88)
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
HARDWARE_VARIANT ?= Teensy
|
||||
MCU ?= at90usb1286
|
||||
|
||||
# UltiMachine Archim1 (with DRV8825 drivers)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1591)
|
||||
HARDWARE_VARIANT ?= archim
|
||||
MCPU = cortex-m3
|
||||
F_CPU = 84000000L
|
||||
IS_MCU = 0
|
||||
# UltiMachine Archim2 (with TMC2130 drivers)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1592)
|
||||
HARDWARE_VARIANT ?= archim
|
||||
MCPU = cortex-m3
|
||||
F_CPU = 84000000L
|
||||
IS_MCU = 0
|
||||
endif
|
||||
|
||||
# Be sure to regenerate speed_lookuptable.h with create_speed_lookuptable.py
|
||||
@@ -411,9 +423,22 @@ endif
|
||||
# Set to 16Mhz if not yet set.
|
||||
F_CPU ?= 16000000
|
||||
|
||||
# Set to arduino, ATmega2560 if not yet set.
|
||||
HARDWARE_VARIANT ?= arduino
|
||||
MCU ?= atmega2560
|
||||
# Set to microcontroller if IS_MCU not yet set
|
||||
IS_MCU ?= 1
|
||||
|
||||
ifeq ($(IS_MCU),1)
|
||||
# Set to arduino, ATmega2560 if not yet set.
|
||||
HARDWARE_VARIANT ?= arduino
|
||||
MCU ?= atmega2560
|
||||
|
||||
TOOL_PREFIX = avr
|
||||
MCU_FLAGS = -mmcu=$(MCU)
|
||||
SIZE_FLAGS = --mcu=$(MCU) -C
|
||||
else
|
||||
TOOL_PREFIX = arm-none-eabi
|
||||
CPU_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
SIZE_FLAGS = -A
|
||||
endif
|
||||
|
||||
# Arduino contained the main source code for the Arduino
|
||||
# Libraries, the "hardware variant" are for boards
|
||||
@@ -434,19 +459,19 @@ VPATH = .
|
||||
VPATH += $(BUILD_DIR)
|
||||
VPATH += $(HARDWARE_SRC)
|
||||
|
||||
# U8glib
|
||||
VPATH += $(ARDUINO_USER_DIR)/libraries/U8glib
|
||||
VPATH += $(ARDUINO_USER_DIR)/libraries/U8glib/clib
|
||||
|
||||
ifeq ($(HARDWARE_VARIANT), $(filter $(HARDWARE_VARIANT),arduino Teensy Sanguino))
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/libraries/LiquidCrystal/src
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/libraries/SPI
|
||||
endif
|
||||
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino
|
||||
ifeq ($(IS_MCU),1)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino
|
||||
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SoftwareSerial/src
|
||||
endif
|
||||
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidCrystal/src
|
||||
ifeq ($(LIQUID_TWI2), 1)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
|
||||
@@ -462,71 +487,90 @@ VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Adafruit_NeoPixel
|
||||
endif
|
||||
ifeq ($(U8GLIB), 1)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/clib
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/csrc
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/cppsrc
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/fntsrc
|
||||
endif
|
||||
ifeq ($(TMC2630), 1)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMC2130Stepper/src
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMC2130Stepper/src/source
|
||||
ifeq ($(TMC), 1)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMCStepper/src
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMCStepper/src/source
|
||||
endif
|
||||
|
||||
ifeq ($(HARDWARE_VARIANT), arduino)
|
||||
HARDWARE_SUB_VARIANT ?= mega
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/variants/$(HARDWARE_SUB_VARIANT)
|
||||
HARDWARE_SUB_VARIANT ?= mega
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/variants/$(HARDWARE_SUB_VARIANT)
|
||||
else ifeq ($(HARDWARE_VARIANT), Sanguino)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/variants/sanguino
|
||||
else ifeq ($(HARDWARE_VARIANT), archim)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/system/libsam
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/system/CMSIS/CMSIS/Include/
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/system/CMSIS/Device/ATMEL/
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/cores/arduino
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/cores/arduino/avr
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/cores/arduino/USB
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/libraries/Wire/src
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/libraries/SPI/src
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/libraries/U8glib/src/clib
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/variants/archim
|
||||
LDSCRIPT = $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/variants/archim/linker_scripts/gcc/flash.ld
|
||||
LDLIBS = $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/variants/archim/libsam_sam3x8e_gcc_rel.a
|
||||
else
|
||||
ifeq ($(HARDWARE_VARIANT), Sanguino)
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/variants/sanguino
|
||||
else
|
||||
HARDWARE_SUB_VARIANT ?= standard
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/$(HARDWARE_VARIANT)/variants/$(HARDWARE_SUB_VARIANT)
|
||||
endif
|
||||
HARDWARE_SUB_VARIANT ?= standard
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/$(HARDWARE_VARIANT)/variants/$(HARDWARE_SUB_VARIANT)
|
||||
endif
|
||||
|
||||
LIB_SRC = wiring.c \
|
||||
wiring_analog.c wiring_digital.c \
|
||||
wiring_pulse.c \
|
||||
wiring_shift.c WInterrupts.c hooks.c
|
||||
wiring_analog.c wiring_digital.c \
|
||||
wiring_shift.c WInterrupts.c hooks.c
|
||||
|
||||
ifeq ($(HARDWARE_VARIANT), archim)
|
||||
LIB_ASRC += wiring_pulse_asm.S
|
||||
else
|
||||
LIB_SRC += wiring_pulse.c
|
||||
endif
|
||||
|
||||
ifeq ($(HARDWARE_VARIANT), Teensy)
|
||||
LIB_SRC = wiring.c
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/teensy/cores/teensy
|
||||
LIB_SRC = wiring.c
|
||||
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/teensy/cores/teensy
|
||||
endif
|
||||
|
||||
LIB_CXXSRC = WMath.cpp WString.cpp Print.cpp SPI.cpp Tone.cpp
|
||||
LIB_CXXSRC = WMath.cpp WString.cpp Print.cpp SPI.cpp
|
||||
|
||||
ifeq ($(NEOPIXEL), 1)
|
||||
LIB_CXXSRC += Adafruit_NeoPixel.cpp
|
||||
LIB_CXXSRC += Adafruit_NeoPixel.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(LIQUID_TWI2), 0)
|
||||
LIB_CXXSRC += LiquidCrystal.cpp
|
||||
LIB_CXXSRC += LiquidCrystal.cpp
|
||||
else
|
||||
LIB_SRC += twi.c
|
||||
LIB_CXXSRC += Wire.cpp LiquidTWI2.cpp
|
||||
LIB_SRC += twi.c
|
||||
LIB_CXXSRC += Wire.cpp LiquidTWI2.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(WIRE), 1)
|
||||
LIB_SRC += twi.c
|
||||
LIB_CXXSRC += Wire.cpp
|
||||
LIB_SRC += twi.c
|
||||
LIB_CXXSRC += Wire.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(U8GLIB), 1)
|
||||
LIB_CXXSRC += U8glib.cpp
|
||||
LIB_SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c u8g_font_data.c
|
||||
LIB_CXXSRC += U8glib.cpp
|
||||
LIB_SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c u8g_font_6x13.c u8g_font_04b_03.c u8g_font_5x8.c
|
||||
endif
|
||||
|
||||
ifeq ($(TMC2630), 1)
|
||||
LIB_CXXSRC += TMC2130Stepper.cpp TMC2130Stepper_COOLCONF.cpp TMC2130Stepper_DRV_STATUS.cpp TMC2130Stepper_IHOLD_IRUN.cpp TMC2130Stepper_CHOPCONF.cpp TMC2130Stepper_GCONF.cpp TMC2130Stepper_PWMCONF.cpp SW_SPI.cpp
|
||||
ifeq ($(TMC), 1)
|
||||
LIB_CXXSRC += TMCStepper.cpp COOLCONF.cpp DRV_STATUS.cpp IHOLD_IRUN.cpp CHOPCONF.cpp GCONF.cpp PWMCONF.cpp DRV_CONF.cpp DRVCONF.cpp DRVCTRL.cpp DRVSTATUS.cpp ENCMODE.cpp RAMP_STAT.cpp SGCSCONF.cpp SHORT_CONF.cpp SMARTEN.cpp SW_MODE.cpp SW_SPI.cpp TMC2130Stepper.cpp TMC2208Stepper.cpp TMC2660Stepper.cpp TMC5130Stepper.cpp TMC5160Stepper.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(RELOC_WORKAROUND), 1)
|
||||
LD_PREFIX=-nodefaultlibs
|
||||
LD_SUFFIX=-lm -lgcc -lc -lgcc
|
||||
LD_PREFIX=-nodefaultlibs
|
||||
LD_SUFFIX=-lm -lgcc -lc -lgcc
|
||||
endif
|
||||
|
||||
#Check for Arduino 1.0.0 or higher and use the correct source files for that version
|
||||
ifeq ($(shell [ $(ARDUINO_VERSION) -ge 100 ] && echo true), true)
|
||||
LIB_CXXSRC += main.cpp
|
||||
LIB_CXXSRC += main.cpp
|
||||
else
|
||||
LIB_SRC += pins_arduino.c main.c
|
||||
LIB_SRC += pins_arduino.c main.c
|
||||
endif
|
||||
|
||||
FORMAT = ihex
|
||||
@@ -544,62 +588,81 @@ OPT = s
|
||||
DEFINES ?=
|
||||
|
||||
# Program settings
|
||||
CC = $(AVR_TOOLS_PATH)avr-gcc
|
||||
CXX = $(AVR_TOOLS_PATH)avr-g++
|
||||
OBJCOPY = $(AVR_TOOLS_PATH)avr-objcopy
|
||||
OBJDUMP = $(AVR_TOOLS_PATH)avr-objdump
|
||||
AR = $(AVR_TOOLS_PATH)avr-ar
|
||||
SIZE = $(AVR_TOOLS_PATH)avr-size
|
||||
NM = $(AVR_TOOLS_PATH)avr-nm
|
||||
CC = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-gcc
|
||||
CXX = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-g++
|
||||
OBJCOPY = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-objcopy
|
||||
OBJDUMP = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-objdump
|
||||
AR = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-ar
|
||||
SIZE = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-size
|
||||
NM = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-nm
|
||||
AVRDUDE = avrdude
|
||||
REMOVE = rm -f
|
||||
MV = mv -f
|
||||
|
||||
# Place -D or -U options here
|
||||
CDEFS = -DF_CPU=$(F_CPU) ${addprefix -D , $(DEFINES)}
|
||||
CDEFS = -DF_CPU=$(F_CPU) ${addprefix -D , $(DEFINES)} -DARDUINO=$(ARDUINO_VERSION)
|
||||
CXXDEFS = $(CDEFS)
|
||||
|
||||
ifeq ($(HARDWARE_VARIANT), Teensy)
|
||||
CDEFS += -DUSB_SERIAL
|
||||
LIB_SRC += usb.c pins_teensy.c
|
||||
LIB_CXXSRC += usb_api.cpp
|
||||
CDEFS += -DUSB_SERIAL
|
||||
LIB_SRC += usb.c pins_teensy.c
|
||||
LIB_CXXSRC += usb_api.cpp
|
||||
|
||||
else ifeq ($(HARDWARE_VARIANT), archim)
|
||||
CDEFS += -DARDUINO_SAM_ARCHIM -DARDUINO_ARCH_SAM -D__SAM3X8E__ -DUSB_VID=0x27b1 -DUSB_PID=0x0001 -DUSBCON '-DUSB_MANUFACTURER="UltiMachine"' '-DUSB_PRODUCT="Archim"'
|
||||
LIB_CXXSRC += variant.cpp IPAddress.cpp Reset.cpp RingBuffer.cpp Stream.cpp UARTClass.cpp USARTClass.cpp abi.cpp new.cpp watchdog.cpp CDC.cpp PluggableUSB.cpp USBCore.cpp
|
||||
LIB_SRC += cortex_handlers.c iar_calls_sam3.c syscalls_sam3.c dtostrf.c itoa.c
|
||||
|
||||
ifeq ($(U8GLIB), 1)
|
||||
LIB_SRC += u8g_com_api.c u8g_pb32h1.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Add all the source directories as include directories too
|
||||
CINCS = ${addprefix -I ,${VPATH}}
|
||||
CXXINCS = ${addprefix -I ,${VPATH}}
|
||||
|
||||
# Silence warnings for library code (won't work for .h files, unfortunately)
|
||||
LIBWARN = -w -Wno-packed-bitfield-compat
|
||||
|
||||
# Compiler flag to set the C/CPP Standard level.
|
||||
CSTANDARD = -std=gnu99
|
||||
CXXSTANDARD = -std=gnu++11
|
||||
CDEBUG = -g$(DEBUG)
|
||||
CWARN = -Wall -Wstrict-prototypes
|
||||
CTUNING = -w -fsigned-char -funsigned-bitfields -fpack-struct \
|
||||
-fshort-enums -ffunction-sections -fdata-sections -flto \
|
||||
-DARDUINO=$(ARDUINO_VERSION)
|
||||
CWARN = -Wall -Wstrict-prototypes -Wno-packed-bitfield-compat -Wno-pragmas
|
||||
CXXWARN = -Wall -Wno-packed-bitfield-compat -Wno-pragmas
|
||||
CTUNING = -fsigned-char -funsigned-bitfields -fpack-struct -fno-exceptions \
|
||||
-fshort-enums -ffunction-sections -fdata-sections
|
||||
ifneq ($(HARDWARE_MOTHERBOARD),)
|
||||
CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
|
||||
CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
|
||||
endif
|
||||
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
|
||||
CEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics
|
||||
|
||||
CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) $(CSTANDARD)
|
||||
CXXFLAGS := $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) $(CXXSTANDARD)
|
||||
CXXEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics -fno-rtti
|
||||
CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CEXTRA) $(CTUNING) $(CSTANDARD)
|
||||
CXXFLAGS := $(CDEFS) $(CINCS) -O$(OPT) $(CXXEXTRA) $(CTUNING) $(CXXSTANDARD)
|
||||
ASFLAGS := $(CDEFS)
|
||||
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
|
||||
LDFLAGS = -lm
|
||||
|
||||
ifeq ($(HARDWARE_VARIANT), archim)
|
||||
LD_PREFIX = -Wl,--gc-sections,-Map,Marlin.ino.map,--cref,--check-sections,--entry=Reset_Handler,--unresolved-symbols=report-all,--warn-common,--warn-section-align
|
||||
LD_SUFFIX = $(LDLIBS)
|
||||
LDFLAGS = -lm -gcc -T$(LDSCRIPT) -u _sbrk -u link -u _close -u _fstat -u _isatty -u _lseek -u _read -u _write -u _exit -u kill -u _getpid
|
||||
else
|
||||
LD_PREFIX = -Wl,--gc-sections,--relax
|
||||
LDFLAGS = -lm
|
||||
CTUNING += -flto
|
||||
endif
|
||||
|
||||
# Programming support using avrdude. Settings and variables.
|
||||
AVRDUDE_PORT = $(UPLOAD_PORT)
|
||||
AVRDUDE_WRITE_FLASH = -Uflash:w:$(BUILD_DIR)/$(TARGET).hex:i
|
||||
ifeq ($(shell uname -s), Linux)
|
||||
AVRDUDE_CONF = /etc/avrdude/avrdude.conf
|
||||
AVRDUDE_CONF = /etc/avrdude/avrdude.conf
|
||||
else
|
||||
AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf
|
||||
AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf
|
||||
endif
|
||||
AVRDUDE_FLAGS = -D -C$(AVRDUDE_CONF) \
|
||||
-p$(MCU) -P$(AVRDUDE_PORT) -c$(AVRDUDE_PROGRAMMER) \
|
||||
-b$(UPLOAD_RATE)
|
||||
-p$(MCU) -P$(AVRDUDE_PORT) -c$(AVRDUDE_PROGRAMMER) \
|
||||
-b$(UPLOAD_RATE)
|
||||
|
||||
# Since Marlin 2.0, the source files may be distributed into several
|
||||
# different directories, so it is necessary to find them recursively
|
||||
@@ -619,17 +682,17 @@ LST = $(LIB_ASRC:.S=.lst) $(LIB_CXXSRC:.cpp=.lst) $(LIB_SRC:.c=.lst)
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
|
||||
ALL_CXXFLAGS = -mmcu=$(MCU) $(CXXFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -x assembler-with-cpp $(ASFLAGS)
|
||||
ALL_CFLAGS = $(MCU_FLAGS) $(CPU_FLAGS) $(CFLAGS) -I.
|
||||
ALL_CXXFLAGS = $(MCU_FLAGS) $(CPU_FLAGS) $(CXXFLAGS)
|
||||
ALL_ASFLAGS = $(MCU_FLAGS) $(CPU_FLAGS) $(ASFLAGS) -x assembler-with-cpp
|
||||
|
||||
# set V=1 (eg, "make V=1") to print the full commands etc.
|
||||
ifneq ($V,1)
|
||||
Pecho=@echo
|
||||
P=@
|
||||
Pecho=@echo
|
||||
P=@
|
||||
else
|
||||
Pecho=@:
|
||||
P=
|
||||
Pecho=@:
|
||||
P=
|
||||
endif
|
||||
|
||||
# Create required build hierarchy if it does not exist
|
||||
@@ -639,9 +702,10 @@ $(shell mkdir -p $(dir $(OBJ)))
|
||||
# Default target.
|
||||
all: sizeafter
|
||||
|
||||
build: elf hex
|
||||
build: elf hex bin
|
||||
|
||||
elf: $(BUILD_DIR)/$(TARGET).elf
|
||||
bin: $(BUILD_DIR)/$(TARGET).bin
|
||||
hex: $(BUILD_DIR)/$(TARGET).hex
|
||||
eep: $(BUILD_DIR)/$(TARGET).eep
|
||||
lss: $(BUILD_DIR)/$(TARGET).lss
|
||||
@@ -658,9 +722,9 @@ ifeq (${AVRDUDE_PROGRAMMER}, arduino)
|
||||
stty -hup < $(UPLOAD_PORT); true
|
||||
endif
|
||||
|
||||
# Display size of file.
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex
|
||||
ELFSIZE = $(SIZE) --mcu=$(MCU) -C $(BUILD_DIR)/$(TARGET).elf; \
|
||||
ELFSIZE = $(SIZE) $(SIZE_FLAGS) $(BUILD_DIR)/$(TARGET).elf; \
|
||||
$(SIZE) $(BUILD_DIR)/$(TARGET).elf
|
||||
sizebefore:
|
||||
$P if [ -f $(BUILD_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
|
||||
@@ -671,10 +735,10 @@ sizeafter: build
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
|
||||
COFFCONVERT=$(OBJCOPY) --debugging \
|
||||
--change-section-address .data-0x800000 \
|
||||
--change-section-address .bss-0x800000 \
|
||||
--change-section-address .noinit-0x800000 \
|
||||
--change-section-address .eeprom-0x810000
|
||||
--change-section-address .data-0x800000 \
|
||||
--change-section-address .bss-0x800000 \
|
||||
--change-section-address .noinit-0x800000 \
|
||||
--change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
coff: $(BUILD_DIR)/$(TARGET).elf
|
||||
@@ -685,16 +749,20 @@ extcoff: $(TARGET).elf
|
||||
$(COFFCONVERT) -O coff-ext-avr $(BUILD_DIR)/$(TARGET).elf $(TARGET).cof
|
||||
|
||||
|
||||
.SUFFIXES: .elf .hex .eep .lss .sym
|
||||
.SUFFIXES: .elf .hex .eep .lss .sym .bin
|
||||
.PRECIOUS: .o
|
||||
|
||||
.elf.hex:
|
||||
$(Pecho) " COPY $@"
|
||||
$P $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
.elf.bin:
|
||||
$(Pecho) " COPY $@"
|
||||
$P $(OBJCOPY) -O binary -R .eeprom $< $@
|
||||
|
||||
.elf.eep:
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
.elf.lss:
|
||||
@@ -704,32 +772,36 @@ extcoff: $(TARGET).elf
|
||||
.elf.sym:
|
||||
$(NM) -n $< > $@
|
||||
|
||||
# Link: create ELF output file from library.
|
||||
# Link: create ELF output file from library.
|
||||
|
||||
$(BUILD_DIR)/$(TARGET).elf: $(OBJ) Configuration.h
|
||||
$(Pecho) " CXX $@"
|
||||
$P $(CC) $(LD_PREFIX) $(ALL_CXXFLAGS) -Wl,--gc-sections,--relax -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX)
|
||||
$P $(CC) $(LD_PREFIX) $(ALL_CXXFLAGS) -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX)
|
||||
|
||||
# Object files that were found in "src" will be stored in $(BUILD_DIR)
|
||||
# in directories that mirror the structure of "src"
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c Configuration.h Configuration_adv.h $(MAKEFILE)
|
||||
$(Pecho) " CC $<"
|
||||
$P $(CC) -MMD -c $(ALL_CFLAGS) $< -o $@
|
||||
$P $(CC) -MMD -c $(ALL_CFLAGS) $(CWARN) $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: %.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
|
||||
$(Pecho) " CXX $<"
|
||||
$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
|
||||
$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $(CXXWARN) $< -o $@
|
||||
|
||||
# Object files for Arduino libs will be created in $(BUILD_DIR)/arduino
|
||||
|
||||
$(BUILD_DIR)/arduino/%.o: %.c Configuration.h Configuration_adv.h $(MAKEFILE)
|
||||
$(Pecho) " CC $<"
|
||||
$P $(CC) -MMD -c $(ALL_CFLAGS) $< -o $@
|
||||
$P $(CC) -MMD -c $(ALL_CFLAGS) $(LIBWARN) $< -o $@
|
||||
|
||||
$(BUILD_DIR)/arduino/%.o: %.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
|
||||
$(Pecho) " CXX $<"
|
||||
$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
|
||||
$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $(LIBWARN) $< -o $@
|
||||
|
||||
$(BUILD_DIR)/arduino/%.o: %.S $(MAKEFILE)
|
||||
$(Pecho) " CXX $<"
|
||||
$P $(CXX) -MMD -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
# Target: clean project.
|
||||
clean:
|
||||
@@ -737,7 +809,7 @@ clean:
|
||||
$P rm -rf $(BUILD_DIR)
|
||||
|
||||
|
||||
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
|
||||
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
|
||||
|
||||
# Automaticaly include the dependency files created by gcc
|
||||
-include ${patsubst %.o, %.d, ${OBJ}}
|
||||
|
||||
+39
-425
@@ -30,431 +30,45 @@
|
||||
* http://marlinfw.org/tools/u8glib/converter.html
|
||||
*/
|
||||
|
||||
//
|
||||
// Status Screen Logo bitmap
|
||||
//
|
||||
#define STATUS_LOGO_Y 3
|
||||
#define STATUS_LOGO_WIDTH 24
|
||||
|
||||
//============================================
|
||||
|
||||
#define STATUS_SCREENWIDTH 128
|
||||
|
||||
#define STATUS_SCREEN_HOTEND_TEXT_X(E) (41 + (E) * 20)
|
||||
|
||||
#define STATUS_SCREEN_BED_TEXT_X (HOTENDS > 1 ? 81 : 73)
|
||||
|
||||
#define FAN_ANIM_FRAMES 3
|
||||
#define STATUS_SCREEN_FAN_TEXT_X (FAN_ANIM_FRAMES == 3 ? 103 : 105)
|
||||
#define STATUS_SCREEN_FAN_TEXT_Y (FAN_ANIM_FRAMES > 2 ? 28 : 27)
|
||||
|
||||
//============================================
|
||||
const unsigned char status_logo_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,
|
||||
B10000000,B00000000,B00000001,
|
||||
B10001110,B00000000,B11100001,
|
||||
B10011111,B00000001,B11110001,
|
||||
B10010011,B10000001,B00111001,
|
||||
B10011111,B10000001,B11111001,
|
||||
B10011111,B10000001,B11111001,
|
||||
B10011111,B10111001,B11111001,
|
||||
B10001111,B00101000,B11110001,
|
||||
B10000000,B00111000,B00000001,
|
||||
B10000000,B00000000,B00000001,
|
||||
B10011111,B11111111,B11111001,
|
||||
B10010001,B01110100,B10011001,
|
||||
B10011011,B00000110,B10101001,
|
||||
B10011011,B01010100,B10101001,
|
||||
B10011011,B01010110,B10101001,
|
||||
B10011011,B01010100,B10011001,
|
||||
B10011111,B11111111,B11111001,
|
||||
B11111111,B11111111,B11111111
|
||||
};
|
||||
|
||||
//
|
||||
// Use default bitmaps
|
||||
//
|
||||
#define STATUS_HOTEND_ANIM
|
||||
#define STATUS_BED_ANIM
|
||||
#if HOTENDS < 2
|
||||
|
||||
#if FAN_ANIM_FRAMES <= 2
|
||||
|
||||
const unsigned char status_screen0_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B00111001,B11001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11111111,B11101000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11000111,B11101000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111111,B11101000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100111,B00111001,B11101000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B00111000,B01101000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B01111100,B00101000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B01111100,B00011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B11111100,B00011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
const unsigned char status_screen1_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100001,B11111111,B10001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100011,B11111111,B00001000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00111111,B11000111,B10001000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B11000111,B11001000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110111,B10000111,B11011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B00000011,B11011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000010,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
#elif FAN_ANIM_FRAMES == 3
|
||||
|
||||
|
||||
const unsigned char status_screen0_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B00111001,B11001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11111111,B11101000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11000111,B11101000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111111,B11101000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100111,B00111001,B11101000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B00111000,B01101000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B01111100,B00101000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B01111100,B00011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B11111100,B00011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
|
||||
const unsigned char status_screen1_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00001111,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110100,B00011111,B11011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110110,B00011111,B10011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00011111,B00001000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10011110,B00001000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111100,B00001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11011100,B00001000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100111,B11101111,B11001000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01110111,B11101000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100000,B01111111,B11101000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B11110011,B11101000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100001,B11110001,B11101000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110011,B11110000,B11011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B11110000,B01011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11100000,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
const unsigned char status_screen2_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100001,B11111111,B10001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100011,B11111111,B00001000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00111111,B11000111,B10001000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B11000111,B11001000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110111,B10000111,B11011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B00000011,B11011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000010,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
#elif FAN_ANIM_FRAMES == 4
|
||||
|
||||
const unsigned char status_screen0_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B00111001,B11001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11111111,B11101000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11000111,B11101000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111111,B11101000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100111,B00111001,B11101000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B00111000,B01101000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B01111100,B00101000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B01111100,B00011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B11111100,B00011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
const unsigned char status_screen1_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00001111,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110100,B00011111,B11011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110110,B00011111,B10011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00011111,B00001000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10011110,B00001000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111100,B00001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11011100,B00001000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100111,B11101111,B11001000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01110111,B11101000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100000,B01111111,B11101000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B11110011,B11101000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100001,B11110001,B11101000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110011,B11110000,B11011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B11110000,B01011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11100000,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
const unsigned char status_screen2_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100001,B11111111,B10001000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01101100,B00001000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100011,B11111111,B00001000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00111111,B11000111,B10001000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B11000111,B11001000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110111,B10000111,B11011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B00000011,B11011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000010,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
|
||||
const unsigned char status_screen3_bmp[] PROGMEM = {
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11110000,B00111000,
|
||||
B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
|
||||
B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100001,B11100001,B11101000,
|
||||
B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B11110011,B11101000,
|
||||
B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01111111,B11101000,
|
||||
B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01110111,B11101000,
|
||||
B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101000,B11101110,B00101000,
|
||||
B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11011100,B00001000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00101111,B11111100,B00001000,
|
||||
B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B10011110,B00001000,
|
||||
B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B00001111,B00001000,
|
||||
B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B00001111,B00011000,
|
||||
B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B00001111,B00011000,
|
||||
B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00011111,B00111000,
|
||||
B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#else // HOTENDS >= 2
|
||||
|
||||
#if FAN_ANIM_FRAMES <= 2
|
||||
|
||||
const unsigned char status_screen0_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11110000,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B11111100,B00110000,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B11111100,B00010000,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B01111000,B00010000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B00110000,B00010000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00000000,B11010000,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00101110,B00110001,B11010000,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00101111,B01111011,B11010000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00101111,B01111011,B11010000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00101110,B00110001,B11010000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00101100,B00000000,B11010000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00100000,B00110000,B00010000,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00100000,B01111000,B00010000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00100000,B11111100,B00010000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110000,B11111100,B00110000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11110000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000
|
||||
};
|
||||
const unsigned char status_screen1_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11110000,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110011,B10000111,B00110000,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B10000111,B10010000,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10000111,B11010000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10000111,B11010000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00000011,B11010000,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00100000,B00110000,B00010000,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00100000,B01111000,B00010000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00100000,B01111000,B00010000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00100000,B00110000,B00010000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00101111,B00000011,B11010000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00101111,B10000111,B11010000,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00101111,B10000111,B11010000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00100111,B10000111,B10010000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110011,B10000111,B00110000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11110000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000
|
||||
};
|
||||
|
||||
#elif FAN_ANIM_FRAMES == 3
|
||||
|
||||
const unsigned char status_screen0_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11000000,B00011111,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B00100000,B00100111,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B11110000,B01111011,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B11110000,B01111011,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000101,B11111000,B11111101,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B11111000,B11111001,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00000100,B00111111,B11100001,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00000100,B00001111,B10000001,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00000100,B00001111,B10000001,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00000100,B00001111,B10000001,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00000100,B00111111,B11100001,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00000100,B11111000,B11111001,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00000101,B11111000,B11111101,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00000110,B11110000,B01111011,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00000110,B11110000,B01111011,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000111,B00100000,B00100111,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00000111,B11000000,B00011111,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000111,B11111111,B11111111
|
||||
};
|
||||
const unsigned char status_screen1_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11000110,B00011111,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B00111110,B00000111,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B00111110,B00000011,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B00011110,B00000011,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00011110,B00001101,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00000110,B00111101,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00000100,B00000111,B00111101,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00000100,B00001111,B11111111,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00000111,B11111111,B11111111,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00000111,B11111111,B10000001,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00000101,B11100111,B00000001,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00000101,B11000011,B00000001,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00000101,B10000011,B11000001,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00000110,B00000011,B11000011,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00000110,B00000011,B11100011,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000111,B00000011,B11100111,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00000111,B11000011,B00011111,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000111,B11111111,B11111111
|
||||
};
|
||||
const unsigned char status_screen2_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11000011,B00011111,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B00000011,B11100111,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B00000011,B11110011,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B10000011,B11100011,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000101,B11000011,B11000001,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000101,B11100011,B10000001,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00000101,B11110111,B00000001,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00000111,B11111111,B10000001,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00000111,B11111111,B11111111,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00000100,B00001111,B11111111,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00000100,B00000111,B01111101,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00000100,B00001110,B00111101,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00000100,B00011110,B00011101,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00000110,B00111110,B00001011,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00000110,B01111110,B00000011,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000111,B00111110,B00000111,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00000111,B11000110,B00011111,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000111,B11111111,B11111111
|
||||
};
|
||||
|
||||
#elif FAN_ANIM_FRAMES == 4
|
||||
|
||||
const unsigned char status_screen0_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00101111,B00111001,B11001000,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00101111,B11111111,B11101000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00101111,B11000111,B11101000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00101111,B11111111,B11101000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00100111,B00111001,B11101000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00100000,B00111000,B01101000,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00100000,B01111100,B00101000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110000,B01111100,B00011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110000,B11111100,B00011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000000,B11111000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
const unsigned char status_screen1_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00001111,B00111000,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110100,B00011111,B11011000,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110110,B00011111,B10011000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00011111,B00001000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10011110,B00001000,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00101111,B11111100,B00001000,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00101111,B11011100,B00001000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00100111,B11101111,B11001000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00100000,B01110111,B11101000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00100000,B01111111,B11101000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00100000,B11110011,B11101000,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00100001,B11110001,B11101000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110011,B11110000,B11011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110111,B11110000,B01011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111001,B11100000,B00111000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000000,B11111000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
const unsigned char status_screen2_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00100001,B11111111,B10001000,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00100000,B01101100,B00001000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00100000,B01101100,B00001000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00100000,B01101100,B00001000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00100011,B11111111,B00001000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00111111,B11000111,B10001000,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00101111,B11000111,B11001000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110111,B10000111,B11011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110111,B00000011,B11011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000010,B11111000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
const unsigned char status_screen3_bmp[] PROGMEM = {
|
||||
B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
|
||||
B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
|
||||
B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11110000,B00111000,
|
||||
B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
|
||||
B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100001,B11100001,B11101000,
|
||||
B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B11110011,B11101000,
|
||||
B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00100000,B01111111,B11101000,
|
||||
B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00100000,B01110111,B11101000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00101000,B11101110,B00101000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00101111,B11011100,B00001000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00101111,B11111100,B00001000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00101111,B10011110,B00001000,
|
||||
B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00101111,B00001111,B00001000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110000,B00001111,B00011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110000,B00001111,B00011000,
|
||||
B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00011111,B00111000,
|
||||
B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000000,B11111000,
|
||||
B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // HOTENDS >= 2
|
||||
#define STATUS_LOGO_X 8
|
||||
#define STATUS_HEATERS_X 40
|
||||
#define STATUS_BED_X 72
|
||||
#else
|
||||
#define STATUS_LOGO_X 0
|
||||
#define STATUS_HEATERS_X 32
|
||||
#define STATUS_BED_X 80
|
||||
#endif
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _HAL_AVR_H_
|
||||
#define _HAL_AVR_H_
|
||||
#pragma once
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
@@ -79,16 +77,32 @@ typedef int8_t pin_t;
|
||||
|
||||
//extern uint8_t MCUSR;
|
||||
|
||||
#define NUM_SERIAL 1
|
||||
|
||||
// Serial ports
|
||||
#ifdef USBCON
|
||||
#if ENABLED(BLUETOOTH)
|
||||
#define MYSERIAL0 bluetoothSerial
|
||||
#else
|
||||
#define MYSERIAL0 Serial
|
||||
#endif
|
||||
#define NUM_SERIAL 1
|
||||
#else
|
||||
#define MYSERIAL0 customizedSerial
|
||||
#if !WITHIN(SERIAL_PORT, -1, 3)
|
||||
#error "SERIAL_PORT must be from -1 to 3"
|
||||
#endif
|
||||
|
||||
#define MYSERIAL0 customizedSerial1
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if !WITHIN(SERIAL_PORT_2, -1, 3)
|
||||
#error "SERIAL_PORT_2 must be from -1 to 3"
|
||||
#elif SERIAL_PORT_2 == SERIAL_PORT
|
||||
#error "SERIAL_PORT_2 must be different than SERIAL_PORT"
|
||||
#endif
|
||||
#define NUM_SERIAL 2
|
||||
#define MYSERIAL1 customizedSerial2
|
||||
#else
|
||||
#define NUM_SERIAL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -358,5 +372,3 @@ inline void HAL_adc_init(void) {
|
||||
|
||||
// AVR compatibility
|
||||
#define strtof strtod
|
||||
|
||||
#endif // _HAL_AVR_H_
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
|
||||
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
|
||||
* Modified 10 June 2018 by Eduardo José Tagle (See #10991)
|
||||
* Templatized 01 October 2018 by Eduardo José Tagle to allow multiple instances
|
||||
*/
|
||||
|
||||
#ifdef __AVR__
|
||||
@@ -42,62 +43,26 @@
|
||||
#include "MarlinSerial.h"
|
||||
#include "../../Marlin.h"
|
||||
|
||||
struct ring_buffer_r {
|
||||
unsigned char buffer[RX_BUFFER_SIZE];
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
};
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
struct ring_buffer_t {
|
||||
unsigned char buffer[TX_BUFFER_SIZE];
|
||||
volatile uint8_t head, tail;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if UART_PRESENT(SERIAL_PORT)
|
||||
ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
|
||||
#endif
|
||||
static bool _written;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
|
||||
XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
// XON / XOFF character definitions
|
||||
constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
|
||||
uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
uint8_t rx_dropped_bytes = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
uint8_t rx_buffer_overruns = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
uint8_t rx_framing_errors = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
ring_buffer_pos_t rx_max_enqueued = 0;
|
||||
#endif
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_r MarlinSerial<Cfg>::rx_buffer = { 0, 0, { 0 } };
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_t MarlinSerial<Cfg>::tx_buffer = { 0 };
|
||||
template<typename Cfg> bool MarlinSerial<Cfg>::_written = false;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::xon_xoff_state = MarlinSerial<Cfg>::XON_XOFF_CHAR_SENT | MarlinSerial<Cfg>::XON_CHAR;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_dropped_bytes = 0;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_buffer_overruns = 0;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_framing_errors = 0;
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::rx_max_enqueued = 0;
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() asm volatile("": : :"memory");
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../../feature/emergency_parser.h"
|
||||
#endif
|
||||
#include "../../feature/emergency_parser.h"
|
||||
|
||||
// "Atomically" read the RX head index value without disabling interrupts:
|
||||
// This MUST be called with RX interrupts enabled, and CAN'T be called
|
||||
// from the RX ISR itself!
|
||||
FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head() {
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::atomic_read_rx_head() {
|
||||
if (Cfg::RX_SIZE > 256) {
|
||||
// Keep reading until 2 consecutive reads return the same value,
|
||||
// meaning there was no update in-between caused by an interrupt.
|
||||
// This works because serial RX interrupts happen at a slower rate
|
||||
@@ -111,23 +76,25 @@
|
||||
sw_barrier();
|
||||
} while (vold != vnew);
|
||||
return vnew;
|
||||
#else
|
||||
}
|
||||
else {
|
||||
// With an 8bit index, reads are always atomic. No need for special handling
|
||||
return rx_buffer.head;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
static volatile bool rx_tail_value_not_stable = false;
|
||||
static volatile uint16_t rx_tail_value_backup = 0;
|
||||
#endif
|
||||
template<typename Cfg>
|
||||
volatile bool MarlinSerial<Cfg>::rx_tail_value_not_stable = false;
|
||||
template<typename Cfg>
|
||||
volatile uint16_t MarlinSerial<Cfg>::rx_tail_value_backup = 0;
|
||||
|
||||
// Set RX tail index, taking into account the RX ISR could interrupt
|
||||
// the write to this variable in the middle - So a backup strategy
|
||||
// is used to ensure reads of the correct values.
|
||||
// -Must NOT be called from the RX ISR -
|
||||
FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value) {
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::atomic_set_rx_tail(typename MarlinSerial<Cfg>::ring_buffer_pos_t value) {
|
||||
if (Cfg::RX_SIZE > 256) {
|
||||
// Store the new value in the backup
|
||||
rx_tail_value_backup = value;
|
||||
sw_barrier();
|
||||
@@ -140,29 +107,29 @@
|
||||
// Signal the new value is completely stored into the value
|
||||
rx_tail_value_not_stable = false;
|
||||
sw_barrier();
|
||||
#else
|
||||
}
|
||||
else
|
||||
rx_buffer.tail = value;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get the RX tail index, taking into account the read could be
|
||||
// interrupting in the middle of the update of that index value
|
||||
// -Called from the RX ISR -
|
||||
FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail() {
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::atomic_read_rx_tail() {
|
||||
if (Cfg::RX_SIZE > 256) {
|
||||
// If the true index is being modified, return the backup value
|
||||
if (rx_tail_value_not_stable) return rx_tail_value_backup;
|
||||
#endif
|
||||
}
|
||||
// The true index is stable, return it
|
||||
return rx_buffer.tail;
|
||||
}
|
||||
|
||||
// (called with RX interrupts disabled)
|
||||
FORCE_INLINE void store_rxd_char() {
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::store_rxd_char() {
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
static EmergencyParser::State emergency_state; // = EP_RESET
|
||||
#endif
|
||||
static EmergencyParser::State emergency_state; // = EP_RESET
|
||||
|
||||
// Get the tail - Nothing can alter its value while this ISR is executing, but there's
|
||||
// a chance that this ISR interrupted the main process while it was updating the index.
|
||||
@@ -173,27 +140,17 @@
|
||||
ring_buffer_pos_t h = rx_buffer.head;
|
||||
|
||||
// Get the next element
|
||||
ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// This must read the M_UCSRxA register before reading the received byte to detect error causes
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
if (TEST(M_UCSRxA, M_DORx) && !++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
if (TEST(M_UCSRxA, M_DORx) && !++rx_buffer_overruns) --rx_buffer_overruns;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
if (TEST(M_UCSRxA, M_FEx) && !++rx_framing_errors) --rx_framing_errors;
|
||||
#endif
|
||||
// This must read the R_UCSRA register before reading the received byte to detect error causes
|
||||
if (Cfg::DROPPED_RX && B_DOR && !++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
if (Cfg::RX_OVERRUNS && B_DOR && !++rx_buffer_overruns) --rx_buffer_overruns;
|
||||
if (Cfg::RX_FRAMING_ERRORS && B_FE && !++rx_framing_errors) --rx_framing_errors;
|
||||
|
||||
// Read the character from the USART
|
||||
uint8_t c = M_UDRx;
|
||||
uint8_t c = R_UDR;
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(emergency_state, c);
|
||||
#endif
|
||||
if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the RX FIFO is
|
||||
@@ -202,29 +159,28 @@
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
if (Cfg::MAX_RX_QUEUED) {
|
||||
// Calculate count of bytes stored into the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Keep track of the maximum count of enqueued bytes
|
||||
NOLESS(rx_max_enqueued, rx_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
if (Cfg::XONOFF) {
|
||||
// If the last char that was sent was an XON
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
|
||||
|
||||
// Bytes stored into the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// If over 12.5% of RX buffer capacity, send XOFF before running out of
|
||||
// RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
|
||||
// and stop sending bytes. This translates to 13mS propagation time.
|
||||
if (rx_count >= (RX_BUFFER_SIZE) / 8) {
|
||||
if (rx_count >= (Cfg::RX_SIZE) / 8) {
|
||||
|
||||
// At this point, definitely no TX interrupt was executing, since the TX ISR can't be preempted.
|
||||
// Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
|
||||
@@ -238,19 +194,17 @@
|
||||
// Wait until the TX register becomes empty and send it - Here there could be a problem
|
||||
// - While waiting for the TX register to empty, the RX register could receive a new
|
||||
// character. This must also handle that situation!
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) {
|
||||
while (!B_UDRE) {
|
||||
|
||||
if (TEST(M_UCSRxA,M_RXCx)) {
|
||||
if (B_RXC) {
|
||||
// A char arrived while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = M_UDRx;
|
||||
c = R_UDR;
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(emergency_state, c);
|
||||
#endif
|
||||
if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
@@ -259,19 +213,18 @@
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
M_UDRx = XOFF_CHAR;
|
||||
R_UDR = XOFF_CHAR;
|
||||
|
||||
// Clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
B_TXC = 1;
|
||||
|
||||
// At this point there could be a race condition between the write() function
|
||||
// and this sending of the XOFF char. This interrupt could happen between the
|
||||
@@ -280,19 +233,18 @@
|
||||
// sure the write() function will succeed is to wait for the XOFF char to be
|
||||
// completely sent. Since an extra character could be received during the wait
|
||||
// it must also be handled!
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) {
|
||||
while (!B_UDRE) {
|
||||
|
||||
if (TEST(M_UCSRxA,M_RXCx)) {
|
||||
if (B_RXC) {
|
||||
// A char arrived while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = M_UDRx;
|
||||
c = R_UDR;
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
if (Cfg::EMERGENCYPARSER)
|
||||
emergency_parser.update(emergency_state, c);
|
||||
#endif
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
@@ -301,9 +253,8 @@
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
@@ -312,78 +263,68 @@
|
||||
// have any issues writing to the UART TX register if it needs to!
|
||||
}
|
||||
}
|
||||
#endif // SERIAL_XON_XOFF
|
||||
}
|
||||
|
||||
// Store the new head value - The main loop will retry until the value is stable
|
||||
rx_buffer.head = h;
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
|
||||
// (called with TX irqs disabled)
|
||||
FORCE_INLINE void _tx_udr_empty_irq(void) {
|
||||
|
||||
// (called with TX irqs disabled)
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::_tx_udr_empty_irq(void) {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Read positions
|
||||
uint8_t t = tx_buffer.tail;
|
||||
const uint8_t h = tx_buffer.head;
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
if (Cfg::XONOFF) {
|
||||
// If an XON char is pending to be sent, do it now
|
||||
if (xon_xoff_state == XON_CHAR) {
|
||||
|
||||
// Send the character
|
||||
M_UDRx = XON_CHAR;
|
||||
R_UDR = XON_CHAR;
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
B_TXC = 1;
|
||||
|
||||
// Remember we sent it.
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// If nothing else to transmit, just disable TX interrupts.
|
||||
if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// If nothing to transmit, just disable TX interrupts. This could
|
||||
// happen as the result of the non atomicity of the disabling of RX
|
||||
// interrupts that could end reenabling TX interrupts as a side effect.
|
||||
if (h == t) {
|
||||
CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
return;
|
||||
}
|
||||
|
||||
// There is something to TX, Send the next byte
|
||||
const uint8_t c = tx_buffer.buffer[t];
|
||||
t = (t + 1) & (TX_BUFFER_SIZE - 1);
|
||||
M_UDRx = c;
|
||||
t = (t + 1) & (Cfg::TX_SIZE - 1);
|
||||
R_UDR = c;
|
||||
tx_buffer.tail = t;
|
||||
|
||||
// Clear the TXC bit (by writing a one to its bit location).
|
||||
// Ensures flush() won't return until the bytes are actually written/
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
B_TXC = 1;
|
||||
|
||||
// Disable interrupts if there is nothing to transmit following this byte
|
||||
if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
}
|
||||
|
||||
#ifdef M_USARTx_UDRE_vect
|
||||
ISR(M_USARTx_UDRE_vect) { _tx_udr_empty_irq(); }
|
||||
#endif
|
||||
|
||||
#endif // TX_BUFFER_SIZE
|
||||
|
||||
#ifdef M_USARTx_RX_vect
|
||||
ISR(M_USARTx_RX_vect) { store_rxd_char(); }
|
||||
#endif
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
|
||||
void MarlinSerial::begin(const long baud) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::begin(const long baud) {
|
||||
uint16_t baud_setting;
|
||||
bool useU2X = true;
|
||||
|
||||
@@ -394,41 +335,41 @@
|
||||
if (baud == 57600) useU2X = false;
|
||||
#endif
|
||||
|
||||
R_UCSRA = 0;
|
||||
if (useU2X) {
|
||||
M_UCSRxA = _BV(M_U2Xx);
|
||||
B_U2X = 1;
|
||||
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||
}
|
||||
else {
|
||||
M_UCSRxA = 0;
|
||||
else
|
||||
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||
}
|
||||
|
||||
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
||||
M_UBRRxH = baud_setting >> 8;
|
||||
M_UBRRxL = baud_setting;
|
||||
R_UBRRH = baud_setting >> 8;
|
||||
R_UBRRL = baud_setting;
|
||||
|
||||
SBI(M_UCSRxB, M_RXENx);
|
||||
SBI(M_UCSRxB, M_TXENx);
|
||||
SBI(M_UCSRxB, M_RXCIEx);
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
CBI(M_UCSRxB, M_UDRIEx);
|
||||
#endif
|
||||
B_RXEN = 1;
|
||||
B_TXEN = 1;
|
||||
B_RXCIE = 1;
|
||||
if (Cfg::TX_SIZE > 0) B_UDRIE = 0;
|
||||
_written = false;
|
||||
}
|
||||
|
||||
void MarlinSerial::end() {
|
||||
CBI(M_UCSRxB, M_RXENx);
|
||||
CBI(M_UCSRxB, M_TXENx);
|
||||
CBI(M_UCSRxB, M_RXCIEx);
|
||||
CBI(M_UCSRxB, M_UDRIEx);
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::end() {
|
||||
B_RXEN = 0;
|
||||
B_TXEN = 0;
|
||||
B_RXCIE = 0;
|
||||
B_UDRIE = 0;
|
||||
}
|
||||
|
||||
int MarlinSerial::peek(void) {
|
||||
template<typename Cfg>
|
||||
int MarlinSerial<Cfg>::peek(void) {
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
|
||||
return h == t ? -1 : rx_buffer.buffer[t];
|
||||
}
|
||||
|
||||
int MarlinSerial::read(void) {
|
||||
template<typename Cfg>
|
||||
int MarlinSerial<Cfg>::read(void) {
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head();
|
||||
|
||||
// Read the tail. Main thread owns it, so it is safe to directly read it
|
||||
@@ -439,42 +380,45 @@
|
||||
|
||||
// Get the next char
|
||||
const int v = rx_buffer.buffer[t];
|
||||
t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
|
||||
t = (ring_buffer_pos_t)(t + 1) & (Cfg::RX_SIZE - 1);
|
||||
|
||||
// Advance tail - Making sure the RX ISR will always get an stable value, even
|
||||
// if it interrupts the writing of the value of that variable in the middle.
|
||||
atomic_set_rx_tail(t);
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
if (Cfg::XONOFF) {
|
||||
// If the XOFF char was sent, or about to be sent...
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
// Get count of bytes in the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
if (rx_count < (RX_BUFFER_SIZE) / 10) {
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
if (rx_count < (Cfg::RX_SIZE) / 10) {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX ISR. Non atomic, but it will eventually enable them
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
#else
|
||||
B_UDRIE = 1;
|
||||
}
|
||||
else {
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
|
||||
M_UDRx = XON_CHAR;
|
||||
#endif
|
||||
while (!B_UDRE) sw_barrier();
|
||||
R_UDR = XON_CHAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
ring_buffer_pos_t MarlinSerial::available(void) {
|
||||
template<typename Cfg>
|
||||
typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::available(void) {
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
|
||||
return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
|
||||
return (ring_buffer_pos_t)(Cfg::RX_SIZE + h - t) & (Cfg::RX_SIZE - 1);
|
||||
}
|
||||
|
||||
void MarlinSerial::flush(void) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::flush(void) {
|
||||
|
||||
// Set the tail to the head:
|
||||
// - Read the RX head index in a safe way. (See atomic_read_rx_head.)
|
||||
@@ -482,26 +426,36 @@
|
||||
// if it interrupts the writing of the value of that variable in the middle.
|
||||
atomic_set_rx_tail(atomic_read_rx_head());
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
if (Cfg::XONOFF) {
|
||||
// If the XOFF char was sent, or about to be sent...
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX ISR. Non atomic, but it will eventually enable it.
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
#else
|
||||
B_UDRIE = 1;
|
||||
}
|
||||
else {
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
|
||||
M_UDRx = XON_CHAR;
|
||||
#endif
|
||||
while (!B_UDRE) sw_barrier();
|
||||
R_UDR = XON_CHAR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
void MarlinSerial::write(const uint8_t c) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::write(const uint8_t c) {
|
||||
if (Cfg::TX_SIZE == 0) {
|
||||
|
||||
_written = true;
|
||||
while (!B_UDRE) sw_barrier();
|
||||
R_UDR = c;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
_written = true;
|
||||
|
||||
// If the TX interrupts are disabled and the data register
|
||||
@@ -511,17 +465,17 @@
|
||||
// interrupt overhead becomes a slowdown.
|
||||
// Yes, there is a race condition between the sending of the
|
||||
// XOFF char at the RX ISR, but it is properly handled there
|
||||
if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
|
||||
M_UDRx = c;
|
||||
if (!B_UDRIE && B_UDRE) {
|
||||
R_UDR = c;
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
B_TXC = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
|
||||
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()) {
|
||||
@@ -530,7 +484,7 @@
|
||||
while (i == tx_buffer.tail) {
|
||||
|
||||
// If we can transmit another byte, do it.
|
||||
if (TEST(M_UCSRxA, M_UDREx)) _tx_udr_empty_irq();
|
||||
if (B_UDRE) _tx_udr_empty_irq();
|
||||
|
||||
// Make sure compiler rereads tx_buffer.tail
|
||||
sw_barrier();
|
||||
@@ -538,7 +492,7 @@
|
||||
}
|
||||
else {
|
||||
// Interrupts are enabled, just wait until there is space
|
||||
while (i == tx_buffer.tail) { sw_barrier(); }
|
||||
while (i == tx_buffer.tail) sw_barrier();
|
||||
}
|
||||
|
||||
// Store new char. head is always safe to move
|
||||
@@ -546,10 +500,27 @@
|
||||
tx_buffer.head = i;
|
||||
|
||||
// Enable TX ISR - Non atomic, but it will eventually enable TX ISR
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
B_UDRIE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::flushTX(void) {
|
||||
|
||||
if (Cfg::TX_SIZE == 0) {
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
|
||||
// Wait until everything was transmitted
|
||||
while (!B_TXC) sw_barrier();
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
void MarlinSerial::flushTX(void) {
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
@@ -558,11 +529,10 @@
|
||||
if (!ISRS_ENABLED()) {
|
||||
|
||||
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
|
||||
while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) {
|
||||
while (tx_buffer.head != tx_buffer.tail || !B_TXC) {
|
||||
|
||||
// If there is more space, send an extra character
|
||||
if (TEST(M_UCSRxA, M_UDREx))
|
||||
_tx_udr_empty_irq();
|
||||
if (B_UDRE) _tx_udr_empty_irq();
|
||||
|
||||
sw_barrier();
|
||||
}
|
||||
@@ -570,55 +540,40 @@
|
||||
}
|
||||
else {
|
||||
// Wait until everything was transmitted
|
||||
while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) sw_barrier();
|
||||
while (tx_buffer.head != tx_buffer.tail || !B_TXC) sw_barrier();
|
||||
}
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
}
|
||||
|
||||
#else // TX_BUFFER_SIZE == 0
|
||||
|
||||
void MarlinSerial::write(const uint8_t c) {
|
||||
_written = true;
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
|
||||
M_UDRx = c;
|
||||
}
|
||||
|
||||
void MarlinSerial::flushTX(void) {
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
|
||||
// Wait until everything was transmitted
|
||||
while (!TEST(M_UCSRxA, M_TXCx)) sw_barrier();
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
}
|
||||
#endif // TX_BUFFER_SIZE == 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports from print.h
|
||||
*/
|
||||
|
||||
void MarlinSerial::print(char c, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::print(char c, int base) {
|
||||
print((long)c, base);
|
||||
}
|
||||
|
||||
void MarlinSerial::print(unsigned char b, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::print(unsigned char b, int base) {
|
||||
print((unsigned long)b, base);
|
||||
}
|
||||
|
||||
void MarlinSerial::print(int n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::print(int n, int base) {
|
||||
print((long)n, base);
|
||||
}
|
||||
|
||||
void MarlinSerial::print(unsigned int n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::print(unsigned int n, int base) {
|
||||
print((unsigned long)n, base);
|
||||
}
|
||||
|
||||
void MarlinSerial::print(long n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::print(long n, int base) {
|
||||
if (base == 0) write(n);
|
||||
else if (base == 10) {
|
||||
if (n < 0) { print('-'); n = -n; }
|
||||
@@ -628,68 +583,81 @@
|
||||
printNumber(n, base);
|
||||
}
|
||||
|
||||
void MarlinSerial::print(unsigned long n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::print(unsigned long n, int base) {
|
||||
if (base == 0) write(n);
|
||||
else printNumber(n, base);
|
||||
}
|
||||
|
||||
void MarlinSerial::print(double n, int digits) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::print(double n, int digits) {
|
||||
printFloat(n, digits);
|
||||
}
|
||||
|
||||
void MarlinSerial::println(void) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(void) {
|
||||
print('\r');
|
||||
print('\n');
|
||||
}
|
||||
|
||||
void MarlinSerial::println(const String& s) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(const String& s) {
|
||||
print(s);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(const char c[]) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(const char c[]) {
|
||||
print(c);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(char c, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(char c, int base) {
|
||||
print(c, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(unsigned char b, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(unsigned char b, int base) {
|
||||
print(b, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(int n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(int n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(unsigned int n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(unsigned int n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(long n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(long n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(unsigned long n, int base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(unsigned long n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
|
||||
void MarlinSerial::println(double n, int digits) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::println(double n, int digits) {
|
||||
print(n, digits);
|
||||
println();
|
||||
}
|
||||
|
||||
// Private Methods
|
||||
|
||||
void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::printNumber(unsigned long n, uint8_t base) {
|
||||
if (n) {
|
||||
unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
|
||||
int8_t i = 0;
|
||||
@@ -704,7 +672,8 @@
|
||||
print('0');
|
||||
}
|
||||
|
||||
void MarlinSerial::printFloat(double number, uint8_t digits) {
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::printFloat(double number, uint8_t digits) {
|
||||
// Handle negative numbers
|
||||
if (number < 0.0) {
|
||||
print('-');
|
||||
@@ -713,9 +682,7 @@
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for (uint8_t i = 0; i < digits; ++i)
|
||||
rounding *= 0.1;
|
||||
|
||||
for (uint8_t i = 0; i < digits; ++i) rounding *= 0.1;
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
@@ -736,8 +703,39 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Hookup ISR handlers
|
||||
ISR(SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT>>::store_rxd_char();
|
||||
}
|
||||
|
||||
ISR(SERIAL_REGNAME(USART,SERIAL_PORT,_UDRE_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT>>::_tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
// Preinstantiate
|
||||
MarlinSerial customizedSerial;
|
||||
template class MarlinSerial<MarlinSerialCfg<SERIAL_PORT>>;
|
||||
|
||||
// Instantiate
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT>> customizedSerial1;
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
|
||||
// Hookup ISR handlers
|
||||
ISR(SERIAL_REGNAME(USART,SERIAL_PORT_2,_RX_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>>::store_rxd_char();
|
||||
}
|
||||
|
||||
ISR(SERIAL_REGNAME(USART,SERIAL_PORT_2,_UDRE_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>>::_tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
// Preinstantiate
|
||||
template class MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>>;
|
||||
|
||||
// Instantiate
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>> customizedSerial2;
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* MarlinSerial.h - Hardware serial library for Wiring
|
||||
@@ -27,12 +28,10 @@
|
||||
* Modified 28 September 2010 by Mark Sproul
|
||||
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
|
||||
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
|
||||
* Templatized 01 October 2018 by Eduardo José Tagle to allow multiple instances
|
||||
*/
|
||||
|
||||
#ifndef _MARLINSERIAL_H_
|
||||
#define _MARLINSERIAL_H_
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../shared/MarlinSerial.h"
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
@@ -40,73 +39,173 @@
|
||||
#define SERIAL_PORT 0
|
||||
#endif
|
||||
|
||||
// The presence of the UBRRH register is used to detect a UART.
|
||||
#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
|
||||
(port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
|
||||
(port == 3 && defined(UBRR3H)))
|
||||
|
||||
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
|
||||
// requires two levels of indirection to expand macro values properly)
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
|
||||
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
|
||||
#else
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
|
||||
#endif
|
||||
|
||||
// Registers used by MarlinSerial class (expanded depending on selected serial port)
|
||||
#define M_UCSRxA SERIAL_REGNAME(UCSR,SERIAL_PORT,A) // defines M_UCSRxA to be UCSRnA where n is the serial port number
|
||||
#define M_UCSRxB SERIAL_REGNAME(UCSR,SERIAL_PORT,B)
|
||||
#define M_RXENx SERIAL_REGNAME(RXEN,SERIAL_PORT,)
|
||||
#define M_TXENx SERIAL_REGNAME(TXEN,SERIAL_PORT,)
|
||||
#define M_TXCx SERIAL_REGNAME(TXC,SERIAL_PORT,)
|
||||
#define M_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
|
||||
#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,)
|
||||
#define M_FEx SERIAL_REGNAME(FE,SERIAL_PORT,)
|
||||
#define M_DORx SERIAL_REGNAME(DOR,SERIAL_PORT,)
|
||||
#define M_UPEx SERIAL_REGNAME(UPE,SERIAL_PORT,)
|
||||
#define M_UDRIEx SERIAL_REGNAME(UDRIE,SERIAL_PORT,)
|
||||
#define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,)
|
||||
#define M_UBRRxH SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
|
||||
#define M_UBRRxL SERIAL_REGNAME(UBRR,SERIAL_PORT,L)
|
||||
#define M_RXCx SERIAL_REGNAME(RXC,SERIAL_PORT,)
|
||||
#define M_USARTx_RX_vect SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect)
|
||||
#define M_U2Xx SERIAL_REGNAME(U2X,SERIAL_PORT,)
|
||||
#define M_USARTx_UDRE_vect SERIAL_REGNAME(USART,SERIAL_PORT,_UDRE_vect)
|
||||
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
#define BYTE 0
|
||||
|
||||
#ifndef USBCON
|
||||
// We're using a ring buffer (I think), in which rx_buffer_head is the index of the
|
||||
// location to which to write the next incoming character and rx_buffer_tail is the
|
||||
// index of the location from which to read.
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
typedef uint16_t ring_buffer_pos_t;
|
||||
|
||||
// The presence of the UBRRH register is used to detect a UART.
|
||||
#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
|
||||
(port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
|
||||
(port == 3 && defined(UBRR3H)))
|
||||
|
||||
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
|
||||
// requires two levels of indirection to expand macro values properly)
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
|
||||
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
|
||||
#else
|
||||
typedef uint8_t ring_buffer_pos_t;
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
extern uint8_t rx_dropped_bytes;
|
||||
// Registers used by MarlinSerial class (expanded depending on selected serial port)
|
||||
|
||||
// Templated 8bit register (generic)
|
||||
#define UART_REGISTER_DECL_BASE(registerbase, suffix) \
|
||||
template<int portNr> struct R_##registerbase##x##suffix {}
|
||||
|
||||
// Templated 8bit register (specialization for each port)
|
||||
#define UART_REGISTER_DECL(port, registerbase, suffix) \
|
||||
template<> struct R_##registerbase##x##suffix<port> { \
|
||||
constexpr R_##registerbase##x##suffix(int) {} \
|
||||
FORCE_INLINE void operator=(uint8_t newVal) const { SERIAL_REGNAME(registerbase,port,suffix) = newVal; } \
|
||||
FORCE_INLINE operator uint8_t() const { return SERIAL_REGNAME(registerbase,port,suffix); } \
|
||||
}
|
||||
|
||||
// Templated 1bit register (generic)
|
||||
#define UART_BIT_DECL_BASE(registerbase, suffix, bit) \
|
||||
template<int portNr>struct B_##bit##x {}
|
||||
|
||||
// Templated 1bit register (specialization for each port)
|
||||
#define UART_BIT_DECL(port, registerbase, suffix, bit) \
|
||||
template<> struct B_##bit##x<port> { \
|
||||
constexpr B_##bit##x(int) {} \
|
||||
FORCE_INLINE void operator=(int newVal) const { \
|
||||
if (newVal) \
|
||||
SBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
|
||||
else \
|
||||
CBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
|
||||
} \
|
||||
FORCE_INLINE operator bool() const { return TEST(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); } \
|
||||
}
|
||||
|
||||
#define UART_DECL_BASE() \
|
||||
UART_REGISTER_DECL_BASE(UCSR,A);\
|
||||
UART_REGISTER_DECL_BASE(UDR,);\
|
||||
UART_REGISTER_DECL_BASE(UBRR,H);\
|
||||
UART_REGISTER_DECL_BASE(UBRR,L);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,RXEN);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,TXEN);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,TXC);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,RXCIE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,UDRE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,FE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,DOR);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,UDRIE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,RXC);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,U2X)
|
||||
|
||||
#define UART_DECL(port) \
|
||||
UART_REGISTER_DECL(port,UCSR,A);\
|
||||
UART_REGISTER_DECL(port,UDR,);\
|
||||
UART_REGISTER_DECL(port,UBRR,H);\
|
||||
UART_REGISTER_DECL(port,UBRR,L);\
|
||||
UART_BIT_DECL(port,UCSR,B,RXEN);\
|
||||
UART_BIT_DECL(port,UCSR,B,TXEN);\
|
||||
UART_BIT_DECL(port,UCSR,A,TXC);\
|
||||
UART_BIT_DECL(port,UCSR,B,RXCIE);\
|
||||
UART_BIT_DECL(port,UCSR,A,UDRE);\
|
||||
UART_BIT_DECL(port,UCSR,A,FE);\
|
||||
UART_BIT_DECL(port,UCSR,A,DOR);\
|
||||
UART_BIT_DECL(port,UCSR,B,UDRIE);\
|
||||
UART_BIT_DECL(port,UCSR,A,RXC);\
|
||||
UART_BIT_DECL(port,UCSR,A,U2X)
|
||||
|
||||
// Declare empty templates
|
||||
UART_DECL_BASE();
|
||||
|
||||
// And all the specializations for each possible serial port
|
||||
#if UART_PRESENT(0)
|
||||
UART_DECL(0);
|
||||
#endif
|
||||
#if UART_PRESENT(1)
|
||||
UART_DECL(1);
|
||||
#endif
|
||||
#if UART_PRESENT(2)
|
||||
UART_DECL(2);
|
||||
#endif
|
||||
#if UART_PRESENT(3)
|
||||
UART_DECL(3);
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
extern uint8_t rx_buffer_overruns;
|
||||
#endif
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
#define BYTE 0
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
extern uint8_t rx_framing_errors;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
extern ring_buffer_pos_t rx_max_enqueued;
|
||||
#endif
|
||||
// Templated type selector
|
||||
template<bool b, typename T, typename F> struct TypeSelector { typedef T type;} ;
|
||||
template<typename T, typename F> struct TypeSelector<false, T, F> { typedef F type; };
|
||||
|
||||
template<typename Cfg>
|
||||
class MarlinSerial {
|
||||
protected:
|
||||
// Registers
|
||||
static constexpr R_UCSRxA<Cfg::PORT> R_UCSRA = 0;
|
||||
static constexpr R_UDRx<Cfg::PORT> R_UDR = 0;
|
||||
static constexpr R_UBRRxH<Cfg::PORT> R_UBRRH = 0;
|
||||
static constexpr R_UBRRxL<Cfg::PORT> R_UBRRL = 0;
|
||||
|
||||
// Bits
|
||||
static constexpr B_RXENx<Cfg::PORT> B_RXEN = 0;
|
||||
static constexpr B_TXENx<Cfg::PORT> B_TXEN = 0;
|
||||
static constexpr B_TXCx<Cfg::PORT> B_TXC = 0;
|
||||
static constexpr B_RXCIEx<Cfg::PORT> B_RXCIE = 0;
|
||||
static constexpr B_UDREx<Cfg::PORT> B_UDRE = 0;
|
||||
static constexpr B_FEx<Cfg::PORT> B_FE = 0;
|
||||
static constexpr B_DORx<Cfg::PORT> B_DOR = 0;
|
||||
static constexpr B_UDRIEx<Cfg::PORT> B_UDRIE = 0;
|
||||
static constexpr B_RXCx<Cfg::PORT> B_RXC = 0;
|
||||
static constexpr B_U2Xx<Cfg::PORT> B_U2X = 0;
|
||||
|
||||
// Base size of type on buffer size
|
||||
typedef typename TypeSelector<(Cfg::RX_SIZE>256), uint16_t, uint8_t>::type ring_buffer_pos_t;
|
||||
|
||||
struct ring_buffer_r {
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
unsigned char buffer[Cfg::RX_SIZE];
|
||||
};
|
||||
|
||||
struct ring_buffer_t {
|
||||
volatile uint8_t head, tail;
|
||||
unsigned char buffer[Cfg::TX_SIZE];
|
||||
};
|
||||
|
||||
static ring_buffer_r rx_buffer;
|
||||
static ring_buffer_t tx_buffer;
|
||||
static bool _written;
|
||||
|
||||
static constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
|
||||
XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
|
||||
// XON / XOFF character definitions
|
||||
static constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
|
||||
static uint8_t xon_xoff_state,
|
||||
rx_dropped_bytes,
|
||||
rx_buffer_overruns,
|
||||
rx_framing_errors;
|
||||
static ring_buffer_pos_t rx_max_enqueued;
|
||||
|
||||
static FORCE_INLINE 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();
|
||||
|
||||
public:
|
||||
|
||||
FORCE_INLINE static void store_rxd_char();
|
||||
FORCE_INLINE static void _tx_udr_empty_irq(void);
|
||||
|
||||
public:
|
||||
MarlinSerial() {};
|
||||
@@ -119,21 +218,10 @@
|
||||
static void write(const uint8_t c);
|
||||
static void flushTX(void);
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
|
||||
#endif
|
||||
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; }
|
||||
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
|
||||
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
|
||||
|
||||
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
|
||||
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
|
||||
@@ -165,7 +253,25 @@
|
||||
static void printFloat(double, uint8_t);
|
||||
};
|
||||
|
||||
extern MarlinSerial customizedSerial;
|
||||
template <uint8_t serial>
|
||||
struct MarlinSerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = RX_BUFFER_SIZE;
|
||||
static constexpr unsigned int TX_SIZE = TX_BUFFER_SIZE;
|
||||
static constexpr bool XONOFF = bSERIAL_XON_XOFF;
|
||||
static constexpr bool EMERGENCYPARSER = bEMERGENCY_PARSER;
|
||||
static constexpr bool DROPPED_RX = bSERIAL_STATS_DROPPED_RX;
|
||||
static constexpr bool RX_OVERRUNS = bSERIAL_STATS_RX_BUFFER_OVERRUNS;
|
||||
static constexpr bool RX_FRAMING_ERRORS = bSERIAL_STATS_RX_FRAMING_ERRORS;
|
||||
static constexpr bool MAX_RX_QUEUED = bSERIAL_STATS_MAX_RX_QUEUED;
|
||||
};
|
||||
extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT>> customizedSerial1;
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
|
||||
extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>> customizedSerial2;
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !USBCON
|
||||
|
||||
@@ -173,5 +279,3 @@
|
||||
#if defined(USBCON) && ENABLED(BLUETOOTH)
|
||||
extern HardwareSerial bluetoothSerial;
|
||||
#endif
|
||||
|
||||
#endif // _MARLINSERIAL_H_
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SANITYCHECK_AVR_8_BIT_H_
|
||||
#define _SANITYCHECK_AVR_8_BIT_H_
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Test AVR specific configuration values for errors at compile-time.
|
||||
@@ -81,11 +79,11 @@
|
||||
#elif PIN_EXISTS(E5_AUTO_FAN) && SPINDLE_LASER_PWM_PIN == E5_AUTO_FAN_PIN
|
||||
#error "SPINDLE_LASER_PWM_PIN is used by E5_AUTO_FAN_PIN."
|
||||
#elif PIN_EXISTS(FAN) && SPINDLE_LASER_PWM_PIN == FAN_PIN
|
||||
#error "SPINDLE_LASER_PWM_PIN is used FAN_PIN."
|
||||
#error "SPINDLE_LASER_PWM_PIN is used by FAN_PIN."
|
||||
#elif PIN_EXISTS(FAN1) && SPINDLE_LASER_PWM_PIN == FAN1_PIN
|
||||
#error "SPINDLE_LASER_PWM_PIN is used FAN1_PIN."
|
||||
#error "SPINDLE_LASER_PWM_PIN is used by FAN1_PIN."
|
||||
#elif PIN_EXISTS(FAN2) && SPINDLE_LASER_PWM_PIN == FAN2_PIN
|
||||
#error "SPINDLE_LASER_PWM_PIN is used FAN2_PIN."
|
||||
#error "SPINDLE_LASER_PWM_PIN is used by FAN2_PIN."
|
||||
#elif PIN_EXISTS(CONTROLLERFAN) && SPINDLE_LASER_PWM_PIN == CONTROLLERFAN_PIN
|
||||
#error "SPINDLE_LASER_PWM_PIN is used by CONTROLLERFAN_PIN."
|
||||
#elif PIN_EXISTS(MOTOR_CURRENT_PWM_XY) && SPINDLE_LASER_PWM_PIN == MOTOR_CURRENT_PWM_XY_PIN
|
||||
@@ -116,5 +114,3 @@
|
||||
|| defined(E4_HARDWARE_SERIAL) )
|
||||
#error "Select hardware UART for TMC2208 to use both TMC2208 and ENDSTOP_INTERRUPTS_FEATURE."
|
||||
#endif
|
||||
|
||||
#endif // _SANITYCHECK_AVR_8_BIT_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* ServoTimers.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
|
||||
@@ -39,9 +40,6 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _SERVOTIMERS_H_
|
||||
#define _SERVOTIMERS_H_
|
||||
|
||||
/**
|
||||
* Defines for 16 bit timers used with Servo library
|
||||
*
|
||||
@@ -91,5 +89,3 @@ typedef enum {
|
||||
#endif
|
||||
_Nbr_16timers
|
||||
} timer16_Sequence_t;
|
||||
|
||||
#endif // _SERVOTIMERS_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Endstop Interrupts
|
||||
@@ -35,9 +36,6 @@
|
||||
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
|
||||
*/
|
||||
|
||||
#ifndef _ENDSTOP_INTERRUPTS_H_
|
||||
#define _ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
#include "../../core/macros.h"
|
||||
#include <stdint.h>
|
||||
#include "../../module/endstops.h"
|
||||
@@ -85,22 +83,21 @@ void pciSetup(const int8_t pin) {
|
||||
SBI(PCICR, digitalPinToPCICRbit(pin)); // enable interrupt for the group
|
||||
}
|
||||
|
||||
|
||||
// Handlers for pin change interrupts
|
||||
#ifdef PCINT0_vect
|
||||
ISR(PCINT0_vect) { endstop_ISR(); }
|
||||
#endif
|
||||
|
||||
#ifdef PCINT1_vect
|
||||
ISR(PCINT1_vect) { endstop_ISR(); }
|
||||
ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect));
|
||||
#endif
|
||||
|
||||
#ifdef PCINT2_vect
|
||||
ISR(PCINT2_vect) { endstop_ISR(); }
|
||||
ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect));
|
||||
#endif
|
||||
|
||||
#ifdef PCINT3_vect
|
||||
ISR(PCINT3_vect) { endstop_ISR(); }
|
||||
ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect));
|
||||
#endif
|
||||
|
||||
void setup_endstop_interrupts( void ) {
|
||||
@@ -257,5 +254,3 @@ void setup_endstop_interrupts( void ) {
|
||||
|
||||
// If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
|
||||
}
|
||||
|
||||
#endif // _ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping for the 1280 and 2560
|
||||
@@ -28,9 +29,6 @@
|
||||
* 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 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_1280_H_
|
||||
#define _FASTIO_1280_H_
|
||||
|
||||
#include "fastio_AVR.h"
|
||||
|
||||
// change for your board
|
||||
@@ -1111,5 +1109,3 @@
|
||||
#define PL7_WPORT PORTL
|
||||
#define PL7_DDR DDRL
|
||||
#define PL7_PWM NULL
|
||||
|
||||
#endif // _FASTIO_1280_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping for the 1281 and 2561
|
||||
@@ -27,9 +28,6 @@
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_1281_H_
|
||||
#define _FASTIO_1281_H_
|
||||
|
||||
#include "fastio_AVR.h"
|
||||
|
||||
// change for your board
|
||||
@@ -715,5 +713,3 @@
|
||||
#define PG5_WPORT PORTG
|
||||
#define PG5_DDR DDRG
|
||||
#define PG5_PWM &OCR0B
|
||||
|
||||
#endif // _FASTIO_1281_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping for the 168, 328, and 328P
|
||||
@@ -27,9 +28,6 @@
|
||||
* Port: B0 B1 B2 B3 B4 B5 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_168_H_
|
||||
#define _FASTIO_168_H_
|
||||
|
||||
#include "fastio_AVR.h"
|
||||
|
||||
#define DEBUG_LED AIO5
|
||||
@@ -357,5 +355,3 @@
|
||||
#define PD7_WPORT PORTD
|
||||
#define PD7_DDR DDRD
|
||||
#define PD7_PWM NULL
|
||||
|
||||
#endif // _FASTIO_168_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping for the 644, 644p, 644pa, and 1284p
|
||||
@@ -53,9 +54,6 @@
|
||||
* +--------+
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_644_H_
|
||||
#define _FASTIO_644_H_
|
||||
|
||||
#include "fastio_AVR.h"
|
||||
|
||||
#define DEBUG_LED DIO0
|
||||
@@ -552,5 +550,3 @@
|
||||
#define PD7_WPORT PORTD
|
||||
#define PD7_DDR DDRD
|
||||
#define PD7_PWM OCR2A
|
||||
|
||||
#endif // _FASTIO_644_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping (Teensy) for AT90USB646, 647, 1286, and 1287
|
||||
@@ -28,9 +29,6 @@
|
||||
* The logical pins 46 and 47 are not supported by Teensyduino, but are supported below as E2 and E3
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_AT90USB_H_
|
||||
#define _FASTIO_AT90USB_H_
|
||||
|
||||
#include "fastio_AVR.h"
|
||||
|
||||
// change for your board
|
||||
@@ -697,5 +695,3 @@
|
||||
#define TIMER3A 5
|
||||
#define TIMER3B 4
|
||||
#define TIMER3C 3
|
||||
|
||||
#endif // _FASTIO_AT90USB_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Fast I/O Routines for AVR
|
||||
@@ -26,9 +27,6 @@
|
||||
* Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_ARDUINO_H_
|
||||
#define _FASTIO_ARDUINO_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "../../core/macros.h"
|
||||
|
||||
@@ -312,5 +310,3 @@ enum ClockSource2 : char {
|
||||
|
||||
// finally - the macro that tells us if a pin is an available hardware PWM
|
||||
#define USEABLE_HARDWARE_PWM(p) (PWM_PINS(p) && !PWM_CHK(p))
|
||||
|
||||
#endif // _FASTIO_ARDUINO_H_
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MATH_AVR_H_
|
||||
#define _MATH_AVR_H_
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Optimized math functions for AVR
|
||||
@@ -38,9 +36,9 @@
|
||||
// D C B A is longIn2
|
||||
//
|
||||
static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
|
||||
register uint8_t tmp1;
|
||||
register uint8_t tmp2;
|
||||
register uint16_t intRes;
|
||||
uint8_t tmp1;
|
||||
uint8_t tmp2;
|
||||
uint16_t intRes;
|
||||
__asm__ __volatile__(
|
||||
A("clr %[tmp1]")
|
||||
A("mul %A[longIn1], %B[longIn2]")
|
||||
@@ -92,8 +90,8 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
|
||||
// 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) {
|
||||
register uint8_t tmp;
|
||||
register uint16_t intRes;
|
||||
uint8_t tmp;
|
||||
uint16_t intRes;
|
||||
__asm__ __volatile__ (
|
||||
A("clr %[tmp]")
|
||||
A("mul %[charIn1], %B[intIn2]")
|
||||
@@ -113,5 +111,3 @@ static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
|
||||
);
|
||||
return intRes;
|
||||
}
|
||||
|
||||
#endif // _MATH_AVR_H_
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
#if ENABLED(EEPROM_SETTINGS) || ENABLED(SD_FIRMWARE_UPDATE)
|
||||
|
||||
#include "../shared/persistent_store_api.h"
|
||||
|
||||
@@ -53,7 +53,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
do {
|
||||
uint8_t c = eeprom_read_byte((unsigned char*)pos);
|
||||
uint8_t c = eeprom_read_byte((uint8_t*)pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
@@ -64,5 +64,5 @@ bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t
|
||||
|
||||
size_t PersistentStore::capacity() { return E2END + 1; }
|
||||
|
||||
#endif // EEPROM_SETTINGS
|
||||
#endif // EEPROM_SETTINGS || SD_FIRMWARE_UPDATE
|
||||
#endif // __AVR__
|
||||
|
||||
@@ -19,14 +19,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* PWM print routines for Atmel 8 bit AVR CPUs
|
||||
*/
|
||||
|
||||
#ifndef _PINSDEBUG_AVR_8_BIT_
|
||||
#define _PINSDEBUG_AVR_8_BIT_
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
|
||||
@@ -406,5 +404,3 @@ static void pwm_details(uint8_t pin) {
|
||||
#endif
|
||||
|
||||
#define PRINT_PIN(p) do {sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer);} while (0)
|
||||
|
||||
#endif // _PINSDEBUG_AVR_8_BIT_
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PINSDEBUG_TEENSYSUINO_H_
|
||||
#define _PINSDEBUG_TEENSYSUINO_H_
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// some of the pin mapping functions of the Teensduino extension to the Arduino IDE
|
||||
@@ -111,5 +109,3 @@ const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
|
||||
// disable the PWMs so we can use it as is
|
||||
|
||||
// portModeRegister(pin) is OK
|
||||
|
||||
#endif // _PINSDEBUG_TEENSYSUINO_H_
|
||||
|
||||
@@ -20,14 +20,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Structures for 2560 family boards that use more than 70 pins
|
||||
*/
|
||||
|
||||
#ifndef _PINSDEBUG_PLUS_70_H_
|
||||
#define _PINSDEBUG_PLUS_70_H_
|
||||
|
||||
#undef NUM_DIGITAL_PINS
|
||||
#if MB(BQ_ZUM_MEGA_3D)
|
||||
#define NUM_DIGITAL_PINS 85
|
||||
@@ -336,6 +334,3 @@ const uint8_t PROGMEM digital_pin_to_timer_PGM_plus_70[] = {
|
||||
* PCINT14 J5 76
|
||||
* PCINT15 J6 77
|
||||
*/
|
||||
|
||||
|
||||
#endif // _PINSDEBUG_PLUS_70_H_
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SPI_PINS_H_
|
||||
#define _SPI_PINS_H_
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Define SPI Pins: SCK, MISO, MOSI, SS
|
||||
@@ -65,6 +63,3 @@
|
||||
#ifndef SS_PIN
|
||||
#define SS_PIN AVR_SS_PIN
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _SPI_PINS_H_
|
||||
|
||||
@@ -63,9 +63,8 @@ void watchdog_init() {
|
||||
ISR(WDT_vect) {
|
||||
sei(); // With the interrupt driven serial we need to allow interrupts.
|
||||
SERIAL_ERROR_START();
|
||||
SERIAL_ERRORLNPGM("Watchdog barked, please turn off the printer.");
|
||||
kill(PSTR("ERR:Watchdog")); //kill blocks //up to 16 characters so it fits on a 16x2 display
|
||||
while (1); //wait for user or serial reset
|
||||
SERIAL_ERRORLNPGM(MSG_WATCHDOG_FIRED);
|
||||
minkill(); // interrupt-safe final kill and infinite loop
|
||||
}
|
||||
#endif // WATCHDOG_RESET_MANUAL
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WATCHDOG_AVR_H_
|
||||
#define _WATCHDOG_AVR_H_
|
||||
#pragma once
|
||||
|
||||
#include <avr/wdt.h>
|
||||
|
||||
@@ -31,5 +29,3 @@ void watchdog_init();
|
||||
// Reset watchdog. MUST be called at least every 4 seconds after the
|
||||
// first watchdog_init or AVR will go into emergency procedures.
|
||||
inline void watchdog_reset() { wdt_reset(); }
|
||||
|
||||
#endif // _WATCHDOG_AVR_H_
|
||||
|
||||
@@ -145,8 +145,8 @@ static const UnwindCallbacks UnwCallbacks = {
|
||||
UnwReadW,
|
||||
UnwReadH,
|
||||
UnwReadB
|
||||
#if defined(UNW_DEBUG)
|
||||
,UnwPrintf
|
||||
#ifdef UNW_DEBUG
|
||||
, UnwPrintf
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Description: HAL for Arduino Due and compatible (SAM3X8E)
|
||||
@@ -26,9 +27,6 @@
|
||||
* For ARDUINO_ARCH_SAM
|
||||
*/
|
||||
|
||||
#ifndef _HAL_DUE_H
|
||||
#define _HAL_DUE_H
|
||||
|
||||
#define CPU_32_BIT
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -41,9 +39,25 @@
|
||||
#include "watchdog_Due.h"
|
||||
#include "HAL_timers_Due.h"
|
||||
|
||||
#define NUM_SERIAL 1
|
||||
// Required before the include or compilation fails
|
||||
#define MYSERIAL0 customizedSerial
|
||||
// Serial ports
|
||||
#if !WITHIN(SERIAL_PORT, -1, 3)
|
||||
#error "SERIAL_PORT must be from -1 to 3"
|
||||
#endif
|
||||
|
||||
// MYSERIAL0 required before MarlinSerial includes!
|
||||
#define MYSERIAL0 customizedSerial1
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if !WITHIN(SERIAL_PORT_2, -1, 3)
|
||||
#error "SERIAL_PORT_2 must be from -1 to 3"
|
||||
#elif SERIAL_PORT_2 == SERIAL_PORT
|
||||
#error "SERIAL_PORT_2 must be different than SERIAL_PORT"
|
||||
#endif
|
||||
#define NUM_SERIAL 2
|
||||
#define MYSERIAL1 customizedSerial2
|
||||
#else
|
||||
#define NUM_SERIAL 1
|
||||
#endif
|
||||
|
||||
#include "MarlinSerial_Due.h"
|
||||
#include "MarlinSerialUSB_Due.h"
|
||||
@@ -108,8 +122,8 @@ uint8_t spiRec(uint32_t chan);
|
||||
//
|
||||
// EEPROM
|
||||
//
|
||||
void eeprom_write_byte(unsigned char *pos, unsigned char value);
|
||||
unsigned char eeprom_read_byte(unsigned char *pos);
|
||||
void eeprom_write_byte(uint8_t *pos, unsigned char value);
|
||||
uint8_t eeprom_read_byte(uint8_t *pos);
|
||||
void eeprom_read_block (void *__dst, const void *__src, size_t __n);
|
||||
void eeprom_update_block (const void *__src, void *__dst, size_t __n);
|
||||
|
||||
@@ -173,5 +187,3 @@ char *dtostrf (double __val, signed char __width, unsigned char __prec, char *__
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _HAL_DUE_H
|
||||
|
||||
@@ -78,11 +78,11 @@
|
||||
|
||||
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
||||
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
|
||||
register uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
||||
register uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
||||
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
register uint32_t idx = 0;
|
||||
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
uint32_t idx = 0;
|
||||
|
||||
/* Negate bout, as the assembler requires a negated value */
|
||||
bout = ~bout;
|
||||
@@ -161,11 +161,11 @@
|
||||
|
||||
// run at ~8 .. ~10Mhz - Rx version (Tx line not altered)
|
||||
static uint8_t spiTransferRx0(uint8_t bout) { // using Mode 0
|
||||
register uint32_t bin = 0;
|
||||
register uint32_t work = 0;
|
||||
register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
||||
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
uint32_t bin = 0;
|
||||
uint32_t work = 0;
|
||||
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
UNUSED(bout);
|
||||
|
||||
/* The software SPI routine */
|
||||
@@ -281,12 +281,12 @@
|
||||
|
||||
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
||||
static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
|
||||
register uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
||||
register uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
||||
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
register uint32_t work = 0;
|
||||
register uint32_t txval = 0;
|
||||
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
uint32_t work = 0;
|
||||
uint32_t txval = 0;
|
||||
|
||||
/* The software SPI routine */
|
||||
__asm__ __volatile__(
|
||||
@@ -360,11 +360,11 @@
|
||||
}
|
||||
|
||||
static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
|
||||
register uint32_t bin = 0;
|
||||
register uint32_t work = 0;
|
||||
register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
||||
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
uint32_t bin = 0;
|
||||
uint32_t work = 0;
|
||||
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
||||
|
||||
/* The software SPI routine */
|
||||
__asm__ __volatile__(
|
||||
@@ -581,84 +581,124 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// hardware SPI
|
||||
// --------------------------------------------------------------------------
|
||||
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
||||
int spiDueDividors[] = { 10, 21, 42, 84, 168, 255, 255 };
|
||||
bool spiInitMaded = false;
|
||||
|
||||
void spiBegin() {
|
||||
if (spiInitMaded == false) {
|
||||
// Configure SPI pins
|
||||
PIO_Configure(
|
||||
g_APinDescription[SCK_PIN].pPort,
|
||||
g_APinDescription[SCK_PIN].ulPinType,
|
||||
g_APinDescription[SCK_PIN].ulPin,
|
||||
g_APinDescription[SCK_PIN].ulPinConfiguration);
|
||||
PIO_Configure(
|
||||
g_APinDescription[MOSI_PIN].pPort,
|
||||
g_APinDescription[MOSI_PIN].ulPinType,
|
||||
g_APinDescription[MOSI_PIN].ulPin,
|
||||
g_APinDescription[MOSI_PIN].ulPinConfiguration);
|
||||
PIO_Configure(
|
||||
g_APinDescription[MISO_PIN].pPort,
|
||||
g_APinDescription[MISO_PIN].ulPinType,
|
||||
g_APinDescription[MISO_PIN].ulPin,
|
||||
g_APinDescription[MISO_PIN].ulPinConfiguration);
|
||||
|
||||
// set master mode, peripheral select, fault detection
|
||||
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
|
||||
SPI_Enable(SPI0);
|
||||
|
||||
#if MB(ALLIGATOR)
|
||||
SET_OUTPUT(DAC0_SYNC);
|
||||
#if EXTRUDERS > 1
|
||||
SET_OUTPUT(DAC1_SYNC);
|
||||
WRITE(DAC1_SYNC, HIGH);
|
||||
#endif
|
||||
SET_OUTPUT(SPI_EEPROM1_CS);
|
||||
SET_OUTPUT(SPI_EEPROM2_CS);
|
||||
SET_OUTPUT(SPI_FLASH_CS);
|
||||
WRITE(DAC0_SYNC, HIGH);
|
||||
WRITE(SPI_EEPROM1_CS, HIGH );
|
||||
WRITE(SPI_EEPROM2_CS, HIGH );
|
||||
WRITE(SPI_FLASH_CS, HIGH );
|
||||
WRITE(SS_PIN, HIGH );
|
||||
#endif // MB(ALLIGATOR)
|
||||
|
||||
OUT_WRITE(SDSS,0);
|
||||
|
||||
PIO_Configure(
|
||||
g_APinDescription[SPI_PIN].pPort,
|
||||
g_APinDescription[SPI_PIN].ulPinType,
|
||||
g_APinDescription[SPI_PIN].ulPin,
|
||||
g_APinDescription[SPI_PIN].ulPinConfiguration);
|
||||
|
||||
spiInit(1);
|
||||
spiInitMaded = true;
|
||||
}
|
||||
}
|
||||
static bool spiInitialized = false;
|
||||
|
||||
void spiInit(uint8_t spiRate) {
|
||||
if (spiInitMaded == false) {
|
||||
if (spiRate > 6) spiRate = 1;
|
||||
if (spiInitialized) return;
|
||||
|
||||
#if MB(ALLIGATOR)
|
||||
// Set SPI mode 1, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN_DAC,
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN_EEPROM1, SPI_CSR_NCPHA |
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
#endif//MB(ALLIGATOR)
|
||||
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
||||
constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
|
||||
if (spiRate > 6) spiRate = 1;
|
||||
|
||||
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN, SPI_CSR_NCPHA |
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
SPI_Enable(SPI0);
|
||||
spiInitMaded = true;
|
||||
// Set SPI mode 1, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN_DAC,
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN_EEPROM1, SPI_CSR_NCPHA |
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
|
||||
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN, SPI_CSR_NCPHA |
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
SPI_Enable(SPI0);
|
||||
spiInitialized = true;
|
||||
}
|
||||
|
||||
void spiBegin() {
|
||||
if (spiInitialized) return;
|
||||
|
||||
// Configure SPI pins
|
||||
PIO_Configure(
|
||||
g_APinDescription[SCK_PIN].pPort,
|
||||
g_APinDescription[SCK_PIN].ulPinType,
|
||||
g_APinDescription[SCK_PIN].ulPin,
|
||||
g_APinDescription[SCK_PIN].ulPinConfiguration);
|
||||
PIO_Configure(
|
||||
g_APinDescription[MOSI_PIN].pPort,
|
||||
g_APinDescription[MOSI_PIN].ulPinType,
|
||||
g_APinDescription[MOSI_PIN].ulPin,
|
||||
g_APinDescription[MOSI_PIN].ulPinConfiguration);
|
||||
PIO_Configure(
|
||||
g_APinDescription[MISO_PIN].pPort,
|
||||
g_APinDescription[MISO_PIN].ulPinType,
|
||||
g_APinDescription[MISO_PIN].ulPin,
|
||||
g_APinDescription[MISO_PIN].ulPinConfiguration);
|
||||
|
||||
// set master mode, peripheral select, fault detection
|
||||
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
|
||||
SPI_Enable(SPI0);
|
||||
|
||||
SET_OUTPUT(DAC0_SYNC);
|
||||
#if EXTRUDERS > 1
|
||||
SET_OUTPUT(DAC1_SYNC);
|
||||
WRITE(DAC1_SYNC, HIGH);
|
||||
#endif
|
||||
SET_OUTPUT(SPI_EEPROM1_CS);
|
||||
SET_OUTPUT(SPI_EEPROM2_CS);
|
||||
SET_OUTPUT(SPI_FLASH_CS);
|
||||
WRITE(DAC0_SYNC, HIGH);
|
||||
WRITE(SPI_EEPROM1_CS, HIGH );
|
||||
WRITE(SPI_EEPROM2_CS, HIGH );
|
||||
WRITE(SPI_FLASH_CS, HIGH );
|
||||
WRITE(SS_PIN, HIGH );
|
||||
|
||||
OUT_WRITE(SDSS,0);
|
||||
|
||||
PIO_Configure(
|
||||
g_APinDescription[SPI_PIN].pPort,
|
||||
g_APinDescription[SPI_PIN].ulPinType,
|
||||
g_APinDescription[SPI_PIN].ulPin,
|
||||
g_APinDescription[SPI_PIN].ulPinConfiguration);
|
||||
|
||||
spiInit(1);
|
||||
}
|
||||
|
||||
// Read single byte from SPI
|
||||
uint8_t spiRec() {
|
||||
// write dummy byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
||||
// wait for transmit register empty
|
||||
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
||||
|
||||
// wait for receive register
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
||||
// get byte from receive register
|
||||
//DELAY_US(1U);
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
uint8_t spiRec(uint32_t chan) {
|
||||
uint8_t spirec_tmp;
|
||||
// wait for transmit register empty
|
||||
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 1)
|
||||
spirec_tmp = SPI0->SPI_RDR;
|
||||
UNUSED(spirec_tmp);
|
||||
|
||||
// write dummy byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
||||
|
||||
// wait for receive register
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
||||
// get byte from receive register
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
// Read from SPI into buffer
|
||||
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
||||
if (nbyte-- == 0) return;
|
||||
|
||||
for (int i = 0; i < nbyte; i++) {
|
||||
//while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN);
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
||||
buf[i] = SPI0->SPI_RDR;
|
||||
//DELAY_US(1U);
|
||||
}
|
||||
buf[nbyte] = spiRec();
|
||||
}
|
||||
|
||||
// Write single byte to SPI
|
||||
@@ -714,51 +754,6 @@
|
||||
spiSend(chan, buf[n - 1]);
|
||||
}
|
||||
|
||||
// Read single byte from SPI
|
||||
uint8_t spiRec() {
|
||||
// write dummy byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
||||
// wait for transmit register empty
|
||||
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
||||
|
||||
// wait for receive register
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
||||
// get byte from receive register
|
||||
//DELAY_US(1U);
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
uint8_t spiRec(uint32_t chan) {
|
||||
uint8_t spirec_tmp;
|
||||
// wait for transmit register empty
|
||||
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 1)
|
||||
spirec_tmp = SPI0->SPI_RDR;
|
||||
UNUSED(spirec_tmp);
|
||||
|
||||
// write dummy byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
||||
|
||||
// wait for receive register
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
||||
// get byte from receive register
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
// Read from SPI into buffer
|
||||
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
||||
if (nbyte-- == 0) return;
|
||||
|
||||
for (int i = 0; i < nbyte; i++) {
|
||||
//while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN);
|
||||
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
||||
buf[i] = SPI0->SPI_RDR;
|
||||
//DELAY_US(1U);
|
||||
}
|
||||
buf[nbyte] = spiRec();
|
||||
}
|
||||
|
||||
// Write from buffer to SPI
|
||||
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
||||
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
|
||||
@@ -780,7 +775,7 @@
|
||||
// TODO: to be implemented
|
||||
}
|
||||
|
||||
#else // U8G compatible hardware SPI
|
||||
#else // U8G compatible hardware SPI
|
||||
|
||||
#define SPI_MODE_0_DUE_HW 2 // DUE CPHA control bit is inverted
|
||||
#define SPI_MODE_1_DUE_HW 3
|
||||
@@ -789,7 +784,7 @@
|
||||
|
||||
void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified)
|
||||
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
||||
int spiDueDividors[] = { 10, 21, 42, 84, 168, 255, 255 };
|
||||
constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
|
||||
if (spiRate > 6) spiRate = 1;
|
||||
|
||||
// Enable PIOA and SPI0
|
||||
@@ -809,7 +804,11 @@
|
||||
// Master mode, no fault detection, PCS bits in data written to TDR select CSR register
|
||||
SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS;
|
||||
// SPI mode 0, 8 Bit data transfer, baud rate
|
||||
SPI0->SPI_CSR[3] = SPI_CSR_SCBR(spiDueDividors[spiRate]) | SPI_CSR_CSAAT | SPI_MODE_0_DUE_HW; // use same CSR as TMC2130
|
||||
SPI0->SPI_CSR[3] = SPI_CSR_SCBR(spiDivider[spiRate]) | SPI_CSR_CSAAT | SPI_MODE_0_DUE_HW; // use same CSR as TMC2130
|
||||
}
|
||||
|
||||
void spiBegin() {
|
||||
spiInit();
|
||||
}
|
||||
|
||||
static uint8_t spiTransfer(uint8_t data) {
|
||||
@@ -828,10 +827,6 @@
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
void spiBegin() {
|
||||
spiInit();
|
||||
}
|
||||
|
||||
uint8_t spiRec() {
|
||||
uint8_t data = spiTransfer(0xFF);
|
||||
return data;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
|
||||
#include "HAL_timers_Due.h"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL for Arduino Due and compatible (SAM3X8E)
|
||||
@@ -25,9 +26,6 @@
|
||||
* For ARDUINO_ARCH_SAM
|
||||
*/
|
||||
|
||||
#ifndef _HAL_TIMERS_DUE_H
|
||||
#define _HAL_TIMERS_DUE_H
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -120,5 +118,3 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
|
||||
}
|
||||
|
||||
#define HAL_timer_isr_epilogue(TIMER_NUM)
|
||||
|
||||
#endif // _HAL_TIMERS_DUE_H
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
#include "InterruptVectors_Due.h"
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* InterruptVectors_Due.h
|
||||
@@ -35,11 +36,6 @@
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
*/
|
||||
|
||||
#ifndef INTERRUPTVECTORS_DUE_H
|
||||
#define INTERRUPTVECTORS_DUE_H
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
// ISR handler type
|
||||
@@ -49,4 +45,3 @@ typedef void (*pfnISR_Handler)(void);
|
||||
pfnISR_Handler install_isr(IRQn_Type irq, pfnISR_Handler newHandler);
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
||||
#endif // INTERRUPTVECTORS_DUE_H
|
||||
|
||||
@@ -143,8 +143,8 @@ void MarlinSerialUSB::write(const uint8_t c) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports from print.h
|
||||
*/
|
||||
* Imports from print.h
|
||||
*/
|
||||
|
||||
void MarlinSerialUSB::print(char c, int base) {
|
||||
print((long)c, base);
|
||||
@@ -285,7 +285,7 @@ void MarlinSerialUSB::printFloat(double number, uint8_t digits) {
|
||||
}
|
||||
|
||||
// Preinstantiate
|
||||
MarlinSerialUSB customizedSerial;
|
||||
MarlinSerialUSB customizedSerial1;
|
||||
|
||||
#endif // SERIAL_PORT == -1
|
||||
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* MarlinSerialUSB_Due.h - Hardware Serial over USB (CDC) library for Arduino DUE
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
*/
|
||||
|
||||
#ifndef MARLINSERIALUSB_DUE_H
|
||||
#define MARLINSERIALUSB_DUE_H
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
@@ -52,11 +50,11 @@ public:
|
||||
static void write(const uint8_t c);
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
FORCE_INLINE static uint32_t dropped() { return 0; }
|
||||
FORCE_INLINE static uint32_t dropped() { return 0; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
FORCE_INLINE static int rxMaxEnqueued() { return 0; }
|
||||
FORCE_INLINE static int rxMaxEnqueued() { return 0; }
|
||||
#endif
|
||||
|
||||
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
|
||||
@@ -89,7 +87,6 @@ private:
|
||||
static void printFloat(double, uint8_t);
|
||||
};
|
||||
|
||||
extern MarlinSerialUSB customizedSerial;
|
||||
extern MarlinSerialUSB customizedSerial1;
|
||||
|
||||
#endif // SERIAL_PORT == -1
|
||||
#endif // MARLINSERIAL_DUE_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* MarlinSerial_Due.h - Hardware serial library for Arduino DUE
|
||||
@@ -26,12 +27,7 @@
|
||||
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
*/
|
||||
|
||||
#ifndef MARLINSERIAL_DUE_H
|
||||
#define MARLINSERIAL_DUE_H
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if SERIAL_PORT >= 0
|
||||
#include "../shared/MarlinSerial.h"
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
@@ -60,29 +56,60 @@
|
||||
// #error "TX_BUFFER_SIZE must be 0, a power of 2 greater than 1, and no greater than 256."
|
||||
//#endif
|
||||
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
typedef uint16_t ring_buffer_pos_t;
|
||||
#else
|
||||
typedef uint8_t ring_buffer_pos_t;
|
||||
#endif
|
||||
// Templated type selector
|
||||
template<bool b, typename T, typename F> struct TypeSelector { typedef T type;} ;
|
||||
template<typename T, typename F> struct TypeSelector<false, T, F> { typedef F type; };
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
extern uint8_t rx_dropped_bytes;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
extern uint8_t rx_buffer_overruns;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
extern uint8_t rx_framing_errors;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
extern ring_buffer_pos_t rx_max_enqueued;
|
||||
#endif
|
||||
// Templated structure wrapper
|
||||
template<typename S, unsigned int addr> struct StructWrapper {
|
||||
constexpr StructWrapper(int) {}
|
||||
FORCE_INLINE S* operator->() const { return (S*)addr; }
|
||||
};
|
||||
|
||||
template<typename Cfg>
|
||||
class MarlinSerial {
|
||||
protected:
|
||||
// Information for all supported UARTs
|
||||
static constexpr uint32_t BASES[] = {0x400E0800U, 0x40098000U, 0x4009C000U, 0x400A0000U, 0x400A4000U};
|
||||
static constexpr IRQn_Type IRQS[] = { UART_IRQn, USART0_IRQn, USART1_IRQn, USART2_IRQn, USART3_IRQn};
|
||||
static constexpr int IRQ_IDS[] = { ID_UART, ID_USART0, ID_USART1, ID_USART2, ID_USART3};
|
||||
|
||||
// Alias for shorter code
|
||||
static constexpr StructWrapper<Uart,BASES[Cfg::PORT]> HWUART = 0;
|
||||
static constexpr IRQn_Type HWUART_IRQ = IRQS[Cfg::PORT];
|
||||
static constexpr int HWUART_IRQ_ID = IRQ_IDS[Cfg::PORT];
|
||||
|
||||
// Base size of type on buffer size
|
||||
typedef typename TypeSelector<(Cfg::RX_SIZE>256), uint16_t, uint8_t>::type ring_buffer_pos_t;
|
||||
|
||||
struct ring_buffer_r {
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
unsigned char buffer[Cfg::RX_SIZE];
|
||||
};
|
||||
|
||||
struct ring_buffer_t {
|
||||
volatile uint8_t head, tail;
|
||||
unsigned char buffer[Cfg::TX_SIZE];
|
||||
};
|
||||
|
||||
static ring_buffer_r rx_buffer;
|
||||
static ring_buffer_t tx_buffer;
|
||||
static bool _written;
|
||||
|
||||
static constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
|
||||
XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
|
||||
// XON / XOFF character definitions
|
||||
static constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
|
||||
static uint8_t xon_xoff_state,
|
||||
rx_dropped_bytes,
|
||||
rx_buffer_overruns,
|
||||
rx_framing_errors;
|
||||
static ring_buffer_pos_t rx_max_enqueued;
|
||||
|
||||
FORCE_INLINE static void store_rxd_char();
|
||||
FORCE_INLINE static void _tx_thr_empty_irq(void);
|
||||
static void UART_ISR(void);
|
||||
|
||||
public:
|
||||
MarlinSerial() {};
|
||||
@@ -95,21 +122,10 @@ public:
|
||||
static void write(const uint8_t c);
|
||||
static void flushTX(void);
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
|
||||
#endif
|
||||
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; }
|
||||
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
|
||||
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
|
||||
|
||||
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
|
||||
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
|
||||
@@ -141,8 +157,28 @@ private:
|
||||
static void printFloat(double, uint8_t);
|
||||
};
|
||||
|
||||
extern MarlinSerial customizedSerial;
|
||||
// Serial port configuration
|
||||
template <uint8_t serial>
|
||||
struct MarlinSerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = RX_BUFFER_SIZE;
|
||||
static constexpr unsigned int TX_SIZE = TX_BUFFER_SIZE;
|
||||
static constexpr bool XONOFF = bSERIAL_XON_XOFF;
|
||||
static constexpr bool EMERGENCYPARSER = bEMERGENCY_PARSER;
|
||||
static constexpr bool DROPPED_RX = bSERIAL_STATS_DROPPED_RX;
|
||||
static constexpr bool RX_OVERRUNS = bSERIAL_STATS_RX_BUFFER_OVERRUNS;
|
||||
static constexpr bool RX_FRAMING_ERRORS = bSERIAL_STATS_RX_FRAMING_ERRORS;
|
||||
static constexpr bool MAX_RX_QUEUED = bSERIAL_STATS_MAX_RX_QUEUED;
|
||||
};
|
||||
|
||||
#if SERIAL_PORT >= 0
|
||||
|
||||
extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT>> customizedSerial1;
|
||||
|
||||
#endif // SERIAL_PORT >= 0
|
||||
|
||||
#endif // MARLINSERIAL_DUE_H
|
||||
#ifdef SERIAL_PORT_2
|
||||
|
||||
extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>> customizedSerial2;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -76,14 +76,14 @@ void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
|
||||
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)
|
||||
digitalWrite(SERVO(timer,Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
||||
else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
|
||||
digitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
||||
|
||||
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
|
||||
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
|
||||
digitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
#include "HAL_timers_Due.h"
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Endstop Interrupts
|
||||
@@ -34,9 +35,6 @@
|
||||
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
|
||||
*/
|
||||
|
||||
#ifndef _ENDSTOP_INTERRUPTS_H_
|
||||
#define _ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
#include "../../module/endstops.h"
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
@@ -82,5 +80,3 @@ void setup_endstop_interrupts(void) {
|
||||
attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //_ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Fast I/O Routines for SAM3X8E
|
||||
@@ -36,9 +37,6 @@
|
||||
* leads to less efficient compiled code!!
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_DUE_H
|
||||
#define _FASTIO_DUE_H
|
||||
|
||||
#include <pins_arduino.h>
|
||||
|
||||
/**
|
||||
@@ -47,7 +45,7 @@
|
||||
|
||||
// Due has 12 PWMs assigned to logical pins 2-13.
|
||||
// 6, 7, 8 & 9 come from the PWM controller. The others come from the timers.
|
||||
#define USEABLE_HARDWARE_PWM(p) ((2 <= p) && (p <= 13))
|
||||
#define USEABLE_HARDWARE_PWM(p) WITHIN(p, 2, 13)
|
||||
|
||||
#ifndef MASK
|
||||
#define MASK(PIN) (1 << PIN)
|
||||
@@ -467,6 +465,9 @@
|
||||
|
||||
#define DIO107_PIN 10
|
||||
#define DIO107_WPORT PIOB
|
||||
|
||||
#define DIO108_PIN 9
|
||||
#define DIO108_WPORT PIOB
|
||||
#else
|
||||
#define DIO92_PIN 5
|
||||
#define DIO92_WPORT PIOA
|
||||
@@ -495,5 +496,3 @@
|
||||
#define DIO100_PIN 11
|
||||
#define DIO100_WPORT PIOC
|
||||
#endif
|
||||
|
||||
#endif // _FASTIO_DUE_H
|
||||
|
||||
@@ -67,7 +67,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
do {
|
||||
uint8_t c = eeprom_read_byte((unsigned char*)pos);
|
||||
uint8_t c = eeprom_read_byte((uint8_t*)pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SPI_PINS_H_
|
||||
#define SPI_PINS_H_
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Define SPI Pins: SCK, MISO, MOSI, SS
|
||||
@@ -48,12 +46,16 @@
|
||||
#else
|
||||
// defaults
|
||||
#define DUE_SOFTWARE_SPI
|
||||
#define SCK_PIN 52
|
||||
#define MISO_PIN 50
|
||||
#define MOSI_PIN 51
|
||||
#ifndef SCK_PIN
|
||||
#define SCK_PIN 52
|
||||
#endif
|
||||
#ifndef MISO_PIN
|
||||
#define MISO_PIN 50
|
||||
#endif
|
||||
#ifndef MOSI_PIN
|
||||
#define MOSI_PIN 51
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* A.28, A.29, B.21, C.26, C.29 */
|
||||
#define SS_PIN SDSS
|
||||
|
||||
#endif /* SPI_PINS_H_ */
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
#if HAS_GRAPHICAL_LCD
|
||||
|
||||
#include <U8glib.h>
|
||||
|
||||
@@ -94,10 +94,8 @@ void u8g_SetPILevel_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
|
||||
else port->PIO_CODR = mask;
|
||||
}
|
||||
|
||||
uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
|
||||
switch(msg) {
|
||||
case U8G_COM_MSG_STOP:
|
||||
break;
|
||||
|
||||
@@ -156,6 +154,6 @@ uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DOGLCD
|
||||
#endif // HAS_GRAPHICAL_LCD
|
||||
|
||||
#endif //__SAM3X8E__
|
||||
#endif //__SAM3X8E__
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
#if HAS_GRAPHICAL_LCD
|
||||
|
||||
#include <U8glib.h>
|
||||
#include <Arduino.h>
|
||||
@@ -180,6 +180,6 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DOGLCD
|
||||
#endif // HAS_GRAPHICAL_LCD
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
||||
|
||||
@@ -40,15 +40,12 @@
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef ARDUINO_DUE_X_H_INCLUDED
|
||||
#define ARDUINO_DUE_X_H_INCLUDED
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* \page arduino_due_x_opfreq "Arduino Due/X - Operating frequencies"
|
||||
* This page lists several definition related to the board operating frequency
|
||||
@@ -98,6 +95,3 @@
|
||||
/*! Active level of the USB_VBOF output pin. */
|
||||
#define USB_VBOF_ACTIVE_LEVEL LOW
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#endif /* ARDUINO_DUE_X_H_INCLUDED */
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
* \brief Marking \a v as a unused parameter or value.
|
||||
*/
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (void) (x)
|
||||
#define UNUSED(x) ((void)(x))
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,10 +49,10 @@
|
||||
|
||||
#undef UNUSED /* To avoid a macro clash as macros.h already defines it */
|
||||
#include "../../../core/macros.h" /* For ENABLED()/DISABLED() */
|
||||
#include "../../../core/boards.h" /* For MB() */
|
||||
#include "../../../../Configuration.h" /* For CUSTOM_MACHINE_NAME definition - We just need the name, no C++ allowed! */
|
||||
#include "compiler.h"
|
||||
|
||||
|
||||
/**
|
||||
* USB Device Configuration
|
||||
* @{
|
||||
@@ -89,7 +89,11 @@
|
||||
//#define USB_DEVICE_LOW_SPEED
|
||||
|
||||
//! To define a Full speed device
|
||||
//#define USB_DEVICE_FULL_SPEED
|
||||
//#define USB_DEVICE_FULL_SPEED
|
||||
|
||||
#if MB(ARCHIM1)
|
||||
#define USB_DEVICE_FULL_SPEED
|
||||
#endif
|
||||
|
||||
//! To authorize the High speed
|
||||
#ifndef USB_DEVICE_FULL_SPEED
|
||||
|
||||
@@ -19,15 +19,17 @@ void sd_mmc_spi_mem_init(void) {
|
||||
}
|
||||
|
||||
Ctrl_status sd_mmc_spi_test_unit_ready(void) {
|
||||
if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
|
||||
return CTRL_NO_PRESENT;
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
// NOTE: This function is defined as returning the address of the last block
|
||||
// in the card, which is cardSize() - 1
|
||||
Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) {
|
||||
if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
|
||||
return CTRL_NO_PRESENT;
|
||||
*nb_sector = card.getSd2Card().cardSize();
|
||||
*nb_sector = card.getSd2Card().cardSize() - 1;
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
@@ -40,7 +42,7 @@ bool sd_mmc_spi_wr_protect(void) {
|
||||
}
|
||||
|
||||
bool sd_mmc_spi_removal(void) {
|
||||
if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -59,7 +61,7 @@ uint8_t sector_buf[SD_MMC_BLOCK_SIZE];
|
||||
// #define DEBUG_MMC
|
||||
|
||||
Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
|
||||
if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
|
||||
return CTRL_NO_PRESENT;
|
||||
|
||||
#ifdef DEBUG_MMC
|
||||
@@ -93,7 +95,7 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
|
||||
}
|
||||
|
||||
Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
|
||||
if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
|
||||
return CTRL_NO_PRESENT;
|
||||
|
||||
#ifdef DEBUG_MMC
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHDOG_DUE_H
|
||||
#define WATCHDOG_DUE_H
|
||||
#pragma once
|
||||
|
||||
// Arduino Due core now has watchdog support
|
||||
|
||||
@@ -33,5 +31,3 @@ void watchdog_init();
|
||||
// Reset watchdog. MUST be called at least every 4 seconds after the
|
||||
// first watchdog_init or AVR will go into emergency procedures.
|
||||
inline void watchdog_reset() { watchdogReset(); }
|
||||
|
||||
#endif // WATCHDOG_DUE_H
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Description: HAL for Espressif ESP32 WiFi
|
||||
*/
|
||||
|
||||
#ifndef _HAL_ESP32_H
|
||||
#define _HAL_ESP32_H
|
||||
|
||||
#define CPU_32_BIT
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -98,8 +96,8 @@ int freeMemory(void);
|
||||
void analogWrite(int pin, int value);
|
||||
|
||||
// EEPROM
|
||||
void eeprom_write_byte(unsigned char *pos, unsigned char value);
|
||||
unsigned char eeprom_read_byte(unsigned char *pos);
|
||||
void eeprom_write_byte(uint8_t *pos, unsigned char value);
|
||||
uint8_t eeprom_read_byte(uint8_t *pos);
|
||||
void eeprom_read_block (void *__dst, const void *__src, size_t __n);
|
||||
void eeprom_update_block (const void *__src, void *__dst, size_t __n);
|
||||
|
||||
@@ -123,5 +121,3 @@ void HAL_adc_start_conversion (uint8_t adc_pin);
|
||||
#define HAL_INIT 1
|
||||
void HAL_idletask(void);
|
||||
void HAL_init(void);
|
||||
|
||||
#endif // _HAL_ESP32_H
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HAL_TIMERS_ESP32_H
|
||||
#define _HAL_TIMERS_ESP32_H
|
||||
#pragma once
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
@@ -104,5 +102,3 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
|
||||
|
||||
#define HAL_timer_isr_prologue(TIMER_NUM)
|
||||
#define HAL_timer_isr_epilogue(TIMER_NUM)
|
||||
|
||||
#endif // _HAL_TIMERS_ESP32_H
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Endstop Interrupts
|
||||
@@ -34,9 +35,6 @@
|
||||
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
|
||||
*/
|
||||
|
||||
#ifndef _ENDSTOP_INTERRUPTS_H_
|
||||
#define _ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
#include "../../module/endstops.h"
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
@@ -77,5 +75,3 @@ void setup_endstop_interrupts(void) {
|
||||
attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //_ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_ESP32_H
|
||||
#define _FASTIO_ESP32_H
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Utility functions
|
||||
@@ -64,9 +62,3 @@
|
||||
// TWI (I2C)
|
||||
#define SCL 5
|
||||
#define SDA 4
|
||||
|
||||
//
|
||||
// pins
|
||||
//
|
||||
|
||||
#endif // _FASTIO_ESP32_H
|
||||
|
||||
@@ -16,11 +16,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _HAL_OTA_H
|
||||
#define _HAL_OTA_H
|
||||
#pragma once
|
||||
|
||||
void OTA_init();
|
||||
void OTA_handle();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,13 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SPI_PINS_H_
|
||||
#define SPI_PINS_H_
|
||||
#pragma once
|
||||
|
||||
#define SS_PIN 5
|
||||
#define SCK_PIN 18
|
||||
#define MISO_PIN 19
|
||||
#define MOSI_PIN 23
|
||||
|
||||
#endif // SPI_PINS_H_
|
||||
|
||||
@@ -19,14 +19,10 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WATCHDOG_ESP32_H
|
||||
#define WATCHDOG_ESP32_H
|
||||
#pragma once
|
||||
|
||||
// Initialize watchdog with a 4 second interrupt time
|
||||
void watchdog_init();
|
||||
|
||||
// Reset watchdog.
|
||||
inline void watchdog_reset() {};
|
||||
|
||||
#endif // WATCHDOG_ESP32_H
|
||||
inline void watchdog_reset() { }
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../core/macros.h"
|
||||
#include "../../core/serial.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "../shared/backtrace/unwinder.h"
|
||||
#include "../shared/backtrace/unwmemaccess.h"
|
||||
#include "watchdog.h"
|
||||
#include <debug_frmwrk.h>
|
||||
|
||||
|
||||
// Debug monitor that dumps to the Programming port all status when
|
||||
// an exception or WDT timeout happens - And then resets the board
|
||||
|
||||
// All the Monitor routines must run with interrupts disabled and
|
||||
// under an ISR execution context. That is why we cannot reuse the
|
||||
// Serial interrupt routines or any C runtime, as we don't know the
|
||||
// state we are when running them
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
|
||||
// (re)initialize UART0 as a monitor output to 250000,n,8,1
|
||||
static void TXBegin(void) {
|
||||
}
|
||||
|
||||
// Send character through UART with no interrupts
|
||||
static void TX(char c) {
|
||||
_DBC(c);
|
||||
}
|
||||
|
||||
// Send String through UART
|
||||
static void TX(const char* s) {
|
||||
while (*s) TX(*s++);
|
||||
}
|
||||
|
||||
static void TXDigit(uint32_t d) {
|
||||
if (d < 10) TX((char)(d+'0'));
|
||||
else if (d < 16) TX((char)(d+'A'-10));
|
||||
else TX('?');
|
||||
}
|
||||
|
||||
// Send Hex number thru UART
|
||||
static void TXHex(uint32_t v) {
|
||||
TX("0x");
|
||||
for (uint8_t i = 0; i < 8; i++, v <<= 4)
|
||||
TXDigit((v >> 28) & 0xF);
|
||||
}
|
||||
|
||||
// Send Decimal number thru UART
|
||||
static void TXDec(uint32_t v) {
|
||||
if (!v) {
|
||||
TX('0');
|
||||
return;
|
||||
}
|
||||
|
||||
char nbrs[14];
|
||||
char *p = &nbrs[0];
|
||||
while (v != 0) {
|
||||
*p++ = '0' + (v % 10);
|
||||
v /= 10;
|
||||
}
|
||||
do {
|
||||
p--;
|
||||
TX(*p);
|
||||
} while (p != &nbrs[0]);
|
||||
}
|
||||
|
||||
// Dump a backtrace entry
|
||||
static bool UnwReportOut(void* ctx, const UnwReport* bte) {
|
||||
int* p = (int*)ctx;
|
||||
|
||||
(*p)++;
|
||||
TX('#'); TXDec(*p); TX(" : ");
|
||||
TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
|
||||
TX('+'); TXDec(bte->address - bte->function);
|
||||
TX(" PC:");TXHex(bte->address); TX('\n');
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef UNW_DEBUG
|
||||
void UnwPrintf(const char* format, ...) {
|
||||
char dest[256];
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vsprintf(dest, format, argptr);
|
||||
va_end(argptr);
|
||||
TX(&dest[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Table of function pointers for passing to the unwinder */
|
||||
static const UnwindCallbacks UnwCallbacks = {
|
||||
UnwReportOut,
|
||||
UnwReadW,
|
||||
UnwReadH,
|
||||
UnwReadB
|
||||
#ifdef UNW_DEBUG
|
||||
,UnwPrintf
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HardFaultHandler_C:
|
||||
* This is called from the HardFault_HandlerAsm with a pointer the Fault stack
|
||||
* as the parameter. We can then read the values from the stack and place them
|
||||
* into local variables for ease of reading.
|
||||
* We then read the various Fault Status and Address Registers to help decode
|
||||
* cause of the fault.
|
||||
* The function ends with a BKPT instruction to force control back into the debugger
|
||||
*/
|
||||
extern "C"
|
||||
void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
|
||||
|
||||
static const char* causestr[] = {
|
||||
"NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
|
||||
};
|
||||
|
||||
UnwindFrame btf;
|
||||
|
||||
// Dump report to the Programming port (interrupts are DISABLED)
|
||||
TXBegin();
|
||||
TX("\n\n## Software Fault detected ##\n");
|
||||
TX("Cause: "); TX(causestr[cause]); TX('\n');
|
||||
|
||||
TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
|
||||
TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
|
||||
TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
|
||||
TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
|
||||
TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
|
||||
TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
|
||||
TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
|
||||
TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
|
||||
|
||||
// Configurable Fault Status Register
|
||||
// Consists of MMSR, BFSR and UFSR
|
||||
TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
|
||||
|
||||
// Hard Fault Status Register
|
||||
TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
|
||||
|
||||
// Debug Fault Status Register
|
||||
TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
|
||||
|
||||
// Auxiliary Fault Status Register
|
||||
TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
|
||||
|
||||
// Read the Fault Address Registers. These may not contain valid values.
|
||||
// Check BFARVALID/MMARVALID to see if they are valid values
|
||||
// MemManage Fault Address Register
|
||||
TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
|
||||
|
||||
// Bus Fault Address Register
|
||||
TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
|
||||
|
||||
TX("ExcLR: "); TXHex(lr); TX('\n');
|
||||
TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
|
||||
|
||||
btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
|
||||
btf.fp = btf.sp;
|
||||
btf.lr = ((unsigned long)sp[5]);
|
||||
btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
|
||||
|
||||
// Perform a backtrace
|
||||
TX("\nBacktrace:\n\n");
|
||||
int ctr = 0;
|
||||
UnwindStart(&btf, &UnwCallbacks, &ctr);
|
||||
|
||||
// Disable all NVIC interrupts
|
||||
NVIC->ICER[0] = 0xFFFFFFFF;
|
||||
NVIC->ICER[1] = 0xFFFFFFFF;
|
||||
|
||||
// Relocate VTOR table to default position
|
||||
SCB->VTOR = 0;
|
||||
|
||||
// Clear cause of reset to prevent entering smoothie bootstrap
|
||||
HAL_clear_reset_source();
|
||||
// Restart watchdog
|
||||
//WDT_Restart(WDT);
|
||||
watchdog_init();
|
||||
|
||||
// Reset controller
|
||||
NVIC_SystemReset();
|
||||
|
||||
while(1) { watchdog_init(); }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
__attribute__((naked)) void NMI_Handler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#0")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void HardFault_Handler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#1")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void MemManage_Handler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#2")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void BusFault_Handler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#3")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void UsageFault_Handler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#4")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void DebugMon_Handler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#5")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
|
||||
__attribute__((naked)) void WDT_IRQHandler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#6")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void RSTC_Handler(void) {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#7")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -22,8 +22,7 @@
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../shared/Delay.h"
|
||||
|
||||
HalSerial usb_serial;
|
||||
#include "../../../gcode/parser.h"
|
||||
|
||||
// U8glib required functions
|
||||
extern "C" void u8g_xMicroDelay(uint16_t val) {
|
||||
@@ -51,231 +50,11 @@ int freeMemory() {
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ADC
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#define ADC_DONE 0x80000000
|
||||
#define ADC_OVERRUN 0x40000000
|
||||
|
||||
void HAL_adc_init(void) {
|
||||
LPC_SC->PCONP |= (1 << 12); // Enable CLOCK for internal ADC controller
|
||||
LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
|
||||
LPC_SC->PCLKSEL0 |= (0x1 << 24); // 0: 25MHz, 1: 100MHz, 2: 50MHz, 3: 12.5MHZ to ADC clock divider
|
||||
LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected
|
||||
| (0xFF << 8) // select slowest clock for A/D conversion 150 - 190 uS for a complete conversion
|
||||
| (0 << 16) // BURST: 0 = software control
|
||||
| (0 << 17) // CLKS: not applicable
|
||||
| (1 << 21) // PDN: 1 = operational
|
||||
| (0 << 24) // START: 0 = no start
|
||||
| (0 << 27); // EDGE: not applicable
|
||||
}
|
||||
|
||||
// externals need to make the call to KILL compile
|
||||
#include "../../core/language.h"
|
||||
|
||||
extern void kill(const char*);
|
||||
extern const char errormagic[];
|
||||
|
||||
void HAL_adc_enable_channel(int ch) {
|
||||
pin_t pin = analogInputToDigitalPin(ch);
|
||||
|
||||
if (pin == -1) {
|
||||
SERIAL_PRINTF("%sINVALID ANALOG PORT:%d\n", errormagic, ch);
|
||||
kill(MSG_KILLED);
|
||||
}
|
||||
|
||||
int8_t pin_port = LPC1768_PIN_PORT(pin),
|
||||
pin_port_pin = LPC1768_PIN_PIN(pin),
|
||||
pinsel_start_bit = pin_port_pin > 15 ? 2 * (pin_port_pin - 16) : 2 * pin_port_pin;
|
||||
uint8_t pin_sel_register = (pin_port == 0 && pin_port_pin <= 15) ? 0 :
|
||||
pin_port == 0 ? 1 :
|
||||
pin_port == 1 ? 3 : 10;
|
||||
|
||||
switch (pin_sel_register) {
|
||||
case 1:
|
||||
LPC_PINCON->PINSEL1 &= ~(0x3 << pinsel_start_bit);
|
||||
LPC_PINCON->PINSEL1 |= (0x1 << pinsel_start_bit);
|
||||
break;
|
||||
case 3:
|
||||
LPC_PINCON->PINSEL3 &= ~(0x3 << pinsel_start_bit);
|
||||
LPC_PINCON->PINSEL3 |= (0x3 << pinsel_start_bit);
|
||||
break;
|
||||
case 0:
|
||||
LPC_PINCON->PINSEL0 &= ~(0x3 << pinsel_start_bit);
|
||||
LPC_PINCON->PINSEL0 |= (0x2 << pinsel_start_bit);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void HAL_adc_start_conversion(const uint8_t ch) {
|
||||
if (analogInputToDigitalPin(ch) == -1) {
|
||||
SERIAL_PRINTF("HAL: HAL_adc_start_conversion: invalid channel %d\n", ch);
|
||||
return;
|
||||
}
|
||||
|
||||
LPC_ADC->ADCR &= ~0xFF; // Reset
|
||||
SBI(LPC_ADC->ADCR, ch); // Select Channel
|
||||
SBI(LPC_ADC->ADCR, 24); // Start conversion
|
||||
}
|
||||
|
||||
bool HAL_adc_finished(void) {
|
||||
return LPC_ADC->ADGDR & ADC_DONE;
|
||||
}
|
||||
|
||||
// possible config options if something similar is extended to more platforms.
|
||||
#define ADC_USE_MEDIAN_FILTER // Filter out erroneous readings
|
||||
#define ADC_MEDIAN_FILTER_SIZE 23 // Higher values increase step delay (phase shift),
|
||||
// (ADC_MEDIAN_FILTER_SIZE + 1) / 2 sample step delay (12 samples @ 500Hz: 24ms phase shift)
|
||||
// Memory usage per ADC channel (bytes): (6 * ADC_MEDIAN_FILTER_SIZE) + 16
|
||||
// 8 * ((6 * 23) + 16 ) = 1232 Bytes for 8 channels
|
||||
|
||||
#define ADC_USE_LOWPASS_FILTER // Filter out high frequency noise
|
||||
#define ADC_LOWPASS_K_VALUE 6 // Higher values increase rise time
|
||||
// Rise time sample delays for 100% signal convergence on full range step
|
||||
// (1 : 13, 2 : 32, 3 : 67, 4 : 139, 5 : 281, 6 : 565, 7 : 1135, 8 : 2273)
|
||||
// K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
|
||||
// Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
|
||||
|
||||
|
||||
// Sourced from https://embeddedgurus.com/stack-overflow/tag/median-filter/
|
||||
struct MedianFilter {
|
||||
#define STOPPER 0 // Smaller than any datum
|
||||
struct Pair {
|
||||
Pair *point; // Pointers forming list linked in sorted order
|
||||
uint16_t value; // Values to sort
|
||||
};
|
||||
|
||||
Pair buffer[ADC_MEDIAN_FILTER_SIZE] = {}; // Buffer of nwidth pairs
|
||||
Pair *datpoint = buffer; // Pointer into circular buffer of data
|
||||
Pair small = {NULL, STOPPER}; // Chain stopper
|
||||
Pair big = {&small, 0}; // Pointer to head (largest) of linked list.
|
||||
|
||||
uint16_t update(uint16_t datum) {
|
||||
Pair *successor; // Pointer to successor of replaced data item
|
||||
Pair *scan; // Pointer used to scan down the sorted list
|
||||
Pair *scanold; // Previous value of scan
|
||||
Pair *median; // Pointer to median
|
||||
uint16_t i;
|
||||
|
||||
if (datum == STOPPER) {
|
||||
datum = STOPPER + 1; // No stoppers allowed.
|
||||
}
|
||||
|
||||
if ( (++datpoint - buffer) >= (ADC_MEDIAN_FILTER_SIZE)) {
|
||||
datpoint = buffer; // Increment and wrap data in pointer.
|
||||
}
|
||||
|
||||
datpoint->value = datum; // Copy in new datum
|
||||
successor = datpoint->point; // Save pointer to old value's successor
|
||||
median = &big; // Median initially to first in chain
|
||||
scanold = NULL; // Scanold initially null.
|
||||
scan = &big; // Points to pointer to first (largest) datum in chain
|
||||
|
||||
// Handle chain-out of first item in chain as special case
|
||||
if (scan->point == datpoint) {
|
||||
scan->point = successor;
|
||||
}
|
||||
scanold = scan; // Save this pointer and
|
||||
scan = scan->point ; // step down chain
|
||||
|
||||
// Loop through the chain, normal loop exit via break.
|
||||
for (i = 0 ; i < ADC_MEDIAN_FILTER_SIZE; ++i) {
|
||||
// Handle odd-numbered item in chain
|
||||
if (scan->point == datpoint) {
|
||||
scan->point = successor; // Chain out the old datum
|
||||
}
|
||||
|
||||
if (scan->value < datum) { // If datum is larger than scanned value
|
||||
datpoint->point = scanold->point; // Chain it in here
|
||||
scanold->point = datpoint; // Mark it chained in
|
||||
datum = STOPPER;
|
||||
}
|
||||
|
||||
// Step median pointer down chain after doing odd-numbered element
|
||||
median = median->point; // Step median pointer
|
||||
if (scan == &small) {
|
||||
break; // Break at end of chain
|
||||
}
|
||||
scanold = scan; // Save this pointer and
|
||||
scan = scan->point; // step down chain
|
||||
|
||||
// Handle even-numbered item in chain.
|
||||
if (scan->point == datpoint) {
|
||||
scan->point = successor;
|
||||
}
|
||||
|
||||
if (scan->value < datum) {
|
||||
datpoint->point = scanold->point;
|
||||
scanold->point = datpoint;
|
||||
datum = STOPPER;
|
||||
}
|
||||
|
||||
if (scan == &small) {
|
||||
break;
|
||||
}
|
||||
|
||||
scanold = scan;
|
||||
scan = scan->point;
|
||||
}
|
||||
return median->value;
|
||||
}
|
||||
};
|
||||
|
||||
struct LowpassFilter {
|
||||
uint32_t data_delay = 0;
|
||||
uint16_t update(const uint16_t value) {
|
||||
data_delay -= (data_delay >> (ADC_LOWPASS_K_VALUE)) - value;
|
||||
return (uint16_t)(data_delay >> (ADC_LOWPASS_K_VALUE));
|
||||
}
|
||||
};
|
||||
|
||||
uint16_t HAL_adc_get_result(void) {
|
||||
uint32_t adgdr = LPC_ADC->ADGDR;
|
||||
CBI(LPC_ADC->ADCR, 24); // Stop conversion
|
||||
|
||||
if (adgdr & ADC_OVERRUN) return 0;
|
||||
uint16_t data = (adgdr >> 4) & 0xFFF; // copy the 12bit data value
|
||||
uint8_t adc_channel = (adgdr >> 24) & 0x7; // copy the 3bit used channel
|
||||
|
||||
#ifdef ADC_USE_MEDIAN_FILTER
|
||||
static MedianFilter median_filter[NUM_ANALOG_INPUTS];
|
||||
data = median_filter[adc_channel].update(data);
|
||||
#endif
|
||||
|
||||
#ifdef ADC_USE_LOWPASS_FILTER
|
||||
static LowpassFilter lowpass_filter[NUM_ANALOG_INPUTS];
|
||||
data = lowpass_filter[adc_channel].update(data);
|
||||
#endif
|
||||
|
||||
return ((data >> 2) & 0x3FF); // return 10bit value as Marlin expects
|
||||
}
|
||||
|
||||
#define SBIT_CNTEN 0
|
||||
#define SBIT_PWMEN 2
|
||||
#define SBIT_PWMMR0R 1
|
||||
|
||||
#define PWM_1 0 //P2_00 (0-1 Bits of PINSEL4)
|
||||
#define PWM_2 2 //P2_01 (2-3 Bits of PINSEL4)
|
||||
#define PWM_3 4 //P2_02 (4-5 Bits of PINSEL4)
|
||||
#define PWM_4 6 //P2_03 (6-7 Bits of PINSEL4)
|
||||
#define PWM_5 8 //P2_04 (8-9 Bits of PINSEL4)
|
||||
#define PWM_6 10 //P2_05 (10-11 Bits of PINSEL4)
|
||||
|
||||
void HAL_pwm_init(void) {
|
||||
LPC_PINCON->PINSEL4 = _BV(PWM_5) | _BV(PWM_6);
|
||||
|
||||
LPC_PWM1->TCR = _BV(SBIT_CNTEN) | _BV(SBIT_PWMEN);
|
||||
LPC_PWM1->PR = 0x0; // No prescalar
|
||||
LPC_PWM1->MCR = _BV(SBIT_PWMMR0R); // Reset on PWMMR0, reset TC if it matches MR0
|
||||
LPC_PWM1->MR0 = 255; // set PWM cycle(Ton+Toff)=255)
|
||||
LPC_PWM1->MR5 = 0; // Set 50% Duty Cycle for the channels
|
||||
LPC_PWM1->MR6 = 0;
|
||||
|
||||
// Trigger the latch Enable Bits to load the new Match Values MR0, MR5, MR6
|
||||
LPC_PWM1->LER = _BV(0) | _BV(5) | _BV(6);
|
||||
// Enable the PWM output pins for PWM_5-PWM_6(P2_04 - P2_05)
|
||||
LPC_PWM1->PCR = _BV(13) | _BV(14);
|
||||
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
|
||||
const uint16_t val = (uint16_t)parser.intval(code), port = val / 100, pin = val % 100;
|
||||
const int16_t ind = (port < (NUM_DIGITAL_PINS >> 5) && (pin < 32))
|
||||
? GET_PIN_MAP_INDEX(port << 5 | pin) : -2;
|
||||
return ind > -2 ? ind : dval;
|
||||
}
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
|
||||
@@ -19,52 +19,35 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL_LPC1768/HAL.h
|
||||
* Hardware Abstraction Layer for NXP LPC1768
|
||||
*/
|
||||
|
||||
#ifndef _HAL_LPC1768_H_
|
||||
#define _HAL_LPC1768_H_
|
||||
|
||||
#define CPU_32_BIT
|
||||
#define HAL_INIT
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
void HAL_init();
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
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
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
//arduino: binary.h (weird defines)
|
||||
#define B01 1
|
||||
#define B10 2
|
||||
extern "C" volatile millis_t _millis;
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <pinmapping.h>
|
||||
#include <CDCSerial.h>
|
||||
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include <adc.h>
|
||||
#include "watchdog.h"
|
||||
#include "HAL_timers.h"
|
||||
#include "MarlinSerial.h"
|
||||
|
||||
//
|
||||
// Default graphical display delays
|
||||
@@ -79,32 +62,20 @@ extern "C" volatile uint32_t _millis;
|
||||
#define ST7920_DELAY_3 DELAY_NS(750)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Arduino-style serial ports
|
||||
//
|
||||
#include "serial.h"
|
||||
#include "HardwareSerial.h"
|
||||
|
||||
extern HalSerial usb_serial;
|
||||
|
||||
#if !WITHIN(SERIAL_PORT, -1, 3)
|
||||
#error "SERIAL_PORT must be from -1 to 3"
|
||||
#endif
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 usb_serial
|
||||
#define MYSERIAL0 UsbSerial
|
||||
#elif SERIAL_PORT == 0
|
||||
extern HardwareSerial Serial;
|
||||
#define MYSERIAL0 Serial
|
||||
#define MYSERIAL0 MSerial
|
||||
#elif SERIAL_PORT == 1
|
||||
extern HardwareSerial Serial1;
|
||||
#define MYSERIAL0 Serial1
|
||||
#define MYSERIAL0 MSerial1
|
||||
#elif SERIAL_PORT == 2
|
||||
extern HardwareSerial Serial2;
|
||||
#define MYSERIAL0 Serial2
|
||||
#define MYSERIAL0 MSerial2
|
||||
#elif SERIAL_PORT == 3
|
||||
#define MYSERIAL0 Serial3
|
||||
extern HardwareSerial Serial3;
|
||||
#define MYSERIAL0 MSerial3
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
@@ -115,19 +86,15 @@ extern HalSerial usb_serial;
|
||||
#endif
|
||||
#define NUM_SERIAL 2
|
||||
#if SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL1 usb_serial
|
||||
#define MYSERIAL1 UsbSerial
|
||||
#elif SERIAL_PORT_2 == 0
|
||||
extern HardwareSerial Serial;
|
||||
#define MYSERIAL1 Serial
|
||||
#define MYSERIAL1 MSerial
|
||||
#elif SERIAL_PORT_2 == 1
|
||||
extern HardwareSerial Serial1;
|
||||
#define MYSERIAL1 Serial1
|
||||
#define MYSERIAL1 MSerial1
|
||||
#elif SERIAL_PORT_2 == 2
|
||||
extern HardwareSerial Serial2;
|
||||
#define MYSERIAL1 Serial2
|
||||
#define MYSERIAL1 MSerial2
|
||||
#elif SERIAL_PORT_2 == 3
|
||||
extern HardwareSerial Serial3;
|
||||
#define MYSERIAL1 Serial3
|
||||
#define MYSERIAL1 MSerial3
|
||||
#endif
|
||||
#else
|
||||
#define NUM_SERIAL 1
|
||||
@@ -159,17 +126,31 @@ void spiSend(uint32_t chan, const uint8_t* buf, size_t n);
|
||||
uint8_t spiRec(uint32_t chan);
|
||||
|
||||
//
|
||||
// ADC
|
||||
// ADC API
|
||||
//
|
||||
#define HAL_ANALOG_SELECT(pin) HAL_adc_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() HAL_adc_finished()
|
||||
|
||||
void HAL_adc_init(void);
|
||||
void HAL_adc_enable_channel(int pin);
|
||||
void HAL_adc_start_conversion(const uint8_t adc_pin);
|
||||
uint16_t HAL_adc_get_result(void);
|
||||
bool HAL_adc_finished(void);
|
||||
#define ADC_MEDIAN_FILTER_SIZE (23) // Higher values increase step delay (phase shift),
|
||||
// (ADC_MEDIAN_FILTER_SIZE + 1) / 2 sample step delay (12 samples @ 500Hz: 24ms phase shift)
|
||||
// Memory usage per ADC channel (bytes): (6 * ADC_MEDIAN_FILTER_SIZE) + 16
|
||||
// 8 * ((6 * 23) + 16 ) = 1232 Bytes for 8 channels
|
||||
|
||||
#endif // _HAL_LPC1768_H_
|
||||
#define ADC_LOWPASS_K_VALUE (6) // Higher values increase rise time
|
||||
// Rise time sample delays for 100% signal convergence on full range step
|
||||
// (1 : 13, 2 : 32, 3 : 67, 4 : 139, 5 : 281, 6 : 565, 7 : 1135, 8 : 2273)
|
||||
// K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
|
||||
// Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
|
||||
|
||||
using FilteredADC = LPC176x::ADC<ADC_LOWPASS_K_VALUE, ADC_MEDIAN_FILTER_SIZE>;
|
||||
#define HAL_adc_init() FilteredADC::init()
|
||||
#define HAL_ANALOG_SELECT(pin) FilteredADC::enable_channel(pin)
|
||||
#define HAL_START_ADC(pin) FilteredADC::start_conversion(pin)
|
||||
#define HAL_READ_ADC() FilteredADC::get_result()
|
||||
#define HAL_ADC_READY() FilteredADC::finished_conversion()
|
||||
|
||||
// Parse a G-code word into a pin index
|
||||
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(void);
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -59,7 +58,6 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if ENABLED(LPC_SOFTWARE_SPI)
|
||||
|
||||
#include "SoftwareSPI.h"
|
||||
@@ -127,8 +125,25 @@
|
||||
#include <lpc17xx_ssp.h>
|
||||
#include <lpc17xx_clkpwr.h>
|
||||
|
||||
void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
|
||||
// decide which HW SPI device to use
|
||||
#ifndef LPC_HW_SPI_DEV
|
||||
#if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09)
|
||||
#define LPC_HW_SPI_DEV 1
|
||||
#else
|
||||
#if (SCK_PIN == P0_15 && MISO_PIN == P0_17 && MOSI_PIN == P0_18)
|
||||
#define LPC_HW_SPI_DEV 0
|
||||
#else
|
||||
#error "Invalid pins selected for hardware SPI"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if (LPC_HW_SPI_DEV == 0)
|
||||
#define LPC_SSPn LPC_SSP0
|
||||
#else
|
||||
#define LPC_SSPn LPC_SSP1
|
||||
#endif
|
||||
|
||||
void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
|
||||
PINSEL_CFG_Type PinCfg; // data structure to hold init values
|
||||
PinCfg.Funcnum = 2;
|
||||
PinCfg.OpenDrain = 0;
|
||||
@@ -147,10 +162,13 @@
|
||||
PinCfg.Portnum = LPC1768_PIN_PORT(MOSI_PIN);
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
SET_OUTPUT(MOSI_PIN);
|
||||
// divide PCLK by 2 for SSP0
|
||||
CLKPWR_SetPCLKDiv(LPC_HW_SPI_DEV == 0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
|
||||
spiInit(0);
|
||||
SSP_Cmd(LPC_SSPn, ENABLE); // start SSP running
|
||||
}
|
||||
|
||||
void spiInit(uint8_t spiRate) {
|
||||
SSP_Cmd(LPC_SSP0, DISABLE); // Disable SSP0 before changing rate
|
||||
// table to convert Marlin spiRates (0-5 plus default) into bit rates
|
||||
uint32_t Marlin_speed[7]; // CPSR is always 2
|
||||
Marlin_speed[0] = 8333333; //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
|
||||
@@ -160,33 +178,32 @@
|
||||
Marlin_speed[4] = 500000; //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
|
||||
Marlin_speed[5] = 250000; //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
|
||||
Marlin_speed[6] = 125000; //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
|
||||
|
||||
// divide PCLK by 2 for SSP0
|
||||
CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_SSP0, CLKPWR_PCLKSEL_CCLK_DIV_2);
|
||||
|
||||
// setup for SPI mode
|
||||
SSP_CFG_Type HW_SPI_init; // data structure to hold init values
|
||||
SSP_ConfigStructInit(&HW_SPI_init); // set values for SPI mode
|
||||
HW_SPI_init.ClockRate = Marlin_speed[MIN(spiRate, 6)]; // put in the specified bit rate
|
||||
SSP_Init(LPC_SSP0, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
|
||||
HW_SPI_init.Mode |= SSP_CR1_SSP_EN;
|
||||
SSP_Init(LPC_SSPn, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
|
||||
}
|
||||
|
||||
SSP_Cmd(LPC_SSP0, ENABLE); // start SSP0 running
|
||||
|
||||
static uint8_t doio(uint8_t b) {
|
||||
/* send and receive a single byte */
|
||||
SSP_SendData(LPC_SSPn, b & 0x00FF);
|
||||
while (SSP_GetStatus(LPC_SSPn, SSP_STAT_BUSY)); // wait for it to finish
|
||||
return SSP_ReceiveData(LPC_SSPn) & 0x00FF;
|
||||
}
|
||||
|
||||
void spiSend(uint8_t b) {
|
||||
while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL)); // wait for room in the buffer
|
||||
SSP_SendData(LPC_SSP0, b & 0x00FF);
|
||||
while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
|
||||
doio(b);
|
||||
}
|
||||
|
||||
|
||||
void spiSend(const uint8_t* buf, size_t n) {
|
||||
if (n == 0) return;
|
||||
for (uint16_t i = 0; i < n; i++) {
|
||||
while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL)); // wait for room in the buffer
|
||||
SSP_SendData(LPC_SSP0, buf[i] & 0x00FF);
|
||||
doio(buf[i]);
|
||||
}
|
||||
while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
|
||||
}
|
||||
|
||||
void spiSend(uint32_t chan, byte b) {
|
||||
@@ -195,17 +212,9 @@
|
||||
void spiSend(uint32_t chan, const uint8_t* buf, size_t n) {
|
||||
}
|
||||
|
||||
static uint8_t get_one_byte() {
|
||||
// send a dummy byte so can clock in receive data
|
||||
SSP_SendData(LPC_SSP0,0x00FF);
|
||||
while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
|
||||
return SSP_ReceiveData(LPC_SSP0) & 0x00FF;
|
||||
}
|
||||
|
||||
// Read single byte from SPI
|
||||
uint8_t spiRec() {
|
||||
while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
|
||||
return get_one_byte();
|
||||
return doio(0xff);
|
||||
}
|
||||
|
||||
uint8_t spiRec(uint32_t chan) {
|
||||
@@ -214,22 +223,25 @@
|
||||
|
||||
// Read from SPI into buffer
|
||||
void spiRead(uint8_t*buf, uint16_t nbyte) {
|
||||
while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
|
||||
if (nbyte == 0) return;
|
||||
for (int i = 0; i < nbyte; i++) {
|
||||
buf[i] = get_one_byte();
|
||||
buf[i] = doio(0xff);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t spiTransfer(uint8_t b) {
|
||||
while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
|
||||
SSP_SendData(LPC_SSP0, b); // send the byte
|
||||
while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
|
||||
return SSP_ReceiveData(LPC_SSP0) & 0x00FF;
|
||||
return doio(b);
|
||||
}
|
||||
|
||||
// Write from buffer to SPI
|
||||
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
||||
uint8_t response;
|
||||
response = spiTransfer(token);
|
||||
|
||||
for (uint16_t i = 0; i < 512; i++) {
|
||||
response = spiTransfer(buf[i]);
|
||||
}
|
||||
UNUSED(response);
|
||||
}
|
||||
|
||||
/** Begin SPI transaction, set clock, bit order, data mode */
|
||||
@@ -270,4 +282,3 @@ uint16_t SPIClass::transfer16(uint16_t data) {
|
||||
SPIClass SPI;
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// blank file needed until I get platformio to update it's copy of U8Glib-HAL
|
||||
@@ -18,16 +18,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL for Arduino Due and compatible (SAM3X8E)
|
||||
*
|
||||
* For ARDUINO_ARCH_SAM
|
||||
* HAL For LPC1768
|
||||
*/
|
||||
|
||||
#ifndef _HAL_TIMERS_H
|
||||
#define _HAL_TIMERS_H
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -167,5 +164,3 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
|
||||
}
|
||||
|
||||
#define HAL_timer_isr_epilogue(TIMER_NUM)
|
||||
|
||||
#endif // _HAL_TIMERS_H
|
||||
|
||||
@@ -1,576 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The class Servo uses the PWM class to implement its functions
|
||||
*
|
||||
* All PWMs use the same repetition rate - 20mS because that's the normal servo rate
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a hybrid system.
|
||||
*
|
||||
* The PWM1 module is used to directly control the Servo 0, 1 & 3 pins and D9 & D10 pins. This keeps
|
||||
* the pulse width jitter to under a microsecond.
|
||||
*
|
||||
* For all other pins a timer is used to generate interrupts. The ISR
|
||||
* routine does the actual setting/clearing of pins. The upside is that any pin can
|
||||
* have a PWM channel assigned to it. The downside is that there is more pulse width
|
||||
* jitter. The jitter depends on what else is happening in the system and what ISRs
|
||||
* pre-empt the PWM ISR.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The data structures are set up to minimize the computation done by the ISR which
|
||||
* minimizes ISR execution time. Execution times are 5-14µs depending on how full the
|
||||
* ISR table is. 14uS is for a 20 element ISR table.
|
||||
*
|
||||
* Two tables are used. One table contains the data used by the ISR to update/control
|
||||
* the PWM pins. The other is used as an aid when updating the ISR table.
|
||||
*
|
||||
* See the end of this file for details on the hardware/firmware interaction
|
||||
*/
|
||||
|
||||
/**
|
||||
* Directly controlled PWM pins (
|
||||
* NA means not being used as a directly controlled PWM pin
|
||||
*
|
||||
* Re-ARM MKS Sbase
|
||||
* PWM1.1 P1_18 SERVO3_PIN NA(no connection)
|
||||
* PWM1.1 P2_00 NA(E0_STEP_PIN) NA(X stepper)
|
||||
* PWM1.2 P1_20 SERVO0_PIN NA(no connection)
|
||||
* PWM1.2 P2_01 NA(X_STEP_PIN) NA(Y stepper)
|
||||
* PWM1.3 P1_21 SERVO1_PIN NA(no connection)
|
||||
* PWM1.3 P2_02 NA(Y_STEP_PIN) NA(Z stepper)
|
||||
* PWM1.4 P1_23 NA(SDSS(SSEL0)) SERVO0_PIN
|
||||
* PWM1.4 P2_03 NA(Z_STEP_PIN) NA(E0 stepper)
|
||||
* PWM1.5 P1_24 NA(X_MIN_PIN) NA(X_MIN_pin)
|
||||
* PWM1.5 P2_04 RAMPS_D9_PIN FAN_PIN
|
||||
* PWM1.6 P1_26 NA(Y_MIN_PIN) NA(Y_MIN_pin)
|
||||
* PWM1.6 P2_05 RAMPS_D10_PIN HEATER_BED_PIN
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include <lpc17xx_pinsel.h>
|
||||
#include "LPC1768_PWM.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#define NUM_ISR_PWMS 20
|
||||
|
||||
#define HAL_PWM_TIMER LPC_TIM3
|
||||
#define HAL_PWM_TIMER_ISR extern "C" void TIMER3_IRQHandler(void)
|
||||
#define HAL_PWM_TIMER_IRQn TIMER3_IRQn
|
||||
|
||||
#define LPC_PORT_OFFSET (0x0020)
|
||||
#define LPC_PIN(pin) (1UL << pin)
|
||||
#define LPC_GPIO(port) ((volatile LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + LPC_PORT_OFFSET * port))
|
||||
|
||||
typedef struct { // holds all data needed to control/init one of the PWM channels
|
||||
bool active_flag; // THIS TABLE ENTRY IS ACTIVELY TOGGLING A PIN
|
||||
pin_t pin;
|
||||
volatile uint32_t* set_register;
|
||||
volatile uint32_t* clr_register;
|
||||
uint32_t write_mask; // USED BY SET/CLEAR COMMANDS
|
||||
uint32_t microseconds; // value written to MR register
|
||||
uint32_t min; // lower value limit checked by WRITE routine before writing to the MR register
|
||||
uint32_t max; // upper value limit checked by WRITE routine before writing to the MR register
|
||||
uint8_t servo_index; // 0 - MAX_SERVO -1 : servo index, 0xFF : PWM channel
|
||||
} PWM_map;
|
||||
|
||||
PWM_map PWM1_map_A[NUM_ISR_PWMS]; // compiler will initialize to all zeros
|
||||
PWM_map PWM1_map_B[NUM_ISR_PWMS]; // compiler will initialize to all zeros
|
||||
|
||||
PWM_map *active_table = PWM1_map_A;
|
||||
PWM_map *work_table = PWM1_map_B;
|
||||
PWM_map *temp_table;
|
||||
|
||||
#define P1_18_PWM_channel 1 // servo 3
|
||||
#define P1_20_PWM_channel 2 // servo 0
|
||||
#define P1_21_PWM_channel 3 // servo 1
|
||||
#define P1_23_PWM_channel 4 // servo 0 for MKS Sbase
|
||||
#define P2_04_PWM_channel 5 // D9
|
||||
#define P2_05_PWM_channel 6 // D10
|
||||
|
||||
typedef struct {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
bool assigned;
|
||||
} table_direct;
|
||||
|
||||
table_direct direct_table[6]; // compiler will initialize to all zeros
|
||||
|
||||
/**
|
||||
* Prescale register and MR0 register values
|
||||
*
|
||||
* 100MHz PCLK 50MHz PCLK 25MHz PCLK 12.5MHz PCLK
|
||||
* ----------------- ----------------- ----------------- -----------------
|
||||
* desired prescale MR0 prescale MR0 prescale MR0 prescale MR0 resolution
|
||||
* prescale register register register register register register register register in degrees
|
||||
* freq value value value value value value value value
|
||||
*
|
||||
* 8 11.5 159,999 5.25 159,999 2.13 159,999 0.5625 159,999 0.023
|
||||
* 4 24 79,999 11.5 79,999 5.25 79,999 2.125 79,999 0.045
|
||||
* 2 49 39,999 24 39,999 11.5 39,999 5.25 39,999 0.090
|
||||
* 1 99 19,999 49 19,999 24 19,999 11.5 19,999 0.180
|
||||
* 0.5 199 9,999 99 9,999 49 9,999 24 9,999 0.360
|
||||
* 0.25 399 4,999 199 4,999 99 4,999 49 4,999 0.720
|
||||
* 0.125 799 2,499 399 2,499 199 2,499 99 2,499 1.440
|
||||
*
|
||||
* The desired prescale frequency column comes from an input in the range of 544 - 2400 microseconds
|
||||
* and the desire to just shift the input left or right as needed.
|
||||
*
|
||||
* A resolution of 0.2 degrees seems reasonable so a prescale frequency output of 1MHz is being used.
|
||||
* It also means we don't need to scale the input.
|
||||
*
|
||||
* The PCLK is set to 25MHz because that's the slowest one that gives whole numbers for prescale and
|
||||
* MR0 registers.
|
||||
*
|
||||
* Final settings:
|
||||
* PCLKSEL0: 0x0
|
||||
* PWM1PR: 0x018 (24)
|
||||
* PWM1MR0: 0x04E1F (19,999)
|
||||
*
|
||||
*/
|
||||
|
||||
void LPC1768_PWM_init(void) {
|
||||
|
||||
///// directly controlled PWM pins (interrupts not used for these)
|
||||
|
||||
#define SBIT_CNTEN 0 // PWM1 counter & pre-scaler enable/disable
|
||||
#define SBIT_CNTRST 1 // reset counters to known state
|
||||
#define SBIT_PWMEN 3 // 1 - PWM, 0 - timer
|
||||
#define SBIT_PWMMR0R 1
|
||||
#define PCPWM1 6
|
||||
#define PCLK_PWM1 12
|
||||
|
||||
SBI(LPC_SC->PCONP, PCPWM1); // Enable PWM1 controller (enabled on power up)
|
||||
LPC_SC->PCLKSEL0 &= ~(0x3 << PCLK_PWM1);
|
||||
LPC_SC->PCLKSEL0 |= (LPC_PWM1_PCLKSEL0 << PCLK_PWM1);
|
||||
|
||||
uint32_t PR = (CLKPWR_GetPCLK(CLKPWR_PCLKSEL_PWM1) / 1000000) - 1; // Prescalar to create 1 MHz output
|
||||
|
||||
LPC_PWM1->MR0 = LPC_PWM1_MR0; // TC resets every 19,999 + 1 cycles - sets PWM cycle(Ton+Toff) to 20 mS
|
||||
// MR0 must be set before TCR enables the PWM
|
||||
LPC_PWM1->TCR = _BV(SBIT_CNTEN) | _BV(SBIT_CNTRST) | _BV(SBIT_PWMEN); // Enable counters, reset counters, set mode to PWM
|
||||
CBI(LPC_PWM1->TCR, SBIT_CNTRST); // Take counters out of reset
|
||||
LPC_PWM1->PR = PR;
|
||||
LPC_PWM1->MCR = _BV(SBIT_PWMMR0R) | _BV(0); // Reset TC if it matches MR0, disable all interrupts except for MR0
|
||||
LPC_PWM1->CTCR = 0; // Disable counter mode (enable PWM mode)
|
||||
LPC_PWM1->LER = 0x07F; // Set the latch Enable Bits to load the new Match Values for MR0 - MR6
|
||||
LPC_PWM1->PCR = 0; // Single edge mode for all channels, PWM1 control of outputs off
|
||||
|
||||
//// interrupt controlled PWM setup
|
||||
|
||||
LPC_SC->PCONP |= 1 << 23; // power on timer3
|
||||
HAL_PWM_TIMER->PR = PR;
|
||||
HAL_PWM_TIMER->MCR = 0x0B; // Interrupt on MR0 & MR1, reset on MR0
|
||||
HAL_PWM_TIMER->MR0 = LPC_PWM1_MR0;
|
||||
HAL_PWM_TIMER->MR1 = 0;
|
||||
HAL_PWM_TIMER->TCR = _BV(0); // enable
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn);
|
||||
NVIC_SetPriority(HAL_PWM_TIMER_IRQn, NVIC_EncodePriority(0, 4, 0));
|
||||
}
|
||||
|
||||
|
||||
bool ISR_table_update = false; // flag to tell the ISR that the tables need to be updated & swapped
|
||||
uint8_t ISR_index = 0; // index used by ISR to skip already actioned entries
|
||||
#define COPY_ACTIVE_TABLE for (uint8_t i = 0; i < NUM_ISR_PWMS ; i++) work_table[i] = active_table[i]
|
||||
uint32_t first_MR1_value = LPC_PWM1_MR0 + 1;
|
||||
|
||||
void LPC1768_PWM_sort(void) {
|
||||
|
||||
for (uint8_t i = NUM_ISR_PWMS; --i;) { // (bubble) sort table by microseconds
|
||||
bool didSwap = false;
|
||||
PWM_map temp;
|
||||
for (uint16_t j = 0; j < i; ++j) {
|
||||
if (work_table[j].microseconds > work_table[j + 1].microseconds) {
|
||||
temp = work_table[j + 1];
|
||||
work_table[j + 1] = work_table[j];
|
||||
work_table[j] = temp;
|
||||
didSwap = true;
|
||||
}
|
||||
}
|
||||
if (!didSwap) break;
|
||||
}
|
||||
}
|
||||
|
||||
bool LPC1768_PWM_attach_pin(pin_t pin, uint32_t min /* = 1 */, uint32_t max /* = (LPC_PWM1_MR0 - 1) */, uint8_t servo_index /* = 0xFF */) {
|
||||
|
||||
pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF)); // Sometimes the upper byte is garbled
|
||||
|
||||
//// direct control PWM code
|
||||
switch (pin) {
|
||||
case P1_23: // MKS Sbase Servo 0, PWM1 channel 4 (J3-8 PWM1.4)
|
||||
direct_table[P1_23_PWM_channel - 1].min = min;
|
||||
direct_table[P1_23_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
|
||||
direct_table[P1_23_PWM_channel - 1].assigned = true;
|
||||
return true;
|
||||
case P1_20: // Servo 0, PWM1 channel 2 (Pin 11 P1.20 PWM1.2)
|
||||
direct_table[P1_20_PWM_channel - 1].min = min;
|
||||
direct_table[P1_20_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
|
||||
direct_table[P1_20_PWM_channel - 1].assigned = true;
|
||||
return true;
|
||||
case P1_21: // Servo 1, PWM1 channel 3 (Pin 6 P1.21 PWM1.3)
|
||||
direct_table[P1_21_PWM_channel - 1].min = min;
|
||||
direct_table[P1_21_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
|
||||
direct_table[P1_21_PWM_channel - 1].assigned = true;
|
||||
return true;
|
||||
case P1_18: // Servo 3, PWM1 channel 1 (Pin 4 P1.18 PWM1.1)
|
||||
direct_table[P1_18_PWM_channel - 1].min = min;
|
||||
direct_table[P1_18_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
|
||||
direct_table[P1_18_PWM_channel - 1].assigned = true;
|
||||
return true;
|
||||
case P2_04: // D9 FET, PWM1 channel 5 (Pin 9 P2_04 PWM1.5)
|
||||
direct_table[P2_04_PWM_channel - 1].min = min;
|
||||
direct_table[P2_04_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
|
||||
direct_table[P2_04_PWM_channel - 1].assigned = true;
|
||||
return true;
|
||||
case P2_05: // D10 FET, PWM1 channel 6 (Pin 10 P2_05 PWM1.6)
|
||||
direct_table[P2_05_PWM_channel - 1].min = min;
|
||||
direct_table[P2_05_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
|
||||
direct_table[P2_05_PWM_channel - 1].assigned = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
//// interrupt controlled PWM code
|
||||
NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn); // make it safe to update the active table
|
||||
// OK to update the active table because the
|
||||
// ISR doesn't use any of the changed items
|
||||
|
||||
// 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();
|
||||
|
||||
if (ISR_table_update) //use work table if that's the newest
|
||||
temp_table = work_table;
|
||||
else
|
||||
temp_table = active_table;
|
||||
|
||||
uint8_t slot = 0;
|
||||
for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // see if already in table
|
||||
if (temp_table[i].pin == pin) {
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (uint8_t i = 1; (i < NUM_ISR_PWMS + 1) && !slot; i++) // find empty slot
|
||||
if ( !(temp_table[i - 1].set_register)) { slot = i; break; } // any item that can't be zero when active or just attached is OK
|
||||
|
||||
if (!slot) {
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
return 0;
|
||||
}
|
||||
|
||||
slot--; // turn it into array index
|
||||
|
||||
temp_table[slot].pin = pin; // init slot
|
||||
temp_table[slot].set_register = &LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOSET;
|
||||
temp_table[slot].clr_register = &LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOCLR;
|
||||
temp_table[slot].write_mask = LPC_PIN(LPC1768_PIN_PIN(pin));
|
||||
temp_table[slot].min = min;
|
||||
temp_table[slot].max = max; // different max for ISR PWMs than for direct PWMs
|
||||
temp_table[slot].servo_index = servo_index;
|
||||
temp_table[slot].active_flag = false;
|
||||
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool LPC1768_PWM_detach_pin(pin_t pin) {
|
||||
|
||||
pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF));
|
||||
|
||||
//// direct control PWM code
|
||||
switch (pin) {
|
||||
case P1_23: // MKS Sbase Servo 0, PWM1 channel 4 (J3-8 PWM1.4)
|
||||
if (!direct_table[P1_23_PWM_channel - 1].assigned) return false;
|
||||
CBI(LPC_PWM1->PCR, 8 + P1_23_PWM_channel); // disable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 &= ~(0x3 << 14); // return pin to general purpose I/O
|
||||
direct_table[P1_23_PWM_channel - 1].assigned = false;
|
||||
return true;
|
||||
case P1_20: // Servo 0, PWM1 channel 2 (Pin 11 P1.20 PWM1.2)
|
||||
if (!direct_table[P1_20_PWM_channel - 1].assigned) return false;
|
||||
CBI(LPC_PWM1->PCR, 8 + P1_20_PWM_channel); // disable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 &= ~(0x3 << 8); // return pin to general purpose I/O
|
||||
direct_table[P1_20_PWM_channel - 1].assigned = false;
|
||||
return true;
|
||||
case P1_21: // Servo 1, PWM1 channel 3 (Pin 6 P1.21 PWM1.3)
|
||||
if (!direct_table[P1_21_PWM_channel - 1].assigned) return false;
|
||||
CBI(LPC_PWM1->PCR, 8 + P1_21_PWM_channel); // disable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 &= ~(0x3 << 10); // return pin to general purpose I/O
|
||||
direct_table[P1_21_PWM_channel - 1].assigned = false;
|
||||
return true;
|
||||
case P1_18: // Servo 3, PWM1 channel 1 (Pin 4 P1.18 PWM1.1)
|
||||
if (!direct_table[P1_18_PWM_channel - 1].assigned) return false;
|
||||
CBI(LPC_PWM1->PCR, 8 + P1_18_PWM_channel); // disable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 &= ~(0x3 << 4); // return pin to general purpose I/O
|
||||
direct_table[P1_18_PWM_channel - 1].assigned = false;
|
||||
return true;
|
||||
case P2_04: // D9 FET, PWM1 channel 5 (Pin 9 P2_04 PWM1.5)
|
||||
if (!direct_table[P2_04_PWM_channel - 1].assigned) return false;
|
||||
CBI(LPC_PWM1->PCR, 8 + P2_04_PWM_channel); // disable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL4 &= ~(0x3 << 10); // return pin to general purpose I/O
|
||||
direct_table[P2_04_PWM_channel - 1].assigned = false;
|
||||
return true;
|
||||
case P2_05: // D10 FET, PWM1 channel 6 (Pin 10 P2_05 PWM1.6)
|
||||
if (!direct_table[P2_05_PWM_channel - 1].assigned) return false;
|
||||
CBI(LPC_PWM1->PCR, 8 + P2_05_PWM_channel); // disable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL4 &= ~(0x3 << 4); // return pin to general purpose I/O
|
||||
direct_table[P2_05_PWM_channel - 1].assigned = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//// interrupt controlled PWM code
|
||||
NVIC_DisableIRQ(HAL_PWM_TIMER_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();
|
||||
|
||||
if (ISR_table_update) {
|
||||
ISR_table_update = false; // don't update yet - have another update to do
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
}
|
||||
else {
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
COPY_ACTIVE_TABLE; // copy active table into work table
|
||||
}
|
||||
|
||||
uint8_t slot = 0xFF;
|
||||
for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) { // find slot
|
||||
if (work_table[i].pin == pin) {
|
||||
slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slot == 0xFF) // return error if pin not found
|
||||
return false;
|
||||
|
||||
work_table[slot] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
LPC1768_PWM_sort(); // sort table by microseconds
|
||||
ISR_table_update = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// value is 0-20,000 microseconds (0% to 100% duty cycle)
|
||||
// servo routine provides values in the 544 - 2400 range
|
||||
bool LPC1768_PWM_write(pin_t pin, uint32_t value) {
|
||||
|
||||
pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF));
|
||||
|
||||
//// direct control PWM code
|
||||
switch (pin) {
|
||||
case P1_23: // MKS Sbase Servo 0, PWM1 channel 4 (J3-8 PWM1.4)
|
||||
if (!direct_table[P1_23_PWM_channel - 1].assigned) return false;
|
||||
LPC_PWM1->PCR |= _BV(8 + P1_23_PWM_channel); // enable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 = 0x2 << 14; // must set pin function AFTER setting PCR
|
||||
// load the new time value
|
||||
LPC_PWM1->MR4 = MAX(MIN(value, direct_table[P1_23_PWM_channel - 1].max), direct_table[P1_23_PWM_channel - 1].min);
|
||||
LPC_PWM1->LER = 0x1 << P1_23_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
|
||||
return true;
|
||||
case P1_20: // Servo 0, PWM1 channel 2 (Pin 11 P1.20 PWM1.2)
|
||||
if (!direct_table[P1_20_PWM_channel - 1].assigned) return false;
|
||||
LPC_PWM1->PCR |= _BV(8 + P1_20_PWM_channel); // enable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 |= 0x2 << 8; // must set pin function AFTER setting PCR
|
||||
// load the new time value
|
||||
LPC_PWM1->MR2 = MAX(MIN(value, direct_table[P1_20_PWM_channel - 1].max), direct_table[P1_20_PWM_channel - 1].min);
|
||||
LPC_PWM1->LER = 0x1 << P1_20_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
|
||||
return true;
|
||||
case P1_21: // Servo 1, PWM1 channel 3 (Pin 6 P1.21 PWM1.3)
|
||||
if (!direct_table[P1_21_PWM_channel - 1].assigned) return false;
|
||||
LPC_PWM1->PCR |= _BV(8 + P1_21_PWM_channel); // enable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 |= 0x2 << 10; // must set pin function AFTER setting PCR
|
||||
// load the new time value
|
||||
LPC_PWM1->MR3 = MAX(MIN(value, direct_table[P1_21_PWM_channel - 1].max), direct_table[P1_21_PWM_channel - 1].min);
|
||||
LPC_PWM1->LER = 0x1 << P1_21_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
|
||||
return true;
|
||||
case P1_18: // Servo 3, PWM1 channel 1 (Pin 4 P1.18 PWM1.1)
|
||||
if (!direct_table[P1_18_PWM_channel - 1].assigned) return false;
|
||||
LPC_PWM1->PCR |= _BV(8 + P1_18_PWM_channel); // enable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL3 |= 0x2 << 4; // must set pin function AFTER setting PCR
|
||||
// load the new time value
|
||||
LPC_PWM1->MR1 = MAX(MIN(value, direct_table[P1_18_PWM_channel - 1].max), direct_table[P1_18_PWM_channel - 1].min);
|
||||
LPC_PWM1->LER = 0x1 << P1_18_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
|
||||
return true;
|
||||
case P2_04: // D9 FET, PWM1 channel 5 (Pin 9 P2_04 PWM1.5)
|
||||
if (!direct_table[P2_04_PWM_channel - 1].assigned) return false;
|
||||
LPC_PWM1->PCR |= _BV(8 + P2_04_PWM_channel); // enable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL4 |= 0x1 << 8; // must set pin function AFTER setting PCR
|
||||
// load the new time value
|
||||
LPC_PWM1->MR5 = MAX(MIN(value, direct_table[P2_04_PWM_channel - 1].max), direct_table[P2_04_PWM_channel - 1].min);
|
||||
LPC_PWM1->LER = 0x1 << P2_04_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
|
||||
return true;
|
||||
case P2_05: // D10 FET, PWM1 channel 6 (Pin 10 P2_05 PWM1.6)
|
||||
if (!direct_table[P2_05_PWM_channel - 1].assigned) return false;
|
||||
LPC_PWM1->PCR |= _BV(8 + P2_05_PWM_channel); // enable PWM1 module control of this pin
|
||||
LPC_PINCON->PINSEL4 |= 0x1 << 10; // must set pin function AFTER setting PCR
|
||||
// load the new time value
|
||||
LPC_PWM1->MR6 = MAX(MIN(value, direct_table[P2_05_PWM_channel - 1].max), direct_table[P2_05_PWM_channel - 1].min);
|
||||
LPC_PWM1->LER = 0x1 << P2_05_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
|
||||
return true;
|
||||
}
|
||||
|
||||
//// interrupt controlled PWM code
|
||||
NVIC_DisableIRQ(HAL_PWM_TIMER_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();
|
||||
|
||||
if (!ISR_table_update) // use the most up to date table
|
||||
COPY_ACTIVE_TABLE; // copy active table into work table
|
||||
|
||||
uint8_t slot = 0xFF;
|
||||
for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // find slot
|
||||
if (work_table[i].pin == pin) { slot = i; break; }
|
||||
if (slot == 0xFF) { // return error if pin not found
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn);
|
||||
return false;
|
||||
}
|
||||
|
||||
work_table[slot].microseconds = MAX(MIN(value, work_table[slot].max), work_table[slot].min);;
|
||||
work_table[slot].active_flag = true;
|
||||
|
||||
LPC1768_PWM_sort(); // sort table by microseconds
|
||||
ISR_table_update = true;
|
||||
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool useable_hardware_PWM(pin_t pin) {
|
||||
|
||||
pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF));
|
||||
|
||||
NVIC_DisableIRQ(HAL_PWM_TIMER_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();
|
||||
|
||||
bool return_flag = false;
|
||||
for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // see if it's already setup
|
||||
if (active_table[i].pin == pin) return_flag = true;
|
||||
for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // see if there is an empty slot
|
||||
if (!active_table[i].set_register) return_flag = true;
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
return return_flag;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#define PWM_LPC1768_ISR_SAFETY_FACTOR 5 // amount of time needed to guarantee MR1 count will be above TC
|
||||
volatile bool in_PWM_isr = false;
|
||||
|
||||
HAL_PWM_TIMER_ISR {
|
||||
bool first_active_entry = true;
|
||||
uint32_t next_MR1_val;
|
||||
|
||||
if (in_PWM_isr) goto exit_PWM_ISR; // prevent re-entering this ISR
|
||||
in_PWM_isr = true;
|
||||
|
||||
if (HAL_PWM_TIMER->IR & 0x01) { // MR0 interrupt
|
||||
next_MR1_val = first_MR1_value; // only used if have a blank ISR table
|
||||
if (ISR_table_update) { // new values have been loaded so swap tables
|
||||
temp_table = active_table;
|
||||
active_table = work_table;
|
||||
work_table = temp_table;
|
||||
ISR_table_update = false;
|
||||
}
|
||||
}
|
||||
HAL_PWM_TIMER->IR = 0x3F; // clear all interrupts
|
||||
|
||||
for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) {
|
||||
if (active_table[i].active_flag) {
|
||||
if (first_active_entry) {
|
||||
first_active_entry = false;
|
||||
next_MR1_val = active_table[i].microseconds;
|
||||
}
|
||||
if (HAL_PWM_TIMER->TC < active_table[i].microseconds) {
|
||||
*active_table[i].set_register = active_table[i].write_mask; // set pin high
|
||||
}
|
||||
else {
|
||||
*active_table[i].clr_register = active_table[i].write_mask; // set pin low
|
||||
next_MR1_val = (i == NUM_ISR_PWMS -1)
|
||||
? LPC_PWM1_MR0 + 1 // done with table, wait for MR0
|
||||
: active_table[i + 1].microseconds; // set next MR1 interrupt?
|
||||
}
|
||||
}
|
||||
}
|
||||
if (first_active_entry) next_MR1_val = LPC_PWM1_MR0 + 1; // empty table so disable MR1 interrupt
|
||||
HAL_PWM_TIMER->MR1 = MAX(next_MR1_val, HAL_PWM_TIMER->TC + PWM_LPC1768_ISR_SAFETY_FACTOR); // set next
|
||||
in_PWM_isr = false;
|
||||
|
||||
exit_PWM_ISR:
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
///////////////// HARDWARE FIRMWARE INTERACTION ////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* There are two distinct systems used for PWMs:
|
||||
* directly controlled pins
|
||||
* ISR controlled pins.
|
||||
*
|
||||
* The two systems are independent of each other. The use the same counter frequency so there's no
|
||||
* translation needed when setting the time values. The init, attach, detach and write routines all
|
||||
* start with the direct pin code which is followed by the ISR pin code.
|
||||
*
|
||||
* The PMW1 module handles the directly controlled pins. Each directly controlled pin is associated
|
||||
* with a match register (MR1 - MR6). When the associated MR equals the module's TIMER/COUNTER (TC)
|
||||
* then the pins is set to low. The MR0 register controls the repetition rate. When the TC equals
|
||||
* MR0 then the TC is reset and ALL directly controlled pins are set high. The resulting pulse widths
|
||||
* are almost immune to system loading and ISRs. No PWM1 interrupts are used.
|
||||
*
|
||||
* The ISR controlled pins use the TIMER/COUNTER, MR0 and MR1 registers from one timer. MR0 controls
|
||||
* period of the controls the repetition rate. When the TC equals MR0 then the TC is reset and an
|
||||
* interrupt is generated. When the TC equals MR1 then an interrupt is generated.
|
||||
*
|
||||
* Each interrupt does the following:
|
||||
* 1) Swaps the tables if it's a MR0 interrupt and the swap flag is set. It then clears the swap flag.
|
||||
* 2) Scans the entire ISR table (it's been sorted low to high time)
|
||||
* a. If its the first active entry then it grabs the time as a tentative time for MR1
|
||||
* b. If active and TC is less than the time then it sets the pin high
|
||||
* c. If active and TC is more than the time it sets the pin high
|
||||
* d. On every entry that sets a pin low it grabs the NEXT entry's time for use as the next MR1.
|
||||
* This results in MR1 being set to the time in the first active entry that does NOT set a
|
||||
* pin low.
|
||||
* e. If it's setting the last entry's pin low then it sets MR1 to a value bigger than MR0
|
||||
* f. If no value has been grabbed for the next MR1 then it's an empty table and MR1 is set to a
|
||||
* value greater than MR0
|
||||
*/
|
||||
@@ -1,79 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The class Servo uses the PWM class to implement its functions
|
||||
*
|
||||
* All PWMs use the same repetition rate - 20mS because that's the normal servo rate
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a hybrid system.
|
||||
*
|
||||
* The PWM1 module is used to directly control the Servo 0, 1 & 3 pins. This keeps
|
||||
* the pulse width jitter to under a microsecond.
|
||||
*
|
||||
* For all other pins the PWM1 module is used to generate interrupts. The ISR
|
||||
* routine does the actual setting/clearing of pins. The upside is that any pin can
|
||||
* have a PWM channel assigned to it. The downside is that there is more pulse width
|
||||
* jitter. The jitter depends on what else is happening in the system and what ISRs
|
||||
* prempt the PWM ISR. Writing to the SD card can add 20 microseconds to the pulse
|
||||
* width.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The data structures are setup to minimize the computation done by the ISR which
|
||||
* minimizes ISR execution time. Execution times are 2.2 - 3.7 microseconds.
|
||||
*
|
||||
* Two tables are used. active_table is used by the ISR. Changes to the table are
|
||||
* are done by copying the active_table into the work_table, updating the work_table
|
||||
* and then swapping the two tables. Swapping is done by manipulating pointers.
|
||||
*
|
||||
* Immediately after the swap the ISR uses the work_table until the start of the
|
||||
* next 20mS cycle. During this transition the "work_table" is actually the table
|
||||
* that was being used before the swap. The "active_table" contains the data that
|
||||
* will start being used at the start of the next 20mS period. This keeps the pins
|
||||
* well behaved during the transition.
|
||||
*
|
||||
* The ISR's priority is set to the maximum otherwise other ISRs can cause considerable
|
||||
* jitter in the PWM high time.
|
||||
*
|
||||
* See the end of this file for details on the hardware/firmware interaction
|
||||
*/
|
||||
|
||||
#ifndef _LPC1768_PWM_H_
|
||||
#define _LPC1768_PWM_H_
|
||||
|
||||
#include <pinmapping.h>
|
||||
#include <lpc17xx_clkpwr.h>
|
||||
|
||||
#define LPC_PWM1_MR0 19999 // base repetition rate minus one count - 20mS
|
||||
#define LPC_PWM1_PCLKSEL0 CLKPWR_PCLKSEL_CCLK_DIV_4 // select clock divider for prescaler - defaults to 4 on power up
|
||||
#define MR0_MARGIN 200 // if channel value too close to MR0 the system locks up
|
||||
|
||||
void LPC1768_PWM_init(void);
|
||||
bool LPC1768_PWM_attach_pin(pin_t pin, uint32_t min=1, uint32_t max=(LPC_PWM1_MR0 - (MR0_MARGIN)), uint8_t servo_index=0xFF);
|
||||
bool LPC1768_PWM_write(pin_t pin, uint32_t value);
|
||||
bool LPC1768_PWM_detach_pin(pin_t pin);
|
||||
bool useable_hardware_PWM(pin_t pin);
|
||||
|
||||
#endif // _LPC1768_PWM_H_
|
||||
@@ -1,163 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on servo.cpp - Interrupt driven Servo library for Arduino using 16 bit
|
||||
* timers- Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
|
||||
* The servos are pulsed in the background using the value most recently written using the write() method
|
||||
*
|
||||
* Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
|
||||
* Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
|
||||
*
|
||||
* The methods are:
|
||||
*
|
||||
* Servo - Class for manipulating servo motors connected to Arduino pins.
|
||||
*
|
||||
* attach(pin) - Attach a servo motor to an i/o pin.
|
||||
* attach(pin, min, max) - Attach to a pin, setting min and max values in microseconds
|
||||
* Default min is 544, max is 2400
|
||||
*
|
||||
* write() - Set the servo angle in degrees. (Invalid angles —over MIN_PULSE_WIDTH— are treated as µs.)
|
||||
* writeMicroseconds() - Set the servo pulse width in microseconds.
|
||||
* move(pin, angle) - Sequence of attach(pin), write(angle), safe_delay(servo_delay[servoIndex]).
|
||||
* With DEACTIVATE_SERVOS_AFTER_MOVE it detaches after servo_delay[servoIndex].
|
||||
* read() - Get the last-written servo pulse width as an angle between 0 and 180.
|
||||
* readMicroseconds() - Get the last-written servo pulse width in microseconds.
|
||||
* attached() - Return true if a servo is attached.
|
||||
* detach() - Stop an attached servo from pulsing its i/o pin.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The only time that this library wants physical movement is when a WRITE
|
||||
* command is issued. Before that all the attach & detach activity is solely
|
||||
* within the data base.
|
||||
*
|
||||
* The PWM output is inactive until the first WRITE. After that it stays active
|
||||
* unless DEACTIVATE_SERVOS_AFTER_MOVE is enabled and a MOVE command was issued.
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SERVOS
|
||||
|
||||
#include "LPC1768_PWM.h"
|
||||
#include "LPC1768_Servo.h"
|
||||
#include "servo_private.h"
|
||||
|
||||
ServoInfo_t servo_info[MAX_SERVOS]; // static array of servo info structures
|
||||
uint8_t ServoCount = 0; // the total number of attached servos
|
||||
|
||||
#define US_TO_PULSE_WIDTH(p) p
|
||||
#define PULSE_WIDTH_TO_US(p) p
|
||||
#define TRIM_DURATION 0
|
||||
#define SERVO_MIN() MIN_PULSE_WIDTH // minimum value in uS for this servo
|
||||
#define SERVO_MAX() MAX_PULSE_WIDTH // maximum value in uS for this servo
|
||||
|
||||
Servo::Servo() {
|
||||
if (ServoCount < MAX_SERVOS) {
|
||||
this->servoIndex = ServoCount++; // assign a servo index to this instance
|
||||
servo_info[this->servoIndex].pulse_width = US_TO_PULSE_WIDTH(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
|
||||
}
|
||||
else
|
||||
this->servoIndex = INVALID_SERVO; // too many servos
|
||||
}
|
||||
|
||||
int8_t Servo::attach(const int pin) {
|
||||
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
|
||||
}
|
||||
|
||||
int8_t Servo::attach(const int pin, const int min, const int max) {
|
||||
|
||||
if (this->servoIndex >= MAX_SERVOS) return -1;
|
||||
|
||||
if (pin > 0) servo_info[this->servoIndex].Pin.nbr = pin; // only assign a pin value if the pin info is
|
||||
// greater than zero. This way the init routine can
|
||||
// assign the pin and the MOVE command only needs the value.
|
||||
|
||||
this->min = MIN_PULSE_WIDTH; //resolution of min/max is 1 uS
|
||||
this->max = MAX_PULSE_WIDTH;
|
||||
|
||||
servo_info[this->servoIndex].Pin.isActive = true;
|
||||
|
||||
return this->servoIndex;
|
||||
}
|
||||
|
||||
void Servo::detach() {
|
||||
servo_info[this->servoIndex].Pin.isActive = false;
|
||||
}
|
||||
|
||||
void Servo::write(int value) {
|
||||
if (value < MIN_PULSE_WIDTH) { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
|
||||
value = map(constrain(value, 0, 180), 0, 180, SERVO_MIN(), SERVO_MAX());
|
||||
// odd - this sets zero degrees to 544 and 180 degrees to 2400 microseconds but the literature says
|
||||
// zero degrees should be 500 microseconds and 180 should be 2500
|
||||
}
|
||||
this->writeMicroseconds(value);
|
||||
}
|
||||
|
||||
void Servo::writeMicroseconds(int value) {
|
||||
// calculate and store the values for the given channel
|
||||
byte channel = this->servoIndex;
|
||||
if (channel < MAX_SERVOS) { // ensure channel is valid
|
||||
// ensure pulse width is valid
|
||||
value = constrain(value, SERVO_MIN(), SERVO_MAX()) - (TRIM_DURATION);
|
||||
value = US_TO_PULSE_WIDTH(value); // convert to pulse_width after compensating for interrupt overhead - 12 Aug 2009
|
||||
|
||||
servo_info[channel].pulse_width = value;
|
||||
LPC1768_PWM_attach_pin(servo_info[this->servoIndex].Pin.nbr, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH, this->servoIndex);
|
||||
LPC1768_PWM_write(servo_info[this->servoIndex].Pin.nbr, value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// return the value as degrees
|
||||
int Servo::read() { return map(this->readMicroseconds() + 1, SERVO_MIN(), SERVO_MAX(), 0, 180); }
|
||||
|
||||
int Servo::readMicroseconds() {
|
||||
return (this->servoIndex == INVALID_SERVO) ? 0 : PULSE_WIDTH_TO_US(servo_info[this->servoIndex].pulse_width) + TRIM_DURATION;
|
||||
}
|
||||
|
||||
bool Servo::attached() { return servo_info[this->servoIndex].Pin.isActive; }
|
||||
|
||||
void Servo::move(const int value) {
|
||||
constexpr uint16_t servo_delay[] = SERVO_DELAY;
|
||||
static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
|
||||
if (this->attach(0) >= 0) { // notice the pin number is zero here
|
||||
this->write(value);
|
||||
safe_delay(servo_delay[this->servoIndex]);
|
||||
#if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
|
||||
this->detach();
|
||||
LPC1768_PWM_detach_pin(servo_info[this->servoIndex].Pin.nbr); // shut down the PWM signal
|
||||
LPC1768_PWM_attach_pin(servo_info[this->servoIndex].Pin.nbr, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH, this->servoIndex); // make sure no one else steals the slot
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_SERVOS
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The class Servo uses the PWM class to implement its functions
|
||||
*
|
||||
* The PWM1 module is only used to generate interrups at specified times. It
|
||||
* is NOT used to directly toggle pins. The ISR writes to the pin assigned to
|
||||
* that interrupt
|
||||
*
|
||||
* All PWMs use the same repetition rate - 20mS because that's the normal servo rate
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LPC1768_SERVO_H
|
||||
#define LPC1768_SERVO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class Servo {
|
||||
public:
|
||||
Servo();
|
||||
int8_t attach(const int pin); // attach the given pin to the next free channel, set pinMode, return channel number (-1 on fail)
|
||||
int8_t attach(const int pin, const int min, const int max); // as above but also sets min and max values for writes.
|
||||
void detach();
|
||||
void write(int value); // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
void writeMicroseconds(int value); // write pulse width in microseconds
|
||||
void move(const int value); // attach the servo, then move to value
|
||||
// if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
// if DEACTIVATE_SERVOS_AFTER_MOVE wait SERVO_DELAY, then detach
|
||||
int read(); // returns current pulse width as an angle between 0 and 180 degrees
|
||||
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
|
||||
bool attached(); // return true if this servo is attached, otherwise false
|
||||
|
||||
private:
|
||||
uint8_t servoIndex; // index into the channel data for this servo
|
||||
int min;
|
||||
int max;
|
||||
};
|
||||
|
||||
#define HAL_SERVO_LIB Servo
|
||||
|
||||
#endif // LPC1768_SERVO_H
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "MarlinSerial.h"
|
||||
|
||||
#if (defined(SERIAL_PORT) && SERIAL_PORT == 0) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 0)
|
||||
MarlinSerial MSerial(LPC_UART0);
|
||||
extern "C" void UART0_IRQHandler(void) {
|
||||
MSerial.IRQHandler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(SERIAL_PORT) && SERIAL_PORT == 1) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 1)
|
||||
MarlinSerial MSerial1((LPC_UART_TypeDef *) LPC_UART1);
|
||||
extern "C" void UART1_IRQHandler(void) {
|
||||
MSerial1.IRQHandler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(SERIAL_PORT) && SERIAL_PORT == 2) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 2)
|
||||
MarlinSerial MSerial2(LPC_UART2);
|
||||
extern "C" void UART2_IRQHandler(void) {
|
||||
MSerial2.IRQHandler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(SERIAL_PORT) && SERIAL_PORT == 3) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 3)
|
||||
MarlinSerial MSerial3(LPC_UART3);
|
||||
extern "C" void UART3_IRQHandler(void) {
|
||||
MSerial3.IRQHandler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <HardwareSerial.h>
|
||||
#include <WString.h>
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../../feature/emergency_parser.h"
|
||||
#endif
|
||||
|
||||
#ifndef SERIAL_PORT
|
||||
#define SERIAL_PORT 0
|
||||
#endif
|
||||
#ifndef RX_BUFFER_SIZE
|
||||
#define RX_BUFFER_SIZE 128
|
||||
#endif
|
||||
#ifndef TX_BUFFER_SIZE
|
||||
#define TX_BUFFER_SIZE 32
|
||||
#endif
|
||||
|
||||
class MarlinSerial : public HardwareSerial<RX_BUFFER_SIZE, TX_BUFFER_SIZE> {
|
||||
public:
|
||||
MarlinSerial(LPC_UART_TypeDef *UARTx) :
|
||||
HardwareSerial<RX_BUFFER_SIZE, TX_BUFFER_SIZE>(UARTx)
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
, emergency_state(EmergencyParser::State::EP_RESET)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
bool recv_callback(const char c) override {
|
||||
emergency_parser.update(emergency_state, c);
|
||||
return true; // do not discard character
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
EmergencyParser::State emergency_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern MarlinSerial MSerial;
|
||||
extern MarlinSerial MSerial1;
|
||||
extern MarlinSerial MSerial2;
|
||||
extern MarlinSerial MSerial3;
|
||||
+17
-31
@@ -38,6 +38,7 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Based on "servo.h - Interrupt driven Servo library for Arduino using 16 bit timers -
|
||||
@@ -47,38 +48,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SERVO_PRIVATE_H
|
||||
#define SERVO_PRIVATE_H
|
||||
#include <Servo.h>
|
||||
|
||||
#include <stdint.h>
|
||||
class MarlinServo: public Servo {
|
||||
public:
|
||||
void move(const int value) {
|
||||
constexpr uint16_t servo_delay[] = SERVO_DELAY;
|
||||
static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
|
||||
|
||||
// Macros
|
||||
//values in microseconds
|
||||
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
|
||||
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
|
||||
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
|
||||
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds
|
||||
if (this->attach(servo_info[this->servoIndex].Pin.nbr) >= 0) { // try to reattach
|
||||
this->write(value);
|
||||
safe_delay(servo_delay[this->servoIndex]); // delay to allow servo to reach position
|
||||
#if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
|
||||
this->detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MAX_SERVOS 4
|
||||
}
|
||||
};
|
||||
|
||||
#define INVALID_SERVO 255 // flag indicating an invalid servo index
|
||||
|
||||
|
||||
// Types
|
||||
|
||||
typedef struct {
|
||||
uint8_t nbr : 8 ; // a pin number from 0 to 254 (255 signals invalid pin)
|
||||
uint8_t isActive : 1 ; // true if this channel is enabled, pin not pulsed if false
|
||||
} ServoPin_t;
|
||||
|
||||
typedef struct {
|
||||
ServoPin_t Pin;
|
||||
unsigned int pulse_width; // pulse width in microseconds
|
||||
} ServoInfo_t;
|
||||
|
||||
// Global variables
|
||||
|
||||
extern uint8_t ServoCount;
|
||||
extern ServoInfo_t servo_info[MAX_SERVOS];
|
||||
|
||||
#endif // SERVO_PRIVATE_H
|
||||
#define HAL_SERVO_LIB MarlinServo
|
||||
@@ -74,3 +74,11 @@
|
||||
|| MB(RAMPS_14_RE_ARM_SF))
|
||||
#error "Re-ARM with REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER and TMC2130 require TMC_USE_SW_SPI"
|
||||
#endif
|
||||
|
||||
#if 1 < (ENABLED(LPC_SD_CUSTOM_CABLE) + ENABLED(LPC_SD_LCD) + ENABLED(LPC_SD_ONBOARD))
|
||||
#error "Enable only one of LPC_SD_CUSTOM_CABLE, LPC_SD_LCD, or LPC_SD_ONBOARD."
|
||||
#endif
|
||||
|
||||
#if 1 < (ENABLED(USB_SD_DISABLED) + ENABLED(USB_SD_ONBOARD))
|
||||
#error "Enable only one of USB_SD_DISABLED or USB_SD_ONBOARD."
|
||||
#endif
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016, 2017 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Software SPI functions originally from Arduino Sd2Card Library
|
||||
* Copyright (C) 2009 by William Greiman
|
||||
*/
|
||||
|
||||
/**
|
||||
* For TARGET_LPC1768
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Software SPI
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This software SPI runs at multiple rates. The SD software provides an index
|
||||
* (spiRate) of 0-6. The mapping is:
|
||||
* 0 - about 5 MHz peak (6 MHz on LPC1769)
|
||||
* 1-2 - about 2 MHz peak
|
||||
* 3 - about 1 MHz peak
|
||||
* 4 - about 500 kHz peak
|
||||
* 5 - about 250 kHz peak
|
||||
* 6 - about 125 kHz peak
|
||||
*/
|
||||
|
||||
uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin) {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (spi_speed == 0) {
|
||||
WRITE(mosi_pin, !!(b & 0x80));
|
||||
WRITE(sck_pin, HIGH);
|
||||
b <<= 1;
|
||||
if (miso_pin >= 0 && READ(miso_pin)) b |= 1;
|
||||
WRITE(sck_pin, LOW);
|
||||
}
|
||||
else {
|
||||
const uint8_t state = (b & 0x80) ? HIGH : LOW;
|
||||
for (uint8_t j = 0; j < spi_speed; j++)
|
||||
WRITE(mosi_pin, state);
|
||||
|
||||
for (uint8_t j = 0; j < spi_speed + (miso_pin >= 0 ? 0 : 1); j++)
|
||||
WRITE(sck_pin, HIGH);
|
||||
|
||||
b <<= 1;
|
||||
if (miso_pin >= 0 && READ(miso_pin)) b |= 1;
|
||||
|
||||
for (uint8_t j = 0; j < spi_speed; j++)
|
||||
WRITE(sck_pin, LOW);
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
void swSpiBegin(const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin) {
|
||||
SET_OUTPUT(sck_pin);
|
||||
if (VALID_PIN(miso_pin)) SET_INPUT(miso_pin);
|
||||
SET_OUTPUT(mosi_pin);
|
||||
}
|
||||
|
||||
uint8_t swSpiInit(const uint8_t spiRate, const pin_t sck_pin, const pin_t mosi_pin) {
|
||||
WRITE(mosi_pin, HIGH);
|
||||
WRITE(sck_pin, LOW);
|
||||
return (SystemCoreClock == 120000000 ? 44 : 38) / POW(2, 6 - MIN(spiRate, 6));
|
||||
}
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SOFTWARE_SPI_H_
|
||||
#define _SOFTWARE_SPI_H_
|
||||
|
||||
#include <pinmapping.h>
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Software SPI
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This software SPI runs at multiple rates. The SD software provides an index
|
||||
* (spiRate) of 0-6. The mapping is:
|
||||
* 0 - about 5 MHz peak (6 MHz on LPC1769)
|
||||
* 1-2 - about 2 MHz peak
|
||||
* 3 - about 1 MHz peak
|
||||
* 4 - about 500 kHz peak
|
||||
* 5 - about 250 kHz peak
|
||||
* 6 - about 125 kHz peak
|
||||
*/
|
||||
|
||||
void swSpiBegin(const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin);
|
||||
|
||||
// Returns the spi_speed value to be passed to swSpiTransfer
|
||||
uint8_t swSpiInit(const uint8_t spiRate, const pin_t sck_pin, const pin_t mosi_pin);
|
||||
|
||||
uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin);
|
||||
|
||||
#endif // _SOFTWARE_SPI_H_
|
||||
@@ -1,162 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2012 Arduino. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#define GNUM 31
|
||||
|
||||
typedef void (*interruptCB)(void);
|
||||
|
||||
static interruptCB callbacksP0[GNUM] = {};
|
||||
static interruptCB callbacksP2[GNUM] = {};
|
||||
|
||||
extern "C" void GpioEnableInt(const uint32_t port, const uint32_t pin, const uint32_t mode);
|
||||
extern "C" void GpioDisableInt(const uint32_t port, const uint32_t pin);
|
||||
|
||||
|
||||
static void __initialize() {
|
||||
NVIC_SetPriority(EINT3_IRQn, NVIC_EncodePriority(0, 1, 0));
|
||||
NVIC_EnableIRQ(EINT3_IRQn);
|
||||
}
|
||||
|
||||
void attachInterrupt(const pin_t pin, void (*callback)(void), uint32_t mode) {
|
||||
static int enabled = 0;
|
||||
|
||||
if (!INTERRUPT_PIN(pin)) return;
|
||||
|
||||
if (!enabled) {
|
||||
__initialize();
|
||||
++enabled;
|
||||
}
|
||||
|
||||
uint8_t myport = LPC1768_PIN_PORT(pin),
|
||||
mypin = LPC1768_PIN_PIN(pin);
|
||||
|
||||
if (myport == 0)
|
||||
callbacksP0[mypin] = callback;
|
||||
else
|
||||
callbacksP2[mypin] = callback;
|
||||
|
||||
// Enable interrupt
|
||||
GpioEnableInt(myport,mypin,mode);
|
||||
}
|
||||
|
||||
void detachInterrupt(const pin_t pin) {
|
||||
if (!INTERRUPT_PIN(pin)) return;
|
||||
|
||||
const uint8_t myport = LPC1768_PIN_PORT(pin),
|
||||
mypin = LPC1768_PIN_PIN(pin);
|
||||
|
||||
// Disable interrupt
|
||||
GpioDisableInt(myport, mypin);
|
||||
|
||||
// unset callback
|
||||
if (myport == 0)
|
||||
callbacksP0[mypin] = 0;
|
||||
else //if (myport == 2 )
|
||||
callbacksP2[mypin] = 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode) {
|
||||
//pin here is the processor pin, not logical pin
|
||||
if (port == 0) {
|
||||
LPC_GPIOINT->IO0IntClr = _BV(pin);
|
||||
if (mode == RISING) {
|
||||
SBI(LPC_GPIOINT->IO0IntEnR, pin);
|
||||
CBI(LPC_GPIOINT->IO0IntEnF, pin);
|
||||
}
|
||||
else if (mode == FALLING) {
|
||||
SBI(LPC_GPIOINT->IO0IntEnF, pin);
|
||||
CBI(LPC_GPIOINT->IO0IntEnR, pin);
|
||||
}
|
||||
else if (mode == CHANGE) {
|
||||
SBI(LPC_GPIOINT->IO0IntEnR, pin);
|
||||
SBI(LPC_GPIOINT->IO0IntEnF, pin);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LPC_GPIOINT->IO2IntClr = _BV(pin);
|
||||
if (mode == RISING) {
|
||||
SBI(LPC_GPIOINT->IO2IntEnR, pin);
|
||||
CBI(LPC_GPIOINT->IO2IntEnF, pin);
|
||||
}
|
||||
else if (mode == FALLING) {
|
||||
SBI(LPC_GPIOINT->IO2IntEnF, pin);
|
||||
CBI(LPC_GPIOINT->IO2IntEnR, pin);
|
||||
}
|
||||
else if (mode == CHANGE) {
|
||||
SBI(LPC_GPIOINT->IO2IntEnR, pin);
|
||||
SBI(LPC_GPIOINT->IO2IntEnF, pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void GpioDisableInt(const uint32_t port, const uint32_t pin) {
|
||||
if (port == 0) {
|
||||
CBI(LPC_GPIOINT->IO0IntEnR, pin);
|
||||
CBI(LPC_GPIOINT->IO0IntEnF, pin);
|
||||
LPC_GPIOINT->IO0IntClr = _BV(pin);
|
||||
}
|
||||
else {
|
||||
CBI(LPC_GPIOINT->IO2IntEnR, pin);
|
||||
CBI(LPC_GPIOINT->IO2IntEnF, pin);
|
||||
LPC_GPIOINT->IO2IntClr = _BV(pin);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void EINT3_IRQHandler(void) {
|
||||
// Read in all current interrupt registers. We do this once as the
|
||||
// GPIO interrupt registers are on the APB bus, and this is slow.
|
||||
uint32_t rise0 = LPC_GPIOINT->IO0IntStatR,
|
||||
fall0 = LPC_GPIOINT->IO0IntStatF,
|
||||
rise2 = LPC_GPIOINT->IO2IntStatR,
|
||||
fall2 = LPC_GPIOINT->IO2IntStatF;
|
||||
|
||||
// Clear the interrupts ASAP
|
||||
LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF;
|
||||
NVIC_ClearPendingIRQ(EINT3_IRQn);
|
||||
|
||||
while (rise0 > 0) { // If multiple pins changes happened continue as long as there are interrupts pending
|
||||
const uint8_t bitloc = 31 - __CLZ(rise0); // CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt
|
||||
if (callbacksP0[bitloc] != NULL) callbacksP0[bitloc]();
|
||||
rise0 -= _BV(bitloc);
|
||||
}
|
||||
|
||||
while (fall0 > 0) {
|
||||
const uint8_t bitloc = 31 - __CLZ(fall0);
|
||||
if (callbacksP0[bitloc] != NULL) callbacksP0[bitloc]();
|
||||
fall0 -= _BV(bitloc);
|
||||
}
|
||||
|
||||
while(rise2 > 0) {
|
||||
const uint8_t bitloc = 31 - __CLZ(rise2);
|
||||
if (callbacksP2[bitloc] != NULL) callbacksP2[bitloc]();
|
||||
rise2 -= _BV(bitloc);
|
||||
}
|
||||
|
||||
while (fall2 > 0) {
|
||||
const uint8_t bitloc = 31 - __CLZ(fall2);
|
||||
if (callbacksP2[bitloc] != NULL) callbacksP2[bitloc]();
|
||||
fall2 -= _BV(bitloc);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,179 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "LPC1768_PWM.h"
|
||||
#include <lpc17xx_pinsel.h>
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../shared/Delay.h"
|
||||
|
||||
// Interrupts
|
||||
void cli(void) { __disable_irq(); } // Disable
|
||||
void sei(void) { __enable_irq(); } // Enable
|
||||
|
||||
// Time functions
|
||||
void _delay_ms(const int delay_ms) {
|
||||
delay(delay_ms);
|
||||
}
|
||||
|
||||
uint32_t millis() {
|
||||
return _millis;
|
||||
}
|
||||
|
||||
// This is required for some Arduino libraries we are using
|
||||
void delayMicroseconds(uint32_t us) {
|
||||
DELAY_US(us);
|
||||
}
|
||||
|
||||
extern "C" void delay(const int msec) {
|
||||
volatile millis_t end = _millis + msec;
|
||||
SysTick->VAL = SysTick->LOAD; // reset systick counter so next systick is in exactly 1ms
|
||||
// this could extend the time between systicks by upto 1ms
|
||||
while PENDING(_millis, end) __WFE();
|
||||
}
|
||||
|
||||
// IO functions
|
||||
// As defined by Arduino INPUT(0x0), OUTPUT(0x1), INPUT_PULLUP(0x2)
|
||||
void pinMode(const pin_t pin, const uint8_t mode) {
|
||||
if (!VALID_PIN(pin)) return;
|
||||
|
||||
PINSEL_CFG_Type config = { LPC1768_PIN_PORT(pin),
|
||||
LPC1768_PIN_PIN(pin),
|
||||
PINSEL_FUNC_0,
|
||||
PINSEL_PINMODE_TRISTATE,
|
||||
PINSEL_PINMODE_NORMAL };
|
||||
switch (mode) {
|
||||
case INPUT:
|
||||
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin));
|
||||
break;
|
||||
case OUTPUT:
|
||||
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR |= LPC_PIN(LPC1768_PIN_PIN(pin));
|
||||
break;
|
||||
case INPUT_PULLUP:
|
||||
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin));
|
||||
config.Pinmode = PINSEL_PINMODE_PULLUP;
|
||||
break;
|
||||
case INPUT_PULLDOWN:
|
||||
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin));
|
||||
config.Pinmode = PINSEL_PINMODE_PULLDOWN;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
PINSEL_ConfigPin(&config);
|
||||
}
|
||||
|
||||
void digitalWrite(pin_t pin, uint8_t pin_status) {
|
||||
if (!VALID_PIN(pin)) return;
|
||||
|
||||
if (pin_status)
|
||||
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOSET = LPC_PIN(LPC1768_PIN_PIN(pin));
|
||||
else
|
||||
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOCLR = LPC_PIN(LPC1768_PIN_PIN(pin));
|
||||
|
||||
pinMode(pin, OUTPUT); // Set pin mode on every write (Arduino version does this)
|
||||
|
||||
/**
|
||||
* Must be done AFTER the output state is set. Doing this before will cause a
|
||||
* 2uS glitch if writing a "1".
|
||||
*
|
||||
* When the Port Direction bit is written to a "1" the output is immediately set
|
||||
* to the value of the FIOPIN bit which is "0" because of power up defaults.
|
||||
*/
|
||||
}
|
||||
|
||||
bool digitalRead(pin_t pin) {
|
||||
if (!VALID_PIN(pin)) return false;
|
||||
|
||||
return LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOPIN & LPC_PIN(LPC1768_PIN_PIN(pin)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void analogWrite(pin_t pin, int pwm_value) { // 1 - 254: pwm_value, 0: LOW, 255: HIGH
|
||||
if (!VALID_PIN(pin)) return;
|
||||
|
||||
#define MR0_MARGIN 200 // if channel value too close to MR0 the system locks up
|
||||
|
||||
static bool out_of_PWM_slots = false;
|
||||
|
||||
uint value = MAX(MIN(pwm_value, 255), 0);
|
||||
if (value == 0 || value == 255) { // treat as digital pin
|
||||
LPC1768_PWM_detach_pin(pin); // turn off PWM
|
||||
digitalWrite(pin, value);
|
||||
}
|
||||
else {
|
||||
if (LPC1768_PWM_attach_pin(pin, 1, LPC_PWM1->MR0, 0xFF))
|
||||
LPC1768_PWM_write(pin, map(value, 0, 255, 1, LPC_PWM1->MR0)); // map 1-254 onto PWM range
|
||||
else { // out of PWM channels
|
||||
if (!out_of_PWM_slots) SERIAL_ECHOPGM(".\nWARNING - OUT OF PWM CHANNELS\n.\n"); //only warn once
|
||||
out_of_PWM_slots = true;
|
||||
digitalWrite(pin, value); // treat as a digital pin if out of channels
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern bool HAL_adc_finished();
|
||||
|
||||
uint16_t analogRead(pin_t adc_pin) {
|
||||
HAL_adc_start_conversion(adc_pin);
|
||||
while (!HAL_adc_finished()); // Wait for conversion to finish
|
||||
return HAL_adc_get_result();
|
||||
}
|
||||
|
||||
// **************************
|
||||
// Persistent Config Storage
|
||||
// **************************
|
||||
|
||||
void eeprom_write_byte(unsigned char *pos, unsigned char value) {
|
||||
|
||||
}
|
||||
|
||||
unsigned char eeprom_read_byte(uint8_t * pos) { return '\0'; }
|
||||
|
||||
void eeprom_read_block(void *__dst, const void *__src, size_t __n) { }
|
||||
|
||||
void eeprom_update_block(const void *__src, void *__dst, size_t __n) { }
|
||||
|
||||
char *dtostrf (double __val, signed char __width, unsigned char __prec, char *__s) {
|
||||
char format_string[20];
|
||||
snprintf(format_string, 20, "%%%d.%df", __width, __prec);
|
||||
sprintf(__s, format_string, __val);
|
||||
return __s;
|
||||
}
|
||||
|
||||
int32_t random(int32_t max) {
|
||||
return rand() % max;
|
||||
}
|
||||
|
||||
int32_t random(int32_t min, int32_t max) {
|
||||
return min + rand() % (max - min);
|
||||
}
|
||||
|
||||
void randomSeed(uint32_t value) {
|
||||
srand(value);
|
||||
}
|
||||
|
||||
int map(uint16_t x, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max) {
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,21 +0,0 @@
|
||||
Import("env")
|
||||
|
||||
env.AddPostAction(
|
||||
"$BUILD_DIR/firmware.hex",
|
||||
env.VerboseAction(" ".join([
|
||||
"sed", "-i.bak",
|
||||
"s/:10040000FFFFFFFFFFFFFFFFFFFFFFFFDEF9FFFF23/:10040000FFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFD/",
|
||||
"$BUILD_DIR/firmware.hex"
|
||||
]), "Fixing $BUILD_DIR/firmware.hex secure flash flags"))
|
||||
env.AddPreAction(
|
||||
"upload",
|
||||
env.VerboseAction(" ".join([
|
||||
"echo",
|
||||
"'h\\nloadfile $BUILD_DIR/firmware.hex\\nr\\nq\\n'",
|
||||
">$BUILD_DIR/aux.jlink"
|
||||
]), "Creating auxiliary files"))
|
||||
|
||||
env.Replace(
|
||||
UPLOADHEXCMD=
|
||||
'JLinkExe -device MK20DX256xxx7 -speed 4000 -if swd -autoconnect 1 -CommanderScript $BUILD_DIR/aux.jlink -SkipProgOnCRCMatch = 1 -VerifyDownload = 1'
|
||||
)
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Endstop Interrupts
|
||||
@@ -34,9 +35,6 @@
|
||||
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
|
||||
*/
|
||||
|
||||
#ifndef _ENDSTOP_INTERRUPTS_H_
|
||||
#define _ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
#include "../../module/endstops.h"
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
@@ -92,9 +90,15 @@ void setup_endstop_interrupts(void) {
|
||||
attachInterrupt(digitalPinToInterrupt(Z2_MIN_PIN), endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_Z3_MAX
|
||||
#if !LPC1768_PIN_INTERRUPT_M(Z3_MIN_PIN)
|
||||
#error "Z3_MIN_PIN is not an INTERRUPT capable pin."
|
||||
#endif
|
||||
attachInterrupt(digitalPinToInterrupt(Z3_MAX_PIN), endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_Z3_MIN
|
||||
#if !LPC1768_PIN_INTERRUPT_M(Z3_MIN_PIN)
|
||||
#error "Z3_MIN_PIN is not an INTERRUPT capable pin."
|
||||
#endif
|
||||
attachInterrupt(digitalPinToInterrupt(Z3_MIN_PIN), endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_Z_MIN_PROBE_PIN
|
||||
@@ -104,5 +108,3 @@ void setup_endstop_interrupts(void) {
|
||||
attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //_ENDSTOP_INTERRUPTS_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Fast I/O Routines for LPC1768/9
|
||||
@@ -32,30 +33,23 @@
|
||||
* For TARGET LPC1768
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_LPC1768_H
|
||||
#define _FASTIO_LPC1768_H
|
||||
|
||||
#include <LPC17xx.h>
|
||||
#include <Arduino.h>
|
||||
#include <pinmapping.h>
|
||||
|
||||
bool useable_hardware_PWM(pin_t pin);
|
||||
#define USEABLE_HARDWARE_PWM(pin) useable_hardware_PWM(pin)
|
||||
#define USEABLE_HARDWARE_PWM(pin) TRUE // all pins are PWM capable
|
||||
|
||||
#define LPC_PORT_OFFSET (0x0020)
|
||||
#define LPC_PIN(pin) (1UL << pin)
|
||||
#define LPC_GPIO(port) ((volatile LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + LPC_PORT_OFFSET * port))
|
||||
#define LPC_PIN(pin) gpio_pin(pin)
|
||||
#define LPC_GPIO(port) gpio_port(port)
|
||||
|
||||
#define SET_DIR_INPUT(IO) (LPC_GPIO(LPC1768_PIN_PORT(IO))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(IO)))
|
||||
#define SET_DIR_OUTPUT(IO) (LPC_GPIO(LPC1768_PIN_PORT(IO))->FIODIR |= LPC_PIN(LPC1768_PIN_PIN(IO)))
|
||||
#define SET_DIR_INPUT(IO) gpio_set_input(IO)
|
||||
#define SET_DIR_OUTPUT(IO) gpio_set_output(IO)
|
||||
|
||||
#define SET_MODE(IO, mode) (pin_mode((LPC1768_PIN_PORT(IO), LPC1768_PIN_PIN(IO)), mode))
|
||||
#define SET_MODE(IO, mode) pinMode(IO, mode)
|
||||
|
||||
#define WRITE_PIN_SET(IO) (LPC_GPIO(LPC1768_PIN_PORT(IO))->FIOSET = LPC_PIN(LPC1768_PIN_PIN(IO)))
|
||||
#define WRITE_PIN_CLR(IO) (LPC_GPIO(LPC1768_PIN_PORT(IO))->FIOCLR = LPC_PIN(LPC1768_PIN_PIN(IO)))
|
||||
#define WRITE_PIN_SET(IO) gpio_set(IO)
|
||||
#define WRITE_PIN_CLR(IO) gpio_clear(IO)
|
||||
|
||||
#define READ_PIN(IO) ((LPC_GPIO(LPC1768_PIN_PORT(IO))->FIOPIN & LPC_PIN(LPC1768_PIN_PIN(IO))) ? 1 : 0)
|
||||
#define WRITE_PIN(IO,V) ((V) ? WRITE_PIN_SET(IO) : WRITE_PIN_CLR(IO))
|
||||
#define READ_PIN(IO) gpio_get(IO)
|
||||
#define WRITE_PIN(IO,V) gpio_set(IO, V)
|
||||
|
||||
/**
|
||||
* Magic I/O routines
|
||||
@@ -89,10 +83,10 @@ bool useable_hardware_PWM(pin_t pin);
|
||||
#define _PULLDOWN(IO,V) pinMode(IO, (V) ? INPUT_PULLDOWN : INPUT)
|
||||
|
||||
/// check if pin is an input
|
||||
#define _GET_INPUT(IO) (LPC_GPIO(LPC1768_PIN_PORT(IO))->FIODIR & LPC_PIN(LPC1768_PIN_PIN(IO)) != 0)
|
||||
#define _GET_INPUT(IO) (!gpio_get_dir(IO))
|
||||
|
||||
/// check if pin is an output
|
||||
#define _GET_OUTPUT(IO) (LPC_GPIO(LPC1768_PIN_PORT(IO))->FIODIR & LPC_PIN(LPC1768_PIN_PIN(IO)) == 0)
|
||||
#define _GET_OUTPUT(IO) (gpio_get_dir(IO))
|
||||
|
||||
/// check if pin is a timer
|
||||
/// all gpio pins are pwm capable, either interrupt or hardware pwm controlled
|
||||
@@ -127,5 +121,3 @@ bool useable_hardware_PWM(pin_t pin);
|
||||
|
||||
// Shorthand
|
||||
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
|
||||
|
||||
#endif // _FASTIO_LPC1768_H
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARDUINO_H__
|
||||
#define __ARDUINO_H__
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <pinmapping.h>
|
||||
|
||||
#define HIGH 0x01
|
||||
#define LOW 0x00
|
||||
|
||||
#define INPUT 0x00
|
||||
#define OUTPUT 0x01
|
||||
#define INPUT_PULLUP 0x02
|
||||
#define INPUT_PULLDOWN 0x03
|
||||
|
||||
#define LSBFIRST 0
|
||||
#define MSBFIRST 1
|
||||
|
||||
#define CHANGE 0x02
|
||||
#define FALLING 0x03
|
||||
#define RISING 0x04
|
||||
|
||||
typedef uint8_t byte;
|
||||
#define PROGMEM
|
||||
#define PSTR(v) (v)
|
||||
#define PGM_P const char *
|
||||
|
||||
// Used for libraries, preprocessor, and constants
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define abs(x) ((x)>0?(x):-(x))
|
||||
|
||||
#ifndef isnan
|
||||
#define isnan std::isnan
|
||||
#endif
|
||||
#ifndef isinf
|
||||
#define isinf std::isinf
|
||||
#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
|
||||
void cli(void); // Disable
|
||||
void sei(void); // Enable
|
||||
void attachInterrupt(const pin_t pin, void (*callback)(void), uint32_t mode);
|
||||
void detachInterrupt(const pin_t pin);
|
||||
extern "C" void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
|
||||
extern "C" void GpioDisableInt(uint32_t port, uint32_t pin);
|
||||
|
||||
// Program Memory
|
||||
#define pgm_read_ptr(addr) (*((void**)(addr)))
|
||||
#define pgm_read_byte_near(addr) (*((uint8_t*)(addr)))
|
||||
#define pgm_read_float_near(addr) (*((float*)(addr)))
|
||||
#define pgm_read_word_near(addr) (*((uint16_t*)(addr)))
|
||||
#define pgm_read_dword_near(addr) (*((uint32_t*)(addr)))
|
||||
#define pgm_read_byte(addr) pgm_read_byte_near(addr)
|
||||
#define pgm_read_float(addr) pgm_read_float_near(addr)
|
||||
#define pgm_read_word(addr) pgm_read_word_near(addr)
|
||||
#define pgm_read_dword(addr) pgm_read_dword_near(addr)
|
||||
|
||||
#define memcpy_P memcpy
|
||||
#define sprintf_P sprintf
|
||||
#define strstr_P strstr
|
||||
#define strncpy_P strncpy
|
||||
#define vsnprintf_P vsnprintf
|
||||
#define strcpy_P strcpy
|
||||
#define snprintf_P snprintf
|
||||
#define strlen_P strlen
|
||||
#define strchr_P strchr
|
||||
|
||||
// Time functions
|
||||
extern "C" {
|
||||
void delay(const int milis);
|
||||
}
|
||||
void _delay_ms(const int delay);
|
||||
void delayMicroseconds(unsigned long);
|
||||
uint32_t millis();
|
||||
|
||||
//IO functions
|
||||
void pinMode(const pin_t, const uint8_t);
|
||||
void digitalWrite(pin_t, uint8_t);
|
||||
bool digitalRead(pin_t);
|
||||
void analogWrite(pin_t, int);
|
||||
uint16_t analogRead(pin_t);
|
||||
|
||||
// EEPROM
|
||||
void eeprom_write_byte(unsigned char *pos, unsigned char value);
|
||||
unsigned char eeprom_read_byte(unsigned char *pos);
|
||||
void eeprom_read_block (void *__dst, const void *__src, size_t __n);
|
||||
void eeprom_update_block (const void *__src, void *__dst, size_t __n);
|
||||
|
||||
int32_t random(int32_t);
|
||||
int32_t random(int32_t, int32_t);
|
||||
void randomSeed(uint32_t);
|
||||
|
||||
char *dtostrf (double __val, signed char __width, unsigned char __prec, char *__s);
|
||||
|
||||
int map(uint16_t x, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max);
|
||||
|
||||
#endif // __ARDUINO_DEF_H__
|
||||
@@ -1,335 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
|
||||
#if SERIAL_PORT == 0 || SERIAL_PORT_2 == 0
|
||||
HardwareSerial Serial = HardwareSerial(LPC_UART0);
|
||||
#elif SERIAL_PORT == 1 || SERIAL_PORT_2 == 1
|
||||
HardwareSerial Serial1 = HardwareSerial((LPC_UART_TypeDef *) LPC_UART1);
|
||||
#elif SERIAL_PORT == 2 || SERIAL_PORT_2 == 2
|
||||
HardwareSerial Serial2 = HardwareSerial(LPC_UART2);
|
||||
#elif SERIAL_PORT == 3 || SERIAL_PORT_2 == 3
|
||||
HardwareSerial Serial3 = HardwareSerial(LPC_UART3);
|
||||
#endif
|
||||
|
||||
void HardwareSerial::begin(uint32_t baudrate) {
|
||||
|
||||
UART_CFG_Type UARTConfigStruct;
|
||||
PINSEL_CFG_Type PinCfg;
|
||||
UART_FIFO_CFG_Type FIFOConfig;
|
||||
|
||||
if (Baudrate == baudrate) return; // No need to re-initialize
|
||||
|
||||
if (UARTx == LPC_UART0) {
|
||||
// Initialize UART0 pin connect
|
||||
PinCfg.Funcnum = 1;
|
||||
PinCfg.OpenDrain = 0;
|
||||
PinCfg.Pinmode = 0;
|
||||
PinCfg.Pinnum = 2;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
PinCfg.Pinnum = 3;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
} else if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1) {
|
||||
// Initialize UART1 pin connect
|
||||
PinCfg.Funcnum = 1;
|
||||
PinCfg.OpenDrain = 0;
|
||||
PinCfg.Pinmode = 0;
|
||||
PinCfg.Pinnum = 15;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
PinCfg.Pinnum = 16;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
} else if (UARTx == LPC_UART2) {
|
||||
// Initialize UART2 pin connect
|
||||
PinCfg.Funcnum = 1;
|
||||
PinCfg.OpenDrain = 0;
|
||||
PinCfg.Pinmode = 0;
|
||||
PinCfg.Pinnum = 10;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
PinCfg.Pinnum = 11;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
} else if (UARTx == LPC_UART3) {
|
||||
// Initialize UART2 pin connect
|
||||
PinCfg.Funcnum = 1;
|
||||
PinCfg.OpenDrain = 0;
|
||||
PinCfg.Pinmode = 0;
|
||||
PinCfg.Pinnum = 0;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
PinCfg.Pinnum = 1;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
}
|
||||
|
||||
/* Initialize UART Configuration parameter structure to default state:
|
||||
* Baudrate = 9600bps
|
||||
* 8 data bit
|
||||
* 1 Stop bit
|
||||
* None parity
|
||||
*/
|
||||
UART_ConfigStructInit(&UARTConfigStruct);
|
||||
|
||||
// Re-configure baudrate
|
||||
UARTConfigStruct.Baud_rate = baudrate;
|
||||
|
||||
// Initialize eripheral with given to corresponding parameter
|
||||
UART_Init(UARTx, &UARTConfigStruct);
|
||||
|
||||
// Enable and reset the TX and RX FIFOs
|
||||
UART_FIFOConfigStructInit(&FIFOConfig);
|
||||
UART_FIFOConfig(UARTx, &FIFOConfig);
|
||||
|
||||
// Enable UART Transmit
|
||||
UART_TxCmd(UARTx, ENABLE);
|
||||
|
||||
// Configure Interrupts
|
||||
UART_IntConfig(UARTx, UART_INTCFG_RBR, ENABLE);
|
||||
UART_IntConfig(UARTx, UART_INTCFG_RLS, ENABLE);
|
||||
|
||||
// Set proper priority and enable interrupts
|
||||
if (UARTx == LPC_UART0) {
|
||||
NVIC_SetPriority(UART0_IRQn, NVIC_EncodePriority(0, 3, 0));
|
||||
NVIC_EnableIRQ(UART0_IRQn);
|
||||
}
|
||||
else if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1) {
|
||||
NVIC_SetPriority(UART1_IRQn, NVIC_EncodePriority(0, 3, 0));
|
||||
NVIC_EnableIRQ(UART1_IRQn);
|
||||
}
|
||||
else if (UARTx == LPC_UART2) {
|
||||
NVIC_SetPriority(UART2_IRQn, NVIC_EncodePriority(0, 3, 0));
|
||||
NVIC_EnableIRQ(UART2_IRQn);
|
||||
}
|
||||
else if (UARTx == LPC_UART3) {
|
||||
NVIC_SetPriority(UART3_IRQn, NVIC_EncodePriority(0, 3, 0));
|
||||
NVIC_EnableIRQ(UART3_IRQn);
|
||||
}
|
||||
|
||||
RxQueueWritePos = RxQueueReadPos = 0;
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
TxQueueWritePos = TxQueueReadPos = 0;
|
||||
#endif
|
||||
|
||||
// Save the configured baudrate
|
||||
Baudrate = baudrate;
|
||||
}
|
||||
|
||||
int16_t HardwareSerial::peek() {
|
||||
int16_t byte = -1;
|
||||
|
||||
// Temporarily lock out UART receive interrupts during this read so the UART receive
|
||||
// interrupt won't cause problems with the index values
|
||||
UART_IntConfig(UARTx, UART_INTCFG_RBR, DISABLE);
|
||||
|
||||
if (RxQueueReadPos != RxQueueWritePos)
|
||||
byte = RxBuffer[RxQueueReadPos];
|
||||
|
||||
// Re-enable UART interrupts
|
||||
UART_IntConfig(UARTx, UART_INTCFG_RBR, ENABLE);
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
int16_t HardwareSerial::read() {
|
||||
int16_t byte = -1;
|
||||
|
||||
// Temporarily lock out UART receive interrupts during this read so the UART receive
|
||||
// interrupt won't cause problems with the index values
|
||||
UART_IntConfig(UARTx, UART_INTCFG_RBR, DISABLE);
|
||||
|
||||
if (RxQueueReadPos != RxQueueWritePos) {
|
||||
byte = RxBuffer[RxQueueReadPos];
|
||||
RxQueueReadPos = (RxQueueReadPos + 1) % RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// Re-enable UART interrupts
|
||||
UART_IntConfig(UARTx, UART_INTCFG_RBR, ENABLE);
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
size_t HardwareSerial::write(uint8_t send) {
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
size_t bytes = 0;
|
||||
uint32_t fifolvl = 0;
|
||||
|
||||
// If the Tx Buffer is full, wait for space to clear
|
||||
if ((TxQueueWritePos+1) % TX_BUFFER_SIZE == TxQueueReadPos) flushTX();
|
||||
|
||||
// Temporarily lock out UART transmit interrupts during this read so the UART transmit interrupt won't
|
||||
// cause problems with the index values
|
||||
UART_IntConfig(UARTx, UART_INTCFG_THRE, DISABLE);
|
||||
|
||||
// LPC17xx.h incorrectly defines FIFOLVL as a uint8_t, when it's actually a 32-bit register
|
||||
if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1) {
|
||||
fifolvl = *(reinterpret_cast<volatile uint32_t *>(&((LPC_UART1_TypeDef *) UARTx)->FIFOLVL));
|
||||
} else fifolvl = *(reinterpret_cast<volatile uint32_t *>(&UARTx->FIFOLVL));
|
||||
|
||||
// If the queue is empty and there's space in the FIFO, immediately send the byte
|
||||
if (TxQueueWritePos == TxQueueReadPos && fifolvl < UART_TX_FIFO_SIZE) {
|
||||
bytes = UART_Send(UARTx, &send, 1, BLOCKING);
|
||||
}
|
||||
// Otherwiise, write the byte to the transmit buffer
|
||||
else if ((TxQueueWritePos+1) % TX_BUFFER_SIZE != TxQueueReadPos) {
|
||||
TxBuffer[TxQueueWritePos] = send;
|
||||
TxQueueWritePos = (TxQueueWritePos+1) % TX_BUFFER_SIZE;
|
||||
bytes++;
|
||||
}
|
||||
|
||||
// Re-enable the TX Interrupt
|
||||
UART_IntConfig(UARTx, UART_INTCFG_THRE, ENABLE);
|
||||
|
||||
return bytes;
|
||||
#else
|
||||
return UART_Send(UARTx, &send, 1, BLOCKING);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
void HardwareSerial::flushTX() {
|
||||
// Wait for the tx buffer and FIFO to drain
|
||||
while (TxQueueWritePos != TxQueueReadPos && UART_CheckBusy(UARTx) == SET);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t HardwareSerial::available() {
|
||||
return (RxQueueWritePos + RX_BUFFER_SIZE - RxQueueReadPos) % RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
void HardwareSerial::flush() {
|
||||
RxQueueWritePos = 0;
|
||||
RxQueueReadPos = 0;
|
||||
}
|
||||
|
||||
size_t HardwareSerial::printf(const char *format, ...) {
|
||||
char RxBuffer[256];
|
||||
va_list vArgs;
|
||||
va_start(vArgs, format);
|
||||
int length = vsnprintf(RxBuffer, 256, format, vArgs);
|
||||
va_end(vArgs);
|
||||
if (length > 0 && length < 256) {
|
||||
for (size_t i = 0; i < (size_t)length; ++i)
|
||||
write(RxBuffer[i]);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
void HardwareSerial::IRQHandler() {
|
||||
uint32_t IIRValue;
|
||||
uint8_t LSRValue, byte;
|
||||
|
||||
IIRValue = UART_GetIntId(UARTx);
|
||||
IIRValue &= UART_IIR_INTID_MASK; // check bit 1~3, interrupt identification
|
||||
|
||||
// Receive Line Status
|
||||
if (IIRValue == UART_IIR_INTID_RLS) {
|
||||
LSRValue = UART_GetLineStatus(UARTx);
|
||||
|
||||
// Receive Line Status
|
||||
if (LSRValue & (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE | UART_LSR_RXFE | UART_LSR_BI)) {
|
||||
// There are errors or break interrupt
|
||||
// Read LSR will clear the interrupt
|
||||
Status = LSRValue;
|
||||
byte = UART_ReceiveByte(UARTx); // Dummy read on RX to clear interrupt, then bail out
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Receive Data Available
|
||||
if (IIRValue == UART_IIR_INTID_RDA) {
|
||||
// Clear the FIFO
|
||||
while (UART_Receive(UARTx, &byte, 1, NONE_BLOCKING)) {
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(emergency_state, byte);
|
||||
#endif
|
||||
if ((RxQueueWritePos + 1) % RX_BUFFER_SIZE != RxQueueReadPos) {
|
||||
RxBuffer[RxQueueWritePos] = byte;
|
||||
RxQueueWritePos = (RxQueueWritePos + 1) % RX_BUFFER_SIZE;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
// Character timeout indicator
|
||||
} else if (IIRValue == UART_IIR_INTID_CTI) {
|
||||
// Character Time-out indicator
|
||||
Status |= 0x100; // Bit 9 as the CTI error
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
if (IIRValue == UART_IIR_INTID_THRE) {
|
||||
// Disable THRE interrupt
|
||||
UART_IntConfig(UARTx, UART_INTCFG_THRE, DISABLE);
|
||||
|
||||
// Wait for FIFO buffer empty
|
||||
while (UART_CheckBusy(UARTx) == SET);
|
||||
|
||||
// Transfer up to UART_TX_FIFO_SIZE bytes of data
|
||||
for (int i = 0; i < UART_TX_FIFO_SIZE && TxQueueWritePos != TxQueueReadPos; i++) {
|
||||
// Move a piece of data into the transmit FIFO
|
||||
if (UART_Send(UARTx, &TxBuffer[TxQueueReadPos], 1, NONE_BLOCKING)) {
|
||||
TxQueueReadPos = (TxQueueReadPos+1) % TX_BUFFER_SIZE;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// If there is no more data to send, disable the transmit interrupt - else enable it or keep it enabled
|
||||
if (TxQueueWritePos == TxQueueReadPos) {
|
||||
UART_IntConfig(UARTx, UART_INTCFG_THRE, DISABLE);
|
||||
} else UART_IntConfig(UARTx, UART_INTCFG_THRE, ENABLE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void UART0_IRQHandler(void) {
|
||||
#if SERIAL_PORT == 0 || SERIAL_PORT_2 == 0
|
||||
Serial.IRQHandler();
|
||||
#endif
|
||||
}
|
||||
|
||||
void UART1_IRQHandler(void) {
|
||||
#if SERIAL_PORT == 1 || SERIAL_PORT_2 == 1
|
||||
Serial1.IRQHandler();
|
||||
#endif
|
||||
}
|
||||
|
||||
void UART2_IRQHandler(void) {
|
||||
#if SERIAL_PORT == 2 || SERIAL_PORT_2 == 2
|
||||
Serial2.IRQHandler();
|
||||
#endif
|
||||
}
|
||||
|
||||
void UART3_IRQHandler(void) {
|
||||
#if SERIAL_PORT == 3 || SERIAL_PORT_2 == 3
|
||||
Serial3.IRQHandler();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_SERIAL_H_
|
||||
#define HARDWARE_SERIAL_H_
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../../../feature/emergency_parser.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <Stream.h>
|
||||
|
||||
extern "C" {
|
||||
#include <lpc17xx_uart.h>
|
||||
#include "lpc17xx_pinsel.h"
|
||||
}
|
||||
|
||||
class HardwareSerial : public Stream {
|
||||
private:
|
||||
LPC_UART_TypeDef *UARTx;
|
||||
|
||||
uint32_t Baudrate;
|
||||
uint32_t Status;
|
||||
uint8_t RxBuffer[RX_BUFFER_SIZE];
|
||||
uint32_t RxQueueWritePos;
|
||||
uint32_t RxQueueReadPos;
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
uint8_t TxBuffer[TX_BUFFER_SIZE];
|
||||
uint32_t TxQueueWritePos;
|
||||
uint32_t TxQueueReadPos;
|
||||
#endif
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
EmergencyParser::State emergency_state;
|
||||
#endif
|
||||
|
||||
public:
|
||||
HardwareSerial(LPC_UART_TypeDef *UARTx)
|
||||
: UARTx(UARTx)
|
||||
, Baudrate(0)
|
||||
, RxQueueWritePos(0)
|
||||
, RxQueueReadPos(0)
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
, TxQueueWritePos(0)
|
||||
, TxQueueReadPos(0)
|
||||
#endif
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
, emergency_state(EmergencyParser::State::EP_RESET)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
void begin(uint32_t baudrate);
|
||||
int16_t peek();
|
||||
int16_t read();
|
||||
size_t write(uint8_t send);
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
void flushTX();
|
||||
#endif
|
||||
size_t available();
|
||||
void flush();
|
||||
size_t printf(const char *format, ...);
|
||||
|
||||
operator bool() { return true; }
|
||||
|
||||
void IRQHandler();
|
||||
|
||||
};
|
||||
|
||||
#endif // MARLIN_SRC_HAL_HAL_SERIAL_H_
|
||||
@@ -1,329 +0,0 @@
|
||||
/*
|
||||
* SoftwareSerial.cpp (formerly NewSoftSerial.cpp)
|
||||
*
|
||||
* Multi-instance software serial library for Arduino/Wiring
|
||||
* -- Interrupt-driven receive and other improvements by ladyada
|
||||
* (http://ladyada.net)
|
||||
* -- Tuning, circular buffer, derivation from class Print/Stream,
|
||||
* multi-instance support, porting to 8MHz processors,
|
||||
* various optimizations, PROGMEM delay tables, inverse logic and
|
||||
* direct port writing by Mikal Hart (http://www.arduiniana.org)
|
||||
* -- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
|
||||
* -- 20MHz processor support by Garrett Mace (http://www.macetech.com)
|
||||
* -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The latest version of this library can always be found at
|
||||
* http://arduiniana.org.
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
//
|
||||
// Includes
|
||||
//
|
||||
//#include <WInterrupts.h>
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
#include "../../shared/Delay.h"
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <Arduino.h>
|
||||
#include <pinmapping.h>
|
||||
#include "../fastio.h"
|
||||
#include "SoftwareSerial.h"
|
||||
|
||||
void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
|
||||
void GpioDisableInt(uint32_t port, uint32_t pin);
|
||||
//
|
||||
// Statics
|
||||
//
|
||||
SoftwareSerial *SoftwareSerial::active_object = 0;
|
||||
unsigned char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
|
||||
volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
|
||||
volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
|
||||
|
||||
typedef struct _DELAY_TABLE {
|
||||
long baud;
|
||||
uint16_t rx_delay_centering;
|
||||
uint16_t rx_delay_intrabit;
|
||||
uint16_t rx_delay_stopbit;
|
||||
uint16_t tx_delay;
|
||||
} DELAY_TABLE;
|
||||
|
||||
// rough delay estimation
|
||||
static const DELAY_TABLE table[] = {
|
||||
//baud |rxcenter|rxintra |rxstop |tx { 250000, 2, 4, 4, 4, }, //Done but not good due to instruction cycle error { 115200, 4, 8, 8, 8, }, //Done but not good due to instruction cycle error
|
||||
//{ 74880, 69, 139, 62, 162, }, // estimation
|
||||
//{ 57600, 100, 185, 1, 208, }, // Done but not good due to instruction cycle error
|
||||
//{ 38400, 13, 26, 26, 26, }, // Done
|
||||
//{ 19200, 26, 52, 52, 52, }, // Done { 9600, 52, 104, 104, 104, }, // Done
|
||||
//{ 4800, 104, 208, 208, 208, },
|
||||
//{ 2400, 208, 417, 417, 417, },
|
||||
//{ 1200, 416, 833, 833, 833,},
|
||||
};
|
||||
|
||||
//
|
||||
// Private methods
|
||||
//
|
||||
|
||||
inline void SoftwareSerial::tunedDelay(const uint32_t count) {
|
||||
DELAY_US(count);
|
||||
}
|
||||
|
||||
// This function sets the current object as the "listening"
|
||||
// one and returns true if it replaces another
|
||||
bool SoftwareSerial::listen() {
|
||||
if (!_rx_delay_stopbit)
|
||||
return false;
|
||||
|
||||
if (active_object != this) {
|
||||
if (active_object)
|
||||
active_object->stopListening();
|
||||
|
||||
_buffer_overflow = false;
|
||||
_receive_buffer_head = _receive_buffer_tail = 0;
|
||||
active_object = this;
|
||||
|
||||
setRxIntMsk(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop listening. Returns true if we were actually listening.
|
||||
bool SoftwareSerial::stopListening() {
|
||||
if (active_object == this) {
|
||||
setRxIntMsk(false);
|
||||
active_object = NULL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// The receive routine called by the interrupt handler
|
||||
//
|
||||
void SoftwareSerial::recv() {
|
||||
uint8_t d = 0;
|
||||
|
||||
// If RX line is high, then we don't see any start bit
|
||||
// so interrupt is probably not for us
|
||||
if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) {
|
||||
// Disable further interrupts during reception, this prevents
|
||||
// triggering another interrupt directly after we return, which can
|
||||
// cause problems at higher baudrates.
|
||||
setRxIntMsk(false);//__disable_irq();//
|
||||
|
||||
// Wait approximately 1/2 of a bit width to "center" the sample
|
||||
tunedDelay(_rx_delay_centering);
|
||||
// Read each of the 8 bits
|
||||
for (uint8_t i=8; i > 0; --i) {
|
||||
tunedDelay(_rx_delay_intrabit);
|
||||
d >>= 1;
|
||||
if (rx_pin_read()) d |= 0x80;
|
||||
}
|
||||
|
||||
if (_inverse_logic) d = ~d;
|
||||
|
||||
// if buffer full, set the overflow flag and return
|
||||
uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
|
||||
if (next != _receive_buffer_head) {
|
||||
// save new data in buffer: tail points to where byte goes
|
||||
_receive_buffer[_receive_buffer_tail] = d; // save new byte
|
||||
_receive_buffer_tail = next;
|
||||
}
|
||||
else {
|
||||
_buffer_overflow = true;
|
||||
}
|
||||
tunedDelay(_rx_delay_stopbit);
|
||||
// Re-enable interrupts when we're sure to be inside the stop bit
|
||||
setRxIntMsk(true); //__enable_irq();//
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SoftwareSerial::rx_pin_read() {
|
||||
return digitalRead(_receivePin);
|
||||
}
|
||||
|
||||
//
|
||||
// Interrupt handling
|
||||
//
|
||||
|
||||
/* static */
|
||||
inline void SoftwareSerial::handle_interrupt() {
|
||||
if (active_object)
|
||||
active_object->recv();
|
||||
}
|
||||
extern "C" void intWrapper() {
|
||||
SoftwareSerial::handle_interrupt();
|
||||
}
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
SoftwareSerial::SoftwareSerial(pin_t receivePin, pin_t transmitPin, bool inverse_logic /* = false */) :
|
||||
_rx_delay_centering(0),
|
||||
_rx_delay_intrabit(0),
|
||||
_rx_delay_stopbit(0),
|
||||
_tx_delay(0),
|
||||
_buffer_overflow(false),
|
||||
_inverse_logic(inverse_logic) {
|
||||
setTX(transmitPin);
|
||||
setRX(receivePin);
|
||||
}
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
SoftwareSerial::~SoftwareSerial() {
|
||||
end();
|
||||
}
|
||||
|
||||
void SoftwareSerial::setTX(pin_t tx) {
|
||||
// First write, then set output. If we do this the other way around,
|
||||
// the pin would be output low for a short while before switching to
|
||||
// output hihg. Now, it is input with pullup for a short while, which
|
||||
// is fine. With inverse logic, either order is fine.
|
||||
|
||||
digitalWrite(tx, _inverse_logic ? LOW : HIGH);
|
||||
pinMode(tx,OUTPUT);
|
||||
_transmitPin = tx;
|
||||
}
|
||||
|
||||
void SoftwareSerial::setRX(pin_t rx) {
|
||||
pinMode(rx, INPUT_PULLUP); // pullup for normal logic!
|
||||
//if (!_inverse_logic)
|
||||
// digitalWrite(rx, HIGH);
|
||||
_receivePin = rx;
|
||||
_receivePort = LPC1768_PIN_PORT(rx);
|
||||
_receivePortPin = LPC1768_PIN_PIN(rx);
|
||||
/* GPIO_T * rxPort = digitalPinToPort(rx);
|
||||
_receivePortRegister = portInputRegister(rxPort);
|
||||
_receiveBitMask = digitalPinToBitMask(rx);*/
|
||||
}
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
|
||||
void SoftwareSerial::begin(long speed) {
|
||||
_rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
|
||||
|
||||
for(uint8_t i = 0; i < sizeof(table)/sizeof(table[0]); ++i) {
|
||||
long baud = table[i].baud;
|
||||
if (baud == speed) {
|
||||
_rx_delay_centering = table[i].rx_delay_centering;
|
||||
_rx_delay_intrabit = table[i].rx_delay_intrabit;
|
||||
_rx_delay_stopbit = table[i].rx_delay_stopbit;
|
||||
_tx_delay = table[i].tx_delay;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
attachInterrupt(_receivePin, intWrapper, CHANGE); //this->handle_interrupt, CHANGE);
|
||||
|
||||
listen();
|
||||
tunedDelay(_tx_delay);
|
||||
|
||||
}
|
||||
|
||||
void SoftwareSerial::setRxIntMsk(bool enable) {
|
||||
if (enable)
|
||||
GpioEnableInt(_receivePort,_receivePin,CHANGE);
|
||||
else
|
||||
GpioDisableInt(_receivePort,_receivePin);
|
||||
}
|
||||
|
||||
void SoftwareSerial::end() {
|
||||
stopListening();
|
||||
}
|
||||
|
||||
|
||||
// Read data from buffer
|
||||
int16_t SoftwareSerial::read() {
|
||||
if (!isListening()) return -1;
|
||||
|
||||
// Empty buffer?
|
||||
if (_receive_buffer_head == _receive_buffer_tail) return -1;
|
||||
|
||||
// Read from "head"
|
||||
uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
|
||||
_receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
|
||||
return d;
|
||||
}
|
||||
|
||||
size_t SoftwareSerial::available() {
|
||||
if (!isListening()) return 0;
|
||||
|
||||
return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
|
||||
}
|
||||
|
||||
size_t SoftwareSerial::write(uint8_t b) {
|
||||
// By declaring these as local variables, the compiler will put them
|
||||
// in registers _before_ disabling interrupts and entering the
|
||||
// critical timing sections below, which makes it a lot easier to
|
||||
// verify the cycle timings
|
||||
|
||||
bool inv = _inverse_logic;
|
||||
uint16_t delay = _tx_delay;
|
||||
|
||||
if (inv) b = ~b;
|
||||
|
||||
cli(); // turn off interrupts for a clean txmit
|
||||
|
||||
// Write the start bit
|
||||
digitalWrite(_transmitPin, !!inv);
|
||||
|
||||
tunedDelay(delay);
|
||||
|
||||
// Write each of the 8 bits
|
||||
for (uint8_t i = 8; i > 0; --i) {
|
||||
digitalWrite(_transmitPin, b & 1); // send 1 //(GPIO_Desc[_transmitPin].P)->DOUT |= GPIO_Desc[_transmitPin].bit;
|
||||
// send 0 //(GPIO_Desc[_transmitPin].P)->DOUT &= ~GPIO_Desc[_transmitPin].bit;
|
||||
tunedDelay(delay);
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
// restore pin to natural state
|
||||
digitalWrite(_transmitPin, !inv);
|
||||
|
||||
sei(); // turn interrupts back on
|
||||
tunedDelay(delay);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SoftwareSerial::flush() {
|
||||
if (!isListening()) return;
|
||||
|
||||
cli();
|
||||
_receive_buffer_head = _receive_buffer_tail = 0;
|
||||
sei();
|
||||
}
|
||||
|
||||
int16_t SoftwareSerial::peek() {
|
||||
if (!isListening())
|
||||
return -1;
|
||||
|
||||
// Empty buffer?
|
||||
if (_receive_buffer_head == _receive_buffer_tail)
|
||||
return -1;
|
||||
|
||||
// Read from "head"
|
||||
return _receive_buffer[_receive_buffer_head];
|
||||
}
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* SoftwareSerial.h (formerly NewSoftSerial.h)
|
||||
*
|
||||
* Multi-instance software serial library for Arduino/Wiring
|
||||
* -- Interrupt-driven receive and other improvements by ladyada
|
||||
* (http://ladyada.net)
|
||||
* -- Tuning, circular buffer, derivation from class Print/Stream,
|
||||
* multi-instance support, porting to 8MHz processors,
|
||||
* various optimizations, PROGMEM delay tables, inverse logic and
|
||||
* direct port writing by Mikal Hart (http://www.arduiniana.org)
|
||||
* -- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
|
||||
* -- 20MHz processor support by Garrett Mace (http://www.macetech.com)
|
||||
* -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The latest version of this library can always be found at
|
||||
* http://arduiniana.org.
|
||||
*/
|
||||
|
||||
#ifndef SOFTWARESERIAL_H
|
||||
#define SOFTWARESERIAL_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
//#include "serial.h"
|
||||
#include <Stream.h>
|
||||
#include <Print.h>
|
||||
|
||||
/******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
#define _SS_MAX_RX_BUFF 64 // RX buffer size
|
||||
|
||||
class SoftwareSerial : public Stream
|
||||
{
|
||||
private:
|
||||
// per object data
|
||||
pin_t _receivePin;
|
||||
pin_t _transmitPin;
|
||||
// uint32_t _receiveBitMask; // for rx interrupts
|
||||
uint32_t _receivePort;
|
||||
uint32_t _receivePortPin;
|
||||
|
||||
|
||||
// Expressed as 4-cycle delays (must never be 0!)
|
||||
uint16_t _rx_delay_centering;
|
||||
uint16_t _rx_delay_intrabit;
|
||||
uint16_t _rx_delay_stopbit;
|
||||
uint16_t _tx_delay;
|
||||
|
||||
uint16_t _buffer_overflow:1;
|
||||
uint16_t _inverse_logic:1;
|
||||
|
||||
// static data
|
||||
static unsigned char _receive_buffer[_SS_MAX_RX_BUFF];
|
||||
static volatile uint8_t _receive_buffer_tail;
|
||||
static volatile uint8_t _receive_buffer_head;
|
||||
static SoftwareSerial *active_object;
|
||||
|
||||
// private methods
|
||||
void recv();
|
||||
uint32_t rx_pin_read();
|
||||
void tx_pin_write(uint8_t pin_state);
|
||||
void setTX(pin_t transmitPin);
|
||||
void setRX(pin_t receivePin);
|
||||
void setRxIntMsk(bool enable);
|
||||
|
||||
// private static method for timing
|
||||
static inline void tunedDelay(uint32_t delay);
|
||||
|
||||
public:
|
||||
// public methods
|
||||
|
||||
SoftwareSerial(pin_t receivePin, pin_t transmitPin, bool inverse_logic = false);
|
||||
~SoftwareSerial();
|
||||
void begin(long speed);
|
||||
bool listen();
|
||||
void end();
|
||||
bool isListening() { return this == active_object; }
|
||||
bool stopListening();
|
||||
bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; }
|
||||
int16_t peek();
|
||||
|
||||
virtual size_t write(uint8_t byte);
|
||||
virtual int16_t read();
|
||||
virtual size_t available();
|
||||
virtual void flush();
|
||||
operator bool() { return true; }
|
||||
|
||||
using Print::write;
|
||||
//using HalSerial::write;
|
||||
|
||||
// public only for easy access by interrupt handlers
|
||||
static inline void handle_interrupt() __attribute__((__always_inline__));
|
||||
};
|
||||
|
||||
// Arduino 0012 workaround
|
||||
#undef int
|
||||
#undef char
|
||||
#undef long
|
||||
#undef byte
|
||||
#undef float
|
||||
#undef abs
|
||||
#undef round
|
||||
|
||||
#endif // SOFTWARESERIAL_H
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
TwoWire.cpp - TWI/I2C library for Wiring & Arduino
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <lpc17xx_i2c.h>
|
||||
#include <lpc17xx_pinsel.h>
|
||||
#include <lpc17xx_libcfg_default.h>
|
||||
}
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
#define USEDI2CDEV_M 1
|
||||
|
||||
#if (USEDI2CDEV_M == 0)
|
||||
#define I2CDEV_M LPC_I2C0
|
||||
#elif (USEDI2CDEV_M == 1)
|
||||
#define I2CDEV_M LPC_I2C1
|
||||
#elif (USEDI2CDEV_M == 2)
|
||||
#define I2CDEV_M LPC_I2C2
|
||||
#else
|
||||
#error "Master I2C device not defined!"
|
||||
#endif
|
||||
|
||||
// Initialize Class Variables //////////////////////////////////////////////////
|
||||
|
||||
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
|
||||
uint8_t TwoWire::rxBufferIndex = 0;
|
||||
uint8_t TwoWire::rxBufferLength = 0;
|
||||
|
||||
uint8_t TwoWire::txAddress = 0;
|
||||
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
|
||||
uint8_t TwoWire::txBufferIndex = 0;
|
||||
uint8_t TwoWire::txBufferLength = 0;
|
||||
|
||||
uint8_t TwoWire::transmitting = 0;
|
||||
|
||||
// Constructors ////////////////////////////////////////////////////////////////
|
||||
|
||||
TwoWire::TwoWire() {
|
||||
}
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
void TwoWire::begin(void) {
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = 0;
|
||||
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
|
||||
/*
|
||||
* Init I2C pin connect
|
||||
*/
|
||||
PINSEL_CFG_Type PinCfg;
|
||||
PinCfg.OpenDrain = 0;
|
||||
PinCfg.Pinmode = 0;
|
||||
|
||||
#if USEDI2CDEV_M == 0
|
||||
PinCfg.Funcnum = 1;
|
||||
PinCfg.Pinnum = 27;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg); // SDA0 / D57 AUX-1
|
||||
PinCfg.Pinnum = 28;
|
||||
PINSEL_ConfigPin(&PinCfg); // SCL0 / D58 AUX-1
|
||||
#endif
|
||||
|
||||
#if USEDI2CDEV_M == 1
|
||||
PinCfg.Funcnum = 3;
|
||||
PinCfg.Pinnum = 0;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg); // SDA1 / D20 SCA
|
||||
PinCfg.Pinnum = 1;
|
||||
PINSEL_ConfigPin(&PinCfg); // SCL1 / D21 SCL
|
||||
#endif
|
||||
|
||||
#if USEDI2CDEV_M == 2
|
||||
PinCfg.Funcnum = 2;
|
||||
PinCfg.Pinnum = 10;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg); // SDA2 / D38 X_ENABLE_PIN
|
||||
PinCfg.Pinnum = 11;
|
||||
PINSEL_ConfigPin(&PinCfg); // SCL2 / D55 X_DIR_PIN
|
||||
#endif
|
||||
|
||||
// Initialize I2C peripheral
|
||||
I2C_Init(I2CDEV_M, 100000);
|
||||
|
||||
// Enable Master I2C operation
|
||||
I2C_Cmd(I2CDEV_M, I2C_MASTER_MODE, ENABLE);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) {
|
||||
// clamp to buffer length
|
||||
if (quantity > BUFFER_LENGTH)
|
||||
quantity = BUFFER_LENGTH;
|
||||
|
||||
// perform blocking read into buffer
|
||||
I2C_M_SETUP_Type transferMCfg;
|
||||
transferMCfg.sl_addr7bit = address >> 1; // not sure about the right shift
|
||||
transferMCfg.tx_data = NULL;
|
||||
transferMCfg.tx_length = 0;
|
||||
transferMCfg.rx_data = rxBuffer;
|
||||
transferMCfg.rx_length = quantity;
|
||||
transferMCfg.retransmissions_max = 3;
|
||||
I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING);
|
||||
|
||||
// set rx buffer iterator vars
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = transferMCfg.rx_count;
|
||||
|
||||
return transferMCfg.rx_count;
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int quantity) {
|
||||
return requestFrom((uint8_t)address, (uint8_t)quantity);
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint8_t address) {
|
||||
// indicate that we are transmitting
|
||||
transmitting = 1;
|
||||
// set address of targeted slave
|
||||
txAddress = address;
|
||||
// reset tx buffer iterator vars
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(int address) {
|
||||
beginTransmission((uint8_t)address);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::endTransmission(void) {
|
||||
// transmit buffer (blocking)
|
||||
I2C_M_SETUP_Type transferMCfg;
|
||||
transferMCfg.sl_addr7bit = txAddress >> 1; // not sure about the right shift
|
||||
transferMCfg.tx_data = txBuffer;
|
||||
transferMCfg.tx_length = txBufferLength;
|
||||
transferMCfg.rx_data = NULL;
|
||||
transferMCfg.rx_length = 0;
|
||||
transferMCfg.retransmissions_max = 3;
|
||||
Status status = I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING);
|
||||
|
||||
// reset tx buffer iterator vars
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
|
||||
// indicate that we are done transmitting
|
||||
transmitting = 0;
|
||||
|
||||
return status == SUCCESS ? 0 : 4;
|
||||
}
|
||||
|
||||
// must be called after beginTransmission(address)
|
||||
size_t TwoWire::write(uint8_t data) {
|
||||
if (transmitting) {
|
||||
// don't bother if buffer is full
|
||||
if (txBufferLength >= BUFFER_LENGTH) return 0;
|
||||
|
||||
// put byte in tx buffer
|
||||
txBuffer[txBufferIndex++] = data;
|
||||
|
||||
// update amount in buffer
|
||||
txBufferLength = txBufferIndex;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// must be called after beginTransmission(address)
|
||||
size_t TwoWire::write(const uint8_t *data, size_t quantity) {
|
||||
size_t sent = 0;
|
||||
if (transmitting)
|
||||
for (sent = 0; sent < quantity; ++sent)
|
||||
if (!write(data[sent])) break;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
// Must be called after requestFrom(address, numBytes)
|
||||
int TwoWire::available(void) {
|
||||
return rxBufferLength - rxBufferIndex;
|
||||
}
|
||||
|
||||
// Must be called after requestFrom(address, numBytes)
|
||||
int TwoWire::read(void) {
|
||||
return rxBufferIndex < rxBufferLength ? rxBuffer[rxBufferIndex++] : -1;
|
||||
}
|
||||
|
||||
// Must be called after requestFrom(address, numBytes)
|
||||
int TwoWire::peek(void) {
|
||||
return rxBufferIndex < rxBufferLength ? rxBuffer[rxBufferIndex] : -1;
|
||||
}
|
||||
|
||||
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||
|
||||
TwoWire Wire = TwoWire();
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* TwoWire.h - TWI/I2C library for Arduino & Wiring
|
||||
* Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
*/
|
||||
|
||||
#ifndef _TWOWIRE_H_
|
||||
#define _TWOWIRE_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define BUFFER_LENGTH 32
|
||||
|
||||
class TwoWire {
|
||||
private:
|
||||
static uint8_t rxBuffer[];
|
||||
static uint8_t rxBufferIndex;
|
||||
static uint8_t rxBufferLength;
|
||||
|
||||
static uint8_t txAddress;
|
||||
static uint8_t txBuffer[];
|
||||
static uint8_t txBufferIndex;
|
||||
static uint8_t txBufferLength;
|
||||
|
||||
static uint8_t transmitting;
|
||||
|
||||
public:
|
||||
TwoWire();
|
||||
void begin();
|
||||
void beginTransmission(uint8_t);
|
||||
void beginTransmission(int);
|
||||
uint8_t endTransmission(void);
|
||||
uint8_t endTransmission(uint8_t);
|
||||
|
||||
uint8_t requestFrom(uint8_t, uint8_t);
|
||||
uint8_t requestFrom(int, int);
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(const uint8_t *, size_t);
|
||||
virtual int available(void);
|
||||
virtual int read(void);
|
||||
virtual int peek(void);
|
||||
|
||||
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||
inline size_t write(long n) { return write((uint8_t)n); }
|
||||
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||
inline size_t write(int n) { return write((uint8_t)n); }
|
||||
};
|
||||
|
||||
extern TwoWire Wire;
|
||||
|
||||
#endif // _TWOWIRE_H_
|
||||
@@ -19,13 +19,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// adapted from I2C/master/master.c example
|
||||
// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
|
||||
|
||||
#ifndef _DIGIPOT_MCP4451_I2C_ROUTINES_H_
|
||||
#define _DIGIPOT_MCP4451_I2C_ROUTINES_H_
|
||||
|
||||
#define USEDI2CDEV_M 1 // use I2C1 controller
|
||||
|
||||
#if USEDI2CDEV_M == 0
|
||||
@@ -53,5 +51,3 @@ uint8_t digipot_mcp4451_send_byte(uint8_t data);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _DIGIPOT_MCP4451_I2C_ROUTINES_H_
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include <pinmapping.h>
|
||||
|
||||
#include "../../../gcode/parser.h"
|
||||
|
||||
// Get the digital pin for an analog index
|
||||
pin_t analogInputToDigitalPin(const int8_t p) {
|
||||
return (WITHIN(p, 0, NUM_ANALOG_INPUTS) ? adc_pin_table[p] : P_NC);
|
||||
}
|
||||
|
||||
// Return the index of a pin number
|
||||
// The pin number given here is in the form ppp:nnnnn
|
||||
int16_t GET_PIN_MAP_INDEX(const pin_t pin) {
|
||||
const uint16_t index = (LPC1768_PIN_PORT(pin) << 5) | LPC1768_PIN_PIN(pin);
|
||||
return (index < NUM_DIGITAL_PINS && pin_map[index] != P_NC) ? index : -1;
|
||||
}
|
||||
|
||||
// Test whether the pin is valid
|
||||
bool VALID_PIN(const pin_t p) {
|
||||
const int16_t ind = GET_PIN_MAP_INDEX(p);
|
||||
return ind >= 0 && pin_map[ind] >= 0;
|
||||
}
|
||||
|
||||
// Get the analog index for a digital pin
|
||||
int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p) {
|
||||
return (VALID_PIN(p) ? LPC1768_PIN_ADC(p) : -1);
|
||||
}
|
||||
|
||||
// Test whether the pin is PWM
|
||||
bool PWM_PIN(const pin_t p) {
|
||||
return VALID_PIN(p) && LPC1768_PIN_PWM(p);
|
||||
}
|
||||
|
||||
// Test whether the pin is interruptable
|
||||
bool INTERRUPT_PIN(const pin_t p) {
|
||||
return VALID_PIN(p) && LPC1768_PIN_INTERRUPT(p);
|
||||
}
|
||||
|
||||
// Get the pin number at the given index
|
||||
pin_t GET_PIN_MAP_PIN(const int16_t ind) {
|
||||
return WITHIN(ind, 0, NUM_DIGITAL_PINS - 1) ? pin_map[ind] : P_NC;
|
||||
}
|
||||
|
||||
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
|
||||
const uint16_t val = (uint16_t)parser.intval(code), port = val / 100, pin = val % 100;
|
||||
const int16_t ind = (port < (NUM_DIGITAL_PINS >> 5) && (pin < 32))
|
||||
? GET_PIN_MAP_INDEX(port << 5 | pin) : -2;
|
||||
return ind > -2 ? ind : dval;
|
||||
}
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -1,294 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PINMAPPING_H_
|
||||
#define _PINMAPPING_H_
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int16_t pin_t;
|
||||
|
||||
#define PORT_0 000
|
||||
#define PORT_1 001
|
||||
#define PORT_2 010
|
||||
#define PORT_3 011
|
||||
#define PORT_4 100
|
||||
|
||||
#define PORT_(p) PORT_##p
|
||||
#define PORT(p) PORT_(p)
|
||||
|
||||
#define PIN_0 00000
|
||||
#define PIN_1 00001
|
||||
#define PIN_2 00010
|
||||
#define PIN_3 00011
|
||||
#define PIN_4 00100
|
||||
#define PIN_5 00101
|
||||
#define PIN_6 00110
|
||||
#define PIN_7 00111
|
||||
#define PIN_8 01000
|
||||
#define PIN_9 01001
|
||||
#define PIN_10 01010
|
||||
#define PIN_11 01011
|
||||
#define PIN_12 01100
|
||||
#define PIN_13 01101
|
||||
#define PIN_14 01110
|
||||
#define PIN_15 01111
|
||||
#define PIN_16 10000
|
||||
#define PIN_17 10001
|
||||
#define PIN_18 10010
|
||||
#define PIN_19 10011
|
||||
#define PIN_20 10100
|
||||
#define PIN_21 10101
|
||||
#define PIN_22 10110
|
||||
#define PIN_23 10111
|
||||
#define PIN_24 11000
|
||||
#define PIN_25 11001
|
||||
#define PIN_26 11010
|
||||
#define PIN_27 11011
|
||||
#define PIN_28 11100
|
||||
#define PIN_29 11101
|
||||
#define PIN_30 11110
|
||||
#define PIN_31 11111
|
||||
|
||||
#define PIN_(p) PIN_##p
|
||||
#define PIN(p) PIN_(p)
|
||||
|
||||
#define ADC_NONE 0000
|
||||
#define ADC_CHAN_0 0001
|
||||
#define ADC_CHAN_1 0010
|
||||
#define ADC_CHAN_2 0011
|
||||
#define ADC_CHAN_3 0100
|
||||
#define ADC_CHAN_4 0101
|
||||
#define ADC_CHAN_5 0110
|
||||
#define ADC_CHAN_6 0111
|
||||
#define ADC_CHAN_7 1000
|
||||
|
||||
#define ADC_CHAN_(c) ADC_CHAN_##c
|
||||
#define ADC_CHAN(p) ADC_CHAN_(p)
|
||||
|
||||
#define BOOL_0 0
|
||||
#define BOOL_1 1
|
||||
#define BOOL_(b) BOOL_##b
|
||||
|
||||
#define INTERRUPT(b) BOOL_(b)
|
||||
#define PWM(b) BOOL_(b)
|
||||
|
||||
// Combine elements into pin bits: 0b00AAAAWIPPPNNNNN
|
||||
#define LPC1768_PIN_(port, pin, int, pwm, adc) 0b00##adc##pwm##int##port##pin
|
||||
#define LPC1768_PIN(port, pin, int, pwm, adc) LPC1768_PIN_(port, pin, int, pwm, adc)
|
||||
|
||||
constexpr uint8_t LPC1768_PIN_PORT(const pin_t pin) { return ((uint8_t)((pin >> 5) & 0b111)); }
|
||||
constexpr uint8_t LPC1768_PIN_PIN(const pin_t pin) { return ((uint8_t)(pin & 0b11111)); }
|
||||
constexpr bool LPC1768_PIN_INTERRUPT(const pin_t pin) { return (((pin >> 8) & 0b1) != 0); }
|
||||
constexpr bool LPC1768_PIN_PWM(const pin_t pin) { return (((pin >> 9) & 0b1) != 0); }
|
||||
constexpr int8_t LPC1768_PIN_ADC(const pin_t pin) { return (int8_t)((pin >> 10) & 0b1111) - 1; }
|
||||
|
||||
// ******************
|
||||
// Runtime pinmapping
|
||||
// ******************
|
||||
#define P_NC -1
|
||||
|
||||
#if SERIAL_PORT != 3 && SERIAL_PORT_2 != 3
|
||||
#define P0_00 LPC1768_PIN(PORT(0), PIN( 0), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_01 LPC1768_PIN(PORT(0), PIN( 1), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#endif
|
||||
#if SERIAL_PORT != 0 && SERIAL_PORT_2 != 0
|
||||
#define P0_02 LPC1768_PIN(PORT(0), PIN( 2), INTERRUPT(1), PWM(0), ADC_CHAN(7))
|
||||
#define P0_03 LPC1768_PIN(PORT(0), PIN( 3), INTERRUPT(1), PWM(0), ADC_CHAN(6))
|
||||
#endif
|
||||
#define P0_04 LPC1768_PIN(PORT(0), PIN( 4), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_05 LPC1768_PIN(PORT(0), PIN( 5), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_06 LPC1768_PIN(PORT(0), PIN( 6), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_07 LPC1768_PIN(PORT(0), PIN( 7), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_08 LPC1768_PIN(PORT(0), PIN( 8), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_09 LPC1768_PIN(PORT(0), PIN( 9), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#if SERIAL_PORT != 2 && SERIAL_PORT_2 != 2
|
||||
#define P0_10 LPC1768_PIN(PORT(0), PIN(10), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_11 LPC1768_PIN(PORT(0), PIN(11), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#endif
|
||||
#if SERIAL_PORT != 1 && SERIAL_PORT_2 != 1
|
||||
#define P0_15 LPC1768_PIN(PORT(0), PIN(15), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_16 LPC1768_PIN(PORT(0), PIN(16), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#endif
|
||||
#define P0_17 LPC1768_PIN(PORT(0), PIN(17), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_18 LPC1768_PIN(PORT(0), PIN(18), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_19 LPC1768_PIN(PORT(0), PIN(19), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_20 LPC1768_PIN(PORT(0), PIN(20), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_21 LPC1768_PIN(PORT(0), PIN(21), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_22 LPC1768_PIN(PORT(0), PIN(22), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_23 LPC1768_PIN(PORT(0), PIN(23), INTERRUPT(1), PWM(0), ADC_CHAN(0))
|
||||
#define P0_24 LPC1768_PIN(PORT(0), PIN(24), INTERRUPT(1), PWM(0), ADC_CHAN(1))
|
||||
#define P0_25 LPC1768_PIN(PORT(0), PIN(25), INTERRUPT(1), PWM(0), ADC_CHAN(2))
|
||||
#define P0_26 LPC1768_PIN(PORT(0), PIN(26), INTERRUPT(1), PWM(0), ADC_CHAN(3))
|
||||
#define P0_27 LPC1768_PIN(PORT(0), PIN(27), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_28 LPC1768_PIN(PORT(0), PIN(28), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#if SERIAL_PORT != -1 && SERIAL_PORT_2 != -1
|
||||
#define P0_29 LPC1768_PIN(PORT(0), PIN(29), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P0_30 LPC1768_PIN(PORT(0), PIN(30), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#endif
|
||||
#define P1_00 LPC1768_PIN(PORT(1), PIN( 0), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_01 LPC1768_PIN(PORT(1), PIN( 1), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_04 LPC1768_PIN(PORT(1), PIN( 4), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_08 LPC1768_PIN(PORT(1), PIN( 8), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_09 LPC1768_PIN(PORT(1), PIN( 9), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_10 LPC1768_PIN(PORT(1), PIN(10), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_14 LPC1768_PIN(PORT(1), PIN(14), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_15 LPC1768_PIN(PORT(1), PIN(15), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_16 LPC1768_PIN(PORT(1), PIN(16), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_17 LPC1768_PIN(PORT(1), PIN(17), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_18 LPC1768_PIN(PORT(1), PIN(18), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P1_19 LPC1768_PIN(PORT(1), PIN(19), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_20 LPC1768_PIN(PORT(1), PIN(20), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P1_21 LPC1768_PIN(PORT(1), PIN(21), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P1_22 LPC1768_PIN(PORT(1), PIN(22), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_23 LPC1768_PIN(PORT(1), PIN(23), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P1_24 LPC1768_PIN(PORT(1), PIN(24), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P1_25 LPC1768_PIN(PORT(1), PIN(25), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_26 LPC1768_PIN(PORT(1), PIN(26), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P1_27 LPC1768_PIN(PORT(1), PIN(27), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_28 LPC1768_PIN(PORT(1), PIN(28), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_29 LPC1768_PIN(PORT(1), PIN(29), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P1_30 LPC1768_PIN(PORT(1), PIN(30), INTERRUPT(0), PWM(0), ADC_CHAN(4))
|
||||
#define P1_31 LPC1768_PIN(PORT(1), PIN(31), INTERRUPT(0), PWM(0), ADC_CHAN(5))
|
||||
#define P2_00 LPC1768_PIN(PORT(2), PIN( 0), INTERRUPT(1), PWM(1), ADC_NONE)
|
||||
#define P2_01 LPC1768_PIN(PORT(2), PIN( 1), INTERRUPT(1), PWM(1), ADC_NONE)
|
||||
#define P2_02 LPC1768_PIN(PORT(2), PIN( 2), INTERRUPT(1), PWM(1), ADC_NONE)
|
||||
#define P2_03 LPC1768_PIN(PORT(2), PIN( 3), INTERRUPT(1), PWM(1), ADC_NONE)
|
||||
#define P2_04 LPC1768_PIN(PORT(2), PIN( 4), INTERRUPT(1), PWM(1), ADC_NONE)
|
||||
#define P2_05 LPC1768_PIN(PORT(2), PIN( 5), INTERRUPT(1), PWM(1), ADC_NONE)
|
||||
#define P2_06 LPC1768_PIN(PORT(2), PIN( 6), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P2_07 LPC1768_PIN(PORT(2), PIN( 7), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P2_08 LPC1768_PIN(PORT(2), PIN( 8), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P2_09 LPC1768_PIN(PORT(2), PIN( 9), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P2_10 LPC1768_PIN(PORT(2), PIN(10), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P2_11 LPC1768_PIN(PORT(2), PIN(11), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P2_12 LPC1768_PIN(PORT(2), PIN(12), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P2_13 LPC1768_PIN(PORT(2), PIN(13), INTERRUPT(1), PWM(0), ADC_NONE)
|
||||
#define P3_25 LPC1768_PIN(PORT(3), PIN(25), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P3_26 LPC1768_PIN(PORT(3), PIN(26), INTERRUPT(0), PWM(1), ADC_NONE)
|
||||
#define P4_28 LPC1768_PIN(PORT(4), PIN(28), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
#define P4_29 LPC1768_PIN(PORT(4), PIN(29), INTERRUPT(0), PWM(0), ADC_NONE)
|
||||
|
||||
// Pin index for M43 and M226
|
||||
constexpr pin_t pin_map[] = {
|
||||
#if SERIAL_PORT != 3 && SERIAL_PORT_2 != 3
|
||||
P0_00, P0_01,
|
||||
#else
|
||||
P_NC, P_NC,
|
||||
#endif
|
||||
#if SERIAL_PORT != 0 && SERIAL_PORT_2 != 0
|
||||
P0_02, P0_03,
|
||||
#else
|
||||
P_NC, P_NC,
|
||||
#endif
|
||||
P0_04, P0_05, P0_06, P0_07,
|
||||
P0_08, P0_09,
|
||||
#if SERIAL_PORT != 2 && SERIAL_PORT_2 != 2
|
||||
P0_10, P0_11,
|
||||
#else
|
||||
P_NC, P_NC,
|
||||
#endif
|
||||
P_NC, P_NC, P_NC,
|
||||
#if SERIAL_PORT != 1 && SERIAL_PORT_2 != 1
|
||||
P0_15,
|
||||
P0_16,
|
||||
#else
|
||||
P_NC,
|
||||
P_NC,
|
||||
#endif
|
||||
P0_17, P0_18, P0_19, P0_20, P0_21, P0_22, P0_23,
|
||||
P0_24, P0_25, P0_26, P0_27, P0_28,
|
||||
#if SERIAL_PORT != -1 && SERIAL_PORT_2 != -1
|
||||
P0_29, P0_30,
|
||||
#else
|
||||
P_NC, P_NC,
|
||||
#endif
|
||||
P_NC,
|
||||
|
||||
P1_00, P1_01, P_NC, P_NC, P1_04, P_NC, P_NC, P_NC,
|
||||
P1_08, P1_09, P1_10, P_NC, P_NC, P_NC, P1_14, P1_15,
|
||||
P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23,
|
||||
P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31,
|
||||
|
||||
P2_00, P2_01, P2_02, P2_03, P2_04, P2_05, P2_06, P2_07,
|
||||
P2_08, P2_09, P2_10, P2_11, P2_12, P2_13, P_NC, P_NC,
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
P_NC, P3_25, P3_26, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC, P_NC,
|
||||
P_NC, P_NC, P_NC, P_NC, P4_28, P4_29, P_NC, P_NC
|
||||
};
|
||||
|
||||
constexpr uint8_t NUM_DIGITAL_PINS = COUNT(pin_map);
|
||||
|
||||
constexpr pin_t adc_pin_table[] = {
|
||||
P0_23, P0_24, P0_25, P0_26, P1_30, P1_31,
|
||||
#if SERIAL_PORT != 0 && SERIAL_PORT_2 != 0
|
||||
P0_03, P0_02
|
||||
#endif
|
||||
};
|
||||
|
||||
#if SERIAL_PORT != 0 && SERIAL_PORT_2 != 0
|
||||
#define NUM_ANALOG_INPUTS 8
|
||||
#else
|
||||
#define NUM_ANALOG_INPUTS 6
|
||||
#endif
|
||||
|
||||
// P0.6 thru P0.9 are for the onboard SD card
|
||||
#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09
|
||||
|
||||
// Get the digital pin for an analog index
|
||||
pin_t analogInputToDigitalPin(const int8_t p);
|
||||
#define digitalPinToInterrupt(pin) (pin)
|
||||
// Return the index of a pin number
|
||||
// The pin number given here is in the form ppp:nnnnn
|
||||
int16_t GET_PIN_MAP_INDEX(const pin_t pin);
|
||||
|
||||
// Test whether the pin is valid
|
||||
bool VALID_PIN(const pin_t p);
|
||||
|
||||
// Get the analog index for a digital pin
|
||||
int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p);
|
||||
|
||||
// Test whether the pin is PWM
|
||||
bool PWM_PIN(const pin_t p);
|
||||
|
||||
// Test whether the pin is interruptable
|
||||
bool INTERRUPT_PIN(const pin_t p);
|
||||
#define LPC1768_PIN_INTERRUPT_M(pin) (((pin >> 8) & 0b1) != 0)
|
||||
|
||||
// Get the pin number at the given index
|
||||
pin_t GET_PIN_MAP_PIN(const int16_t ind);
|
||||
|
||||
// Parse a G-code word into a pin index
|
||||
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
|
||||
|
||||
#endif // _PINMAPPING_H_
|
||||
@@ -1,161 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HAL_SERIAL_H_
|
||||
#define _HAL_SERIAL_H_
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../../../feature/emergency_parser.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <Print.h>
|
||||
|
||||
/**
|
||||
* Generic RingBuffer
|
||||
* T type of the buffer array
|
||||
* S size of the buffer (must be power of 2)
|
||||
*/
|
||||
|
||||
template <typename T, uint32_t S> class RingBuffer {
|
||||
public:
|
||||
RingBuffer() {index_read = index_write = 0;}
|
||||
|
||||
uint32_t available() {return mask(index_write - index_read);}
|
||||
uint32_t free() {return buffer_size - available();}
|
||||
bool empty() {return index_read == index_write;}
|
||||
bool full() {return next(index_write) == index_read;}
|
||||
void clear() {index_read = index_write = 0;}
|
||||
|
||||
bool peek(T *const value) {
|
||||
if (value == nullptr || empty()) return false;
|
||||
*value = buffer[index_read];
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t read(T *const value) {
|
||||
if (value == nullptr || empty()) return 0;
|
||||
*value = buffer[index_read];
|
||||
index_read = next(index_read);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t write(T value) {
|
||||
uint32_t next_head = next(index_write);
|
||||
if (next_head == index_read) return 0; // buffer full
|
||||
buffer[index_write] = value;
|
||||
index_write = next_head;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
inline uint32_t mask(uint32_t val) {
|
||||
return val & buffer_mask;
|
||||
}
|
||||
|
||||
inline uint32_t next(uint32_t val) {
|
||||
return mask(val + 1);
|
||||
}
|
||||
|
||||
static const uint32_t buffer_size = S;
|
||||
static const uint32_t buffer_mask = buffer_size - 1;
|
||||
T buffer[buffer_size];
|
||||
volatile uint32_t index_write;
|
||||
volatile uint32_t index_read;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serial Interface Class
|
||||
* Data is injected directly into, and consumed from, the fifo buffers
|
||||
*/
|
||||
|
||||
class HalSerial: public Print {
|
||||
public:
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
EmergencyParser::State emergency_state;
|
||||
#endif
|
||||
|
||||
HalSerial() : host_connected(false) { }
|
||||
virtual ~HalSerial() { }
|
||||
|
||||
operator bool() { return host_connected; }
|
||||
|
||||
void begin(int32_t baud) { }
|
||||
|
||||
int16_t peek() {
|
||||
uint8_t value;
|
||||
return receive_buffer.peek(&value) ? value : -1;
|
||||
}
|
||||
|
||||
int16_t read() {
|
||||
uint8_t value;
|
||||
return receive_buffer.read(&value) ? value : -1;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t c) {
|
||||
if (!host_connected) return 0; // Do not fill buffer when host disconnected
|
||||
while (transmit_buffer.write(c) == 0) { // Block until there is free room in buffer
|
||||
if (!host_connected) return 0; // Break infinite loop on host disconect
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t available() {
|
||||
return (size_t)receive_buffer.available();
|
||||
}
|
||||
|
||||
void flush() {
|
||||
receive_buffer.clear();
|
||||
}
|
||||
|
||||
uint8_t availableForWrite(void) {
|
||||
return transmit_buffer.free() > 255 ? 255 : (uint8_t)transmit_buffer.free();
|
||||
}
|
||||
|
||||
void flushTX(void) {
|
||||
while (transmit_buffer.available() && host_connected) { /* nada */}
|
||||
}
|
||||
|
||||
size_t printf(const char *format, ...) {
|
||||
static char buffer[256];
|
||||
va_list vArgs;
|
||||
va_start(vArgs, format);
|
||||
int length = vsnprintf((char *) buffer, 256, (char const *) format, vArgs);
|
||||
va_end(vArgs);
|
||||
size_t i = 0;
|
||||
if (length > 0 && length < 256) {
|
||||
while (i < (size_t)length && host_connected) {
|
||||
i += transmit_buffer.write(buffer[i]);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
RingBuffer<uint8_t, 128> receive_buffer;
|
||||
RingBuffer<uint8_t, 128> transmit_buffer;
|
||||
volatile bool host_connected;
|
||||
};
|
||||
|
||||
#endif // _HAL_SERIAL_H_
|
||||
@@ -1,60 +0,0 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
#dynamic build flags for generic compile options
|
||||
if __name__ == "__main__":
|
||||
args = " ".join([ "-std=gnu11",
|
||||
"-std=gnu++11",
|
||||
"-Os",
|
||||
"-mcpu=cortex-m3",
|
||||
"-mthumb",
|
||||
|
||||
"-fsigned-char",
|
||||
"-fno-move-loop-invariants",
|
||||
"-fno-strict-aliasing",
|
||||
"-fsingle-precision-constant",
|
||||
|
||||
"--specs=nano.specs",
|
||||
"--specs=nosys.specs",
|
||||
|
||||
# For external libraries
|
||||
"-IMarlin/src/HAL/HAL_LPC1768/include",
|
||||
|
||||
# For MarlinFirmware/U8glib-HAL
|
||||
"-IMarlin/src/HAL/HAL_LPC1768/u8g",
|
||||
"-DU8G_HAL_LINKS",
|
||||
|
||||
"-MMD",
|
||||
"-MP",
|
||||
"-DTARGET_LPC1768"
|
||||
])
|
||||
|
||||
for i in range(1, len(sys.argv)):
|
||||
args += " " + sys.argv[i]
|
||||
|
||||
print(args)
|
||||
|
||||
# extra script for linker options
|
||||
else:
|
||||
from SCons.Script import DefaultEnvironment
|
||||
env = DefaultEnvironment()
|
||||
env.Append(
|
||||
ARFLAGS=["rcs"],
|
||||
|
||||
ASFLAGS=["-x", "assembler-with-cpp"],
|
||||
|
||||
CXXFLAGS=[
|
||||
"-fabi-version=0",
|
||||
"-fno-use-cxa-atexit",
|
||||
"-fno-threadsafe-statics"
|
||||
],
|
||||
LINKFLAGS=[
|
||||
"-Wl,-Tframeworks/CMSIS/LPC1768/system/LPC1768.ld,--gc-sections",
|
||||
"-Os",
|
||||
"-mcpu=cortex-m3",
|
||||
"-mthumb",
|
||||
"--specs=nano.specs",
|
||||
"--specs=nosys.specs",
|
||||
"-u_printf_float"
|
||||
],
|
||||
)
|
||||
@@ -1,15 +1,5 @@
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
// ---------------------
|
||||
// Userspace entry point
|
||||
// ---------------------
|
||||
extern void setup();
|
||||
extern void loop();
|
||||
|
||||
extern "C" {
|
||||
#include <lpc17xx_gpio.h>
|
||||
}
|
||||
|
||||
#include <usb/usb.h>
|
||||
#include <usb/usbcfg.h>
|
||||
#include <usb/usbhw.h>
|
||||
@@ -17,84 +7,78 @@ extern "C" {
|
||||
#include <usb/cdc.h>
|
||||
#include <usb/cdcuser.h>
|
||||
#include <usb/mscuser.h>
|
||||
#include <CDCSerial.h>
|
||||
#include <usb/mscuser.h>
|
||||
|
||||
extern "C" {
|
||||
#include <debug_frmwrk.h>
|
||||
#include <chanfs/diskio.h>
|
||||
#include <chanfs/ff.h>
|
||||
}
|
||||
|
||||
#include "../../sd/cardreader.h"
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
#include "fastio.h"
|
||||
#include "HAL_timers.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <Arduino.h>
|
||||
#include "serial.h"
|
||||
#include "LPC1768_PWM.h"
|
||||
|
||||
static __INLINE uint32_t SysTick_Config(uint32_t ticks) {
|
||||
if (ticks > SysTick_LOAD_RELOAD_Msk) return 1;
|
||||
|
||||
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; // Set reload register
|
||||
SysTick->VAL = 0; // Load the SysTick Counter Value
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk; // Enable SysTick IRQ and SysTick Timer
|
||||
|
||||
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(0, 0, 0)); // Set Priority for Cortex-M3 System Interrupts
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern int isLPC1769();
|
||||
extern void disk_timerproc(void);
|
||||
volatile uint32_t _millis;
|
||||
|
||||
void SysTick_Handler(void) {
|
||||
++_millis;
|
||||
disk_timerproc();
|
||||
}
|
||||
|
||||
// Runs after clock init and before global static constructors
|
||||
void SystemPostInit() {
|
||||
_millis = 0; // Initialize the millisecond counter value
|
||||
SysTick_Config(SystemCoreClock / 1000); // Start millisecond global counter
|
||||
|
||||
// Runs before setup() to configure LED_PIN and used to indicate successful bootloader execution
|
||||
#if PIN_EXISTS(LED)
|
||||
SET_DIR_OUTPUT(LED_PIN);
|
||||
WRITE_PIN_CLR(LED_PIN);
|
||||
|
||||
// MKS_SBASE has 3 other LEDs the bootloader uses during flashing. Clear them.
|
||||
SET_DIR_OUTPUT(P1_19);
|
||||
WRITE_PIN_CLR(P1_19);
|
||||
SET_DIR_OUTPUT(P1_20);
|
||||
WRITE_PIN_CLR(P1_20);
|
||||
SET_DIR_OUTPUT(P1_21);
|
||||
WRITE_PIN_CLR(P1_21);
|
||||
|
||||
for (uint8_t i = 6; i--;) {
|
||||
TOGGLE(LED_PIN);
|
||||
delay(100);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
extern uint32_t MSC_SD_Init(uint8_t pdrv);
|
||||
extern "C" int isLPC1769();
|
||||
extern "C" void disk_timerproc(void);
|
||||
|
||||
int main(void) {
|
||||
void SysTick_Callback() {
|
||||
disk_timerproc();
|
||||
}
|
||||
|
||||
(void)MSC_SD_Init(0);
|
||||
void HAL_init() {
|
||||
|
||||
// Support the 4 LEDs some LPC176x boards have
|
||||
#if PIN_EXISTS(LED)
|
||||
SET_DIR_OUTPUT(LED_PIN);
|
||||
WRITE_PIN_CLR(LED_PIN);
|
||||
#if PIN_EXISTS(LED2)
|
||||
SET_DIR_OUTPUT(LED2_PIN);
|
||||
WRITE_PIN_CLR(LED2_PIN);
|
||||
#if PIN_EXISTS(LED3)
|
||||
SET_DIR_OUTPUT(LED3_PIN);
|
||||
WRITE_PIN_CLR(LED3_PIN);
|
||||
#if PIN_EXISTS(LED4)
|
||||
SET_DIR_OUTPUT(LED4_PIN);
|
||||
WRITE_PIN_CLR(LED4_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Flash status LED 3 times to indicate Marlin has started booting
|
||||
for (uint8_t i = 0; i < 6; ++i) {
|
||||
TOGGLE(LED_PIN);
|
||||
delay(100);
|
||||
}
|
||||
#endif
|
||||
|
||||
//debug_frmwrk_init();
|
||||
//_DBG("\n\nDebug running\n");
|
||||
// Initialise the SD card chip select pins as soon as possible
|
||||
#if PIN_EXISTS(SS)
|
||||
WRITE(SS_PIN, HIGH);
|
||||
SET_OUTPUT(SS_PIN);
|
||||
#endif
|
||||
|
||||
#if defined(ONBOARD_SD_CS) && ONBOARD_SD_CS > -1
|
||||
WRITE(ONBOARD_SD_CS, HIGH);
|
||||
SET_OUTPUT(ONBOARD_SD_CS);
|
||||
#endif
|
||||
|
||||
USB_Init(); // USB Initialization
|
||||
USB_Connect(TRUE); // USB Connect
|
||||
USB_Connect(FALSE); // USB clear connection
|
||||
delay(1000); // Give OS time to notice
|
||||
USB_Connect(TRUE);
|
||||
|
||||
const uint32_t usb_timeout = millis() + 2000;
|
||||
#if DISABLED(USB_SD_DISABLED)
|
||||
MSC_SD_Init(0); // Enable USB SD card access
|
||||
#endif
|
||||
|
||||
const millis_t usb_timeout = millis() + 2000;
|
||||
while (!USB_Configuration && PENDING(millis(), usb_timeout)) {
|
||||
delay(50);
|
||||
HAL_idletask();
|
||||
#if PIN_EXISTS(LED)
|
||||
TOGGLE(LED_PIN); // Flash quickly during USB initialization
|
||||
#endif
|
||||
@@ -110,11 +94,25 @@ int main(void) {
|
||||
#endif
|
||||
|
||||
HAL_timer_init();
|
||||
}
|
||||
|
||||
LPC1768_PWM_init();
|
||||
|
||||
setup();
|
||||
for (;;) loop();
|
||||
// HAL idle task
|
||||
void HAL_idletask(void) {
|
||||
#if ENABLED(SDSUPPORT) && ENABLED(SHARED_SD_CARD)
|
||||
// If Marlin is using the SD card we need to lock it to prevent access from
|
||||
// a PC via USB.
|
||||
// Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
|
||||
// this will not reliably detect delete operations. To be safe we will lock
|
||||
// the disk if Marlin has it mounted. Unfortuately there is currently no way
|
||||
// to unmount the disk from the LCD menu.
|
||||
// if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
|
||||
if (card.flag.cardOK)
|
||||
MSC_Aquire_Lock();
|
||||
else
|
||||
MSC_Release_Lock();
|
||||
#endif
|
||||
// Perform USB stack housekeeping
|
||||
MSC_RunDeferredCommands();
|
||||
}
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
|
||||
@@ -21,4 +21,4 @@
|
||||
*/
|
||||
#include "../shared/persistent_store_api.h"
|
||||
|
||||
//#define FLASH_EEPROM
|
||||
#define FLASH_EEPROM
|
||||
|
||||
@@ -57,7 +57,7 @@ extern "C" {
|
||||
#define EEPROM_ERASE (0xff)
|
||||
#define SLOT_ADDRESS(sector, slot) (((uint8_t *)SECTOR_START(sector)) + slot * EEPROM_SIZE)
|
||||
|
||||
static uint8_t ram_eeprom[EEPROM_SIZE];
|
||||
static uint8_t ram_eeprom[EEPROM_SIZE] __attribute__((aligned(4))) = {0};
|
||||
static bool eeprom_dirty = false;
|
||||
static int current_slot = 0;
|
||||
|
||||
@@ -69,20 +69,15 @@ bool PersistentStore::access_start() {
|
||||
__disable_irq();
|
||||
status = BlankCheckSector(EEPROM_SECTOR, EEPROM_SECTOR, &first_nblank_loc, &first_nblank_val);
|
||||
__enable_irq();
|
||||
SERIAL_PROTOCOLLNPAIR("Blank check status: ", status);
|
||||
|
||||
if (status == CMD_SUCCESS) {
|
||||
// sector is blank so nothing stored yet
|
||||
SERIAL_PROTOCOLLNPGM("FLASH empty");
|
||||
for (int i = 0; i < EEPROM_SIZE; i++) ram_eeprom[i] = EEPROM_ERASE;
|
||||
current_slot = EEPROM_SLOTS;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// current slot is the first non blank one
|
||||
current_slot = first_nblank_loc / EEPROM_SIZE;
|
||||
SERIAL_PROTOCOLLNPAIR("Flash slot: ", current_slot);
|
||||
uint8_t *eeprom_data = SLOT_ADDRESS(EEPROM_SECTOR, current_slot);
|
||||
SERIAL_PROTOCOLLNPAIR("Address: ", (int)eeprom_data);
|
||||
|
||||
// load current settings
|
||||
for (int i = 0; i < EEPROM_SIZE; i++) ram_eeprom[i] = eeprom_data[i];
|
||||
}
|
||||
@@ -97,18 +92,16 @@ bool PersistentStore::access_finish() {
|
||||
if (--current_slot < 0) {
|
||||
// all slots have been used, erase everything and start again
|
||||
__disable_irq();
|
||||
PrepareSector(EEPROM_SECTOR, EEPROM_SECTOR);
|
||||
status = EraseSector(EEPROM_SECTOR, EEPROM_SECTOR);
|
||||
__enable_irq();
|
||||
SERIAL_PROTOCOLLNPAIR("Erase status: ", status);
|
||||
|
||||
current_slot = EEPROM_SLOTS - 1;
|
||||
}
|
||||
SERIAL_PROTOCOLLNPAIR("Writing data to: ", current_slot);
|
||||
|
||||
__disable_irq();
|
||||
PrepareSector(EEPROM_SECTOR, EEPROM_SECTOR);
|
||||
status = CopyRAM2Flash(SLOT_ADDRESS(EEPROM_SECTOR, current_slot), ram_eeprom, IAP_WRITE_4096);
|
||||
__enable_irq();
|
||||
SERIAL_PROTOCOLLNPAIR("CopyRAM2Flash status: ", status);
|
||||
|
||||
if (status != CMD_SUCCESS) return false;
|
||||
eeprom_dirty = false;
|
||||
}
|
||||
@@ -116,7 +109,7 @@ bool PersistentStore::access_finish() {
|
||||
}
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
for (int i = 0; i < size; i++) ram_eeprom[pos + i] = value[i];
|
||||
for (size_t i = 0; i < size; i++) ram_eeprom[pos + i] = value[i];
|
||||
eeprom_dirty = true;
|
||||
crc16(crc, value, size);
|
||||
pos += size;
|
||||
@@ -125,7 +118,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
const uint8_t * const buff = writing ? &value[0] : &ram_eeprom[pos];
|
||||
if (writing) for (int i = 0; i < size; i++) value[i] = ram_eeprom[pos + i];
|
||||
if (writing) for (size_t i = 0; i < size; i++) value[i] = ram_eeprom[pos + i];
|
||||
crc16(crc, buff, size);
|
||||
pos += size;
|
||||
return false; // return true for any error
|
||||
|
||||
@@ -79,7 +79,7 @@ bool PersistentStore::access_finish() {
|
||||
// This extra chit-chat goes away soon, but is helpful for now
|
||||
// to see errors that are happening in read_data / write_data
|
||||
static void debug_rw(const bool write, int &pos, const uint8_t *value, const size_t size, const FRESULT s, const size_t total=0) {
|
||||
const char * const rw_str = write ? PSTR("write") : PSTR("read");
|
||||
PGM_P const rw_str = write ? PSTR("write") : PSTR("read");
|
||||
SERIAL_PROTOCOLCHAR(' ');
|
||||
serialprintPGM(rw_str);
|
||||
SERIAL_PROTOCOLPAIR("_data(", pos);
|
||||
|
||||
@@ -19,13 +19,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SPI_PINS_LPC1768_H
|
||||
#define SPI_PINS_LPC1768_H
|
||||
#pragma once
|
||||
|
||||
#include "src/core/macros.h"
|
||||
|
||||
#if ENABLED(SDSUPPORT) && ENABLED(DOGLCD) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
|
||||
#if ENABLED(SDSUPPORT) && HAS_GRAPHICAL_LCD && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == 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 requred for communicating with each device being different.
|
||||
// This requirement can be removed if the SPI access to these devices is updated to use
|
||||
@@ -50,8 +48,7 @@
|
||||
#ifndef SS_PIN
|
||||
#define SS_PIN P1_23
|
||||
#endif
|
||||
#ifndef SDSS
|
||||
#if !defined(SDSS) || SDSS == P_NC // gets defaulted in pins.h
|
||||
#undef SDSS
|
||||
#define SDSS SS_PIN
|
||||
#endif
|
||||
|
||||
#endif // SPI_PINS_LPC1768_H
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <lpc17xx_pinsel.h>
|
||||
#include <lpc17xx_libcfg_default.h>
|
||||
|
||||
#include "../../../core/millis_t.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// These two routines are exact copies of the lpc17xx_i2c.c routines. Couldn't link to
|
||||
@@ -149,14 +151,14 @@ void u8g_i2c_init(uint8_t clock_option) {
|
||||
u8g_i2c_start(0); // send slave address and write bit
|
||||
}
|
||||
|
||||
volatile extern uint32_t _millis;
|
||||
volatile extern millis_t _millis;
|
||||
uint8_t u8g_i2c_send_byte(uint8_t data) {
|
||||
#define I2C_TIMEOUT 3
|
||||
LPC_I2C1->I2DAT = data & I2C_I2DAT_BITMASK; // transmit data
|
||||
LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
|
||||
LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
|
||||
uint32_t timeout = _millis + I2C_TIMEOUT;
|
||||
while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK) && (timeout > _millis)); // wait for xmit to finish
|
||||
const millis_t timeout = _millis + I2C_TIMEOUT;
|
||||
while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK) && PENDING(_millis, timeout)); // wait for xmit to finish
|
||||
// had hangs with SH1106 so added time out - have seen temporary screen corruption when this happens
|
||||
return 1;
|
||||
}
|
||||
|
||||
+3
-3
@@ -55,9 +55,9 @@
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
#if HAS_GRAPHICAL_LCD
|
||||
|
||||
//#include <inttypes.h>
|
||||
#include <U8glib.h>
|
||||
@@ -132,6 +132,6 @@ uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DOGLCD
|
||||
#endif // HAS_GRAPHICAL_LCD
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
+5
-5
@@ -77,9 +77,9 @@
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
#if HAS_GRAPHICAL_LCD
|
||||
|
||||
#include <U8glib.h>
|
||||
|
||||
@@ -156,7 +156,7 @@ uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_v
|
||||
return 0;
|
||||
}
|
||||
|
||||
register uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
if (u8g_i2c_send_byte(*ptr++) == 0) {
|
||||
u8g_i2c_stop();
|
||||
@@ -175,7 +175,7 @@ uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_v
|
||||
return 0;
|
||||
}
|
||||
|
||||
register uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
if (u8g_i2c_send_byte(u8g_pgm_read(ptr)) == 0)
|
||||
return 0;
|
||||
@@ -198,6 +198,6 @@ uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_v
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DOGLCD
|
||||
#endif // HAS_GRAPHICAL_LCD
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
+4
-4
@@ -63,7 +63,7 @@
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
#if HAS_GRAPHICAL_LCD
|
||||
|
||||
#include <U8glib.h>
|
||||
|
||||
@@ -214,7 +214,7 @@ uint8_t u8g_com_HAL_LPC1768_ssd_sw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_v
|
||||
if (u8g_com_ssd_I2C_start_sequence_sw(u8g) == 0)
|
||||
return u8g_i2c_stop_sw(), 0;
|
||||
|
||||
register uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
if (u8g_i2c_send_byte_sw(*ptr++) == 0)
|
||||
return u8g_i2c_stop_sw(), 0;
|
||||
@@ -229,7 +229,7 @@ uint8_t u8g_com_HAL_LPC1768_ssd_sw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_v
|
||||
if (u8g_com_ssd_I2C_start_sequence_sw(u8g) == 0)
|
||||
return u8g_i2c_stop_sw(), 0;
|
||||
|
||||
register uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
if (u8g_i2c_send_byte_sw(u8g_pgm_read(ptr)) == 0) return 0;
|
||||
ptr++;
|
||||
@@ -249,6 +249,6 @@ uint8_t u8g_com_HAL_LPC1768_ssd_sw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_v
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DOGLCD
|
||||
#endif // HAS_GRAPHICAL_LCD
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
+4
-4
@@ -55,13 +55,13 @@
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
#if HAS_GRAPHICAL_LCD
|
||||
|
||||
//#include <inttypes.h>
|
||||
#include <U8glib.h>
|
||||
#include "../shared/Delay.h"
|
||||
#include "../../shared/Delay.h"
|
||||
|
||||
#define SPI_FULL_SPEED 0
|
||||
#define SPI_HALF_SPEED 1
|
||||
@@ -148,6 +148,6 @@ uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t ar
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DOGLCD
|
||||
#endif // HAS_GRAPHICAL_LCD
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
+5
-4
@@ -55,14 +55,15 @@
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
#if HAS_GRAPHICAL_LCD
|
||||
|
||||
#include <U8glib.h>
|
||||
#include "SoftwareSPI.h"
|
||||
#include "../shared/Delay.h"
|
||||
#include "../../shared/Delay.h"
|
||||
|
||||
#undef SPI_SPEED
|
||||
#define SPI_SPEED 3 // About 1 MHz
|
||||
|
||||
static pin_t SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL;
|
||||
@@ -150,6 +151,6 @@ uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t ar
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DOGLCD
|
||||
#endif // HAS_GRAPHICAL_LCD
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user