[
  {
    "path": "README",
    "content": "The leading developers of Sprinter are currently Kliment, caru and midopple, though many others contribute with their patches.\r\n\r\nThis is a firmware for RAMPS and other reprap single-processor electronics setups. It supports printing from SD card, active heatbed control, and ATmega internal pullups.\r\n\r\nThis work is licensed under the GNU GPL v3 or (at the user's discretion) any later version.\r\n\r\nIt is based on Tonokips's firmware, which was licensed under GPL v2 or later.\r\n\r\nWARNING: This version (April 19th, 2011) fixes a bug that caused speeds to be lower than what\r\n    set in GCODE. So before attempting any print, you will have to check all\r\n    your axis max speed, including the extruder retract speed. Not following\r\n    this guidelines can seriously damage your printer.\r\n\r\nThe configuration file now has an option to set the wanted temperature table file. If you copy and paste a temperature file from older versions, make sure that the configuration is pointing to it. For example:\r\n#include \"ThermistorTable.h\"\r\n\r\nIn addition, you can optionally use a different thermistor table for hot-end and bed. To do so, comment out the following lines in configuration.h:\r\n#define BNUMTEMPS NUMPTEMPS\r\n#define bedtemptable temptable\r\nThen add a line pointing to your second thermistor table, for example:\r\n#include \"BedThermistorTable.h\"\r\nFinally, make sure that the nozzle thermistor table, inside ThermistorTable.h in this case, is defined as \"temptable\" and that the bed thermistor table is defined as \"bedtemptable\", and that the number of temps is defined as NUMTEMPS for the heater and BNUMTEMPS for the bed.\r\n\r\nThere are examples of all these configurations in the configuration.h file. Please look at them before you change anything.\r\n\r\n\r\nComplete beginners guide\r\n=======================\r\n\r\nFrom a fresh Ubuntu install how to update the firmware of your Prusa Mendel ?\r\n(the specifics are for the Prusa Mendel built at the Bath RepRap masterclass.\r\nThis version uses the http://reprap.org/wiki/Sanguinololu. \r\nSome details may not fit your hardware, be sure to check what you are doing)\r\n\r\nSteps 3,10,11 are hardware-specific to the Sanguinololu and Bath Prusa and should be skipped or modified accordingly for other hardware such as the Arduino Mega 2560\r\n\r\nSoftware installation\r\n----------------------\r\n\r\n1. Install the required packages (gcc-avr, avr-libc, etc.)\r\n  sudo apt-get install arduino-core\r\n\r\n2. Get the arduino software version 0023, uncompress it in a directory.\r\nArduino software v1 has not been tested much, but is known to work with some boards.\r\n   http://www.arduino.cc/en/Main/Software\r\n\r\n3. Get the sanguino software, version 0023\r\n   http://sanguino.cc/softwareforlinux\r\n\r\nfollow the sanguino's readme so that your arduino hardware folder looks like \r\n  arduino-0023/hardware/arduino\r\n  arduino-0023/hardware/sanguino\r\n  arduino-0023/hardware/tools\r\n\r\n4. Clone the Sprinter git repository. \r\n   git clone https://github.com/kliment/Sprinter.git\r\nOptionally, switch to the desired branch\r\n  git branch -a\r\n  git checkout THE_BRANCH_YOU_WANT\r\n  \r\nFirmware compilation and upload\r\n-------------------------------\r\n\r\n5. Edit INSTALL_DIR inside Sprinter/Makefile (do not mind the default reference to arduino 0022)\r\n\r\n6. Run make. If everything goes well Sprinter/applet/Sprinter.cpp should have been created.\r\nYou can safely ignore the error message mentioning arduino-0023/hardware/arduino/cores/arduino/WString.o\r\n\r\n7. Connect your Sanguinololu to your computer\r\n   http://reprap.org/wiki/Sanguinololu\r\n\r\n8. Launch arduino-0023/arduino, open Sprinter/Sprinter.pde\r\n\r\n9. Go to Tools -> Serial Port, and select the relevant option\r\n\r\n10. Go to Tools -> Board, select Sanguino\r\n\r\n11. Go to the Configuration.h file and edit the following lines:\r\n   #define MOTHERBOARD 62\r\n62 indicates Sanguino 1.2 or superior\r\n\r\n  float axis_steps_per_unit[] \r\n\r\nset values that match your hardware. For the special cast gears of the Bath Masterclass Prusa Mendel, these values are  \r\n  float axis_steps_per_unit[] = {91.42857, 91.42857, 3200/1.25,700}; \r\n\r\nalso for the mentioned hardware setup\r\n  const bool ENDSTOPS_INVERTING = false; //set to true to invert the logic of the endstops\r\n  // false because the switch SIG signal is linked to the ground\r\n  // \"no touch == closed circuit == SIG connects to GND\"\r\n  // see http://reprap.org/wiki/Sanguinololu#Endstops\r\n\r\n12. Click on the \"play\" button to compile. If everything goes well you should see a \"Binary sketch size: \" message.\r\n\r\n13. Click on \"the arrow going to the right\" button to upload (you had done steps 7,8,9 before, right ?). \r\nIf everything goes well you should see the message \"Done uploading\".\r\n\r\nif GEN7 with 20 Mhz is in use set the Fuses for Bootloader to\r\nlfuse= 0xF7 hfuse = 0xD4 efuse = FD\r\nBrownout must be 2,7 V\r\n\r\nCongratulations, you have just upgraded the firmware of your RepRap !\r\n\r\nYou can use pronterface.py to do some manual verifications by moving the printer's tip along \r\nthe axes and verifying that the physical displacements match the ones indicated on the interface. \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Sprinter/Configuration.h",
    "content": "#ifndef CONFIGURATION_H\n#define CONFIGURATION_H\n\n// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration\n\n//// The following define selects which electronics board you have. Please choose the one that matches your setup\n// MEGA/RAMPS up to 1.2  = 3,\n// RAMPS 1.3/1.4 = 33\n// Gen6 = 5, \n// Gen6 deluxe = 51\n// Sanguinololu up to 1.1 = 6\n// Sanguinololu 1.2 and above = 62\n// Gen 7 @ 16MHZ only= 7\n// Gen 7 @ 20MHZ only= 71\n// Teensylu (at90usb) = 8\n// Printrboard Rev. B (ATMEGA90USB1286) = 9\n// Gen 3 Plus = 21\n// gen 3  Monolithic Electronics = 22\n// Gen3 PLUS for TechZone Gen3 Remix Motherboard = 23\n#define MOTHERBOARD 33\n\n//// Thermistor settings:\n// 1 is 100k thermistor\n// 2 is 200k thermistor\n// 3 is mendel-parts thermistor\n// 4 is 10k thermistor\n// 5 is ParCan supplied 104GT-2 100K\n// 6 is EPCOS 100k\n// 7 is 100k Honeywell thermistor 135-104LAG-J01\n#define THERMISTORHEATER 1\n#define THERMISTORBED 1\n\n//// Calibration variables\n// X, Y, Z, E steps per unit - Metric Prusa Mendel with Wade extruder:\n#define _AXIS_STEP_PER_UNIT {80, 80, 3200/1.25,700}\n// Metric Prusa Mendel with Makergear geared stepper extruder:\n//#define _AXIS_STEP_PER_UNIT {80,80,3200/1.25,1380}\n// MakerGear Hybrid Prusa Mendel:\n// Z axis value is for .9 stepper(if you have 1.8 steppers for Z, you need to use 2272.7272)\n//#define _AXIS_STEP_PER_UNIT {104.987, 104.987, 4545.4544, 1487}\n\n\n//// Endstop Settings\n#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors\n// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins.\n//If your axes are only moving in one direction, make sure the endstops are connected properly.\n//If your axes move in one direction ONLY when the endstops are triggered, set [XYZ]_ENDSTOP_INVERT to true here:\nconst bool X_ENDSTOP_INVERT = false;\nconst bool Y_ENDSTOP_INVERT = false;\nconst bool Z_ENDSTOP_INVERT = false;\n\n// This determines the communication speed of the printer\n#define BAUDRATE 115200\n//#define BAUDRATE 250000\n\n// Comment out (using // at the start of the line) to disable SD support:\n#define SDSUPPORT\n\n// Uncomment to make run init.g from SD on boot\n//#define SDINITFILE\n\n//Only work with Atmega1284 you need +1 kb ram\n//#define SD_FAST_XFER_AKTIV\n\n//-----------------------------------------------------------------------\n//// STORE SETTINGS TO EEPROM\n//-----------------------------------------------------------------------\n// the microcontroller can store settings in the EEPROM\n// M500 - stores paramters in EEPROM\n// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).\n// M502 - reverts to the default \"factory settings\". You still need to store them in EEPROM afterwards if you want to.\n// M503 - Print settings\n// define this to enable eeprom support\n//#define USE_EEPROM_SETTINGS\n\n// to disable EEPROM Serial responses and decrease program space by ~1000 byte: comment this out:\n// please keep turned on if you can.\n//#define PRINT_EEPROM_SETTING\n\n//-----------------------------------------------------------------------\n//// ARC Function (G2/G3 Command)\n//-----------------------------------------------------------------------\n//Uncomment to aktivate the arc (circle) function (G2/G3 Command)\n//Without SD function an ARC function the used Flash is smaller 31 kb\n#define USE_ARC_FUNCTION\n\n//-----------------------------------------------------------------------\n//// ADVANCED SETTINGS - to tweak parameters\n//-----------------------------------------------------------------------\n\n#ifdef SDSUPPORT\n\t#ifdef SD_FAST_XFER_AKTIV\n\t\t//Fast transfer chunk size (> 1024 is unstable, change at your own risk).\n\t\t#define SD_FAST_XFER_CHUNK_SIZE 1024\n\t#endif\n#endif\n\n//-----------------------------------------------------------------------\n// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1\n//-----------------------------------------------------------------------\n#define X_ENABLE_ON 0\n#define Y_ENABLE_ON 0\n#define Z_ENABLE_ON 0\n#define E_ENABLE_ON 0\n\n//Uncomment if you have problems with a stepper driver enabeling too late, this will also set how many microseconds delay there will be after enabeling the driver\n//#define DELAY_ENABLE 15\n\n//-----------------------------------------------------------------------\n// Disables axis when it's not being used.\n//-----------------------------------------------------------------------\nconst bool DISABLE_X = false;\nconst bool DISABLE_Y = false;\nconst bool DISABLE_Z = true;\nconst bool DISABLE_E = false;\n\n//-----------------------------------------------------------------------\n// Inverting axis direction\n//-----------------------------------------------------------------------\nconst bool INVERT_X_DIR = false;\nconst bool INVERT_Y_DIR = false;\nconst bool INVERT_Z_DIR = true;\nconst bool INVERT_E_DIR = false;\n\n//-----------------------------------------------------------------------\n//// ENDSTOP SETTINGS:\n//-----------------------------------------------------------------------\n// Sets direction of endstops when homing; 1=MAX, -1=MIN\n#define X_HOME_DIR -1\n#define Y_HOME_DIR -1\n#define Z_HOME_DIR -1\n\n//#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing\n\nconst bool min_software_endstops = false; //If true, axis won't move to coordinates less than zero.\nconst bool max_software_endstops = true; //If true, axis won't move to coordinates greater than the defined lengths below.\n\n\n//-----------------------------------------------------------------------\n//Max Length for Prusa Mendel, check the ways of your axis and set this Values\n//-----------------------------------------------------------------------\nconst int X_MAX_LENGTH = 200;\nconst int Y_MAX_LENGTH = 200;\nconst int Z_MAX_LENGTH = 100;\n\n//-----------------------------------------------------------------------\n//// MOVEMENT SETTINGS\n//-----------------------------------------------------------------------\nconst int NUM_AXIS = 4; // The axis order in all axis related arrays is X, Y, Z, E\n#define _MAX_FEEDRATE {400, 400, 2, 45}       // (mm/sec)    \n#define _HOMING_FEEDRATE {1500,1500,120}      // (mm/min) !!\n#define _AXIS_RELATIVE_MODES {false, false, false, false}\n\n#define MAX_STEP_FREQUENCY 30000 // Max step frequency\n\n//For the retract (negative Extruder) move this maxiumum Limit of Feedrate is used\n//The next positive Extruder move use also this Limit, \n//then for the next (second after retract) move the original Maximum (_MAX_FEEDRATE) Limit is used\n#define MAX_RETRACT_FEEDRATE 100    //mm/sec\n\n//-----------------------------------------------------------------------\n//// Not used at the Moment\n//-----------------------------------------------------------------------\n\n// Min step delay in microseconds. If you are experiencing missing steps, try to raise the delay microseconds, but be aware this\n// If you enable this, make sure STEP_DELAY_RATIO is disabled.\n//#define STEP_DELAY_MICROS 1\n\n// Step delay over interval ratio. If you are still experiencing missing steps, try to uncomment the following line, but be aware this\n// If you enable this, make sure STEP_DELAY_MICROS is disabled. (except for Gen6: both need to be enabled.)\n//#define STEP_DELAY_RATIO 0.25\n\n///Oscillation reduction.  Forces x,y,or z axis to be stationary for ## ms before allowing axis to switch direcitons.  Alternative method to prevent skipping steps.  Uncomment the line below to activate.\n// At this Version with Planner this Function ist not used\n//#define RAPID_OSCILLATION_REDUCTION\n\n#ifdef RAPID_OSCILLATION_REDUCTION\nconst long min_time_before_dir_change = 30; //milliseconds\n#endif\n\n//-----------------------------------------------------------------------\n//// Acceleration settings\n//-----------------------------------------------------------------------\n// X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot.\n#define _ACCELERATION 1000         // Axis Normal acceleration mm/s^2\n#define _RETRACT_ACCELERATION 2000 // Extruder Normal acceleration mm/s^2\n#define _MAX_XY_JERK 20.0\n#define _MAX_Z_JERK 0.4\n#define _MAX_E_JERK 5.0    // (mm/sec)\n//#define _MAX_START_SPEED_UNITS_PER_SECOND {25.0,25.0,0.2,10.0}\n#define _MAX_ACCELERATION_UNITS_PER_SQ_SECOND {5000,5000,50,5000}    // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts\n\n\n// Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end\n// of the buffer and all stops. This should not be much greater than zero and should only be changed\n// if unwanted behavior is observed on a user's machine when running at very slow speeds.\n#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)\n\n#define DEFAULT_MINIMUMFEEDRATE       0.0     // minimum feedrate\n#define DEFAULT_MINTRAVELFEEDRATE     0.0\n\n#define _MIN_SEG_TIME 20000\n\n// If defined the movements slow down when the look ahead buffer is only half full\n#define SLOWDOWN\n\n\nconst int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement\n\n//-----------------------------------------------------------------------\n// Machine UUID\n//-----------------------------------------------------------------------\n// This may be useful if you have multiple machines and wish to identify them by using the M115 command. \n// By default we set it to zeros.\n#define _DEF_CHAR_UUID \"00000000-0000-0000-0000-000000000000\"\n\n\n\n//-----------------------------------------------------------------------\n//// Planner buffer Size\n//-----------------------------------------------------------------------\n\n// The number of linear motions that can be in the plan at any give time\n// if the SD Card need to much memory reduce the Values for Plannerpuffer (base of 2)\n#ifdef SDSUPPORT\n  #define BLOCK_BUFFER_SIZE 16\n  #define BLOCK_BUFFER_MASK 0x0f\n#else\n  #define BLOCK_BUFFER_SIZE 16  \n  #define BLOCK_BUFFER_MASK 0x0f\n#endif \n\n//-----------------------------------------------------------------------\n//// SETTINGS FOR ARC FUNCTION (Command G2/G2)\n//-----------------------------------------------------------------------\n\n// Arc interpretation settings:\n//Step to split a cirrcle in small Lines \n#define MM_PER_ARC_SEGMENT 1\n//After this count of steps a new SIN / COS caluclation is startet to correct the circle interpolation\n#define N_ARC_CORRECTION 25\n\n//-----------------------------------------------------------------------\n//// FANCONTROL WITH SOFT PWM\n//-----------------------------------------------------------------------\n\n//With this option its possible to drive the fan with SOFT PWM (500hz) and use\n//every Digital output for it, main usage for Sanguinololu\n#define FAN_SOFT_PWM\n\n//-----------------------------------------------------------------------\n//// MINIMUM START SPEED FOR FAN\n//-----------------------------------------------------------------------\n\n//Minimum start speed for FAN when the last speed was zero\n//Set to 0 to deaktivate\n//If value is set the fan will drive with this minimum speed for MINIMUM_FAN_START_TIME\n#define MINIMUM_FAN_START_SPEED  0\n\n//This is the time how long the minimum FAN speed is set\n#define MINIMUM_FAN_START_TIME  6000    //6sec\n\n//-----------------------------------------------------------------------\n//// HEATERCONTROL AND PID PARAMETERS\n//-----------------------------------------------------------------------\n\n//Testfunction to adjust the Hotend temperatur in case of Printingspeed\n//If the Printer print slow the Temp is going to AUTO_TEMP_MIN\n//At the moment this Value dont change the targettemp from the Hotend\n//The result of this function is only send with the Temperaturerequest to the host\n//#define AUTOTEMP \n#ifdef AUTOTEMP\n    #define AUTO_TEMP_MAX 240\n    #define AUTO_TEMP_MIN 205\n    #define AUTO_TEMP_FACTOR 0.025\n    #define AUTOTEMP_OLDWEIGHT 0.98\n#endif\n\n//// AD595 THERMOCOUPLE SUPPORT UNTESTED... USE WITH CAUTION!!!!\n\n//// PID settings:\n// Uncomment the following line to enable PID support. This is untested and could be disastrous. Be careful.\n#define PIDTEMP 1\n#ifdef PIDTEMP\n//Sanguinololu 1.2 and above, the PWM Output Hotend Timer 1 is used for the Hardware PWM\n//but in this Software use Timer1 for the Stepperfunction so it is not possible to use the \"analogWrite\" function.\n//This Soft PWM use Timer 2 with 400 Hz to drive the PWM for the hotend\n#define PID_SOFT_PWM\n\n//Measure the MIN/MAX Value of the Hotend Temp and show it with\n//Command M601 / Command M602 Reset the MIN/MAX Value\n//#define DEBUG_HEATER_TEMP\n\n// M303 - PID relay autotune S<temperature> sets the target temperature. \n// (default target temperature = 150C)\n#define PID_AUTOTUNE\n\n//PID Controler Settings\n#define PID_INTEGRAL_DRIVE_MAX 80 // too big, and heater will lag after changing temperature, too small and it might not compensate enough for long-term errors\n#define PID_PGAIN 2560 //256 is 1.0  // value of X means that error of 1 degree is changing PWM duty by X, probably no need to go over 25\n#define PID_IGAIN 64 //256 is 1.0  // value of X (e.g 0.25) means that each degree error over 1 sec (2 measurements) changes duty cycle by 2X (=0.5) units (verify?)\n#define PID_DGAIN 4096 //256 is 1.0  // value of X means that around reached setpoint, each degree change over one measurement (half second) adjusts PWM by X units to compensate\n\n// magic formula 1, to get approximate \"zero error\" PWM duty. Take few measurements with low PWM duty and make linear fit to get the formula\n// for my makergear hot-end: linear fit {50,10},{60,20},{80,30},{105,50},{176,100},{128,64},{208,128}\n#define HEATER_DUTY_FOR_SETPOINT(setpoint) ((int)((187L*(long)setpoint)>>8)-27)  \n// magic formula 2, to make led brightness approximately linear\n#define LED_PWM_FOR_BRIGHTNESS(brightness) ((64*brightness-1384)/(300-brightness))\n#endif\n\n// Change this value (range 30-255) to limit the current to the nozzle\n#define HEATER_CURRENT 255\n\n// How often should the heater check for new temp readings, in milliseconds\n#define HEATER_CHECK_INTERVAL 500\n#define BED_CHECK_INTERVAL 5000\n\n// Comment the following line to enable heat management during acceleration\n#define DISABLE_CHECK_DURING_ACC\n#ifndef DISABLE_CHECK_DURING_ACC\n  // Uncomment the following line to disable heat management during moves\n  //#define DISABLE_CHECK_DURING_MOVE\n#endif\n\n// Uncomment the following line to disable heat management during travel moves (and extruder-only moves, eg: retracts), strongly recommended if you are missing steps mid print.\n// Probably this should remain commented if are using PID.\n// It also defines the max milliseconds interval after which a travel move is not considered so for the sake of this feature.\n#define DISABLE_CHECK_DURING_TRAVEL 1000\n\n//// Temperature smoothing - only uncomment this if your temp readings are noisy (Gen6 without EvdZ's 5V hack)\n//#define SMOOTHING\n//#define SMOOTHFACTOR 16 //best to use a power of two here - determines how many values are averaged together by the smoothing algorithm\n\n\n//// Experimental watchdog and minimal temp\n// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature\n// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109\n//#define WATCHPERIOD 5000 //5 seconds\n\n// Actual temperature must be close to target for this long before M109 returns success\n//#define TEMP_RESIDENCY_TIME 20  // (seconds)\n//#define TEMP_HYSTERESIS 5       // (C°) range of +/- temperatures considered \"close\" to the target one\n\n//// The minimal temperature defines the temperature below which the heater will not be enabled\n#define MINTEMP 5\n\n//// Experimental max temp\n// When temperature exceeds max temp, your heater will be switched off.\n// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure!\n// You should use MINTEMP for thermistor short/failure protection.\n#define MAXTEMP 275\n\n// Select one of these only to define how the nozzle temp is read.\n#define HEATER_USES_THERMISTOR\n//#define HEATER_USES_AD595\n//#define HEATER_USES_MAX6675\n\n// Select one of these only to define how the bed temp is read.\n#define BED_USES_THERMISTOR\n//#define BED_USES_AD595\n\n//This is for controlling a fan to cool down the stepper drivers\n//it will turn on when any driver is enabled\n//and turn off after the set amount of seconds from last driver being disabled again\n//#define CONTROLLERFAN_PIN 23 //Pin used for the fan to cool controller, comment out to disable this function\n#define CONTROLLERFAN_SEC 60 //How many seconds, after all motors were disabled, the fan should run\n\n//This is for controlling a fan that will keep the extruder cool.\n//#define EXTRUDERFAN_PIN 66 //Pin used to control the fan, comment out to disable this function\n#define EXTRUDERFAN_DEC 50 //Hotend temperature from where the fan will be turned on\n\n//#define CHAIN_OF_COMMAND 1 //Finish buffered moves before executing M42, fan speed, heater target, and so...\n\n//-----------------------------------------------------------------------\n// DEBUGING\n//-----------------------------------------------------------------------\n\n\n//Uncomment this to see on the host if a wrong or unknown Command is recived\n//Only for Testing !!!\n//#define SEND_WRONG_CMD_INFO\n\n// Uncomment the following line to enable debugging. You can better control debugging below the following line\n//#define DEBUG\n#ifdef DEBUG\n  //#define DEBUG_PREPARE_MOVE //Enable this to debug prepare_move() function\n  //#define DEBUG_MOVE_TIME //Enable this to time each move and print the result   \n  //#define DEBUG_HEAT_MGMT //Enable this to debug heat management. WARNING, this will cause axes to jitter!\n  //#define DEBUG_DISABLE_CHECK_DURING_TRAVEL //Debug the namesake feature, see above in this file\n#endif\n\n#endif\n"
  },
  {
    "path": "Sprinter/FatStructs.h",
    "content": "/* Arduino SdFat Library\r\n * Copyright (C) 2009 by William Greiman\r\n *\r\n * This file is part of the Arduino SdFat Library\r\n *\r\n * This Library is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino SdFat Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n#ifndef FatStructs_h\r\n#define FatStructs_h\r\n/**\r\n * \\file\r\n * FAT file structures\r\n */\r\n/*\r\n * mostly from Microsoft document fatgen103.doc\r\n * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx\r\n */\r\n//------------------------------------------------------------------------------\r\n/** Value for byte 510 of boot block or MBR */\r\nuint8_t const BOOTSIG0 = 0X55;\r\n/** Value for byte 511 of boot block or MBR */\r\nuint8_t const BOOTSIG1 = 0XAA;\r\n//------------------------------------------------------------------------------\r\n/**\r\n * \\struct partitionTable\r\n * \\brief MBR partition table entry\r\n *\r\n * A partition table entry for a MBR formatted storage device.\r\n * The MBR partition table has four entries.\r\n */\r\nstruct partitionTable {\r\n          /**\r\n           * Boot Indicator . Indicates whether the volume is the active\r\n           * partition.  Legal values include: 0X00. Do not use for booting.\r\n           * 0X80 Active partition.\r\n           */\r\n  uint8_t  boot;\r\n          /**\r\n            * Head part of Cylinder-head-sector address of the first block in\r\n            * the partition. Legal values are 0-255. Only used in old PC BIOS.\r\n            */\r\n  uint8_t  beginHead;\r\n          /**\r\n           * Sector part of Cylinder-head-sector address of the first block in\r\n           * the partition. Legal values are 1-63. Only used in old PC BIOS.\r\n           */\r\n  unsigned beginSector : 6;\r\n           /** High bits cylinder for first block in partition. */\r\n  unsigned beginCylinderHigh : 2;\r\n          /**\r\n           * Combine beginCylinderLow with beginCylinderHigh. Legal values\r\n           * are 0-1023.  Only used in old PC BIOS.\r\n           */\r\n  uint8_t  beginCylinderLow;\r\n          /**\r\n           * Partition type. See defines that begin with PART_TYPE_ for\r\n           * some Microsoft partition types.\r\n           */\r\n  uint8_t  type;\r\n          /**\r\n           * head part of cylinder-head-sector address of the last sector in the\r\n           * partition.  Legal values are 0-255. Only used in old PC BIOS.\r\n           */\r\n  uint8_t  endHead;\r\n          /**\r\n           * Sector part of cylinder-head-sector address of the last sector in\r\n           * the partition.  Legal values are 1-63. Only used in old PC BIOS.\r\n           */\r\n  unsigned endSector : 6;\r\n           /** High bits of end cylinder */\r\n  unsigned endCylinderHigh : 2;\r\n          /**\r\n           * Combine endCylinderLow with endCylinderHigh. Legal values\r\n           * are 0-1023.  Only used in old PC BIOS.\r\n           */\r\n  uint8_t  endCylinderLow;\r\n           /** Logical block address of the first block in the partition. */\r\n  uint32_t firstSector;\r\n           /** Length of the partition, in blocks. */\r\n  uint32_t totalSectors;\r\n};\r\n/** Type name for partitionTable */\r\ntypedef struct partitionTable part_t;\r\n//------------------------------------------------------------------------------\r\n/**\r\n * \\struct masterBootRecord\r\n *\r\n * \\brief Master Boot Record\r\n *\r\n * The first block of a storage device that is formatted with a MBR.\r\n */\r\nstruct masterBootRecord {\r\n           /** Code Area for master boot program. */\r\n  uint8_t  codeArea[440];\r\n           /** Optional WindowsNT disk signature. May contain more boot code. */\r\n  uint32_t diskSignature;\r\n           /** Usually zero but may be more boot code. */\r\n  uint16_t usuallyZero;\r\n           /** Partition tables. */\r\n  part_t   part[4];\r\n           /** First MBR signature byte. Must be 0X55 */\r\n  uint8_t  mbrSig0;\r\n           /** Second MBR signature byte. Must be 0XAA */\r\n  uint8_t  mbrSig1;\r\n};\r\n/** Type name for masterBootRecord */\r\ntypedef struct masterBootRecord mbr_t;\r\n//------------------------------------------------------------------------------\r\n/** \r\n * \\struct biosParmBlock\r\n *\r\n * \\brief BIOS parameter block\r\n * \r\n *  The BIOS parameter block describes the physical layout of a FAT volume.\r\n */\r\nstruct biosParmBlock {\r\n          /**\r\n           * Count of bytes per sector. This value may take on only the\r\n           * following values: 512, 1024, 2048 or 4096\r\n           */\r\n  uint16_t bytesPerSector;\r\n          /**\r\n           * Number of sectors per allocation unit. This value must be a\r\n           * power of 2 that is greater than 0. The legal values are\r\n           * 1, 2, 4, 8, 16, 32, 64, and 128.\r\n           */\r\n  uint8_t  sectorsPerCluster;\r\n          /**\r\n           * Number of sectors before the first FAT.\r\n           * This value must not be zero.\r\n           */\r\n  uint16_t reservedSectorCount;\r\n          /** The count of FAT data structures on the volume. This field should\r\n           *  always contain the value 2 for any FAT volume of any type.\r\n           */\r\n  uint8_t  fatCount;\r\n          /**\r\n          * For FAT12 and FAT16 volumes, this field contains the count of\r\n          * 32-byte directory entries in the root directory. For FAT32 volumes,\r\n          * this field must be set to 0. For FAT12 and FAT16 volumes, this\r\n          * value should always specify a count that when multiplied by 32\r\n          * results in a multiple of bytesPerSector.  FAT16 volumes should\r\n          * use the value 512.\r\n          */\r\n  uint16_t rootDirEntryCount;\r\n          /**\r\n           * This field is the old 16-bit total count of sectors on the volume.\r\n           * This count includes the count of all sectors in all four regions\r\n           * of the volume. This field can be 0; if it is 0, then totalSectors32\r\n           * must be non-zero.  For FAT32 volumes, this field must be 0. For\r\n           * FAT12 and FAT16 volumes, this field contains the sector count, and\r\n           * totalSectors32 is 0 if the total sector count fits\r\n           * (is less than 0x10000).\r\n           */\r\n  uint16_t totalSectors16;\r\n          /**\r\n           * This dates back to the old MS-DOS 1.x media determination and is\r\n           * no longer usually used for anything.  0xF8 is the standard value\r\n           * for fixed (non-removable) media. For removable media, 0xF0 is\r\n           * frequently used. Legal values are 0xF0 or 0xF8-0xFF.\r\n           */\r\n  uint8_t  mediaType;\r\n          /**\r\n           * Count of sectors occupied by one FAT on FAT12/FAT16 volumes.\r\n           * On FAT32 volumes this field must be 0, and sectorsPerFat32\r\n           * contains the FAT size count.\r\n           */\r\n  uint16_t sectorsPerFat16;\r\n           /** Sectors per track for interrupt 0x13. Not used otherwise. */\r\n  uint16_t sectorsPerTrtack;\r\n           /** Number of heads for interrupt 0x13.  Not used otherwise. */\r\n  uint16_t headCount;\r\n          /**\r\n           * Count of hidden sectors preceding the partition that contains this\r\n           * FAT volume. This field is generally only relevant for media\r\n           *  visible on interrupt 0x13.\r\n           */\r\n  uint32_t hidddenSectors;\r\n          /**\r\n           * This field is the new 32-bit total count of sectors on the volume.\r\n           * This count includes the count of all sectors in all four regions\r\n           * of the volume.  This field can be 0; if it is 0, then\r\n           * totalSectors16 must be non-zero.\r\n           */\r\n  uint32_t totalSectors32;\r\n          /**\r\n           * Count of sectors occupied by one FAT on FAT32 volumes.\r\n           */\r\n  uint32_t sectorsPerFat32;\r\n          /**\r\n           * This field is only defined for FAT32 media and does not exist on\r\n           * FAT12 and FAT16 media.\r\n           * Bits 0-3 -- Zero-based number of active FAT.\r\n           *             Only valid if mirroring is disabled.\r\n           * Bits 4-6 -- Reserved.\r\n           * Bit 7\t-- 0 means the FAT is mirrored at runtime into all FATs.\r\n\t         *        -- 1 means only one FAT is active; it is the one referenced in bits 0-3.\r\n           * Bits 8-15 \t-- Reserved.\r\n           */\r\n  uint16_t fat32Flags;\r\n          /**\r\n           * FAT32 version. High byte is major revision number.\r\n           * Low byte is minor revision number. Only 0.0 define.\r\n           */\r\n  uint16_t fat32Version;\r\n          /**\r\n           * Cluster number of the first cluster of the root directory for FAT32.\r\n           * This usually 2 but not required to be 2.\r\n           */\r\n  uint32_t fat32RootCluster;\r\n          /**\r\n           * Sector number of FSINFO structure in the reserved area of the\r\n           * FAT32 volume. Usually 1.\r\n           */\r\n  uint16_t fat32FSInfo;\r\n          /**\r\n           * If non-zero, indicates the sector number in the reserved area\r\n           * of the volume of a copy of the boot record. Usually 6.\r\n           * No value other than 6 is recommended.\r\n           */\r\n  uint16_t fat32BackBootBlock;\r\n          /**\r\n           * Reserved for future expansion. Code that formats FAT32 volumes\r\n           * should always set all of the bytes of this field to 0.\r\n           */\r\n  uint8_t  fat32Reserved[12];\r\n};\r\n/** Type name for biosParmBlock */\r\ntypedef struct biosParmBlock bpb_t;\r\n//------------------------------------------------------------------------------\r\n/**\r\n * \\struct fat32BootSector\r\n *\r\n * \\brief Boot sector for a FAT16 or FAT32 volume.\r\n * \r\n */  \r\nstruct fat32BootSector {\r\n           /** X86 jmp to boot program */\r\n  uint8_t  jmpToBootCode[3];\r\n           /** informational only - don't depend on it */\r\n  char     oemName[8];\r\n           /** BIOS Parameter Block */\r\n  bpb_t    bpb;\r\n           /** for int0x13 use value 0X80 for hard drive */\r\n  uint8_t  driveNumber;\r\n           /** used by Windows NT - should be zero for FAT */\r\n  uint8_t  reserved1;\r\n           /** 0X29 if next three fields are valid */\r\n  uint8_t  bootSignature;\r\n           /** usually generated by combining date and time */\r\n  uint32_t volumeSerialNumber;\r\n           /** should match volume label in root dir */\r\n  char     volumeLabel[11];\r\n           /** informational only - don't depend on it */\r\n  char     fileSystemType[8];\r\n           /** X86 boot code */\r\n  uint8_t  bootCode[420];\r\n           /** must be 0X55 */\r\n  uint8_t  bootSectorSig0;\r\n           /** must be 0XAA */\r\n  uint8_t  bootSectorSig1;\r\n};\r\n//------------------------------------------------------------------------------\r\n// End Of Chain values for FAT entries\r\n/** FAT16 end of chain value used by Microsoft. */\r\nuint16_t const FAT16EOC = 0XFFFF;\r\n/** Minimum value for FAT16 EOC.  Use to test for EOC. */\r\nuint16_t const FAT16EOC_MIN = 0XFFF8;\r\n/** FAT32 end of chain value used by Microsoft. */\r\nuint32_t const FAT32EOC = 0X0FFFFFFF;\r\n/** Minimum value for FAT32 EOC.  Use to test for EOC. */\r\nuint32_t const FAT32EOC_MIN = 0X0FFFFFF8;\r\n/** Mask a for FAT32 entry. Entries are 28 bits. */\r\nuint32_t const FAT32MASK = 0X0FFFFFFF;\r\n\r\n/** Type name for fat32BootSector */\r\ntypedef struct fat32BootSector fbs_t;\r\n//------------------------------------------------------------------------------\r\n/**\r\n * \\struct directoryEntry\r\n * \\brief FAT short directory entry\r\n *\r\n * Short means short 8.3 name, not the entry size.\r\n *  \r\n * Date Format. A FAT directory entry date stamp is a 16-bit field that is \r\n * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the\r\n * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the \r\n * 16-bit word):\r\n *   \r\n * Bits 9-15: Count of years from 1980, valid value range 0-127 \r\n * inclusive (1980-2107).\r\n *   \r\n * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.\r\n *\r\n * Bits 0-4: Day of month, valid value range 1-31 inclusive.\r\n *\r\n * Time Format. A FAT directory entry time stamp is a 16-bit field that has\r\n * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the \r\n * 16-bit word, bit 15 is the MSB of the 16-bit word).\r\n *   \r\n * Bits 11-15: Hours, valid value range 0-23 inclusive.\r\n * \r\n * Bits 5-10: Minutes, valid value range 0-59 inclusive.\r\n *      \r\n * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).\r\n *   \r\n * The valid time range is from Midnight 00:00:00 to 23:59:58.\r\n */\r\nstruct directoryEntry {\r\n           /**\r\n            * Short 8.3 name.\r\n            * The first eight bytes contain the file name with blank fill.\r\n            * The last three bytes contain the file extension with blank fill.\r\n            */\r\n  uint8_t  name[11];\r\n          /** Entry attributes.\r\n           *\r\n           * The upper two bits of the attribute byte are reserved and should\r\n           * always be set to 0 when a file is created and never modified or\r\n           * looked at after that.  See defines that begin with DIR_ATT_.\r\n           */\r\n  uint8_t  attributes;\r\n          /**\r\n           * Reserved for use by Windows NT. Set value to 0 when a file is\r\n           * created and never modify or look at it after that.\r\n           */\r\n  uint8_t  reservedNT;\r\n          /**\r\n           * The granularity of the seconds part of creationTime is 2 seconds\r\n           * so this field is a count of tenths of a second and its valid\r\n           * value range is 0-199 inclusive. (WHG note - seems to be hundredths)\r\n           */\r\n  uint8_t  creationTimeTenths;\r\n           /** Time file was created. */\r\n  uint16_t creationTime;\r\n           /** Date file was created. */\r\n  uint16_t creationDate;\r\n          /**\r\n           * Last access date. Note that there is no last access time, only\r\n           * a date.  This is the date of last read or write. In the case of\r\n           * a write, this should be set to the same date as lastWriteDate.\r\n           */\r\n  uint16_t lastAccessDate;\r\n          /**\r\n           * High word of this entry's first cluster number (always 0 for a\r\n           * FAT12 or FAT16 volume).\r\n           */\r\n  uint16_t firstClusterHigh;\r\n           /** Time of last write. File creation is considered a write. */\r\n  uint16_t lastWriteTime;\r\n           /** Date of last write. File creation is considered a write. */\r\n  uint16_t lastWriteDate;\r\n           /** Low word of this entry's first cluster number. */\r\n  uint16_t firstClusterLow;\r\n           /** 32-bit unsigned holding this file's size in bytes. */\r\n  uint32_t fileSize;\r\n};\r\n//------------------------------------------------------------------------------\r\n// Definitions for directory entries\r\n//\r\n/** Type name for directoryEntry */\r\ntypedef struct directoryEntry dir_t;\r\n/** escape for name[0] = 0XE5 */\r\nuint8_t const DIR_NAME_0XE5 = 0X05;\r\n/** name[0] value for entry that is free after being \"deleted\" */\r\nuint8_t const DIR_NAME_DELETED = 0XE5;\r\n/** name[0] value for entry that is free and no allocated entries follow */\r\nuint8_t const DIR_NAME_FREE = 0X00;\r\n/** file is read-only */\r\nuint8_t const DIR_ATT_READ_ONLY = 0X01;\r\n/** File should hidden in directory listings */\r\nuint8_t const DIR_ATT_HIDDEN = 0X02;\r\n/** Entry is for a system file */\r\nuint8_t const DIR_ATT_SYSTEM = 0X04;\r\n/** Directory entry contains the volume label */\r\nuint8_t const DIR_ATT_VOLUME_ID = 0X08;\r\n/** Entry is for a directory */\r\nuint8_t const DIR_ATT_DIRECTORY = 0X10;\r\n/** Old DOS archive bit for backup support */\r\nuint8_t const DIR_ATT_ARCHIVE = 0X20;\r\n/** Test value for long name entry.  Test is\r\n  (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */\r\nuint8_t const DIR_ATT_LONG_NAME = 0X0F;\r\n/** Test mask for long name entry */\r\nuint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F;\r\n/** defined attribute bits */\r\nuint8_t const DIR_ATT_DEFINED_BITS = 0X3F;\r\n/** Directory entry is part of a long name */\r\nstatic inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {\r\n  return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;\r\n}\r\n/** Mask for file/subdirectory tests */\r\nuint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);\r\n/** Directory entry is for a file */\r\nstatic inline uint8_t DIR_IS_FILE(const dir_t* dir) {\r\n  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;\r\n}\r\n/** Directory entry is for a subdirectory */\r\nstatic inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {\r\n  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;\r\n}\r\n/** Directory entry is for a file or subdirectory */\r\nstatic inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {\r\n  return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;\r\n}\r\n#endif  // FatStructs_h\r\n"
  },
  {
    "path": "Sprinter/Makefile",
    "content": "# Sprinter Arduino Project Makefile\n# \n# Makefile Based on:\n# Arduino 0011 Makefile\n# Arduino adaptation by mellis, eighthave, oli.keller\n#\n# This has been tested with Arduino 0022.\n# \n# This makefile allows you to build sketches from the command line\n# without the Arduino environment (or Java).\n#\n# Detailed instructions for using the makefile:\n#\n#  1. Modify the line containg \"INSTALL_DIR\" to point to the directory that\n#     contains the Arduino installation (for example, under Mac OS X, this\n#     might be /Applications/arduino-0012).\n#\n#  2. Modify the line containing \"PORT\" to refer to the filename\n#     representing the USB or serial connection to your Arduino board\n#     (e.g. PORT = /dev/tty.USB0).  If the exact name of this file\n#     changes, you can use * as a wildcard (e.g. PORT = /dev/tty.usb*).\n#\n#  3. Set the line containing \"MCU\" to match your board's processor. \n#     Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth\n#     or Diecimila have the atmega168.  If you're using a LilyPad Arduino,\n#     change F_CPU to 8000000.\n#\n#  4. Type \"make\" and press enter to compile/verify your program.\n#\n#  5. Type \"make upload\", reset your Arduino board, and press enter to\n#     upload your program to the Arduino board.\n#\n# $Id$\n\nTARGET = $(notdir $(CURDIR))\nINSTALL_DIR = ../../arduino22/arduino-0022/\nUPLOAD_RATE = 38400\nAVRDUDE_PROGRAMMER = stk500v1\nPORT = /dev/ttyUSB0\nMCU = atmega2560\n#For \"old\" Arduino Mega\n#MCU = atmega1280\n#For Sanguinololu\n#MCU = atmega644p \nF_CPU = 16000000\n\n\n############################################################################\n# Below here nothing should be changed...\n\nARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino\nAVR_TOOLS_PATH = /usr/bin\nSRC =  $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \\\n$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \\\n$(ARDUINO)/wiring_pulse.c \\\n$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c\nCXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp $(ARDUINO)/WString.cpp\\\n$(ARDUINO)/Print.cpp ./SdFile.cpp ./SdVolume.cpp ./Sd2Card.cpp ./heater.cpp ./arc_func.cpp ./store_eeprom.cpp\nFORMAT = ihex\n\n\n# Name of this Makefile (used for \"make depend\").\nMAKEFILE = Makefile\n\n# Debugging format.\n# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.\n# AVR (extended) COFF requires stabs, plus an avr-objcopy run.\nDEBUG = stabs\n\nOPT = s\n\n# Place -D or -U options here\nCDEFS = -DF_CPU=$(F_CPU)\nCXXDEFS = -DF_CPU=$(F_CPU)\n\n# Place -I options here\nCINCS = -I$(ARDUINO)\nCXXINCS = -I$(ARDUINO)\n\n# Compiler flag to set the C Standard level.\n# c89   - \"ANSI\" C\n# gnu89 - c89 plus GCC extensions\n# c99   - ISO C99 standard (not yet fully implemented)\n# gnu99 - c99 plus GCC extensions\n#CSTANDARD = -std=gnu99\nCDEBUG = -g$(DEBUG)\nCWARN = -Wall -Wstrict-prototypes\nCTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -w -ffunction-sections -fdata-sections -DARDUINO=22\n#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)\n\nCFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING)\nCXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING)\n#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs \nLDFLAGS = -lm\n\n\n# Programming support using avrdude. Settings and variables.\nAVRDUDE_PORT = $(PORT)\nAVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex:i\nAVRDUDE_FLAGS = -D -C $(INSTALL_DIR)/hardware/tools/avrdude.conf \\\n-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \\\n-b $(UPLOAD_RATE)\n\n# Program settings\nCC = $(AVR_TOOLS_PATH)/avr-gcc\nCXX = $(AVR_TOOLS_PATH)/avr-g++\nOBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy\nOBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump\nAR  = $(AVR_TOOLS_PATH)/avr-ar\nSIZE = $(AVR_TOOLS_PATH)/avr-size\nNM = $(AVR_TOOLS_PATH)/avr-nm\nAVRDUDE = $(INSTALL_DIR)/hardware/tools/avrdude\nREMOVE = rm -f\nMV = mv -f\n\n# Define all object files.\nOBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) \n\n# Define all listing files.\nLST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)\n\n# Combine all necessary flags and optional flags.\n# Add target processor to flags.\nALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)\nALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)\nALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)\n\n\n# Default target.\nall: build sizeafter\n\nbuild: elf hex \n\napplet/$(TARGET).cpp: $(TARGET).pde\n\t# Here is the \"preprocessing\".\n\t# It creates a .cpp file based with the same name as the .pde file.\n\t# On top of the new .cpp file comes the WProgram.h header.\n\t# At the end there is a generic main() function attached.\n\t# Then the .cpp file will be compiled. Errors during compile will\n\t# refer to this new, automatically generated, file. \n\t# Not the original .pde file you actually edit...\n\ttest -d applet || mkdir applet\n\techo '#include \"WProgram.h\"' > applet/$(TARGET).cpp\n\tcat $(TARGET).pde >> applet/$(TARGET).cpp\n\tcat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp\n\nelf: applet/$(TARGET).elf\nhex: applet/$(TARGET).hex\neep: applet/$(TARGET).eep\nlss: applet/$(TARGET).lss \nsym: applet/$(TARGET).sym\n\n# Program the device.  \nupload: applet/$(TARGET).hex\n\t$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)\n\n\n# Display size of file.\nHEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex\nELFSIZE = $(SIZE)  applet/$(TARGET).elf\nsizebefore:\n\t@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi\n\nsizeafter:\n\t@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi\n\n\n# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.\nCOFFCONVERT=$(OBJCOPY) --debugging \\\n--change-section-address .data-0x800000 \\\n--change-section-address .bss-0x800000 \\\n--change-section-address .noinit-0x800000 \\\n--change-section-address .eeprom-0x810000 \n\n\ncoff: applet/$(TARGET).elf\n\t$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof\n\n\nextcoff: $(TARGET).elf\n\t$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof\n\n\n.SUFFIXES: .elf .hex .eep .lss .sym\n\n.elf.hex:\n\t$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@\n\n.elf.eep:\n\t-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom=\"alloc,load\" \\\n\t--change-section-lma .eeprom=0 -O $(FORMAT) $< $@\n\n# Create extended listing file from ELF output file.\n.elf.lss:\n\t$(OBJDUMP) -h -S $< > $@\n\n# Create a symbol table from ELF output file.\n.elf.sym:\n\t$(NM) -n $< > $@\n\n# Link: create ELF output file from library.\napplet/$(TARGET).elf: applet/$(TARGET).cpp applet/core.a\n\t$(CC) $(ALL_CFLAGS) -Wl,--gc-sections -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS)\n\napplet/core.a: $(OBJ)\n\t@for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done\n\n\n\n# Compile: create object files from C++ source files.\n.cpp.o:\n\t$(CXX) -c $(ALL_CXXFLAGS) $< -o $@ \n\n# Compile: create object files from C source files.\n.c.o:\n\t$(CC) -c $(ALL_CFLAGS) $< -o $@ \n\n\n# Compile: create assembler files from C source files.\n.c.s:\n\t$(CC) -S $(ALL_CFLAGS) $< -o $@\n\n\n# Assemble: create object files from assembler source files.\n.S.o:\n\t$(CC) -c $(ALL_ASFLAGS) $< -o $@\n\n\n\n# Target: clean project.\nclean:\n\t$(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \\\n\tapplet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \\\n\t$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)\n\ndepend:\n\tif grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \\\n\tthen \\\n\t\tsed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \\\n\t\t\t$(MAKEFILE).$$$$ && \\\n\t\t$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \\\n\tfi\n\techo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \\\n\t\t>> $(MAKEFILE); \\\n\t$(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE)\n\n.PHONY:\tall build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter\n"
  },
  {
    "path": "Sprinter/Sd2Card.cpp",
    "content": "/* Arduino Sd2Card Library\r\n * Copyright (C) 2009 by William Greiman\r\n *\r\n * This file is part of the Arduino Sd2Card Library\r\n *\r\n * This Library is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino Sd2Card Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n#if defined(ARDUINO) && ARDUINO >= 100\r\n#include <Arduino.h>\r\n#else\r\n#include <WProgram.h>\r\n#endif\r\n#include \"Sd2Card.h\"\r\n//------------------------------------------------------------------------------\r\n#ifndef SOFTWARE_SPI\r\n// functions for hardware SPI\r\n/** Send a byte to the card */\r\nstatic void spiSend(uint8_t b) {\r\n  SPDR = b;\r\n  while (!(SPSR & (1 << SPIF)));\r\n}\r\n/** Receive a byte from the card */\r\nstatic  uint8_t spiRec(void) {\r\n  spiSend(0XFF);\r\n  return SPDR;\r\n}\r\n#else  // SOFTWARE_SPI\r\n//------------------------------------------------------------------------------\r\n/** nop to tune soft SPI timing */\r\n#define nop asm volatile (\"nop\\n\\t\")\r\n//------------------------------------------------------------------------------\r\n/** Soft SPI receive */\r\nuint8_t spiRec(void) {\r\n  uint8_t data = 0;\r\n  // no interrupts during byte receive - about 8 us\r\n  cli();\r\n  // output pin high - like sending 0XFF\r\n  fastDigitalWrite(SPI_MOSI_PIN, HIGH);\r\n\r\n  for (uint8_t i = 0; i < 8; i++) {\r\n    fastDigitalWrite(SPI_SCK_PIN, HIGH);\r\n\r\n    // adjust so SCK is nice\r\n    nop;\r\n    nop;\r\n\r\n    data <<= 1;\r\n\r\n    if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;\r\n\r\n    fastDigitalWrite(SPI_SCK_PIN, LOW);\r\n  }\r\n  // enable interrupts\r\n  sei();\r\n  return data;\r\n}\r\n//------------------------------------------------------------------------------\r\n/** Soft SPI send */\r\nvoid spiSend(uint8_t data) {\r\n  // no interrupts during byte send - about 8 us\r\n  cli();\r\n  for (uint8_t i = 0; i < 8; i++) {\r\n    fastDigitalWrite(SPI_SCK_PIN, LOW);\r\n\r\n    fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);\r\n\r\n    data <<= 1;\r\n\r\n    fastDigitalWrite(SPI_SCK_PIN, HIGH);\r\n  }\r\n  // hold SCK high for a few ns\r\n  nop;\r\n  nop;\r\n  nop;\r\n  nop;\r\n\r\n  fastDigitalWrite(SPI_SCK_PIN, LOW);\r\n  // enable interrupts\r\n  sei();\r\n}\r\n#endif  // SOFTWARE_SPI\r\n//------------------------------------------------------------------------------\r\n// send command and return error code.  Return zero for OK\r\nuint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {\r\n  // end read if in partialBlockRead mode\r\n  readEnd();\r\n\r\n  // select card\r\n  chipSelectLow();\r\n\r\n  // wait up to 300 ms if busy\r\n  waitNotBusy(300);\r\n\r\n  // send command\r\n  spiSend(cmd | 0x40);\r\n\r\n  // send argument\r\n  for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);\r\n\r\n  // send CRC\r\n  uint8_t crc = 0XFF;\r\n  if (cmd == CMD0) crc = 0X95;  // correct crc for CMD0 with arg 0\r\n  if (cmd == CMD8) crc = 0X87;  // correct crc for CMD8 with arg 0X1AA\r\n  spiSend(crc);\r\n\r\n  // wait for response\r\n  for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++);\r\n  return status_;\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Determine the size of an SD flash memory card.\r\n *\r\n * \\return The number of 512 byte data blocks in the card\r\n *         or zero if an error occurs.\r\n */\r\nuint32_t Sd2Card::cardSize(void) {\r\n  csd_t csd;\r\n  if (!readCSD(&csd)) return 0;\r\n  if (csd.v1.csd_ver == 0) {\r\n    uint8_t read_bl_len = csd.v1.read_bl_len;\r\n    uint16_t c_size = (csd.v1.c_size_high << 10)\r\n                      | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;\r\n    uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)\r\n                          | csd.v1.c_size_mult_low;\r\n    return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);\r\n  } else if (csd.v2.csd_ver == 1) {\r\n    uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)\r\n                      | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;\r\n    return (c_size + 1) << 10;\r\n  } else {\r\n    error(SD_CARD_ERROR_BAD_CSD);\r\n    return 0;\r\n  }\r\n}\r\n//------------------------------------------------------------------------------\r\nvoid Sd2Card::chipSelectHigh(void) {\r\n  digitalWrite(chipSelectPin_, HIGH);\r\n}\r\n//------------------------------------------------------------------------------\r\nvoid Sd2Card::chipSelectLow(void) {\r\n  digitalWrite(chipSelectPin_, LOW);\r\n}\r\n//------------------------------------------------------------------------------\r\n/** Erase a range of blocks.\r\n *\r\n * \\param[in] firstBlock The address of the first block in the range.\r\n * \\param[in] lastBlock The address of the last block in the range.\r\n *\r\n * \\note This function requests the SD card to do a flash erase for a\r\n * range of blocks.  The data on the card after an erase operation is\r\n * either 0 or 1, depends on the card vendor.  The card must support\r\n * single block erase.\r\n *\r\n * \\return The value one, true, is returned for success and\r\n * the value zero, false, is returned for failure.\r\n */\r\nuint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {\r\n  if (!eraseSingleBlockEnable()) {\r\n    error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);\r\n    goto fail;\r\n  }\r\n  if (type_ != SD_CARD_TYPE_SDHC) {\r\n    firstBlock <<= 9;\r\n    lastBlock <<= 9;\r\n  }\r\n  if (cardCommand(CMD32, firstBlock)\r\n    || cardCommand(CMD33, lastBlock)\r\n    || cardCommand(CMD38, 0)) {\r\n      error(SD_CARD_ERROR_ERASE);\r\n      goto fail;\r\n  }\r\n  if (!waitNotBusy(SD_ERASE_TIMEOUT)) {\r\n    error(SD_CARD_ERROR_ERASE_TIMEOUT);\r\n    goto fail;\r\n  }\r\n  chipSelectHigh();\r\n  return true;\r\n\r\n fail:\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/** Determine if card supports single block erase.\r\n *\r\n * \\return The value one, true, is returned if single block erase is supported.\r\n * The value zero, false, is returned if single block erase is not supported.\r\n */\r\nuint8_t Sd2Card::eraseSingleBlockEnable(void) {\r\n  csd_t csd;\r\n  return readCSD(&csd) ? csd.v1.erase_blk_en : 0;\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Initialize an SD flash memory card.\r\n *\r\n * \\param[in] sckRateID SPI clock rate selector. See setSckRate().\r\n * \\param[in] chipSelectPin SD chip select pin number.\r\n *\r\n * \\return The value one, true, is returned for success and\r\n * the value zero, false, is returned for failure.  The reason for failure\r\n * can be determined by calling errorCode() and errorData().\r\n */\r\nuint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {\r\n  errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;\r\n  chipSelectPin_ = chipSelectPin;\r\n  // 16-bit init start time allows over a minute\r\n  uint16_t t0 = (uint16_t)millis();\r\n  uint32_t arg;\r\n\r\n  // set pin modes\r\n  pinMode(chipSelectPin_, OUTPUT);\r\n  chipSelectHigh();\r\n  pinMode(SPI_MISO_PIN, INPUT);\r\n  pinMode(SPI_MOSI_PIN, OUTPUT);\r\n  pinMode(SPI_SCK_PIN, OUTPUT);\r\n\r\n#ifndef SOFTWARE_SPI\r\n  // SS must be in output mode even it is not chip select\r\n  pinMode(SS_PIN, OUTPUT);\r\n  // Enable SPI, Master, clock rate f_osc/128\r\n  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);\r\n  // clear double speed\r\n  SPSR &= ~(1 << SPI2X);\r\n#endif  // SOFTWARE_SPI\r\n\r\n  // must supply min of 74 clock cycles with CS high.\r\n  for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);\r\n\r\n  chipSelectLow();\r\n\r\n  // command to go idle in SPI mode\r\n  while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {\r\n    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {\r\n      error(SD_CARD_ERROR_CMD0);\r\n      goto fail;\r\n    }\r\n  }\r\n  // check SD version\r\n  if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {\r\n    type(SD_CARD_TYPE_SD1);\r\n  } else {\r\n    // only need last byte of r7 response\r\n    for (uint8_t i = 0; i < 4; i++) status_ = spiRec();\r\n    if (status_ != 0XAA) {\r\n      error(SD_CARD_ERROR_CMD8);\r\n      goto fail;\r\n    }\r\n    type(SD_CARD_TYPE_SD2);\r\n  }\r\n  // initialize card and send host supports SDHC if SD2\r\n  arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;\r\n\r\n  while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {\r\n    // check for timeout\r\n    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {\r\n      error(SD_CARD_ERROR_ACMD41);\r\n      goto fail;\r\n    }\r\n  }\r\n  // if SD2 read OCR register to check for SDHC card\r\n  if (type() == SD_CARD_TYPE_SD2) {\r\n    if (cardCommand(CMD58, 0)) {\r\n      error(SD_CARD_ERROR_CMD58);\r\n      goto fail;\r\n    }\r\n    if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);\r\n    // discard rest of ocr - contains allowed voltage range\r\n    for (uint8_t i = 0; i < 3; i++) spiRec();\r\n  }\r\n  chipSelectHigh();\r\n\r\n#ifndef SOFTWARE_SPI\r\n  return setSckRate(sckRateID);\r\n#else  // SOFTWARE_SPI\r\n  return true;\r\n#endif  // SOFTWARE_SPI\r\n\r\n fail:\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Enable or disable partial block reads.\r\n *\r\n * Enabling partial block reads improves performance by allowing a block\r\n * to be read over the SPI bus as several sub-blocks.  Errors may occur\r\n * if the time between reads is too long since the SD card may timeout.\r\n * The SPI SS line will be held low until the entire block is read or\r\n * readEnd() is called.\r\n *\r\n * Use this for applications like the Adafruit Wave Shield.\r\n *\r\n * \\param[in] value The value TRUE (non-zero) or FALSE (zero).)\r\n */\r\nvoid Sd2Card::partialBlockRead(uint8_t value) {\r\n  readEnd();\r\n  partialBlockRead_ = value;\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Read a 512 byte block from an SD card device.\r\n *\r\n * \\param[in] block Logical block to be read.\r\n * \\param[out] dst Pointer to the location that will receive the data.\r\n\r\n * \\return The value one, true, is returned for success and\r\n * the value zero, false, is returned for failure.\r\n */\r\nuint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) {\r\n  return readData(block, 0, 512, dst);\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Read part of a 512 byte block from an SD card.\r\n *\r\n * \\param[in] block Logical block to be read.\r\n * \\param[in] offset Number of bytes to skip at start of block\r\n * \\param[out] dst Pointer to the location that will receive the data.\r\n * \\param[in] count Number of bytes to read\r\n * \\return The value one, true, is returned for success and\r\n * the value zero, false, is returned for failure.\r\n */\r\nuint8_t Sd2Card::readData(uint32_t block,\r\n        uint16_t offset, uint16_t count, uint8_t* dst) {\r\n  uint16_t n;\r\n  if (count == 0) return true;\r\n  if ((count + offset) > 512) {\r\n    goto fail;\r\n  }\r\n  if (!inBlock_ || block != block_ || offset < offset_) {\r\n    block_ = block;\r\n    // use address if not SDHC card\r\n    if (type()!= SD_CARD_TYPE_SDHC) block <<= 9;\r\n    if (cardCommand(CMD17, block)) {\r\n      error(SD_CARD_ERROR_CMD17);\r\n      goto fail;\r\n    }\r\n    if (!waitStartBlock()) {\r\n      goto fail;\r\n    }\r\n    offset_ = 0;\r\n    inBlock_ = 1;\r\n  }\r\n\r\n#ifdef OPTIMIZE_HARDWARE_SPI\r\n  // start first spi transfer\r\n  SPDR = 0XFF;\r\n\r\n  // skip data before offset\r\n  for (;offset_ < offset; offset_++) {\r\n    while (!(SPSR & (1 << SPIF)));\r\n    SPDR = 0XFF;\r\n  }\r\n  // transfer data\r\n  n = count - 1;\r\n  for (uint16_t i = 0; i < n; i++) {\r\n    while (!(SPSR & (1 << SPIF)));\r\n    dst[i] = SPDR;\r\n    SPDR = 0XFF;\r\n  }\r\n  // wait for last byte\r\n  while (!(SPSR & (1 << SPIF)));\r\n  dst[n] = SPDR;\r\n\r\n#else  // OPTIMIZE_HARDWARE_SPI\r\n\r\n  // skip data before offset\r\n  for (;offset_ < offset; offset_++) {\r\n    spiRec();\r\n  }\r\n  // transfer data\r\n  for (uint16_t i = 0; i < count; i++) {\r\n    dst[i] = spiRec();\r\n  }\r\n#endif  // OPTIMIZE_HARDWARE_SPI\r\n\r\n  offset_ += count;\r\n  if (!partialBlockRead_ || offset_ >= 512) {\r\n    // read rest of data, checksum and set chip select high\r\n    readEnd();\r\n  }\r\n  return true;\r\n\r\n fail:\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/** Skip remaining data in a block when in partial block read mode. */\r\nvoid Sd2Card::readEnd(void) {\r\n  if (inBlock_) {\r\n      // skip data and crc\r\n#ifdef OPTIMIZE_HARDWARE_SPI\r\n    // optimize skip for hardware\r\n    SPDR = 0XFF;\r\n    while (offset_++ < 513) {\r\n      while (!(SPSR & (1 << SPIF)));\r\n      SPDR = 0XFF;\r\n    }\r\n    // wait for last crc byte\r\n    while (!(SPSR & (1 << SPIF)));\r\n#else  // OPTIMIZE_HARDWARE_SPI\r\n    while (offset_++ < 514) spiRec();\r\n#endif  // OPTIMIZE_HARDWARE_SPI\r\n    chipSelectHigh();\r\n    inBlock_ = 0;\r\n  }\r\n}\r\n//------------------------------------------------------------------------------\r\n/** read CID or CSR register */\r\nuint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {\r\n  uint8_t* dst = reinterpret_cast<uint8_t*>(buf);\r\n  if (cardCommand(cmd, 0)) {\r\n    error(SD_CARD_ERROR_READ_REG);\r\n    goto fail;\r\n  }\r\n  if (!waitStartBlock()) goto fail;\r\n  // transfer data\r\n  for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec();\r\n  spiRec();  // get first crc byte\r\n  spiRec();  // get second crc byte\r\n  chipSelectHigh();\r\n  return true;\r\n\r\n fail:\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Set the SPI clock rate.\r\n *\r\n * \\param[in] sckRateID A value in the range [0, 6].\r\n *\r\n * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum\r\n * SPI rate is F_CPU/2 for \\a sckRateID = 0 and the minimum rate is F_CPU/128\r\n * for \\a scsRateID = 6.\r\n *\r\n * \\return The value one, true, is returned for success and the value zero,\r\n * false, is returned for an invalid value of \\a sckRateID.\r\n */\r\nuint8_t Sd2Card::setSckRate(uint8_t sckRateID) {\r\n  if (sckRateID > 6) {\r\n    error(SD_CARD_ERROR_SCK_RATE);\r\n    return false;\r\n  }\r\n  // see avr processor datasheet for SPI register bit definitions\r\n  if ((sckRateID & 1) || sckRateID == 6) {\r\n    SPSR &= ~(1 << SPI2X);\r\n  } else {\r\n    SPSR |= (1 << SPI2X);\r\n  }\r\n  SPCR &= ~((1 <<SPR1) | (1 << SPR0));\r\n  SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)\r\n    | (sckRateID & 2 ? (1 << SPR0) : 0);\r\n  return true;\r\n}\r\n//------------------------------------------------------------------------------\r\n// wait for card to go not busy\r\nuint8_t Sd2Card::waitNotBusy(uint16_t timeoutMillis) {\r\n  uint16_t t0 = millis();\r\n  do {\r\n    if (spiRec() == 0XFF) return true;\r\n  }\r\n  while (((uint16_t)millis() - t0) < timeoutMillis);\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/** Wait for start block token */\r\nuint8_t Sd2Card::waitStartBlock(void) {\r\n  uint16_t t0 = millis();\r\n  while ((status_ = spiRec()) == 0XFF) {\r\n    if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {\r\n      error(SD_CARD_ERROR_READ_TIMEOUT);\r\n      goto fail;\r\n    }\r\n  }\r\n  if (status_ != DATA_START_BLOCK) {\r\n    error(SD_CARD_ERROR_READ);\r\n    goto fail;\r\n  }\r\n  return true;\r\n\r\n fail:\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Writes a 512 byte block to an SD card.\r\n *\r\n * \\param[in] blockNumber Logical block to be written.\r\n * \\param[in] src Pointer to the location of the data to be written.\r\n * \\return The value one, true, is returned for success and\r\n * the value zero, false, is returned for failure.\r\n */\r\nuint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {\r\n#if SD_PROTECT_BLOCK_ZERO\r\n  // don't allow write to first block\r\n  if (blockNumber == 0) {\r\n    error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);\r\n    goto fail;\r\n  }\r\n#endif  // SD_PROTECT_BLOCK_ZERO\r\n\r\n  // use address if not SDHC card\r\n  if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;\r\n  if (cardCommand(CMD24, blockNumber)) {\r\n    error(SD_CARD_ERROR_CMD24);\r\n    goto fail;\r\n  }\r\n  if (!writeData(DATA_START_BLOCK, src)) goto fail;\r\n\r\n  // wait for flash programming to complete\r\n  if (!waitNotBusy(SD_WRITE_TIMEOUT)) {\r\n    error(SD_CARD_ERROR_WRITE_TIMEOUT);\r\n    goto fail;\r\n  }\r\n  // response is r2 so get and check two bytes for nonzero\r\n  if (cardCommand(CMD13, 0) || spiRec()) {\r\n    error(SD_CARD_ERROR_WRITE_PROGRAMMING);\r\n    goto fail;\r\n  }\r\n  chipSelectHigh();\r\n  return true;\r\n\r\n fail:\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/** Write one data block in a multiple block write sequence */\r\nuint8_t Sd2Card::writeData(const uint8_t* src) {\r\n  // wait for previous write to finish\r\n  if (!waitNotBusy(SD_WRITE_TIMEOUT)) {\r\n    error(SD_CARD_ERROR_WRITE_MULTIPLE);\r\n    chipSelectHigh();\r\n    return false;\r\n  }\r\n  return writeData(WRITE_MULTIPLE_TOKEN, src);\r\n}\r\n//------------------------------------------------------------------------------\r\n// send one block of data for write block or write multiple blocks\r\nuint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {\r\n#ifdef OPTIMIZE_HARDWARE_SPI\r\n\r\n  // send data - optimized loop\r\n  SPDR = token;\r\n\r\n  // send two byte per iteration\r\n  for (uint16_t i = 0; i < 512; i += 2) {\r\n    while (!(SPSR & (1 << SPIF)));\r\n    SPDR = src[i];\r\n    while (!(SPSR & (1 << SPIF)));\r\n    SPDR = src[i+1];\r\n  }\r\n\r\n  // wait for last data byte\r\n  while (!(SPSR & (1 << SPIF)));\r\n\r\n#else  // OPTIMIZE_HARDWARE_SPI\r\n  spiSend(token);\r\n  for (uint16_t i = 0; i < 512; i++) {\r\n    spiSend(src[i]);\r\n  }\r\n#endif  // OPTIMIZE_HARDWARE_SPI\r\n  spiSend(0xff);  // dummy crc\r\n  spiSend(0xff);  // dummy crc\r\n\r\n  status_ = spiRec();\r\n  if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {\r\n    error(SD_CARD_ERROR_WRITE);\r\n    chipSelectHigh();\r\n    return false;\r\n  }\r\n  return true;\r\n}\r\n//------------------------------------------------------------------------------\r\n/** Start a write multiple blocks sequence.\r\n *\r\n * \\param[in] blockNumber Address of first block in sequence.\r\n * \\param[in] eraseCount The number of blocks to be pre-erased.\r\n *\r\n * \\note This function is used with writeData() and writeStop()\r\n * for optimized multiple block writes.\r\n *\r\n * \\return The value one, true, is returned for success and\r\n * the value zero, false, is returned for failure.\r\n */\r\nuint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {\r\n#if SD_PROTECT_BLOCK_ZERO\r\n  // don't allow write to first block\r\n  if (blockNumber == 0) {\r\n    error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);\r\n    goto fail;\r\n  }\r\n#endif  // SD_PROTECT_BLOCK_ZERO\r\n  // send pre-erase count\r\n  if (cardAcmd(ACMD23, eraseCount)) {\r\n    error(SD_CARD_ERROR_ACMD23);\r\n    goto fail;\r\n  }\r\n  // use address if not SDHC card\r\n  if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;\r\n  if (cardCommand(CMD25, blockNumber)) {\r\n    error(SD_CARD_ERROR_CMD25);\r\n    goto fail;\r\n  }\r\n  return true;\r\n\r\n fail:\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n//------------------------------------------------------------------------------\r\n/** End a write multiple blocks sequence.\r\n *\r\n* \\return The value one, true, is returned for success and\r\n * the value zero, false, is returned for failure.\r\n */\r\nuint8_t Sd2Card::writeStop(void) {\r\n  if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;\r\n  spiSend(STOP_TRAN_TOKEN);\r\n  if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;\r\n  chipSelectHigh();\r\n  return true;\r\n\r\n fail:\r\n  error(SD_CARD_ERROR_STOP_TRAN);\r\n  chipSelectHigh();\r\n  return false;\r\n}\r\n"
  },
  {
    "path": "Sprinter/Sd2Card.h",
    "content": "/* Arduino Sd2Card Library\r\n * Copyright (C) 2009 by William Greiman\r\n *\r\n * This file is part of the Arduino Sd2Card Library\r\n *\r\n * This Library is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino Sd2Card Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n#ifndef Sd2Card_h\r\n#define Sd2Card_h\r\n/**\r\n * \\file\r\n * Sd2Card class\r\n */\r\n#include \"Sd2PinMap.h\"\r\n#include \"SdInfo.h\"\r\n/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */\r\nuint8_t const SPI_FULL_SPEED = 0;\r\n/** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */\r\nuint8_t const SPI_HALF_SPEED = 1;\r\n/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */\r\nuint8_t const SPI_QUARTER_SPEED = 2;\r\n/**\r\n * Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos.\r\n * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.\r\n *\r\n * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used\r\n * on Mega Arduinos.  Software SPI works well with GPS Shield V1.1\r\n * but many SD cards will fail with GPS Shield V1.0.\r\n */\r\n#define MEGA_SOFT_SPI 0\r\n//------------------------------------------------------------------------------\r\n#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__))\r\n#define SOFTWARE_SPI\r\n#endif  // MEGA_SOFT_SPI\r\n//------------------------------------------------------------------------------\r\n// SPI pin definitions\r\n//\r\n#ifndef SOFTWARE_SPI\r\n// hardware pin defs\r\n/**\r\n * SD Chip Select pin\r\n *\r\n * Warning if this pin is redefined the hardware SS will pin will be enabled\r\n * as an output by init().  An avr processor will not function as an SPI\r\n * master unless SS is set to output mode.\r\n */\r\n/** The default chip select pin for the SD card is SS. */\r\nuint8_t const  SD_CHIP_SELECT_PIN = SS_PIN;\r\n// The following three pins must not be redefined for hardware SPI.\r\n/** SPI Master Out Slave In pin */\r\nuint8_t const  SPI_MOSI_PIN = MOSI_PIN;\r\n/** SPI Master In Slave Out pin */\r\nuint8_t const  SPI_MISO_PIN = MISO_PIN;\r\n/** SPI Clock pin */\r\nuint8_t const  SPI_SCK_PIN = SCK_PIN;\r\n/** optimize loops for hardware SPI */\r\n#define OPTIMIZE_HARDWARE_SPI\r\n\r\n#else  // SOFTWARE_SPI\r\n// define software SPI pins so Mega can use unmodified GPS Shield\r\n/** SPI chip select pin */\r\nuint8_t const SD_CHIP_SELECT_PIN = 10;\r\n/** SPI Master Out Slave In pin */\r\nuint8_t const SPI_MOSI_PIN = 11;\r\n/** SPI Master In Slave Out pin */\r\nuint8_t const SPI_MISO_PIN = 12;\r\n/** SPI Clock pin */\r\nuint8_t const SPI_SCK_PIN = 13;\r\n#endif  // SOFTWARE_SPI\r\n//------------------------------------------------------------------------------\r\n/** Protect block zero from write if nonzero */\r\n#define SD_PROTECT_BLOCK_ZERO 1\r\n/** init timeout ms */\r\nuint16_t const SD_INIT_TIMEOUT = 2000;\r\n/** erase timeout ms */\r\nuint16_t const SD_ERASE_TIMEOUT = 10000;\r\n/** read timeout ms */\r\nuint16_t const SD_READ_TIMEOUT = 300;\r\n/** write time out ms */\r\nuint16_t const SD_WRITE_TIMEOUT = 600;\r\n//------------------------------------------------------------------------------\r\n// SD card errors\r\n/** timeout error for command CMD0 */\r\nuint8_t const SD_CARD_ERROR_CMD0 = 0X1;\r\n/** CMD8 was not accepted - not a valid SD card*/\r\nuint8_t const SD_CARD_ERROR_CMD8 = 0X2;\r\n/** card returned an error response for CMD17 (read block) */\r\nuint8_t const SD_CARD_ERROR_CMD17 = 0X3;\r\n/** card returned an error response for CMD24 (write block) */\r\nuint8_t const SD_CARD_ERROR_CMD24 = 0X4;\r\n/**  WRITE_MULTIPLE_BLOCKS command failed */\r\nuint8_t const SD_CARD_ERROR_CMD25 = 0X05;\r\n/** card returned an error response for CMD58 (read OCR) */\r\nuint8_t const SD_CARD_ERROR_CMD58 = 0X06;\r\n/** SET_WR_BLK_ERASE_COUNT failed */\r\nuint8_t const SD_CARD_ERROR_ACMD23 = 0X07;\r\n/** card's ACMD41 initialization process timeout */\r\nuint8_t const SD_CARD_ERROR_ACMD41 = 0X08;\r\n/** card returned a bad CSR version field */\r\nuint8_t const SD_CARD_ERROR_BAD_CSD = 0X09;\r\n/** erase block group command failed */\r\nuint8_t const SD_CARD_ERROR_ERASE = 0X0A;\r\n/** card not capable of single block erase */\r\nuint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B;\r\n/** Erase sequence timed out */\r\nuint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C;\r\n/** card returned an error token instead of read data */\r\nuint8_t const SD_CARD_ERROR_READ = 0X0D;\r\n/** read CID or CSD failed */\r\nuint8_t const SD_CARD_ERROR_READ_REG = 0X0E;\r\n/** timeout while waiting for start of read data */\r\nuint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F;\r\n/** card did not accept STOP_TRAN_TOKEN */\r\nuint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10;\r\n/** card returned an error token as a response to a write operation */\r\nuint8_t const SD_CARD_ERROR_WRITE = 0X11;\r\n/** attempt to write protected block zero */\r\nuint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12;\r\n/** card did not go ready for a multiple block write */\r\nuint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13;\r\n/** card returned an error to a CMD13 status check after a write */\r\nuint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14;\r\n/** timeout occurred during write programming */\r\nuint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15;\r\n/** incorrect rate selected */\r\nuint8_t const SD_CARD_ERROR_SCK_RATE = 0X16;\r\n//------------------------------------------------------------------------------\r\n// card types\r\n/** Standard capacity V1 SD card */\r\nuint8_t const SD_CARD_TYPE_SD1 = 1;\r\n/** Standard capacity V2 SD card */\r\nuint8_t const SD_CARD_TYPE_SD2 = 2;\r\n/** High Capacity SD card */\r\nuint8_t const SD_CARD_TYPE_SDHC = 3;\r\n//------------------------------------------------------------------------------\r\n/**\r\n * \\class Sd2Card\r\n * \\brief Raw access to SD and SDHC flash memory cards.\r\n */\r\nclass Sd2Card {\r\n public:\r\n  /** Construct an instance of Sd2Card. */\r\n  Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {}\r\n  uint32_t cardSize(void);\r\n  uint8_t erase(uint32_t firstBlock, uint32_t lastBlock);\r\n  uint8_t eraseSingleBlockEnable(void);\r\n  /**\r\n   * \\return error code for last error. See Sd2Card.h for a list of error codes.\r\n   */\r\n  uint8_t errorCode(void) const {return errorCode_;}\r\n  /** \\return error data for last error. */\r\n  uint8_t errorData(void) const {return status_;}\r\n  /**\r\n   * Initialize an SD flash memory card with default clock rate and chip\r\n   * select pin.  See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).\r\n   */\r\n  uint8_t init(void) {\r\n    return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN);\r\n  }\r\n  /**\r\n   * Initialize an SD flash memory card with the selected SPI clock rate\r\n   * and the default SD chip select pin.\r\n   * See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).\r\n   */\r\n  uint8_t init(uint8_t sckRateID) {\r\n    return init(sckRateID, SD_CHIP_SELECT_PIN);\r\n  }\r\n  uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin);\r\n  void partialBlockRead(uint8_t value);\r\n  /** Returns the current value, true or false, for partial block read. */\r\n  uint8_t partialBlockRead(void) const {return partialBlockRead_;}\r\n  uint8_t readBlock(uint32_t block, uint8_t* dst);\r\n  uint8_t readData(uint32_t block,\r\n          uint16_t offset, uint16_t count, uint8_t* dst);\r\n  /**\r\n   * Read a cards CID register. The CID contains card identification\r\n   * information such as Manufacturer ID, Product name, Product serial\r\n   * number and Manufacturing date. */\r\n  uint8_t readCID(cid_t* cid) {\r\n    return readRegister(CMD10, cid);\r\n  }\r\n  /**\r\n   * Read a cards CSD register. The CSD contains Card-Specific Data that\r\n   * provides information regarding access to the card's contents. */\r\n  uint8_t readCSD(csd_t* csd) {\r\n    return readRegister(CMD9, csd);\r\n  }\r\n  void readEnd(void);\r\n  uint8_t setSckRate(uint8_t sckRateID);\r\n  /** Return the card type: SD V1, SD V2 or SDHC */\r\n  uint8_t type(void) const {return type_;}\r\n  uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src);\r\n  uint8_t writeData(const uint8_t* src);\r\n  uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount);\r\n  uint8_t writeStop(void);\r\n private:\r\n  uint32_t block_;\r\n  uint8_t chipSelectPin_;\r\n  uint8_t errorCode_;\r\n  uint8_t inBlock_;\r\n  uint16_t offset_;\r\n  uint8_t partialBlockRead_;\r\n  uint8_t status_;\r\n  uint8_t type_;\r\n  // private functions\r\n  uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {\r\n    cardCommand(CMD55, 0);\r\n    return cardCommand(cmd, arg);\r\n  }\r\n  uint8_t cardCommand(uint8_t cmd, uint32_t arg);\r\n  void error(uint8_t code) {errorCode_ = code;}\r\n  uint8_t readRegister(uint8_t cmd, void* buf);\r\n  uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount);\r\n  void chipSelectHigh(void);\r\n  void chipSelectLow(void);\r\n  void type(uint8_t value) {type_ = value;}\r\n  uint8_t waitNotBusy(uint16_t timeoutMillis);\r\n  uint8_t writeData(uint8_t token, const uint8_t* src);\r\n  uint8_t waitStartBlock(void);\r\n};\r\n#endif  // Sd2Card_h\r\n"
  },
  {
    "path": "Sprinter/Sd2PinMap.h",
    "content": "/* Arduino SdFat Library\r\n * Copyright (C) 2010 by William Greiman\r\n *\r\n * This file is part of the Arduino SdFat Library\r\n *\r\n * This Library is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino SdFat Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n// Warning this file was generated by a program.\r\n#ifndef Sd2PinMap_h\r\n#define Sd2PinMap_h\r\n#include <avr/io.h>\r\n\r\n//------------------------------------------------------------------------------\r\n/** struct for mapping digital pins */\r\nstruct pin_map_t {\r\n  volatile uint8_t* ddr;\r\n  volatile uint8_t* pin;\r\n  volatile uint8_t* port;\r\n  uint8_t bit;\r\n};\r\n//------------------------------------------------------------------------------\r\n#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)\r\n// Mega\r\n\r\n// Two Wire (aka I2C) ports\r\nuint8_t const SDA_PIN = 20;\r\nuint8_t const SCL_PIN = 21;\r\n\r\n// SPI port\r\nuint8_t const SS_PIN = 53;\r\nuint8_t const MOSI_PIN = 51;\r\nuint8_t const MISO_PIN = 50;\r\nuint8_t const SCK_PIN = 52;\r\n\r\nstatic const pin_map_t digitalPinMap[] = {\r\n  {&DDRE, &PINE, &PORTE, 0},  // E0  0\r\n  {&DDRE, &PINE, &PORTE, 1},  // E1  1\r\n  {&DDRE, &PINE, &PORTE, 4},  // E4  2\r\n  {&DDRE, &PINE, &PORTE, 5},  // E5  3\r\n  {&DDRG, &PING, &PORTG, 5},  // G5  4\r\n  {&DDRE, &PINE, &PORTE, 3},  // E3  5\r\n  {&DDRH, &PINH, &PORTH, 3},  // H3  6\r\n  {&DDRH, &PINH, &PORTH, 4},  // H4  7\r\n  {&DDRH, &PINH, &PORTH, 5},  // H5  8\r\n  {&DDRH, &PINH, &PORTH, 6},  // H6  9\r\n  {&DDRB, &PINB, &PORTB, 4},  // B4 10\r\n  {&DDRB, &PINB, &PORTB, 5},  // B5 11\r\n  {&DDRB, &PINB, &PORTB, 6},  // B6 12\r\n  {&DDRB, &PINB, &PORTB, 7},  // B7 13\r\n  {&DDRJ, &PINJ, &PORTJ, 1},  // J1 14\r\n  {&DDRJ, &PINJ, &PORTJ, 0},  // J0 15\r\n  {&DDRH, &PINH, &PORTH, 1},  // H1 16\r\n  {&DDRH, &PINH, &PORTH, 0},  // H0 17\r\n  {&DDRD, &PIND, &PORTD, 3},  // D3 18\r\n  {&DDRD, &PIND, &PORTD, 2},  // D2 19\r\n  {&DDRD, &PIND, &PORTD, 1},  // D1 20\r\n  {&DDRD, &PIND, &PORTD, 0},  // D0 21\r\n  {&DDRA, &PINA, &PORTA, 0},  // A0 22\r\n  {&DDRA, &PINA, &PORTA, 1},  // A1 23\r\n  {&DDRA, &PINA, &PORTA, 2},  // A2 24\r\n  {&DDRA, &PINA, &PORTA, 3},  // A3 25\r\n  {&DDRA, &PINA, &PORTA, 4},  // A4 26\r\n  {&DDRA, &PINA, &PORTA, 5},  // A5 27\r\n  {&DDRA, &PINA, &PORTA, 6},  // A6 28\r\n  {&DDRA, &PINA, &PORTA, 7},  // A7 29\r\n  {&DDRC, &PINC, &PORTC, 7},  // C7 30\r\n  {&DDRC, &PINC, &PORTC, 6},  // C6 31\r\n  {&DDRC, &PINC, &PORTC, 5},  // C5 32\r\n  {&DDRC, &PINC, &PORTC, 4},  // C4 33\r\n  {&DDRC, &PINC, &PORTC, 3},  // C3 34\r\n  {&DDRC, &PINC, &PORTC, 2},  // C2 35\r\n  {&DDRC, &PINC, &PORTC, 1},  // C1 36\r\n  {&DDRC, &PINC, &PORTC, 0},  // C0 37\r\n  {&DDRD, &PIND, &PORTD, 7},  // D7 38\r\n  {&DDRG, &PING, &PORTG, 2},  // G2 39\r\n  {&DDRG, &PING, &PORTG, 1},  // G1 40\r\n  {&DDRG, &PING, &PORTG, 0},  // G0 41\r\n  {&DDRL, &PINL, &PORTL, 7},  // L7 42\r\n  {&DDRL, &PINL, &PORTL, 6},  // L6 43\r\n  {&DDRL, &PINL, &PORTL, 5},  // L5 44\r\n  {&DDRL, &PINL, &PORTL, 4},  // L4 45\r\n  {&DDRL, &PINL, &PORTL, 3},  // L3 46\r\n  {&DDRL, &PINL, &PORTL, 2},  // L2 47\r\n  {&DDRL, &PINL, &PORTL, 1},  // L1 48\r\n  {&DDRL, &PINL, &PORTL, 0},  // L0 49\r\n  {&DDRB, &PINB, &PORTB, 3},  // B3 50\r\n  {&DDRB, &PINB, &PORTB, 2},  // B2 51\r\n  {&DDRB, &PINB, &PORTB, 1},  // B1 52\r\n  {&DDRB, &PINB, &PORTB, 0},  // B0 53\r\n  {&DDRF, &PINF, &PORTF, 0},  // F0 54\r\n  {&DDRF, &PINF, &PORTF, 1},  // F1 55\r\n  {&DDRF, &PINF, &PORTF, 2},  // F2 56\r\n  {&DDRF, &PINF, &PORTF, 3},  // F3 57\r\n  {&DDRF, &PINF, &PORTF, 4},  // F4 58\r\n  {&DDRF, &PINF, &PORTF, 5},  // F5 59\r\n  {&DDRF, &PINF, &PORTF, 6},  // F6 60\r\n  {&DDRF, &PINF, &PORTF, 7},  // F7 61\r\n  {&DDRK, &PINK, &PORTK, 0},  // K0 62\r\n  {&DDRK, &PINK, &PORTK, 1},  // K1 63\r\n  {&DDRK, &PINK, &PORTK, 2},  // K2 64\r\n  {&DDRK, &PINK, &PORTK, 3},  // K3 65\r\n  {&DDRK, &PINK, &PORTK, 4},  // K4 66\r\n  {&DDRK, &PINK, &PORTK, 5},  // K5 67\r\n  {&DDRK, &PINK, &PORTK, 6},  // K6 68\r\n  {&DDRK, &PINK, &PORTK, 7}   // K7 69\r\n};\r\n//------------------------------------------------------------------------------\r\n#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__)\r\n// Sanguino\r\n\r\n// Two Wire (aka I2C) ports\r\nuint8_t const SDA_PIN = 17;\r\nuint8_t const SCL_PIN = 18;\r\n\r\n// SPI port\r\nuint8_t const SS_PIN = 4;\r\nuint8_t const MOSI_PIN = 5;\r\nuint8_t const MISO_PIN = 6;\r\nuint8_t const SCK_PIN = 7;\r\n\r\nstatic const pin_map_t digitalPinMap[] = {\r\n  {&DDRB, &PINB, &PORTB, 0},  // B0  0\r\n  {&DDRB, &PINB, &PORTB, 1},  // B1  1\r\n  {&DDRB, &PINB, &PORTB, 2},  // B2  2\r\n  {&DDRB, &PINB, &PORTB, 3},  // B3  3\r\n  {&DDRB, &PINB, &PORTB, 4},  // B4  4\r\n  {&DDRB, &PINB, &PORTB, 5},  // B5  5\r\n  {&DDRB, &PINB, &PORTB, 6},  // B6  6\r\n  {&DDRB, &PINB, &PORTB, 7},  // B7  7\r\n  {&DDRD, &PIND, &PORTD, 0},  // D0  8\r\n  {&DDRD, &PIND, &PORTD, 1},  // D1  9\r\n  {&DDRD, &PIND, &PORTD, 2},  // D2 10\r\n  {&DDRD, &PIND, &PORTD, 3},  // D3 11\r\n  {&DDRD, &PIND, &PORTD, 4},  // D4 12\r\n  {&DDRD, &PIND, &PORTD, 5},  // D5 13\r\n  {&DDRD, &PIND, &PORTD, 6},  // D6 14\r\n  {&DDRD, &PIND, &PORTD, 7},  // D7 15\r\n  {&DDRC, &PINC, &PORTC, 0},  // C0 16\r\n  {&DDRC, &PINC, &PORTC, 1},  // C1 17\r\n  {&DDRC, &PINC, &PORTC, 2},  // C2 18\r\n  {&DDRC, &PINC, &PORTC, 3},  // C3 19\r\n  {&DDRC, &PINC, &PORTC, 4},  // C4 20\r\n  {&DDRC, &PINC, &PORTC, 5},  // C5 21\r\n  {&DDRC, &PINC, &PORTC, 6},  // C6 22\r\n  {&DDRC, &PINC, &PORTC, 7},  // C7 23\r\n  {&DDRA, &PINA, &PORTA, 7},  // A7 24\r\n  {&DDRA, &PINA, &PORTA, 6},  // A6 25\r\n  {&DDRA, &PINA, &PORTA, 5},  // A5 26\r\n  {&DDRA, &PINA, &PORTA, 4},  // A4 27\r\n  {&DDRA, &PINA, &PORTA, 3},  // A3 28\r\n  {&DDRA, &PINA, &PORTA, 2},  // A2 29\r\n  {&DDRA, &PINA, &PORTA, 1},  // A1 30\r\n  {&DDRA, &PINA, &PORTA, 0}   // A0 31\r\n};\r\n//------------------------------------------------------------------------------\r\n#elif defined(__AVR_ATmega32U4__)\r\n// Teensy 2.0\r\n\r\n// Two Wire (aka I2C) ports\r\nuint8_t const SDA_PIN = 6;\r\nuint8_t const SCL_PIN = 5;\r\n\r\n// SPI port\r\nuint8_t const SS_PIN = 0;\r\nuint8_t const MOSI_PIN = 2;\r\nuint8_t const MISO_PIN = 3;\r\nuint8_t const SCK_PIN = 1;\r\n\r\nstatic const pin_map_t digitalPinMap[] = {\r\n  {&DDRB, &PINB, &PORTB, 0},  // B0  0\r\n  {&DDRB, &PINB, &PORTB, 1},  // B1  1\r\n  {&DDRB, &PINB, &PORTB, 2},  // B2  2\r\n  {&DDRB, &PINB, &PORTB, 3},  // B3  3\r\n  {&DDRB, &PINB, &PORTB, 7},  // B7  4\r\n  {&DDRD, &PIND, &PORTD, 0},  // D0  5\r\n  {&DDRD, &PIND, &PORTD, 1},  // D1  6\r\n  {&DDRD, &PIND, &PORTD, 2},  // D2  7\r\n  {&DDRD, &PIND, &PORTD, 3},  // D3  8\r\n  {&DDRC, &PINC, &PORTC, 6},  // C6  9\r\n  {&DDRC, &PINC, &PORTC, 7},  // C7 10\r\n  {&DDRD, &PIND, &PORTD, 6},  // D6 11\r\n  {&DDRD, &PIND, &PORTD, 7},  // D7 12\r\n  {&DDRB, &PINB, &PORTB, 4},  // B4 13\r\n  {&DDRB, &PINB, &PORTB, 5},  // B5 14\r\n  {&DDRB, &PINB, &PORTB, 6},  // B6 15\r\n  {&DDRF, &PINF, &PORTF, 7},  // F7 16\r\n  {&DDRF, &PINF, &PORTF, 6},  // F6 17\r\n  {&DDRF, &PINF, &PORTF, 5},  // F5 18\r\n  {&DDRF, &PINF, &PORTF, 4},  // F4 19\r\n  {&DDRF, &PINF, &PORTF, 1},  // F1 20\r\n  {&DDRF, &PINF, &PORTF, 0},  // F0 21\r\n  {&DDRD, &PIND, &PORTD, 4},  // D4 22\r\n  {&DDRD, &PIND, &PORTD, 5},  // D5 23\r\n  {&DDRE, &PINE, &PORTE, 6}   // E6 24\r\n};\r\n//------------------------------------------------------------------------------\r\n#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)\r\n// Teensy++ 1.0 & 2.0\r\n\r\n// Two Wire (aka I2C) ports\r\nuint8_t const SDA_PIN = 1;\r\nuint8_t const SCL_PIN = 0;\r\n\r\n// SPI port\r\nuint8_t const SS_PIN = 20;\r\nuint8_t const MOSI_PIN = 22;\r\nuint8_t const MISO_PIN = 23;\r\nuint8_t const SCK_PIN = 21;\r\n\r\nstatic const pin_map_t digitalPinMap[] = {\r\n  {&DDRD, &PIND, &PORTD, 0},  // D0  0\r\n  {&DDRD, &PIND, &PORTD, 1},  // D1  1\r\n  {&DDRD, &PIND, &PORTD, 2},  // D2  2\r\n  {&DDRD, &PIND, &PORTD, 3},  // D3  3\r\n  {&DDRD, &PIND, &PORTD, 4},  // D4  4\r\n  {&DDRD, &PIND, &PORTD, 5},  // D5  5\r\n  {&DDRD, &PIND, &PORTD, 6},  // D6  6\r\n  {&DDRD, &PIND, &PORTD, 7},  // D7  7\r\n  {&DDRE, &PINE, &PORTE, 0},  // E0  8\r\n  {&DDRE, &PINE, &PORTE, 1},  // E1  9\r\n  {&DDRC, &PINC, &PORTC, 0},  // C0 10\r\n  {&DDRC, &PINC, &PORTC, 1},  // C1 11\r\n  {&DDRC, &PINC, &PORTC, 2},  // C2 12\r\n  {&DDRC, &PINC, &PORTC, 3},  // C3 13\r\n  {&DDRC, &PINC, &PORTC, 4},  // C4 14\r\n  {&DDRC, &PINC, &PORTC, 5},  // C5 15\r\n  {&DDRC, &PINC, &PORTC, 6},  // C6 16\r\n  {&DDRC, &PINC, &PORTC, 7},  // C7 17\r\n  {&DDRE, &PINE, &PORTE, 6},  // E6 18\r\n  {&DDRE, &PINE, &PORTE, 7},  // E7 19\r\n  {&DDRB, &PINB, &PORTB, 0},  // B0 20\r\n  {&DDRB, &PINB, &PORTB, 1},  // B1 21\r\n  {&DDRB, &PINB, &PORTB, 2},  // B2 22\r\n  {&DDRB, &PINB, &PORTB, 3},  // B3 23\r\n  {&DDRB, &PINB, &PORTB, 4},  // B4 24\r\n  {&DDRB, &PINB, &PORTB, 5},  // B5 25\r\n  {&DDRB, &PINB, &PORTB, 6},  // B6 26\r\n  {&DDRB, &PINB, &PORTB, 7},  // B7 27\r\n  {&DDRA, &PINA, &PORTA, 0},  // A0 28\r\n  {&DDRA, &PINA, &PORTA, 1},  // A1 29\r\n  {&DDRA, &PINA, &PORTA, 2},  // A2 30\r\n  {&DDRA, &PINA, &PORTA, 3},  // A3 31\r\n  {&DDRA, &PINA, &PORTA, 4},  // A4 32\r\n  {&DDRA, &PINA, &PORTA, 5},  // A5 33\r\n  {&DDRA, &PINA, &PORTA, 6},  // A6 34\r\n  {&DDRA, &PINA, &PORTA, 7},  // A7 35\r\n  {&DDRE, &PINE, &PORTE, 4},  // E4 36\r\n  {&DDRE, &PINE, &PORTE, 5},  // E5 37\r\n  {&DDRF, &PINF, &PORTF, 0},  // F0 38\r\n  {&DDRF, &PINF, &PORTF, 1},  // F1 39\r\n  {&DDRF, &PINF, &PORTF, 2},  // F2 40\r\n  {&DDRF, &PINF, &PORTF, 3},  // F3 41\r\n  {&DDRF, &PINF, &PORTF, 4},  // F4 42\r\n  {&DDRF, &PINF, &PORTF, 5},  // F5 43\r\n  {&DDRF, &PINF, &PORTF, 6},  // F6 44\r\n  {&DDRF, &PINF, &PORTF, 7}   // F7 45\r\n};\r\n//------------------------------------------------------------------------------\r\n#else  // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)\r\n// 168 and 328 Arduinos\r\n\r\n// Two Wire (aka I2C) ports\r\nuint8_t const SDA_PIN = 18;\r\nuint8_t const SCL_PIN = 19;\r\n\r\n// SPI port\r\nuint8_t const SS_PIN = 10;\r\nuint8_t const MOSI_PIN = 11;\r\nuint8_t const MISO_PIN = 12;\r\nuint8_t const SCK_PIN = 13;\r\n\r\nstatic const pin_map_t digitalPinMap[] = {\r\n  {&DDRD, &PIND, &PORTD, 0},  // D0  0\r\n  {&DDRD, &PIND, &PORTD, 1},  // D1  1\r\n  {&DDRD, &PIND, &PORTD, 2},  // D2  2\r\n  {&DDRD, &PIND, &PORTD, 3},  // D3  3\r\n  {&DDRD, &PIND, &PORTD, 4},  // D4  4\r\n  {&DDRD, &PIND, &PORTD, 5},  // D5  5\r\n  {&DDRD, &PIND, &PORTD, 6},  // D6  6\r\n  {&DDRD, &PIND, &PORTD, 7},  // D7  7\r\n  {&DDRB, &PINB, &PORTB, 0},  // B0  8\r\n  {&DDRB, &PINB, &PORTB, 1},  // B1  9\r\n  {&DDRB, &PINB, &PORTB, 2},  // B2 10\r\n  {&DDRB, &PINB, &PORTB, 3},  // B3 11\r\n  {&DDRB, &PINB, &PORTB, 4},  // B4 12\r\n  {&DDRB, &PINB, &PORTB, 5},  // B5 13\r\n  {&DDRC, &PINC, &PORTC, 0},  // C0 14\r\n  {&DDRC, &PINC, &PORTC, 1},  // C1 15\r\n  {&DDRC, &PINC, &PORTC, 2},  // C2 16\r\n  {&DDRC, &PINC, &PORTC, 3},  // C3 17\r\n  {&DDRC, &PINC, &PORTC, 4},  // C4 18\r\n  {&DDRC, &PINC, &PORTC, 5}   // C5 19\r\n};\r\n#endif  // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)\r\n//------------------------------------------------------------------------------\r\nstatic const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);\r\n\r\nuint8_t badPinNumber(void)\r\n  __attribute__((error(\"Pin number is too large or not a constant\")));\r\n\r\nstatic inline __attribute__((always_inline))\r\n  uint8_t getPinMode(uint8_t pin) {\r\n  if (__builtin_constant_p(pin) && pin < digitalPinCount) {\r\n    return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;\r\n  } else {\r\n    return badPinNumber();\r\n  }\r\n}\r\nstatic inline __attribute__((always_inline))\r\n  void setPinMode(uint8_t pin, uint8_t mode) {\r\n  if (__builtin_constant_p(pin) && pin < digitalPinCount) {\r\n    if (mode) {\r\n      *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit;\r\n    } else {\r\n      *digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit);\r\n    }\r\n  } else {\r\n    badPinNumber();\r\n  }\r\n}\r\nstatic inline __attribute__((always_inline))\r\n  uint8_t fastDigitalRead(uint8_t pin) {\r\n  if (__builtin_constant_p(pin) && pin < digitalPinCount) {\r\n    return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;\r\n  } else {\r\n    return badPinNumber();\r\n  }\r\n}\r\nstatic inline __attribute__((always_inline))\r\n  void fastDigitalWrite(uint8_t pin, uint8_t value) {\r\n  if (__builtin_constant_p(pin) && pin < digitalPinCount) {\r\n    if (value) {\r\n      *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit;\r\n    } else {\r\n      *digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit);\r\n    }\r\n  } else {\r\n    badPinNumber();\r\n  }\r\n}\r\n#endif  // Sd2PinMap_h\r\n"
  },
  {
    "path": "Sprinter/SdFat.h",
    "content": "/* Arduino SdFat Library\r\n * Copyright (C) 2009 by William Greiman\r\n *\r\n * This file is part of the Arduino SdFat Library\r\n *\r\n * This Library is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino SdFat Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n#ifndef SdFat_h\r\n#define SdFat_h\r\n/**\r\n * \\file\r\n * SdFile and SdVolume classes\r\n */\r\n#include <avr/pgmspace.h>\r\n#include \"Sd2Card.h\"\r\n#include \"FatStructs.h\"\r\n#include \"Print.h\"\r\n//------------------------------------------------------------------------------\r\n/**\r\n * Allow use of deprecated functions if non-zero\r\n */\r\n#define ALLOW_DEPRECATED_FUNCTIONS 1\r\n//------------------------------------------------------------------------------\r\n// forward declaration since SdVolume is used in SdFile\r\nclass SdVolume;\r\n//==============================================================================\r\n// SdFile class\r\n\r\n// flags for ls()\r\n/** ls() flag to print modify date */\r\nuint8_t const LS_DATE = 1;\r\n/** ls() flag to print file size */\r\nuint8_t const LS_SIZE = 2;\r\n/** ls() flag for recursive list of subdirectories */\r\nuint8_t const LS_R = 4;\r\n\r\n// use the gnu style oflag in open()\r\n/** open() oflag for reading */\r\nuint8_t const O_READ = 0X01;\r\n/** open() oflag - same as O_READ */\r\nuint8_t const O_RDONLY = O_READ;\r\n/** open() oflag for write */\r\nuint8_t const O_WRITE = 0X02;\r\n/** open() oflag - same as O_WRITE */\r\nuint8_t const O_WRONLY = O_WRITE;\r\n/** open() oflag for reading and writing */\r\nuint8_t const O_RDWR = (O_READ | O_WRITE);\r\n/** open() oflag mask for access modes */\r\nuint8_t const O_ACCMODE = (O_READ | O_WRITE);\r\n/** The file offset shall be set to the end of the file prior to each write. */\r\nuint8_t const O_APPEND = 0X04;\r\n/** synchronous writes - call sync() after each write */\r\nuint8_t const O_SYNC = 0X08;\r\n/** create the file if nonexistent */\r\nuint8_t const O_CREAT = 0X10;\r\n/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */\r\nuint8_t const O_EXCL = 0X20;\r\n/** truncate the file to zero length */\r\nuint8_t const O_TRUNC = 0X40;\r\n\r\n// flags for timestamp\r\n/** set the file's last access date */\r\nuint8_t const T_ACCESS = 1;\r\n/** set the file's creation date and time */\r\nuint8_t const T_CREATE = 2;\r\n/** Set the file's write date and time */\r\nuint8_t const T_WRITE = 4;\r\n// values for type_\r\n/** This SdFile has not been opened. */\r\nuint8_t const FAT_FILE_TYPE_CLOSED = 0;\r\n/** SdFile for a file */\r\nuint8_t const FAT_FILE_TYPE_NORMAL = 1;\r\n/** SdFile for a FAT16 root directory */\r\nuint8_t const FAT_FILE_TYPE_ROOT16 = 2;\r\n/** SdFile for a FAT32 root directory */\r\nuint8_t const FAT_FILE_TYPE_ROOT32 = 3;\r\n/** SdFile for a subdirectory */\r\nuint8_t const FAT_FILE_TYPE_SUBDIR = 4;\r\n/** Test value for directory type */\r\nuint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16;\r\n\r\n/** date field for FAT directory entry */\r\nstatic inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {\r\n  return (year - 1980) << 9 | month << 5 | day;\r\n}\r\n/** year part of FAT directory date field */\r\nstatic inline uint16_t FAT_YEAR(uint16_t fatDate) {\r\n  return 1980 + (fatDate >> 9);\r\n}\r\n/** month part of FAT directory date field */\r\nstatic inline uint8_t FAT_MONTH(uint16_t fatDate) {\r\n  return (fatDate >> 5) & 0XF;\r\n}\r\n/** day part of FAT directory date field */\r\nstatic inline uint8_t FAT_DAY(uint16_t fatDate) {\r\n  return fatDate & 0X1F;\r\n}\r\n/** time field for FAT directory entry */\r\nstatic inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {\r\n  return hour << 11 | minute << 5 | second >> 1;\r\n}\r\n/** hour part of FAT directory time field */\r\nstatic inline uint8_t FAT_HOUR(uint16_t fatTime) {\r\n  return fatTime >> 11;\r\n}\r\n/** minute part of FAT directory time field */\r\nstatic inline uint8_t FAT_MINUTE(uint16_t fatTime) {\r\n  return(fatTime >> 5) & 0X3F;\r\n}\r\n/** second part of FAT directory time field */\r\nstatic inline uint8_t FAT_SECOND(uint16_t fatTime) {\r\n  return 2*(fatTime & 0X1F);\r\n}\r\n/** Default date for file timestamps is 1 Jan 2000 */\r\nuint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;\r\n/** Default time for file timestamp is 1 am */\r\nuint16_t const FAT_DEFAULT_TIME = (1 << 11);\r\n//------------------------------------------------------------------------------\r\n/**\r\n * \\class SdFile\r\n * \\brief Access FAT16 and FAT32 files on SD and SDHC cards.\r\n */\r\nclass SdFile : public Print {\r\n public:\r\n  /** Create an instance of SdFile. */\r\n  SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {}\r\n  /**\r\n   * writeError is set to true if an error occurs during a write().\r\n   * Set writeError to false before calling print() and/or write() and check\r\n   * for true after calls to print() and/or write().\r\n   */\r\n  bool writeError;\r\n  /**\r\n   * Cancel unbuffered reads for this file.\r\n   * See setUnbufferedRead()\r\n   */\r\n  void clearUnbufferedRead(void) {\r\n    flags_ &= ~F_FILE_UNBUFFERED_READ;\r\n  }\r\n  uint8_t close(void);\r\n  uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);\r\n  uint8_t createContiguous(SdFile* dirFile,\r\n          const char* fileName, uint32_t size);\r\n  /** \\return The current cluster number for a file or directory. */\r\n  uint32_t curCluster(void) const {return curCluster_;}\r\n  /** \\return The current position for a file or directory. */\r\n  uint32_t curPosition(void) const {return curPosition_;}\r\n  /**\r\n   * Set the date/time callback function\r\n   *\r\n   * \\param[in] dateTime The user's call back function.  The callback\r\n   * function is of the form:\r\n   *\r\n   * \\code\r\n   * void dateTime(uint16_t* date, uint16_t* time) {\r\n   *   uint16_t year;\r\n   *   uint8_t month, day, hour, minute, second;\r\n   *\r\n   *   // User gets date and time from GPS or real-time clock here\r\n   *\r\n   *   // return date using FAT_DATE macro to format fields\r\n   *   *date = FAT_DATE(year, month, day);\r\n   *\r\n   *   // return time using FAT_TIME macro to format fields\r\n   *   *time = FAT_TIME(hour, minute, second);\r\n   * }\r\n   * \\endcode\r\n   *\r\n   * Sets the function that is called when a file is created or when\r\n   * a file's directory entry is modified by sync(). All timestamps,\r\n   * access, creation, and modify, are set when a file is created.\r\n   * sync() maintains the last access date and last modify date/time.\r\n   *\r\n   * See the timestamp() function.\r\n   */\r\n  static void dateTimeCallback(\r\n    void (*dateTime)(uint16_t* date, uint16_t* time)) {\r\n    dateTime_ = dateTime;\r\n  }\r\n  /**\r\n   * Cancel the date/time callback function.\r\n   */\r\n  static void dateTimeCallbackCancel(void) {\r\n    // use explicit zero since NULL is not defined for Sanguino\r\n    dateTime_ = 0;\r\n  }\r\n  /** \\return Address of the block that contains this file's directory. */\r\n  uint32_t dirBlock(void) const {return dirBlock_;}\r\n  uint8_t dirEntry(dir_t* dir);\r\n  /** \\return Index of this file's directory in the block dirBlock. */\r\n  uint8_t dirIndex(void) const {return dirIndex_;}\r\n  static void dirName(const dir_t& dir, char* name);\r\n  /** \\return The total number of bytes in a file or directory. */\r\n  uint32_t fileSize(void) const {return fileSize_;}\r\n  /** \\return The first cluster number for a file or directory. */\r\n  uint32_t firstCluster(void) const {return firstCluster_;}\r\n  /** \\return True if this is a SdFile for a directory else false. */\r\n  uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}\r\n  /** \\return True if this is a SdFile for a file else false. */\r\n  uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;}\r\n  /** \\return True if this is a SdFile for an open file/directory else false. */\r\n  uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;}\r\n  /** \\return True if this is a SdFile for a subdirectory else false. */\r\n  uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;}\r\n  /** \\return True if this is a SdFile for the root directory. */\r\n  uint8_t isRoot(void) const {\r\n    return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32;\r\n  }\r\n  void ls(uint8_t flags = 0, uint8_t indent = 0);\r\n  uint8_t makeDir(SdFile* dir, const char* dirName);\r\n  uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag);\r\n  uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag);\r\n\r\n  uint8_t openRoot(SdVolume* vol);\r\n  static void printDirName(const dir_t& dir, uint8_t width);\r\n  static void printFatDate(uint16_t fatDate);\r\n  static void printFatTime(uint16_t fatTime);\r\n  static void printTwoDigits(uint8_t v);\r\n  /**\r\n   * Read the next byte from a file.\r\n   *\r\n   * \\return For success read returns the next byte in the file as an int.\r\n   * If an error occurs or end of file is reached -1 is returned.\r\n   */\r\n  int16_t read(void) {\r\n    uint8_t b;\r\n    return read(&b, 1) == 1 ? b : -1;\r\n  }\r\n  int16_t read(void* buf, uint16_t nbyte);\r\n  int8_t readDir(dir_t* dir);\r\n  static uint8_t remove(SdFile* dirFile, const char* fileName);\r\n  uint8_t remove(void);\r\n  /** Set the file's current position to zero. */\r\n  void rewind(void) {\r\n    curPosition_ = curCluster_ = 0;\r\n  }\r\n  uint8_t rmDir(void);\r\n  uint8_t rmRfStar(void);\r\n  /** Set the files position to current position + \\a pos. See seekSet(). */\r\n  uint8_t seekCur(uint32_t pos) {\r\n    return seekSet(curPosition_ + pos);\r\n  }\r\n  /**\r\n   *  Set the files current position to end of file.  Useful to position\r\n   *  a file for append. See seekSet().\r\n   */\r\n  uint8_t seekEnd(void) {return seekSet(fileSize_);}\r\n  uint8_t seekSet(uint32_t pos);\r\n  /**\r\n   * Use unbuffered reads to access this file.  Used with Wave\r\n   * Shield ISR.  Used with Sd2Card::partialBlockRead() in WaveRP.\r\n   *\r\n   * Not recommended for normal applications.\r\n   */\r\n  void setUnbufferedRead(void) {\r\n    if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ;\r\n  }\r\n  uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,\r\n          uint8_t hour, uint8_t minute, uint8_t second);\r\n  uint8_t sync(void);\r\n  /** Type of this SdFile.  You should use isFile() or isDir() instead of type()\r\n   * if possible.\r\n   *\r\n   * \\return The file or directory type.\r\n   */\r\n  uint8_t type(void) const {return type_;}\r\n  uint8_t truncate(uint32_t size);\r\n  /** \\return Unbuffered read flag. */\r\n  uint8_t unbufferedRead(void) const {\r\n    return flags_ & F_FILE_UNBUFFERED_READ;\r\n  }\r\n  /** \\return SdVolume that contains this file. */\r\n  SdVolume* volume(void) const {return vol_;}\r\n#if ARDUINO >= 100\r\n  size_t write(uint8_t b);\r\n#else\r\n  void write(uint8_t b);\r\n#endif\r\n  int16_t write(const void* buf, uint16_t nbyte);\r\n  void write(const char* str);\r\n  void write_P(PGM_P str);\r\n  void writeln_P(PGM_P str);\r\n//------------------------------------------------------------------------------\r\n#if ALLOW_DEPRECATED_FUNCTIONS\r\n// Deprecated functions  - suppress cpplint warnings with NOLINT comment\r\n  /** \\deprecated Use:\r\n   * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);\r\n   */\r\n  uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) {  // NOLINT\r\n    return contiguousRange(&bgnBlock, &endBlock);\r\n  }\r\n /** \\deprecated Use:\r\n   * uint8_t SdFile::createContiguous(SdFile* dirFile,\r\n   *   const char* fileName, uint32_t size)\r\n   */\r\n  uint8_t createContiguous(SdFile& dirFile,  // NOLINT\r\n    const char* fileName, uint32_t size) {\r\n    return createContiguous(&dirFile, fileName, size);\r\n  }\r\n\r\n  /**\r\n   * \\deprecated Use:\r\n   * static void SdFile::dateTimeCallback(\r\n   *   void (*dateTime)(uint16_t* date, uint16_t* time));\r\n   */\r\n  static void dateTimeCallback(\r\n    void (*dateTime)(uint16_t& date, uint16_t& time)) {  // NOLINT\r\n    oldDateTime_ = dateTime;\r\n    dateTime_ = dateTime ? oldToNew : 0;\r\n  }\r\n  /** \\deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */\r\n  uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);}  // NOLINT\r\n  /** \\deprecated Use:\r\n   * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName);\r\n   */\r\n  uint8_t makeDir(SdFile& dir, const char* dirName) {  // NOLINT\r\n    return makeDir(&dir, dirName);\r\n  }\r\n  /** \\deprecated Use:\r\n   * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag);\r\n   */\r\n  uint8_t open(SdFile& dirFile, // NOLINT\r\n    const char* fileName, uint8_t oflag) {\r\n    return open(&dirFile, fileName, oflag);\r\n  }\r\n  /** \\deprecated  Do not use in new apps */\r\n  uint8_t open(SdFile& dirFile, const char* fileName) {  // NOLINT\r\n    return open(dirFile, fileName, O_RDWR);\r\n  }\r\n  /** \\deprecated Use:\r\n   * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag);\r\n   */\r\n  uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) {  // NOLINT\r\n    return open(&dirFile, index, oflag);\r\n  }\r\n  /** \\deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */\r\n  uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);}  // NOLINT\r\n\r\n  /** \\deprecated Use: int8_t SdFile::readDir(dir_t* dir); */\r\n  int8_t readDir(dir_t& dir) {return readDir(&dir);}  // NOLINT\r\n  /** \\deprecated Use:\r\n   * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName);\r\n   */\r\n  static uint8_t remove(SdFile& dirFile, const char* fileName) {  // NOLINT\r\n    return remove(&dirFile, fileName);\r\n  }\r\n//------------------------------------------------------------------------------\r\n// rest are private\r\n private:\r\n  static void (*oldDateTime_)(uint16_t& date, uint16_t& time);  // NOLINT\r\n  static void oldToNew(uint16_t* date, uint16_t* time) {\r\n    uint16_t d;\r\n    uint16_t t;\r\n    oldDateTime_(d, t);\r\n    *date = d;\r\n    *time = t;\r\n  }\r\n#endif  // ALLOW_DEPRECATED_FUNCTIONS\r\n private:\r\n  // bits defined in flags_\r\n  // should be 0XF\r\n  static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);\r\n  // available bits\r\n  static uint8_t const F_UNUSED = 0X30;\r\n  // use unbuffered SD read\r\n  static uint8_t const F_FILE_UNBUFFERED_READ = 0X40;\r\n  // sync of directory entry required\r\n  static uint8_t const F_FILE_DIR_DIRTY = 0X80;\r\n\r\n// make sure F_OFLAG is ok\r\n#if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)\r\n#error flags_ bits conflict\r\n#endif  // flags_ bits\r\n\r\n  // private data\r\n  uint8_t   flags_;         // See above for definition of flags_ bits\r\n  uint8_t   type_;          // type of file see above for values\r\n  uint32_t  curCluster_;    // cluster for current file position\r\n  uint32_t  curPosition_;   // current file position in bytes from beginning\r\n  uint32_t  dirBlock_;      // SD block that contains directory entry for file\r\n  uint8_t   dirIndex_;      // index of entry in dirBlock 0 <= dirIndex_ <= 0XF\r\n  uint32_t  fileSize_;      // file size in bytes\r\n  uint32_t  firstCluster_;  // first cluster of file\r\n  SdVolume* vol_;           // volume where file is located\r\n\r\n  // private functions\r\n  uint8_t addCluster(void);\r\n  uint8_t addDirCluster(void);\r\n  dir_t* cacheDirEntry(uint8_t action);\r\n  static void (*dateTime_)(uint16_t* date, uint16_t* time);\r\n  static uint8_t make83Name(const char* str, uint8_t* name);\r\n  uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags);\r\n  dir_t* readDirCache(void);\r\n};\r\n//==============================================================================\r\n// SdVolume class\r\n/**\r\n * \\brief Cache for an SD data block\r\n */\r\nunion cache_t {\r\n           /** Used to access cached file data blocks. */\r\n  uint8_t  data[512];\r\n           /** Used to access cached FAT16 entries. */\r\n  uint16_t fat16[256];\r\n           /** Used to access cached FAT32 entries. */\r\n  uint32_t fat32[128];\r\n           /** Used to access cached directory entries. */\r\n  dir_t    dir[16];\r\n           /** Used to access a cached MasterBoot Record. */\r\n  mbr_t    mbr;\r\n           /** Used to access to a cached FAT boot sector. */\r\n  fbs_t    fbs;\r\n};\r\n//------------------------------------------------------------------------------\r\n/**\r\n * \\class SdVolume\r\n * \\brief Access FAT16 and FAT32 volumes on SD and SDHC cards.\r\n */\r\nclass SdVolume {\r\n public:\r\n  /** Create an instance of SdVolume */\r\n  SdVolume(void) :allocSearchStart_(2), fatType_(0) {}\r\n  /** Clear the cache and returns a pointer to the cache.  Used by the WaveRP\r\n   *  recorder to do raw write to the SD card.  Not for normal apps.\r\n   */\r\n  static uint8_t* cacheClear(void) {\r\n    cacheFlush();\r\n    cacheBlockNumber_ = 0XFFFFFFFF;\r\n    return cacheBuffer_.data;\r\n  }\r\n  /**\r\n   * Initialize a FAT volume.  Try partition one first then try super\r\n   * floppy format.\r\n   *\r\n   * \\param[in] dev The Sd2Card where the volume is located.\r\n   *\r\n   * \\return The value one, true, is returned for success and\r\n   * the value zero, false, is returned for failure.  Reasons for\r\n   * failure include not finding a valid partition, not finding a valid\r\n   * FAT file system or an I/O error.\r\n   */\r\n  uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}\r\n  uint8_t init(Sd2Card* dev, uint8_t part);\r\n\r\n  // inline functions that return volume info\r\n  /** \\return The volume's cluster size in blocks. */\r\n  uint8_t blocksPerCluster(void) const {return blocksPerCluster_;}\r\n  /** \\return The number of blocks in one FAT. */\r\n  uint32_t blocksPerFat(void)  const {return blocksPerFat_;}\r\n  /** \\return The total number of clusters in the volume. */\r\n  uint32_t clusterCount(void) const {return clusterCount_;}\r\n  /** \\return The shift count required to multiply by blocksPerCluster. */\r\n  uint8_t clusterSizeShift(void) const {return clusterSizeShift_;}\r\n  /** \\return The logical block number for the start of file data. */\r\n  uint32_t dataStartBlock(void) const {return dataStartBlock_;}\r\n  /** \\return The number of FAT structures on the volume. */\r\n  uint8_t fatCount(void) const {return fatCount_;}\r\n  /** \\return The logical block number for the start of the first FAT. */\r\n  uint32_t fatStartBlock(void) const {return fatStartBlock_;}\r\n  /** \\return The FAT type of the volume. Values are 12, 16 or 32. */\r\n  uint8_t fatType(void) const {return fatType_;}\r\n  /** \\return The number of entries in the root directory for FAT16 volumes. */\r\n  uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;}\r\n  /** \\return The logical block number for the start of the root directory\r\n       on FAT16 volumes or the first cluster number on FAT32 volumes. */\r\n  uint32_t rootDirStart(void) const {return rootDirStart_;}\r\n  /** return a pointer to the Sd2Card object for this volume */\r\n  static Sd2Card* sdCard(void) {return sdCard_;}\r\n//------------------------------------------------------------------------------\r\n#if ALLOW_DEPRECATED_FUNCTIONS\r\n  // Deprecated functions  - suppress cpplint warnings with NOLINT comment\r\n  /** \\deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */\r\n  uint8_t init(Sd2Card& dev) {return init(&dev);}  // NOLINT\r\n\r\n  /** \\deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */\r\n  uint8_t init(Sd2Card& dev, uint8_t part) {  // NOLINT\r\n    return init(&dev, part);\r\n  }\r\n#endif  // ALLOW_DEPRECATED_FUNCTIONS\r\n//------------------------------------------------------------------------------\r\n  private:\r\n  // Allow SdFile access to SdVolume private data.\r\n  friend class SdFile;\r\n\r\n  // value for action argument in cacheRawBlock to indicate read from cache\r\n  static uint8_t const CACHE_FOR_READ = 0;\r\n  // value for action argument in cacheRawBlock to indicate cache dirty\r\n  static uint8_t const CACHE_FOR_WRITE = 1;\r\n\r\n  static cache_t cacheBuffer_;        // 512 byte cache for device blocks\r\n  static uint32_t cacheBlockNumber_;  // Logical number of block in the cache\r\n  static Sd2Card* sdCard_;            // Sd2Card object for cache\r\n  static uint8_t cacheDirty_;         // cacheFlush() will write block if true\r\n  static uint32_t cacheMirrorBlock_;  // block number for mirror FAT\r\n//\r\n  uint32_t allocSearchStart_;   // start cluster for alloc search\r\n  uint8_t blocksPerCluster_;    // cluster size in blocks\r\n  uint32_t blocksPerFat_;       // FAT size in blocks\r\n  uint32_t clusterCount_;       // clusters in one FAT\r\n  uint8_t clusterSizeShift_;    // shift to convert cluster count to block count\r\n  uint32_t dataStartBlock_;     // first data block number\r\n  uint8_t fatCount_;            // number of FATs on volume\r\n  uint32_t fatStartBlock_;      // start block for first FAT\r\n  uint8_t fatType_;             // volume type (12, 16, OR 32)\r\n  uint16_t rootDirEntryCount_;  // number of entries in FAT16 root dir\r\n  uint32_t rootDirStart_;       // root start block for FAT16, cluster for FAT32\r\n  //----------------------------------------------------------------------------\r\n  uint8_t allocContiguous(uint32_t count, uint32_t* curCluster);\r\n  uint8_t blockOfCluster(uint32_t position) const {\r\n          return (position >> 9) & (blocksPerCluster_ - 1);}\r\n  uint32_t clusterStartBlock(uint32_t cluster) const {\r\n           return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}\r\n  uint32_t blockNumber(uint32_t cluster, uint32_t position) const {\r\n           return clusterStartBlock(cluster) + blockOfCluster(position);}\r\n  static uint8_t cacheFlush(void);\r\n  static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action);\r\n  static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;}\r\n  static uint8_t cacheZeroBlock(uint32_t blockNumber);\r\n  uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const;\r\n  uint8_t fatGet(uint32_t cluster, uint32_t* value) const;\r\n  uint8_t fatPut(uint32_t cluster, uint32_t value);\r\n  uint8_t fatPutEOC(uint32_t cluster) {\r\n    return fatPut(cluster, 0x0FFFFFFF);\r\n  }\r\n  uint8_t freeChain(uint32_t cluster);\r\n  uint8_t isEOC(uint32_t cluster) const {\r\n    return  cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN);\r\n  }\r\n  uint8_t readBlock(uint32_t block, uint8_t* dst) {\r\n    return sdCard_->readBlock(block, dst);}\r\n  uint8_t readData(uint32_t block, uint16_t offset,\r\n    uint16_t count, uint8_t* dst) {\r\n      return sdCard_->readData(block, offset, count, dst);\r\n  }\r\n  uint8_t writeBlock(uint32_t block, const uint8_t* dst) {\r\n    return sdCard_->writeBlock(block, dst);\r\n  }\r\n};\r\n#endif  // SdFat_h\r\n"
  },
  {
    "path": "Sprinter/SdFatUtil.h",
    "content": "/* Arduino SdFat Library\r\n * Copyright (C) 2008 by William Greiman\r\n *\r\n * This file is part of the Arduino SdFat Library\r\n *\r\n * This Library is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino SdFat Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n#ifndef SdFatUtil_h\r\n#define SdFatUtil_h\r\n/**\r\n * \\file\r\n * Useful utility functions.\r\n */\r\n#if defined(ARDUINO) && ARDUINO >= 100\r\n#include <Arduino.h>\r\n#else\r\n#include <WProgram.h>\r\n#endif\r\n#include <avr/pgmspace.h>\r\n/** Store and print a string in flash memory.*/\r\n#define PgmPrint(x) SerialPrint_P(PSTR(x))\r\n/** Store and print a string in flash memory followed by a CR/LF.*/\r\n#define PgmPrintln(x) SerialPrintln_P(PSTR(x))\r\n/** Defined so doxygen works for function definitions. */\r\n#define NOINLINE __attribute__((noinline))\r\n//------------------------------------------------------------------------------\r\n/** Return the number of bytes currently free in RAM. */\r\nstatic int FreeRam(void) {\r\n  extern int  __bss_end;\r\n  extern int* __brkval;\r\n  int free_memory;\r\n  if (reinterpret_cast<int>(__brkval) == 0) {\r\n    // if no heap use from end of bss section\r\n    free_memory = reinterpret_cast<int>(&free_memory)\r\n                  - reinterpret_cast<int>(&__bss_end);\r\n  } else {\r\n    // use from top of stack to heap\r\n    free_memory = reinterpret_cast<int>(&free_memory)\r\n                  - reinterpret_cast<int>(__brkval);\r\n  }\r\n  return free_memory;\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * %Print a string in flash memory to the serial port.\r\n *\r\n * \\param[in] str Pointer to string stored in flash memory.\r\n */\r\nstatic NOINLINE void SerialPrint_P(PGM_P str) {\r\n  for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.print(char(c));\r\n}\r\n//------------------------------------------------------------------------------\r\n/**\r\n * %Print a string in flash memory followed by a CR/LF.\r\n *\r\n * \\param[in] str Pointer to string stored in flash memory.\r\n */\r\nstatic NOINLINE void SerialPrintln_P(PGM_P str) {\r\n  SerialPrint_P(str);\r\n  Serial.println();\r\n}\r\n#endif  // #define SdFatUtil_h\r\n"
  },
  {
    "path": "Sprinter/SdFatmainpage.h",
    "content": "/* Arduino SdFat Library\r\n * Copyright (C) 2009 by William Greiman\r\n *  \r\n * This file is part of the Arduino SdFat Library\r\n *  \r\n * This Library is free software: you can redistribute it and/or modify \r\n * it under the terms of the GNU General Public License as published by \r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n * \r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino SdFat Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n\r\n/**\r\n\\mainpage Arduino SdFat Library\r\n<CENTER>Copyright &copy; 2009 by William Greiman\r\n</CENTER>\r\n\r\n\\section Intro Introduction\r\nThe Arduino SdFat Library is a minimal implementation of FAT16 and FAT32\r\nfile systems on SD flash memory cards.  Standard SD and high capacity\r\nSDHC cards are supported.\r\n\r\nThe SdFat only supports short 8.3 names.\r\n\r\nThe main classes in SdFat are Sd2Card, SdVolume, and SdFile.\r\n\r\nThe Sd2Card class supports access to standard SD cards and SDHC cards.  Most\r\napplications will only need to call the Sd2Card::init() member function.\r\n\r\nThe SdVolume class supports FAT16 and FAT32 partitions.  Most applications\r\nwill only need to call the SdVolume::init() member function.\r\n\r\nThe SdFile class provides file access functions such as open(), read(),\r\nremove(), write(), close() and sync(). This class supports access to the root\r\ndirectory and subdirectories.\r\n\r\nA number of example are provided in the SdFat/examples folder.  These were\r\ndeveloped to test SdFat and illustrate its use.\r\n\r\nSdFat was developed for high speed data recording.  SdFat was used to implement\r\nan audio record/play class, WaveRP, for the Adafruit Wave Shield.  This\r\napplication uses special Sd2Card calls to write to contiguous files in raw mode.\r\nThese functions reduce write latency so that audio can be recorded with the\r\nsmall amount of RAM in the Arduino.\r\n\r\n\\section SDcard SD\\SDHC Cards\r\n\r\nArduinos access SD cards using the cards SPI protocol.  PCs, Macs, and\r\nmost consumer devices use the 4-bit parallel SD protocol.  A card that\r\nfunctions well on A PC or Mac may not work well on the Arduino.\r\n\r\nMost cards have good SPI read performance but cards vary widely in SPI\r\nwrite performance.  Write performance is limited by how efficiently the\r\ncard manages internal erase/remapping operations.  The Arduino cannot\r\noptimize writes to reduce erase operations because of its limit RAM.\r\n\r\nSanDisk cards generally have good write performance.  They seem to have\r\nmore internal RAM buffering than other cards and therefore can limit\r\nthe number of flash erase operations that the Arduino forces due to its\r\nlimited RAM.\r\n\r\n\\section Hardware Hardware Configuration\r\n\r\nSdFat was developed using an\r\n<A HREF = \"http://www.adafruit.com/\"> Adafruit Industries</A> \r\n<A HREF = \"http://www.ladyada.net/make/waveshield/\"> Wave Shield</A>.\r\n\r\nThe hardware interface to the SD card should not use a resistor based level\r\nshifter.  SdFat sets the SPI bus frequency to 8 MHz which results in signal\r\nrise times that are too slow for the edge detectors in many newer SD card\r\ncontrollers when resistor voltage dividers are used.\r\n\r\nThe 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the\r\n74HC4050N based circuit shown in the file SdLevel.png.  The Adafruit Wave Shield\r\nuses a 74AHC125N.  Gravitech sells SD and MicroSD Card Adapters based on the\r\n74LCX245.\r\n\r\nIf you are using a resistor based level shifter and are having problems try\r\nsetting the SPI bus frequency to 4 MHz.  This can be done by using \r\ncard.init(SPI_HALF_SPEED) to initialize the SD card.\r\n\r\n\\section comment Bugs and Comments\r\n\r\nIf you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net.\r\n\r\n\\section SdFatClass SdFat Usage\r\n\r\nSdFat uses a slightly restricted form of short names.\r\nOnly printable ASCII characters are supported. No characters with code point\r\nvalues greater than 127 are allowed.  Space is not allowed even though space\r\nwas allowed in the API of early versions of DOS.\r\n\r\nShort names are limited to 8 characters followed by an optional period (.)\r\nand extension of up to 3 characters.  The characters may be any combination\r\nof letters and digits.  The following special characters are also allowed:\r\n\r\n$ % ' - _ @ ~ ` ! ( ) { } ^ # &\r\n\r\nShort names are always converted to upper case and their original case\r\nvalue is lost.\r\n\r\n\\note\r\n  The Arduino Print class uses character\r\nat a time writes so it was necessary to use a \\link SdFile::sync() sync() \\endlink\r\nfunction to control when data is written to the SD card.\r\n\r\n\\par\r\nAn application which writes to a file using \\link Print::print() print()\\endlink,\r\n\\link Print::println() println() \\endlink\r\nor \\link SdFile::write write() \\endlink must call \\link SdFile::sync() sync() \\endlink\r\nat the appropriate time to force data and directory information to be written\r\nto the SD Card.  Data and directory information are also written to the SD card\r\nwhen \\link SdFile::close() close() \\endlink is called.\r\n\r\n\\par\r\nApplications must use care calling \\link SdFile::sync() sync() \\endlink\r\nsince 2048 bytes of I/O is required to update file and\r\ndirectory information.  This includes writing the current data block, reading\r\nthe block that contains the directory entry for update, writing the directory\r\nblock back and reading back the current data block.\r\n\r\nIt is possible to open a file with two or more instances of SdFile.  A file may\r\nbe corrupted if data is written to the file by more than one instance of SdFile.\r\n\r\n\\section HowTo How to format SD Cards as FAT Volumes\r\n\r\nYou should use a freshly formatted SD card for best performance.  FAT\r\nfile systems become slower if many files have been created and deleted.\r\nThis is because the directory entry for a deleted file is marked as deleted,\r\nbut is not deleted.  When a new file is created, these entries must be scanned\r\nbefore creating the file, a flaw in the FAT design.  Also files can become\r\nfragmented which causes reads and writes to be slower.\r\n\r\nMicrosoft operating systems support removable media formatted with a\r\nMaster Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector\r\nin block zero.\r\n\r\nMicrosoft operating systems expect MBR formatted removable media\r\nto have only one partition. The first partition should be used.\r\n\r\nMicrosoft operating systems do not support partitioning SD flash cards.\r\nIf you erase an SD card with a program like KillDisk, Most versions of\r\nWindows will format the card as a super floppy.\r\n\r\nThe best way to restore an SD card's format is to use SDFormatter\r\nwhich can be downloaded from:\r\n\r\nhttp://www.sdcard.org/consumers/formatter/\r\n\r\nSDFormatter aligns flash erase boundaries with file\r\nsystem structures which reduces write latency and file system overhead.\r\n\r\nSDFormatter does not have an option for FAT type so it may format\r\nsmall cards as FAT12.\r\n\r\nAfter the MBR is restored by SDFormatter you may need to reformat small\r\ncards that have been formatted FAT12 to force the volume type to be FAT16.\r\n\r\nIf you reformat the SD card with an OS utility, choose a cluster size that\r\nwill result in:\r\n\r\n4084 < CountOfClusters && CountOfClusters < 65525\r\n\r\nThe volume will then be FAT16.\r\n\r\nIf you are formatting an SD card on OS X or Linux, be sure to use the first\r\npartition. Format this partition with a cluster count in above range.\r\n\r\n\\section  References References\r\n\r\nAdafruit Industries:\r\n\r\nhttp://www.adafruit.com/\r\n\r\nhttp://www.ladyada.net/make/waveshield/\r\n\r\nThe Arduino site:\r\n\r\nhttp://www.arduino.cc/\r\n\r\nFor more information about FAT file systems see:\r\n\r\nhttp://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx\r\n\r\nFor information about using SD cards as SPI devices see:\r\n\r\nhttp://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf\r\n\r\nThe ATmega328 datasheet:\r\n\r\nhttp://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf\r\n \r\n\r\n */  \r\n"
  },
  {
    "path": "Sprinter/SdFile.cpp",
    "content": "/* Arduino SdFat Library\n * Copyright (C) 2009 by William Greiman\n *\n * This file is part of the Arduino SdFat Library\n *\n * This Library is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This Library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with the Arduino SdFat Library.  If not, see\n * <http://www.gnu.org/licenses/>.\n */\n#include \"SdFat.h\"\n#include <avr/pgmspace.h>\n#if defined(ARDUINO) && ARDUINO >= 100\n#include <Arduino.h>\n#else\n#include <WProgram.h>\n#endif\n//------------------------------------------------------------------------------\n// callback function for date/time\nvoid (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL;\n\n#if ALLOW_DEPRECATED_FUNCTIONS\n// suppress cpplint warnings with NOLINT comment\nvoid (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL;  // NOLINT\n#endif  // ALLOW_DEPRECATED_FUNCTIONS\n//------------------------------------------------------------------------------\n// add a cluster to a file\nuint8_t SdFile::addCluster() {\n  if (!vol_->allocContiguous(1, &curCluster_)) return false;\n\n  // if first cluster of file link to directory entry\n  if (firstCluster_ == 0) {\n    firstCluster_ = curCluster_;\n    flags_ |= F_FILE_DIR_DIRTY;\n  }\n  return true;\n}\n//------------------------------------------------------------------------------\n// Add a cluster to a directory file and zero the cluster.\n// return with first block of cluster in the cache\nuint8_t SdFile::addDirCluster(void) {\n  if (!addCluster()) return false;\n\n  // zero data in cluster insure first cluster is in cache\n  uint32_t block = vol_->clusterStartBlock(curCluster_);\n  for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) {\n    if (!SdVolume::cacheZeroBlock(block + i - 1)) return false;\n  }\n  // Increase directory file size by cluster size\n  fileSize_ += 512UL << vol_->clusterSizeShift_;\n  return true;\n}\n//------------------------------------------------------------------------------\n// cache a file's directory entry\n// return pointer to cached entry or null for failure\ndir_t* SdFile::cacheDirEntry(uint8_t action) {\n  if (!SdVolume::cacheRawBlock(dirBlock_, action)) return NULL;\n  return SdVolume::cacheBuffer_.dir + dirIndex_;\n}\n//------------------------------------------------------------------------------\n/**\n *  Close a file and force cached data and directory information\n *  to be written to the storage device.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include no file is open or an I/O error.\n */\nuint8_t SdFile::close(void) {\n  if (!sync())return false;\n  type_ = FAT_FILE_TYPE_CLOSED;\n  return true;\n}\n//------------------------------------------------------------------------------\n/**\n * Check for contiguous file and return its raw block range.\n *\n * \\param[out] bgnBlock the first block address for the file.\n * \\param[out] endBlock the last  block address for the file.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include file is not contiguous, file has zero length\n * or an I/O error occurred.\n */\nuint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {\n  // error if no blocks\n  if (firstCluster_ == 0) return false;\n\n  for (uint32_t c = firstCluster_; ; c++) {\n    uint32_t next;\n    if (!vol_->fatGet(c, &next)) return false;\n\n    // check for contiguous\n    if (next != (c + 1)) {\n      // error if not end of chain\n      if (!vol_->isEOC(next)) return false;\n      *bgnBlock = vol_->clusterStartBlock(firstCluster_);\n      *endBlock = vol_->clusterStartBlock(c)\n                  + vol_->blocksPerCluster_ - 1;\n      return true;\n    }\n  }\n}\n//------------------------------------------------------------------------------\n/**\n * Create and open a new contiguous file of a specified size.\n *\n * \\note This function only supports short DOS 8.3 names.\n * See open() for more information.\n *\n * \\param[in] dirFile The directory where the file will be created.\n * \\param[in] fileName A valid DOS 8.3 file name.\n * \\param[in] size The desired file size.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include \\a fileName contains\n * an invalid DOS 8.3 file name, the FAT volume has not been initialized,\n * a file is already open, the file already exists, the root\n * directory is full or an I/O error.\n *\n */\nuint8_t SdFile::createContiguous(SdFile* dirFile,\n        const char* fileName, uint32_t size) {\n  // don't allow zero length file\n  if (size == 0) return false;\n  if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) return false;\n\n  // calculate number of clusters needed\n  uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1;\n\n  // allocate clusters\n  if (!vol_->allocContiguous(count, &firstCluster_)) {\n    remove();\n    return false;\n  }\n  fileSize_ = size;\n\n  // insure sync() will update dir entry\n  flags_ |= F_FILE_DIR_DIRTY;\n  return sync();\n}\n//------------------------------------------------------------------------------\n/**\n * Return a files directory entry\n *\n * \\param[out] dir Location for return of the files directory entry.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n */\nuint8_t SdFile::dirEntry(dir_t* dir) {\n  // make sure fields on SD are correct\n  if (!sync()) return false;\n\n  // read entry\n  dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ);\n  if (!p) return false;\n\n  // copy to caller's struct\n  memcpy(dir, p, sizeof(dir_t));\n  return true;\n}\n//------------------------------------------------------------------------------\n/**\n * Format the name field of \\a dir into the 13 byte array\n * \\a name in standard 8.3 short name format.\n *\n * \\param[in] dir The directory structure containing the name.\n * \\param[out] name A 13 byte char array for the formatted name.\n */\nvoid SdFile::dirName(const dir_t& dir, char* name) {\n  uint8_t j = 0;\n  for (uint8_t i = 0; i < 11; i++) {\n    if (dir.name[i] == ' ')continue;\n    if (i == 8) name[j++] = '.';\n    name[j++] = dir.name[i];\n  }\n  name[j] = 0;\n}\n//------------------------------------------------------------------------------\n/** List directory contents to Serial.\n *\n * \\param[in] flags The inclusive OR of\n *\n * LS_DATE - %Print file modification date\n *\n * LS_SIZE - %Print file size.\n *\n * LS_R - Recursive list of subdirectories.\n *\n * \\param[in] indent Amount of space before file name. Used for recursive\n * list to indicate subdirectory level.\n */\nvoid SdFile::ls(uint8_t flags, uint8_t indent) {\n  dir_t* p;\n\n  rewind();\n  while ((p = readDirCache())) {\n    // done if past last used entry\n    if (p->name[0] == DIR_NAME_FREE) break;\n\n    // skip deleted entry and entries for . and  ..\n    if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;\n\n    // only list subdirectories and files\n    if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;\n\n    // print any indent spaces\n    for (int8_t i = 0; i < indent; i++) Serial.print(char(' '));\n\n    // print file name with possible blank fill\n    printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0);\n\n    // print modify date/time if requested\n    if (flags & LS_DATE) {\n       printFatDate(p->lastWriteDate);\n       Serial.print(char(' '));\n       printFatTime(p->lastWriteTime);\n    }\n    // print size if requested\n    if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) {\n      Serial.print(char(' '));\n      Serial.print(p->fileSize);\n    }\n    Serial.println();\n\n    // list subdirectory content if requested\n    if ((flags & LS_R) && DIR_IS_SUBDIR(p)) {\n      uint16_t index = curPosition()/32 - 1;\n      SdFile s;\n      if (s.open(this, index, O_READ)) s.ls(flags, indent + 2);\n      seekSet(32 * (index + 1));\n    }\n  }\n}\n//------------------------------------------------------------------------------\n// format directory name field from a 8.3 name string\nuint8_t SdFile::make83Name(const char* str, uint8_t* name) {\n  uint8_t c;\n  uint8_t n = 7;  // max index for part before dot\n  uint8_t i = 0;\n  // blank fill name and extension\n  while (i < 11) name[i++] = ' ';\n  i = 0;\n  while ((c = *str++) != '\\0') {\n    if (c == '.') {\n      if (n == 10) return false;  // only one dot allowed\n      n = 10;  // max index for full 8.3 name\n      i = 8;   // place for extension\n    } else {\n      // illegal FAT characters\n      PGM_P p = PSTR(\"|<>^+=?/[];,*\\\"\\\\\");\n      uint8_t b;\n      while ((b = pgm_read_byte(p++))) if (b == c) return false;\n      // check size and only allow ASCII printable characters\n      if (i > n || c < 0X21 || c > 0X7E)return false;\n      // only upper case allowed in 8.3 names - convert lower to upper\n      name[i++] = c < 'a' || c > 'z' ?  c : c + ('A' - 'a');\n    }\n  }\n  // must have a file name, extension is optional\n  return name[0] != ' ';\n}\n//------------------------------------------------------------------------------\n/** Make a new directory.\n *\n * \\param[in] dir An open SdFat instance for the directory that will containing\n * the new directory.\n *\n * \\param[in] dirName A valid 8.3 DOS name for the new directory.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include this SdFile is already open, \\a dir is not a\n * directory, \\a dirName is invalid or already exists in \\a dir.\n */\nuint8_t SdFile::makeDir(SdFile* dir, const char* dirName) {\n  dir_t d;\n\n  // create a normal file\n  if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) return false;\n\n  // convert SdFile to directory\n  flags_ = O_READ;\n  type_ = FAT_FILE_TYPE_SUBDIR;\n\n  // allocate and zero first cluster\n  if (!addDirCluster())return false;\n\n  // force entry to SD\n  if (!sync()) return false;\n\n  // cache entry - should already be in cache due to sync() call\n  dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);\n  if (!p) return false;\n\n  // change directory entry  attribute\n  p->attributes = DIR_ATT_DIRECTORY;\n\n  // make entry for '.'\n  memcpy(&d, p, sizeof(d));\n  for (uint8_t i = 1; i < 11; i++) d.name[i] = ' ';\n  d.name[0] = '.';\n\n  // cache block for '.'  and '..'\n  uint32_t block = vol_->clusterStartBlock(firstCluster_);\n  if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;\n\n  // copy '.' to block\n  memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d));\n\n  // make entry for '..'\n  d.name[1] = '.';\n  if (dir->isRoot()) {\n    d.firstClusterLow = 0;\n    d.firstClusterHigh = 0;\n  } else {\n    d.firstClusterLow = dir->firstCluster_ & 0XFFFF;\n    d.firstClusterHigh = dir->firstCluster_ >> 16;\n  }\n  // copy '..' to block\n  memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d));\n\n  // set position after '..'\n  curPosition_ = 2 * sizeof(d);\n\n  // write first block\n  return SdVolume::cacheFlush();\n}\n//------------------------------------------------------------------------------\n/**\n * Open a file or directory by name.\n *\n * \\param[in] dirFile An open SdFat instance for the directory containing the\n * file to be opened.\n *\n * \\param[in] fileName A valid 8.3 DOS name for a file to be opened.\n *\n * \\param[in] oflag Values for \\a oflag are constructed by a bitwise-inclusive\n * OR of flags from the following list\n *\n * O_READ - Open for reading.\n *\n * O_RDONLY - Same as O_READ.\n *\n * O_WRITE - Open for writing.\n *\n * O_WRONLY - Same as O_WRITE.\n *\n * O_RDWR - Open for reading and writing.\n *\n * O_APPEND - If set, the file offset shall be set to the end of the\n * file prior to each write.\n *\n * O_CREAT - If the file exists, this flag has no effect except as noted\n * under O_EXCL below. Otherwise, the file shall be created\n *\n * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists.\n *\n * O_SYNC - Call sync() after each write.  This flag should not be used with\n * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class.\n * These functions do character at a time writes so sync() will be called\n * after each byte.\n *\n * O_TRUNC - If the file exists and is a regular file, and the file is\n * successfully opened and is not read only, its length shall be truncated to 0.\n *\n * \\note Directory files must be opened read only.  Write and truncation is\n * not allowed for directory files.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include this SdFile is already open, \\a difFile is not\n * a directory, \\a fileName is invalid, the file does not exist\n * or can't be opened in the access mode specified by oflag.\n */\nuint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) {\n  uint8_t dname[11];\n  dir_t* p;\n\n  // error if already open\n  if (isOpen())return false;\n\n  if (!make83Name(fileName, dname)) return false;\n  vol_ = dirFile->vol_;\n  dirFile->rewind();\n\n  // bool for empty entry found\n  uint8_t emptyFound = false;\n\n  // search for file\n  while (dirFile->curPosition_ < dirFile->fileSize_) {\n    uint8_t index = 0XF & (dirFile->curPosition_ >> 5);\n    p = dirFile->readDirCache();\n    if (p == NULL) return false;\n\n    if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) {\n      // remember first empty slot\n      if (!emptyFound) {\n        emptyFound = true;\n        dirIndex_ = index;\n        dirBlock_ = SdVolume::cacheBlockNumber_;\n      }\n      // done if no entries follow\n      if (p->name[0] == DIR_NAME_FREE) break;\n    } else if (!memcmp(dname, p->name, 11)) {\n      // don't open existing file if O_CREAT and O_EXCL\n      if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false;\n\n      // open found file\n      return openCachedEntry(0XF & index, oflag);\n    }\n  }\n  // only create file if O_CREAT and O_WRITE\n  if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false;\n\n  // cache found slot or add cluster if end of file\n  if (emptyFound) {\n    p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);\n    if (!p) return false;\n  } else {\n    if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false;\n\n    // add and zero cluster for dirFile - first cluster is in cache for write\n    if (!dirFile->addDirCluster()) return false;\n\n    // use first entry in cluster\n    dirIndex_ = 0;\n    p = SdVolume::cacheBuffer_.dir;\n  }\n  // initialize as empty file\n  memset(p, 0, sizeof(dir_t));\n  memcpy(p->name, dname, 11);\n\n  // set timestamps\n  if (dateTime_) {\n    // call user function\n    dateTime_(&p->creationDate, &p->creationTime);\n  } else {\n    // use default date/time\n    p->creationDate = FAT_DEFAULT_DATE;\n    p->creationTime = FAT_DEFAULT_TIME;\n  }\n  p->lastAccessDate = p->creationDate;\n  p->lastWriteDate = p->creationDate;\n  p->lastWriteTime = p->creationTime;\n\n  // force write of entry to SD\n  if (!SdVolume::cacheFlush()) return false;\n\n  // open entry in cache\n  return openCachedEntry(dirIndex_, oflag);\n}\n//------------------------------------------------------------------------------\n/**\n * Open a file by index.\n *\n * \\param[in] dirFile An open SdFat instance for the directory.\n *\n * \\param[in] index The \\a index of the directory entry for the file to be\n * opened.  The value for \\a index is (directory file position)/32.\n *\n * \\param[in] oflag Values for \\a oflag are constructed by a bitwise-inclusive\n * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.\n *\n * See open() by fileName for definition of flags and return values.\n *\n */\nuint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) {\n  // error if already open\n  if (isOpen())return false;\n\n  // don't open existing file if O_CREAT and O_EXCL - user call error\n  if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false;\n\n  vol_ = dirFile->vol_;\n\n  // seek to location of entry\n  if (!dirFile->seekSet(32 * index)) return false;\n\n  // read entry into cache\n  dir_t* p = dirFile->readDirCache();\n  if (p == NULL) return false;\n\n  // error if empty slot or '.' or '..'\n  if (p->name[0] == DIR_NAME_FREE ||\n      p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {\n    return false;\n  }\n  // open cached entry\n  return openCachedEntry(index & 0XF, oflag);\n}\n//------------------------------------------------------------------------------\n// open a cached directory entry. Assumes vol_ is initializes\nuint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {\n  // location of entry in cache\n  dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex;\n\n  // write or truncate is an error for a directory or read-only file\n  if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {\n    if (oflag & (O_WRITE | O_TRUNC)) return false;\n  }\n  // remember location of directory entry on SD\n  dirIndex_ = dirIndex;\n  dirBlock_ = SdVolume::cacheBlockNumber_;\n\n  // copy first cluster number for directory fields\n  firstCluster_ = (uint32_t)p->firstClusterHigh << 16;\n  firstCluster_ |= p->firstClusterLow;\n\n  // make sure it is a normal file or subdirectory\n  if (DIR_IS_FILE(p)) {\n    fileSize_ = p->fileSize;\n    type_ = FAT_FILE_TYPE_NORMAL;\n  } else if (DIR_IS_SUBDIR(p)) {\n    if (!vol_->chainSize(firstCluster_, &fileSize_)) return false;\n    type_ = FAT_FILE_TYPE_SUBDIR;\n  } else {\n    return false;\n  }\n  // save open flags for read/write\n  flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND);\n\n  // set to start of file\n  curCluster_ = 0;\n  curPosition_ = 0;\n\n  // truncate file to zero length if requested\n  if (oflag & O_TRUNC) return truncate(0);\n  return true;\n}\n//------------------------------------------------------------------------------\n/**\n * Open a volume's root directory.\n *\n * \\param[in] vol The FAT volume containing the root directory to be opened.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include the FAT volume has not been initialized\n * or it a FAT12 volume.\n */\nuint8_t SdFile::openRoot(SdVolume* vol) {\n  // error if file is already open\n  if (isOpen()) return false;\n\n  if (vol->fatType() == 16) {\n    type_ = FAT_FILE_TYPE_ROOT16;\n    firstCluster_ = 0;\n    fileSize_ = 32 * vol->rootDirEntryCount();\n  } else if (vol->fatType() == 32) {\n    type_ = FAT_FILE_TYPE_ROOT32;\n    firstCluster_ = vol->rootDirStart();\n    if (!vol->chainSize(firstCluster_, &fileSize_)) return false;\n  } else {\n    // volume is not initialized or FAT12\n    return false;\n  }\n  vol_ = vol;\n  // read only\n  flags_ = O_READ;\n\n  // set to start of file\n  curCluster_ = 0;\n  curPosition_ = 0;\n\n  // root has no directory entry\n  dirBlock_ = 0;\n  dirIndex_ = 0;\n  return true;\n}\n//------------------------------------------------------------------------------\n/** %Print the name field of a directory entry in 8.3 format to Serial.\n *\n * \\param[in] dir The directory structure containing the name.\n * \\param[in] width Blank fill name if length is less than \\a width.\n */\nvoid SdFile::printDirName(const dir_t& dir, uint8_t width) {\n  uint8_t w = 0;\n  for (uint8_t i = 0; i < 11; i++) {\n    if (dir.name[i] == ' ')continue;\n    if (i == 8) {\n      Serial.print(char('.'));\n      w++;\n    }\n    Serial.print(char(dir.name[i]));\n    w++;\n  }\n  if (DIR_IS_SUBDIR(&dir)) {\n    Serial.print(char('/'));\n    w++;\n  }\n  while (w < width) {\n    Serial.print(char(' '));\n    w++;\n  }\n}\n//------------------------------------------------------------------------------\n/** %Print a directory date field to Serial.\n *\n *  Format is yyyy-mm-dd.\n *\n * \\param[in] fatDate The date field from a directory entry.\n */\nvoid SdFile::printFatDate(uint16_t fatDate) {\n  Serial.print(FAT_YEAR(fatDate));\n  Serial.print(char('-'));\n  printTwoDigits(FAT_MONTH(fatDate));\n  Serial.print(char('-'));\n  printTwoDigits(FAT_DAY(fatDate));\n}\n//------------------------------------------------------------------------------\n/** %Print a directory time field to Serial.\n *\n * Format is hh:mm:ss.\n *\n * \\param[in] fatTime The time field from a directory entry.\n */\nvoid SdFile::printFatTime(uint16_t fatTime) {\n  printTwoDigits(FAT_HOUR(fatTime));\n  Serial.print(char(':'));\n  printTwoDigits(FAT_MINUTE(fatTime));\n  Serial.print(char(':'));\n  printTwoDigits(FAT_SECOND(fatTime));\n}\n//------------------------------------------------------------------------------\n/** %Print a value as two digits to Serial.\n *\n * \\param[in] v Value to be printed, 0 <= \\a v <= 99\n */\nvoid SdFile::printTwoDigits(uint8_t v) {\n  char str[3];\n  str[0] = '0' + v/10;\n  str[1] = '0' + v % 10;\n  str[2] = 0;\n  Serial.print(str);\n}\n//------------------------------------------------------------------------------\n/**\n * Read data from a file starting at the current position.\n *\n * \\param[out] buf Pointer to the location that will receive the data.\n *\n * \\param[in] nbyte Maximum number of bytes to read.\n *\n * \\return For success read() returns the number of bytes read.\n * A value less than \\a nbyte, including zero, will be returned\n * if end of file is reached.\n * If an error occurs, read() returns -1.  Possible errors include\n * read() called before a file has been opened, corrupt file system\n * or an I/O error occurred.\n */\nint16_t SdFile::read(void* buf, uint16_t nbyte) {\n  uint8_t* dst = reinterpret_cast<uint8_t*>(buf);\n\n  // error if not open or write only\n  if (!isOpen() || !(flags_ & O_READ)) return -1;\n\n  // max bytes left in file\n  if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_;\n\n  // amount left to read\n  uint16_t toRead = nbyte;\n  while (toRead > 0) {\n    uint32_t block;  // raw device block number\n    uint16_t offset = curPosition_ & 0X1FF;  // offset in block\n    if (type_ == FAT_FILE_TYPE_ROOT16) {\n      block = vol_->rootDirStart() + (curPosition_ >> 9);\n    } else {\n      uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);\n      if (offset == 0 && blockOfCluster == 0) {\n        // start of new cluster\n        if (curPosition_ == 0) {\n          // use first cluster in file\n          curCluster_ = firstCluster_;\n        } else {\n          // get next cluster from FAT\n          if (!vol_->fatGet(curCluster_, &curCluster_)) return -1;\n        }\n      }\n      block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;\n    }\n    uint16_t n = toRead;\n\n    // amount to be read from current block\n    if (n > (512 - offset)) n = 512 - offset;\n\n    // no buffering needed if n == 512 or user requests no buffering\n    if ((unbufferedRead() || n == 512) &&\n      block != SdVolume::cacheBlockNumber_) {\n      if (!vol_->readData(block, offset, n, dst)) return -1;\n      dst += n;\n    } else {\n      // read block to cache and copy data to caller\n      if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1;\n      uint8_t* src = SdVolume::cacheBuffer_.data + offset;\n      uint8_t* end = src + n;\n      while (src != end) *dst++ = *src++;\n    }\n    curPosition_ += n;\n    toRead -= n;\n  }\n  return nbyte;\n}\n//------------------------------------------------------------------------------\n/**\n * Read the next directory entry from a directory file.\n *\n * \\param[out] dir The dir_t struct that will receive the data.\n *\n * \\return For success readDir() returns the number of bytes read.\n * A value of zero will be returned if end of file is reached.\n * If an error occurs, readDir() returns -1.  Possible errors include\n * readDir() called before a directory has been opened, this is not\n * a directory file or an I/O error occurred.\n */\nint8_t SdFile::readDir(dir_t* dir) {\n  int8_t n;\n  // if not a directory file or miss-positioned return an error\n  if (!isDir() || (0X1F & curPosition_)) return -1;\n\n  while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) {\n    // last entry if DIR_NAME_FREE\n    if (dir->name[0] == DIR_NAME_FREE) break;\n    // skip empty entries and entry for .  and ..\n    if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue;\n    // return if normal file or subdirectory\n    if (DIR_IS_FILE_OR_SUBDIR(dir)) return n;\n  }\n  // error, end of file, or past last entry\n  return n < 0 ? -1 : 0;\n}\n//------------------------------------------------------------------------------\n// Read next directory entry into the cache\n// Assumes file is correctly positioned\ndir_t* SdFile::readDirCache(void) {\n  // error if not directory\n  if (!isDir()) return NULL;\n\n  // index of entry in cache\n  uint8_t i = (curPosition_ >> 5) & 0XF;\n\n  // use read to locate and cache block\n  if (read() < 0) return NULL;\n\n  // advance to next entry\n  curPosition_ += 31;\n\n  // return pointer to entry\n  return (SdVolume::cacheBuffer_.dir + i);\n}\n//------------------------------------------------------------------------------\n/**\n * Remove a file.\n *\n * The directory entry and all data for the file are deleted.\n *\n * \\note This function should not be used to delete the 8.3 version of a\n * file that has a long name. For example if a file has the long name\n * \"New Text Document.txt\" you should not delete the 8.3 name \"NEWTEX~1.TXT\".\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include the file read-only, is a directory,\n * or an I/O error occurred.\n */\nuint8_t SdFile::remove(void) {\n  // free any clusters - will fail if read-only or directory\n  if (!truncate(0)) return false;\n\n  // cache directory entry\n  dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);\n  if (!d) return false;\n\n  // mark entry deleted\n  d->name[0] = DIR_NAME_DELETED;\n\n  // set this SdFile closed\n  type_ = FAT_FILE_TYPE_CLOSED;\n\n  // write entry to SD\n  return SdVolume::cacheFlush();\n}\n//------------------------------------------------------------------------------\n/**\n * Remove a file.\n *\n * The directory entry and all data for the file are deleted.\n *\n * \\param[in] dirFile The directory that contains the file.\n * \\param[in] fileName The name of the file to be removed.\n *\n * \\note This function should not be used to delete the 8.3 version of a\n * file that has a long name. For example if a file has the long name\n * \"New Text Document.txt\" you should not delete the 8.3 name \"NEWTEX~1.TXT\".\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include the file is a directory, is read only,\n * \\a dirFile is not a directory, \\a fileName is not found\n * or an I/O error occurred.\n */\nuint8_t SdFile::remove(SdFile* dirFile, const char* fileName) {\n  SdFile file;\n  if (!file.open(dirFile, fileName, O_WRITE)) return false;\n  return file.remove();\n}\n//------------------------------------------------------------------------------\n/** Remove a directory file.\n *\n * The directory file will be removed only if it is empty and is not the\n * root directory.  rmDir() follows DOS and Windows and ignores the\n * read-only attribute for the directory.\n *\n * \\note This function should not be used to delete the 8.3 version of a\n * directory that has a long name. For example if a directory has the\n * long name \"New folder\" you should not delete the 8.3 name \"NEWFOL~1\".\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include the file is not a directory, is the root\n * directory, is not empty, or an I/O error occurred.\n */\nuint8_t SdFile::rmDir(void) {\n  // must be open subdirectory\n  if (!isSubDir()) return false;\n\n  rewind();\n\n  // make sure directory is empty\n  while (curPosition_ < fileSize_) {\n    dir_t* p = readDirCache();\n    if (p == NULL) return false;\n    // done if past last used entry\n    if (p->name[0] == DIR_NAME_FREE) break;\n    // skip empty slot or '.' or '..'\n    if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;\n    // error not empty\n    if (DIR_IS_FILE_OR_SUBDIR(p)) return false;\n  }\n  // convert empty directory to normal file for remove\n  type_ = FAT_FILE_TYPE_NORMAL;\n  flags_ |= O_WRITE;\n  return remove();\n}\n//------------------------------------------------------------------------------\n/** Recursively delete a directory and all contained files.\n *\n * This is like the Unix/Linux 'rm -rf *' if called with the root directory\n * hence the name.\n *\n * Warning - This will remove all contents of the directory including\n * subdirectories.  The directory will then be removed if it is not root.\n * The read-only attribute for files will be ignored.\n *\n * \\note This function should not be used to delete the 8.3 version of\n * a directory that has a long name.  See remove() and rmDir().\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n */\nuint8_t SdFile::rmRfStar(void) {\n  rewind();\n  while (curPosition_ < fileSize_) {\n    SdFile f;\n\n    // remember position\n    uint16_t index = curPosition_/32;\n\n    dir_t* p = readDirCache();\n    if (!p) return false;\n\n    // done if past last entry\n    if (p->name[0] == DIR_NAME_FREE) break;\n\n    // skip empty slot or '.' or '..'\n    if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;\n\n    // skip if part of long file name or volume label in root\n    if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;\n\n    if (!f.open(this, index, O_READ)) return false;\n    if (f.isSubDir()) {\n      // recursively delete\n      if (!f.rmRfStar()) return false;\n    } else {\n      // ignore read-only\n      f.flags_ |= O_WRITE;\n      if (!f.remove()) return false;\n    }\n    // position to next entry if required\n    if (curPosition_ != (32*(index + 1))) {\n      if (!seekSet(32*(index + 1))) return false;\n    }\n  }\n  // don't try to delete root\n  if (isRoot()) return true;\n  return rmDir();\n}\n//------------------------------------------------------------------------------\n/**\n * Sets a file's position.\n *\n * \\param[in] pos The new position in bytes from the beginning of the file.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n */\nuint8_t SdFile::seekSet(uint32_t pos) {\n  // error if file not open or seek past end of file\n  if (!isOpen() || pos > fileSize_) return false;\n\n  if (type_ == FAT_FILE_TYPE_ROOT16) {\n    curPosition_ = pos;\n    return true;\n  }\n  if (pos == 0) {\n    // set position to start of file\n    curCluster_ = 0;\n    curPosition_ = 0;\n    return true;\n  }\n  // calculate cluster index for cur and new position\n  uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9);\n  uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9);\n\n  if (nNew < nCur || curPosition_ == 0) {\n    // must follow chain from first cluster\n    curCluster_ = firstCluster_;\n  } else {\n    // advance from curPosition\n    nNew -= nCur;\n  }\n  while (nNew--) {\n    if (!vol_->fatGet(curCluster_, &curCluster_)) return false;\n  }\n  curPosition_ = pos;\n  return true;\n}\n//------------------------------------------------------------------------------\n/**\n * The sync() call causes all modified data and directory fields\n * to be written to the storage device.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include a call to sync() before a file has been\n * opened or an I/O error.\n */\nuint8_t SdFile::sync(void) {\n  // only allow open files and directories\n  if (!isOpen()) return false;\n\n  if (flags_ & F_FILE_DIR_DIRTY) {\n    dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);\n    if (!d) return false;\n\n    // do not set filesize for dir files\n    if (!isDir()) d->fileSize = fileSize_;\n\n    // update first cluster fields\n    d->firstClusterLow = firstCluster_ & 0XFFFF;\n    d->firstClusterHigh = firstCluster_ >> 16;\n\n    // set modify time if user supplied a callback date/time function\n    if (dateTime_) {\n      dateTime_(&d->lastWriteDate, &d->lastWriteTime);\n      d->lastAccessDate = d->lastWriteDate;\n    }\n    // clear directory dirty\n    flags_ &= ~F_FILE_DIR_DIRTY;\n  }\n  return SdVolume::cacheFlush();\n}\n//------------------------------------------------------------------------------\n/**\n * Set a file's timestamps in its directory entry.\n *\n * \\param[in] flags Values for \\a flags are constructed by a bitwise-inclusive\n * OR of flags from the following list\n *\n * T_ACCESS - Set the file's last access date.\n *\n * T_CREATE - Set the file's creation date and time.\n *\n * T_WRITE - Set the file's last write/modification date and time.\n *\n * \\param[in] year Valid range 1980 - 2107 inclusive.\n *\n * \\param[in] month Valid range 1 - 12 inclusive.\n *\n * \\param[in] day Valid range 1 - 31 inclusive.\n *\n * \\param[in] hour Valid range 0 - 23 inclusive.\n *\n * \\param[in] minute Valid range 0 - 59 inclusive.\n *\n * \\param[in] second Valid range 0 - 59 inclusive\n *\n * \\note It is possible to set an invalid date since there is no check for\n * the number of days in a month.\n *\n * \\note\n * Modify and access timestamps may be overwritten if a date time callback\n * function has been set by dateTimeCallback().\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n */\nuint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,\n         uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {\n  if (!isOpen()\n    || year < 1980\n    || year > 2107\n    || month < 1\n    || month > 12\n    || day < 1\n    || day > 31\n    || hour > 23\n    || minute > 59\n    || second > 59) {\n      return false;\n  }\n  dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);\n  if (!d) return false;\n\n  uint16_t dirDate = FAT_DATE(year, month, day);\n  uint16_t dirTime = FAT_TIME(hour, minute, second);\n  if (flags & T_ACCESS) {\n    d->lastAccessDate = dirDate;\n  }\n  if (flags & T_CREATE) {\n    d->creationDate = dirDate;\n    d->creationTime = dirTime;\n    // seems to be units of 1/100 second not 1/10 as Microsoft states\n    d->creationTimeTenths = second & 1 ? 100 : 0;\n  }\n  if (flags & T_WRITE) {\n    d->lastWriteDate = dirDate;\n    d->lastWriteTime = dirTime;\n  }\n  SdVolume::cacheSetDirty();\n  return sync();\n}\n//------------------------------------------------------------------------------\n/**\n * Truncate a file to a specified length.  The current file position\n * will be maintained if it is less than or equal to \\a length otherwise\n * it will be set to end of file.\n *\n * \\param[in] length The desired length for the file.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.\n * Reasons for failure include file is read only, file is a directory,\n * \\a length is greater than the current file size or an I/O error occurs.\n */\nuint8_t SdFile::truncate(uint32_t length) {\n// error if not a normal file or read-only\n  if (!isFile() || !(flags_ & O_WRITE)) return false;\n\n  // error if length is greater than current size\n  if (length > fileSize_) return false;\n\n  // fileSize and length are zero - nothing to do\n  if (fileSize_ == 0) return true;\n\n  // remember position for seek after truncation\n  uint32_t newPos = curPosition_ > length ? length : curPosition_;\n\n  // position to last cluster in truncated file\n  if (!seekSet(length)) return false;\n\n  if (length == 0) {\n    // free all clusters\n    if (!vol_->freeChain(firstCluster_)) return false;\n    firstCluster_ = 0;\n  } else {\n    uint32_t toFree;\n    if (!vol_->fatGet(curCluster_, &toFree)) return false;\n\n    if (!vol_->isEOC(toFree)) {\n      // free extra clusters\n      if (!vol_->freeChain(toFree)) return false;\n\n      // current cluster is end of chain\n      if (!vol_->fatPutEOC(curCluster_)) return false;\n    }\n  }\n  fileSize_ = length;\n\n  // need to update directory entry\n  flags_ |= F_FILE_DIR_DIRTY;\n\n  if (!sync()) return false;\n\n  // set file to correct position\n  return seekSet(newPos);\n}\n//------------------------------------------------------------------------------\n/**\n * Write data to an open file.\n *\n * \\note Data is moved to the cache but may not be written to the\n * storage device until sync() is called.\n *\n * \\param[in] buf Pointer to the location of the data to be written.\n *\n * \\param[in] nbyte Number of bytes to write.\n *\n * \\return For success write() returns the number of bytes written, always\n * \\a nbyte.  If an error occurs, write() returns -1.  Possible errors\n * include write() is called before a file has been opened, write is called\n * for a read-only file, device is full, a corrupt file system or an I/O error.\n *\n */\nint16_t SdFile::write(const void* buf, uint16_t nbyte) {\n  // convert void* to uint8_t*  -  must be before goto statements\n  const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);\n\n  // number of bytes left to write  -  must be before goto statements\n  uint16_t nToWrite = nbyte;\n\n  // error if not a normal file or is read-only\n  if (!isFile() || !(flags_ & O_WRITE)) goto writeErrorReturn;\n\n  // seek to end of file if append flag\n  if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {\n    if (!seekEnd()) goto writeErrorReturn;\n  }\n\n  while (nToWrite > 0) {\n    uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);\n    uint16_t blockOffset = curPosition_ & 0X1FF;\n    if (blockOfCluster == 0 && blockOffset == 0) {\n      // start of new cluster\n      if (curCluster_ == 0) {\n        if (firstCluster_ == 0) {\n          // allocate first cluster of file\n          if (!addCluster()) goto writeErrorReturn;\n        } else {\n          curCluster_ = firstCluster_;\n        }\n      } else {\n        uint32_t next;\n        if (!vol_->fatGet(curCluster_, &next)) return false;\n        if (vol_->isEOC(next)) {\n          // add cluster if at end of chain\n          if (!addCluster()) goto writeErrorReturn;\n        } else {\n          curCluster_ = next;\n        }\n      }\n    }\n    // max space in block\n    uint16_t n = 512 - blockOffset;\n\n    // lesser of space and amount to write\n    if (n > nToWrite) n = nToWrite;\n\n    // block for data write\n    uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;\n    if (n == 512) {\n      // full block - don't need to use cache\n      // invalidate cache if block is in cache\n      if (SdVolume::cacheBlockNumber_ == block) {\n        SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;\n      }\n      if (!vol_->writeBlock(block, src)) goto writeErrorReturn;\n      src += 512;\n    } else {\n      if (blockOffset == 0 && curPosition_ >= fileSize_) {\n        // start of new block don't need to read into cache\n        if (!SdVolume::cacheFlush()) goto writeErrorReturn;\n        SdVolume::cacheBlockNumber_ = block;\n        SdVolume::cacheSetDirty();\n      } else {\n        // rewrite part of block\n        if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) {\n          goto writeErrorReturn;\n        }\n      }\n      uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset;\n      uint8_t* end = dst + n;\n      while (dst != end) *dst++ = *src++;\n    }\n    nToWrite -= n;\n    curPosition_ += n;\n  }\n  if (curPosition_ > fileSize_) {\n    // update fileSize and insure sync will update dir entry\n    fileSize_ = curPosition_;\n    flags_ |= F_FILE_DIR_DIRTY;\n  } else if (dateTime_ && nbyte) {\n    // insure sync will update modified date and time\n    flags_ |= F_FILE_DIR_DIRTY;\n  }\n\n  if (flags_ & O_SYNC) {\n    if (!sync()) goto writeErrorReturn;\n  }\n  return nbyte;\n\n writeErrorReturn:\n  // return for write error\n  writeError = true;\n  return -1;\n}\n//------------------------------------------------------------------------------\n/**\n * Write a byte to a file. Required by the Arduino Print class.\n *\n * Use SdFile::writeError to check for errors.\n */\n#if ARDUINO >= 100\nsize_t SdFile::write(uint8_t b)\n#else\nvoid SdFile::write(uint8_t b)\n#endif\n{\n#if ARDUINO >= 100\n  return (size_t) write(&b, 1);\n#else\n  write(&b, 1);\n#endif\n}\n//------------------------------------------------------------------------------\n/**\n * Write a string to a file. Used by the Arduino Print class.\n *\n * Use SdFile::writeError to check for errors.\n */\nvoid SdFile::write(const char* str) {\n  write(str, strlen(str));\n}\n//------------------------------------------------------------------------------\n/**\n * Write a PROGMEM string to a file.\n *\n * Use SdFile::writeError to check for errors.\n */\nvoid SdFile::write_P(PGM_P str) {\n  for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);\n}\n//------------------------------------------------------------------------------\n/**\n * Write a PROGMEM string followed by CR/LF to a file.\n *\n * Use SdFile::writeError to check for errors.\n */\nvoid SdFile::writeln_P(PGM_P str) {\n  write_P(str);\n  println();\n}\n"
  },
  {
    "path": "Sprinter/SdInfo.h",
    "content": "/* Arduino Sd2Card Library\r\n * Copyright (C) 2009 by William Greiman\r\n *\r\n * This file is part of the Arduino Sd2Card Library\r\n *\r\n * This Library is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This Library is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with the Arduino Sd2Card Library.  If not, see\r\n * <http://www.gnu.org/licenses/>.\r\n */\r\n#ifndef SdInfo_h\r\n#define SdInfo_h\r\n#include <stdint.h>\r\n// Based on the document:\r\n//\r\n// SD Specifications\r\n// Part 1\r\n// Physical Layer\r\n// Simplified Specification\r\n// Version 2.00\r\n// September 25, 2006\r\n//\r\n// www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf\r\n//------------------------------------------------------------------------------\r\n// SD card commands\r\n/** GO_IDLE_STATE - init card in spi mode if CS low */\r\nuint8_t const CMD0 = 0X00;\r\n/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/\r\nuint8_t const CMD8 = 0X08;\r\n/** SEND_CSD - read the Card Specific Data (CSD register) */\r\nuint8_t const CMD9 = 0X09;\r\n/** SEND_CID - read the card identification information (CID register) */\r\nuint8_t const CMD10 = 0X0A;\r\n/** SEND_STATUS - read the card status register */\r\nuint8_t const CMD13 = 0X0D;\r\n/** READ_BLOCK - read a single data block from the card */\r\nuint8_t const CMD17 = 0X11;\r\n/** WRITE_BLOCK - write a single data block to the card */\r\nuint8_t const CMD24 = 0X18;\r\n/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */\r\nuint8_t const CMD25 = 0X19;\r\n/** ERASE_WR_BLK_START - sets the address of the first block to be erased */\r\nuint8_t const CMD32 = 0X20;\r\n/** ERASE_WR_BLK_END - sets the address of the last block of the continuous\r\n    range to be erased*/\r\nuint8_t const CMD33 = 0X21;\r\n/** ERASE - erase all previously selected blocks */\r\nuint8_t const CMD38 = 0X26;\r\n/** APP_CMD - escape for application specific command */\r\nuint8_t const CMD55 = 0X37;\r\n/** READ_OCR - read the OCR register of a card */\r\nuint8_t const CMD58 = 0X3A;\r\n/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be\r\n     pre-erased before writing */\r\nuint8_t const ACMD23 = 0X17;\r\n/** SD_SEND_OP_COMD - Sends host capacity support information and\r\n    activates the card's initialization process */\r\nuint8_t const ACMD41 = 0X29;\r\n//------------------------------------------------------------------------------\r\n/** status for card in the ready state */\r\nuint8_t const R1_READY_STATE = 0X00;\r\n/** status for card in the idle state */\r\nuint8_t const R1_IDLE_STATE = 0X01;\r\n/** status bit for illegal command */\r\nuint8_t const R1_ILLEGAL_COMMAND = 0X04;\r\n/** start data token for read or write single block*/\r\nuint8_t const DATA_START_BLOCK = 0XFE;\r\n/** stop token for write multiple blocks*/\r\nuint8_t const STOP_TRAN_TOKEN = 0XFD;\r\n/** start data token for write multiple blocks*/\r\nuint8_t const WRITE_MULTIPLE_TOKEN = 0XFC;\r\n/** mask for data response tokens after a write block operation */\r\nuint8_t const DATA_RES_MASK = 0X1F;\r\n/** write data accepted token */\r\nuint8_t const DATA_RES_ACCEPTED = 0X05;\r\n//------------------------------------------------------------------------------\r\ntypedef struct CID {\r\n  // byte 0\r\n  uint8_t mid;  // Manufacturer ID\r\n  // byte 1-2\r\n  char oid[2];  // OEM/Application ID\r\n  // byte 3-7\r\n  char pnm[5];  // Product name\r\n  // byte 8\r\n  unsigned prv_m : 4;  // Product revision n.m\r\n  unsigned prv_n : 4;\r\n  // byte 9-12\r\n  uint32_t psn;  // Product serial number\r\n  // byte 13\r\n  unsigned mdt_year_high : 4;  // Manufacturing date\r\n  unsigned reserved : 4;\r\n  // byte 14\r\n  unsigned mdt_month : 4;\r\n  unsigned mdt_year_low :4;\r\n  // byte 15\r\n  unsigned always1 : 1;\r\n  unsigned crc : 7;\r\n}cid_t;\r\n//------------------------------------------------------------------------------\r\n// CSD for version 1.00 cards\r\ntypedef struct CSDV1 {\r\n  // byte 0\r\n  unsigned reserved1 : 6;\r\n  unsigned csd_ver : 2;\r\n  // byte 1\r\n  uint8_t taac;\r\n  // byte 2\r\n  uint8_t nsac;\r\n  // byte 3\r\n  uint8_t tran_speed;\r\n  // byte 4\r\n  uint8_t ccc_high;\r\n  // byte 5\r\n  unsigned read_bl_len : 4;\r\n  unsigned ccc_low : 4;\r\n  // byte 6\r\n  unsigned c_size_high : 2;\r\n  unsigned reserved2 : 2;\r\n  unsigned dsr_imp : 1;\r\n  unsigned read_blk_misalign :1;\r\n  unsigned write_blk_misalign : 1;\r\n  unsigned read_bl_partial : 1;\r\n  // byte 7\r\n  uint8_t c_size_mid;\r\n  // byte 8\r\n  unsigned vdd_r_curr_max : 3;\r\n  unsigned vdd_r_curr_min : 3;\r\n  unsigned c_size_low :2;\r\n  // byte 9\r\n  unsigned c_size_mult_high : 2;\r\n  unsigned vdd_w_cur_max : 3;\r\n  unsigned vdd_w_curr_min : 3;\r\n  // byte 10\r\n  unsigned sector_size_high : 6;\r\n  unsigned erase_blk_en : 1;\r\n  unsigned c_size_mult_low : 1;\r\n  // byte 11\r\n  unsigned wp_grp_size : 7;\r\n  unsigned sector_size_low : 1;\r\n  // byte 12\r\n  unsigned write_bl_len_high : 2;\r\n  unsigned r2w_factor : 3;\r\n  unsigned reserved3 : 2;\r\n  unsigned wp_grp_enable : 1;\r\n  // byte 13\r\n  unsigned reserved4 : 5;\r\n  unsigned write_partial : 1;\r\n  unsigned write_bl_len_low : 2;\r\n  // byte 14\r\n  unsigned reserved5: 2;\r\n  unsigned file_format : 2;\r\n  unsigned tmp_write_protect : 1;\r\n  unsigned perm_write_protect : 1;\r\n  unsigned copy : 1;\r\n  unsigned file_format_grp : 1;\r\n  // byte 15\r\n  unsigned always1 : 1;\r\n  unsigned crc : 7;\r\n}csd1_t;\r\n//------------------------------------------------------------------------------\r\n// CSD for version 2.00 cards\r\ntypedef struct CSDV2 {\r\n  // byte 0\r\n  unsigned reserved1 : 6;\r\n  unsigned csd_ver : 2;\r\n  // byte 1\r\n  uint8_t taac;\r\n  // byte 2\r\n  uint8_t nsac;\r\n  // byte 3\r\n  uint8_t tran_speed;\r\n  // byte 4\r\n  uint8_t ccc_high;\r\n  // byte 5\r\n  unsigned read_bl_len : 4;\r\n  unsigned ccc_low : 4;\r\n  // byte 6\r\n  unsigned reserved2 : 4;\r\n  unsigned dsr_imp : 1;\r\n  unsigned read_blk_misalign :1;\r\n  unsigned write_blk_misalign : 1;\r\n  unsigned read_bl_partial : 1;\r\n  // byte 7\r\n  unsigned reserved3 : 2;\r\n  unsigned c_size_high : 6;\r\n  // byte 8\r\n  uint8_t c_size_mid;\r\n  // byte 9\r\n  uint8_t c_size_low;\r\n  // byte 10\r\n  unsigned sector_size_high : 6;\r\n  unsigned erase_blk_en : 1;\r\n  unsigned reserved4 : 1;\r\n  // byte 11\r\n  unsigned wp_grp_size : 7;\r\n  unsigned sector_size_low : 1;\r\n  // byte 12\r\n  unsigned write_bl_len_high : 2;\r\n  unsigned r2w_factor : 3;\r\n  unsigned reserved5 : 2;\r\n  unsigned wp_grp_enable : 1;\r\n  // byte 13\r\n  unsigned reserved6 : 5;\r\n  unsigned write_partial : 1;\r\n  unsigned write_bl_len_low : 2;\r\n  // byte 14\r\n  unsigned reserved7: 2;\r\n  unsigned file_format : 2;\r\n  unsigned tmp_write_protect : 1;\r\n  unsigned perm_write_protect : 1;\r\n  unsigned copy : 1;\r\n  unsigned file_format_grp : 1;\r\n  // byte 15\r\n  unsigned always1 : 1;\r\n  unsigned crc : 7;\r\n}csd2_t;\r\n//------------------------------------------------------------------------------\r\n// union of old and new style CSD register\r\nunion csd_t {\r\n  csd1_t v1;\r\n  csd2_t v2;\r\n};\r\n#endif  // SdInfo_h\r\n"
  },
  {
    "path": "Sprinter/SdVolume.cpp",
    "content": "/* Arduino SdFat Library\n * Copyright (C) 2009 by William Greiman\n *\n * This file is part of the Arduino SdFat Library\n *\n * This Library is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This Library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with the Arduino SdFat Library.  If not, see\n * <http://www.gnu.org/licenses/>.\n */\n#include \"SdFat.h\"\n//------------------------------------------------------------------------------\n// raw block cache\n// init cacheBlockNumber_to invalid SD block number\nuint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;\ncache_t  SdVolume::cacheBuffer_;     // 512 byte cache for Sd2Card\nSd2Card* SdVolume::sdCard_;          // pointer to SD card object\nuint8_t  SdVolume::cacheDirty_ = 0;  // cacheFlush() will write block if true\nuint32_t SdVolume::cacheMirrorBlock_ = 0;  // mirror  block for second FAT\n//------------------------------------------------------------------------------\n// find a contiguous group of clusters\nuint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {\n  // start of group\n  uint32_t bgnCluster;\n\n  // flag to save place to start next search\n  uint8_t setStart;\n\n  // set search start cluster\n  if (*curCluster) {\n    // try to make file contiguous\n    bgnCluster = *curCluster + 1;\n\n    // don't save new start location\n    setStart = false;\n  } else {\n    // start at likely place for free cluster\n    bgnCluster = allocSearchStart_;\n\n    // save next search start if one cluster\n    setStart = 1 == count;\n  }\n  // end of group\n  uint32_t endCluster = bgnCluster;\n\n  // last cluster of FAT\n  uint32_t fatEnd = clusterCount_ + 1;\n\n  // search the FAT for free clusters\n  for (uint32_t n = 0;; n++, endCluster++) {\n    // can't find space checked all clusters\n    if (n >= clusterCount_) return false;\n\n    // past end - start from beginning of FAT\n    if (endCluster > fatEnd) {\n      bgnCluster = endCluster = 2;\n    }\n    uint32_t f;\n    if (!fatGet(endCluster, &f)) return false;\n\n    if (f != 0) {\n      // cluster in use try next cluster as bgnCluster\n      bgnCluster = endCluster + 1;\n    } else if ((endCluster - bgnCluster + 1) == count) {\n      // done - found space\n      break;\n    }\n  }\n  // mark end of chain\n  if (!fatPutEOC(endCluster)) return false;\n\n  // link clusters\n  while (endCluster > bgnCluster) {\n    if (!fatPut(endCluster - 1, endCluster)) return false;\n    endCluster--;\n  }\n  if (*curCluster != 0) {\n    // connect chains\n    if (!fatPut(*curCluster, bgnCluster)) return false;\n  }\n  // return first cluster number to caller\n  *curCluster = bgnCluster;\n\n  // remember possible next free cluster\n  if (setStart) allocSearchStart_ = bgnCluster + 1;\n\n  return true;\n}\n//------------------------------------------------------------------------------\nuint8_t SdVolume::cacheFlush(void) {\n  if (cacheDirty_) {\n    if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {\n      return false;\n    }\n    // mirror FAT tables\n    if (cacheMirrorBlock_) {\n      if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {\n        return false;\n      }\n      cacheMirrorBlock_ = 0;\n    }\n    cacheDirty_ = 0;\n  }\n  return true;\n}\n//------------------------------------------------------------------------------\nuint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) {\n  if (cacheBlockNumber_ != blockNumber) {\n    if (!cacheFlush()) return false;\n    if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false;\n    cacheBlockNumber_ = blockNumber;\n  }\n  cacheDirty_ |= action;\n  return true;\n}\n//------------------------------------------------------------------------------\n// cache a zero block for blockNumber\nuint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) {\n  if (!cacheFlush()) return false;\n\n  // loop take less flash than memset(cacheBuffer_.data, 0, 512);\n  for (uint16_t i = 0; i < 512; i++) {\n    cacheBuffer_.data[i] = 0;\n  }\n  cacheBlockNumber_ = blockNumber;\n  cacheSetDirty();\n  return true;\n}\n//------------------------------------------------------------------------------\n// return the size in bytes of a cluster chain\nuint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const {\n  uint32_t s = 0;\n  do {\n    if (!fatGet(cluster, &cluster)) return false;\n    s += 512UL << clusterSizeShift_;\n  } while (!isEOC(cluster));\n  *size = s;\n  return true;\n}\n//------------------------------------------------------------------------------\n// Fetch a FAT entry\nuint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const {\n  if (cluster > (clusterCount_ + 1)) return false;\n  uint32_t lba = fatStartBlock_;\n  lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;\n  if (lba != cacheBlockNumber_) {\n    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;\n  }\n  if (fatType_ == 16) {\n    *value = cacheBuffer_.fat16[cluster & 0XFF];\n  } else {\n    *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;\n  }\n  return true;\n}\n//------------------------------------------------------------------------------\n// Store a FAT entry\nuint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) {\n  // error if reserved cluster\n  if (cluster < 2) return false;\n\n  // error if not in FAT\n  if (cluster > (clusterCount_ + 1)) return false;\n\n  // calculate block address for entry\n  uint32_t lba = fatStartBlock_;\n  lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;\n\n  if (lba != cacheBlockNumber_) {\n    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;\n  }\n  // store entry\n  if (fatType_ == 16) {\n    cacheBuffer_.fat16[cluster & 0XFF] = value;\n  } else {\n    cacheBuffer_.fat32[cluster & 0X7F] = value;\n  }\n  cacheSetDirty();\n\n  // mirror second FAT\n  if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;\n  return true;\n}\n//------------------------------------------------------------------------------\n// free a cluster chain\nuint8_t SdVolume::freeChain(uint32_t cluster) {\n  // clear free cluster location\n  allocSearchStart_ = 2;\n\n  do {\n    uint32_t next;\n    if (!fatGet(cluster, &next)) return false;\n\n    // free cluster\n    if (!fatPut(cluster, 0)) return false;\n\n    cluster = next;\n  } while (!isEOC(cluster));\n\n  return true;\n}\n//------------------------------------------------------------------------------\n/**\n * Initialize a FAT volume.\n *\n * \\param[in] dev The SD card where the volume is located.\n *\n * \\param[in] part The partition to be used.  Legal values for \\a part are\n * 1-4 to use the corresponding partition on a device formatted with\n * a MBR, Master Boot Record, or zero if the device is formatted as\n * a super floppy with the FAT boot sector in block zero.\n *\n * \\return The value one, true, is returned for success and\n * the value zero, false, is returned for failure.  Reasons for\n * failure include not finding a valid partition, not finding a valid\n * FAT file system in the specified partition or an I/O error.\n */\nuint8_t SdVolume::init(Sd2Card* dev, uint8_t part) {\n  uint32_t volumeStartBlock = 0;\n  sdCard_ = dev;\n  // if part == 0 assume super floppy with FAT boot sector in block zero\n  // if part > 0 assume mbr volume with partition table\n  if (part) {\n    if (part > 4)return false;\n    if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;\n    part_t* p = &cacheBuffer_.mbr.part[part-1];\n    if ((p->boot & 0X7F) !=0  ||\n      p->totalSectors < 100 ||\n      p->firstSector == 0) {\n      // not a valid partition\n      return false;\n    }\n    volumeStartBlock = p->firstSector;\n  }\n  if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;\n  bpb_t* bpb = &cacheBuffer_.fbs.bpb;\n  if (bpb->bytesPerSector != 512 ||\n    bpb->fatCount == 0 ||\n    bpb->reservedSectorCount == 0 ||\n    bpb->sectorsPerCluster == 0) {\n       // not valid FAT volume\n      return false;\n  }\n  fatCount_ = bpb->fatCount;\n  blocksPerCluster_ = bpb->sectorsPerCluster;\n\n  // determine shift that is same as multiply by blocksPerCluster_\n  clusterSizeShift_ = 0;\n  while (blocksPerCluster_ != (1 << clusterSizeShift_)) {\n    // error if not power of 2\n    if (clusterSizeShift_++ > 7) return false;\n  }\n  blocksPerFat_ = bpb->sectorsPerFat16 ?\n                    bpb->sectorsPerFat16 : bpb->sectorsPerFat32;\n\n  fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount;\n\n  // count for FAT16 zero for FAT32\n  rootDirEntryCount_ = bpb->rootDirEntryCount;\n\n  // directory start for FAT16 dataStart for FAT32\n  rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_;\n\n  // data start for FAT16 and FAT32\n  dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512);\n\n  // total blocks for FAT16 or FAT32\n  uint32_t totalBlocks = bpb->totalSectors16 ?\n                           bpb->totalSectors16 : bpb->totalSectors32;\n  // total data blocks\n  clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);\n\n  // divide by cluster size to get cluster count\n  clusterCount_ >>= clusterSizeShift_;\n\n  // FAT type is determined by cluster count\n  if (clusterCount_ < 4085) {\n    fatType_ = 12;\n  } else if (clusterCount_ < 65525) {\n    fatType_ = 16;\n  } else {\n    rootDirStart_ = bpb->fat32RootCluster;\n    fatType_ = 32;\n  }\n  return true;\n}\n"
  },
  {
    "path": "Sprinter/Sprinter.h",
    "content": "// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.\n// Licence: GPL\n\n//Check Version of Arduino and then include the right libraries\n#if defined(ARDUINO) && ARDUINO >= 100\n  #include \"Arduino.h\"\n#else\n  #include <WProgram.h>  \n#endif\n\n#include \"fastio.h\"\n\nextern \"C\" void __cxa_pure_virtual();\n\n#define  FORCE_INLINE __attribute__((always_inline)) inline\n\n#if X_ENABLE_PIN > -1\n#define  enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)\n#define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON)\n#else\n#define enable_x() ;\n#define disable_x() ;\n#endif\n#if Y_ENABLE_PIN > -1\n#define  enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)\n#define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON)\n#else\n#define enable_y() ;\n#define disable_y() ;\n#endif\n#if Z_ENABLE_PIN > -1\n#define  enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)\n#define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON)\n#else\n#define enable_z() ;\n#define disable_z() ;\n#endif\n#if E_ENABLE_PIN > -1\n#define  enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON)\n#define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON)\n#else\n#define enable_e() ;\n#define disable_e() ;\n#endif\n\n#define X_AXIS 0\n#define Y_AXIS 1\n#define Z_AXIS 2\n#define E_AXIS 3\n\n\n// This struct is used when buffering the setup for each linear movement \"nominal\" values are as specified in \n// the source g-code and may never actually be reached if acceleration management is active.\ntypedef struct {\n  // Fields used by the bresenham algorithm for tracing the line\n  long steps_x, steps_y, steps_z, steps_e;  // Step count along each axis\n\n  unsigned long step_event_count;                    // The number of step events required to complete this block\n  long accelerate_until;           // The index of the step event on which to stop acceleration\n  long decelerate_after;           // The index of the step event on which to start decelerating\n  long acceleration_rate;          // The acceleration rate used for acceleration calculation\n  unsigned char direction_bits;             // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)\n\n  #ifdef ADVANCE\n    long advance_rate;\n    volatile long initial_advance;\n    volatile long final_advance;\n    float advance;\n  #endif\n\n  // Fields used by the motion planner to manage acceleration\n//  float speed_x, speed_y, speed_z, speed_e;          // Nominal mm/minute for each axis\n  float nominal_speed;                               // The nominal speed for this block in mm/min  \n  float entry_speed;                                 // Entry speed at previous-current junction in mm/min\n  float max_entry_speed;                             // Maximum allowable junction entry speed in mm/min\n  float millimeters;                                 // The total travel of this block in mm\n  float acceleration;                                // acceleration mm/sec^2\n  unsigned char recalculate_flag;                    // Planner flag to recalculate trapezoids on entry junction\n  unsigned char nominal_length_flag;                 // Planner flag for nominal speed always reached\n\n\n  // Settings for the trapezoid generator\n  long nominal_rate;                                 // The nominal step rate for this block in step_events/sec \n  long initial_rate;                        // The jerk-adjusted step rate at start of block  \n  long final_rate;                          // The minimal rate at exit\n  long acceleration_st;                              // acceleration steps/sec^2\n  volatile char busy;\n} block_t;\n\n\nvoid FlushSerialRequestResend();\nvoid ClearToSend();\n\nvoid analogWrite_check(uint8_t check_pin, int val);\nvoid showString (PGM_P s);\n\nvoid manage_inactivity(byte debug);\n\nvoid get_command();\nvoid get_coordinates();\nvoid prepare_move();\nvoid prepare_arc_move(char isclockwise);\nFORCE_INLINE void process_commands();\n#ifdef USE_ARC_FUNCTION\n  FORCE_INLINE void get_arc_coordinates();\n#endif\n\nvoid kill(byte debug);\n\nvoid check_axes_activity();\nvoid plan_init();\nvoid st_init();\nvoid tp_init();\nvoid plan_buffer_line(float x, float y, float z, float e, float feed_rate);\nvoid plan_set_position(float x, float y, float z, float e);\nvoid st_wake_up();\nvoid st_synchronize();\nvoid st_set_position(const long &x, const long &y, const long &z, const long &e);\n\nvoid check_buffer_while_arc();\n\n#ifdef SDSUPPORT\nvoid print_disk_info(void);\n#endif //SDSUPPORT\n\n#if (MINIMUM_FAN_START_SPEED > 0)\nvoid manage_fan_start_speed(void);\n#endif\n\n#ifdef DEBUG\nvoid log_message(char*   message);\nvoid log_bool(char* message, bool value);\nvoid log_int(char* message, int value);\nvoid log_long(char* message, long value);\nvoid log_float(char* message, float value);\nvoid log_uint(char* message, unsigned int value);\nvoid log_ulong(char* message, unsigned long value);\n#endif\n"
  },
  {
    "path": "Sprinter/Sprinter.pde",
    "content": "/*\n Reprap firmware based on Sprinter\n Optimized for Sanguinololu 1.2 and above / RAMPS \n \n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n \n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n \n You should have received a copy of the GNU General Public License\n along with this program.  If not, see <http://www.gnu.org/licenses/>. */\n\n/*\n  This firmware is a mashup between Sprinter, grbl and parts from marlin.\n  (https://github.com/kliment/Sprinter)\n  \n  Changes by Doppler Michael (midopple)\n  \n  Planner is from Simen Svale Skogsrud\n  https://github.com/simen/grbl\n\n  Parts of Marlin Firmware from ErikZalm\n  https://github.com/ErikZalm/Marlin-non-gen6\n  \n  Sprinter Changelog\n  -  Look forward function --> calculate 16 Steps forward, get from Firmaware Marlin and Grbl\n  -  Stepper control with Timer 1 (Interrupt)\n  -  Extruder heating with PID use a Softpwm (Timer 2) with 500 hz to free Timer1 for Steppercontrol\n  -  command M220 Sxxx --> tune Printing speed online (+/- 50 %)\n  -  G2 / G3 command --> circle function\n  -  Baudrate set to 250 kbaud\n  -  Testet on Sanguinololu Board\n  -  M30 Command can delete files on SD Card\n  -  move string to flash to free RAM vor forward planner\n  -  M203 Temperature monitor for Repetier\n\n Version 1.3.04T\n  - Implement Plannercode from Marlin V1 big thanks to Erik\n  - Stepper interrupt with Step loops\n  - Stepperfrequency 30 Khz\n  - New Command\n    * M202 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec\n    * M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 \n    * M205 - advanced settings:  minimum travel speed S=while printing T=travel only,  X= maximum xy jerk, Z=maximum Z jerk, E = max E jerk\n  - Remove unused Variables\n  - Check Uart Puffer while circle processing (CMD: G2 / G3)\n  - Fast Xfer Function --> move Text to Flash\n  - Option to deactivate ARC (G2/G3) function (save flash)\n  - Removed modulo (%) operator, which uses an expensive divide\n\n Version 1.3.05T\n  - changed homing function to not conflict with min_software_endstops/max_software_endstops (thanks rGlory)\n  - Changed check in arc_func\n  - Corrected distance calculation. (thanks jv4779)\n  - MAX Feed Rate for Z-Axis reduced to 2 mm/s some Printers had problems with 4 mm/s\n  \n Version 1.3.06T\n - the microcontroller can store settings in the EEPROM\n - M500 - stores paramters in EEPROM\n - M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).\n - M502 - reverts to the default \"factory settings\". You still need to store them in EEPROM afterwards if you want to.\n - M503 - Print settings\n \n Version 1.3.07T\n - Optimize Variable Size (faster Code)\n - Remove unused Code from Interrupt --> faster ~ 22 us per step\n - Replace abs with fabs --> Faster and smaler\n - Add \"store_eeprom.cpp\" to makefile\n\n Version 1.3.08T\n - If a line starts with ';', it is ignored but comment_mode is reset.\n   A ';' inside a line ignores just the portion following the ';' character.\n   The beginning of the line is still interpreted.\n   \n - Same fix for SD Card, tested and work\n\n Version 1.3.09T\n - Move SLOWDOWN Function up\n \n Version 1.3.10T\n- Add info to GEN7 Pins\n- Update pins.h for gen7, working setup for 20MHz\n- calculate feedrate without extrude before planner block is set\n- New Board --> GEN7 @ 20 Mhz …\n- ENDSTOPS_ONLY_FOR_HOMING Option ignore Endstop always --> fault is cleared\n\n Version 1.3.11T\n- fix for broken include in store_eeprom.cpp  --> Thanks to kmeehl (issue #145)\n- Make fastio & Arduino pin numbering consistent for AT90USB128x. --> Thanks to lincomatic\n- Select Speedtable with F_CPU\n- Use same Values for Speedtables as Marlin \n\n Version 1.3.12T\n- Fixed arc offset.\n\n Version 1.3.13T\n- Extrudemultiply with code M221 Sxxx (S100 original Extrude value)\n- use Feedratefactor only when Extrude > 0\n- M106 / M107 can drive the FAN with PWM + Port check for not using Timer 1\n- Added M93 command. Sends current steps for all axis.\n- New Option --> FAN_SOFT_PWM, with this option the FAN PWM can use every digital I/O\n\n Version 1.3.14T\n- When endstop is hit count the virtual steps, so the print lose no position when endstop is hit\n\n Version 1.3.15T\n- M206 - set additional homing offset \n- Option for minimum FAN start speed --> #define MINIMUM_FAN_START_SPEED  50  (set it to zero to deactivate)\n  \n Version 1.3.16T\n- Extra Max Feedrate for Retract (MAX_RETRACT_FEEDRATE)\n\n Version 1.3.17T\n- M303 - PID relay autotune possible\n- G4 Wait until last move is done\n\n Version 1.3.18T\n- Problem with Thermistor 3 table when sensor is broken and temp is -20 °C\n\n Version 1.3.19T\n- Set maximum acceleration. If \"steps per unit\" is Change the acc were not recalculated\n- Extra Parameter for Max Extruder Jerk\n- New Parameter (max_e_jerk) in EEPROM --> Default settings after update !\n\n Version 1.3.20T\n- fix a few typos and correct english usage\n- reimplement homing routine as an inline function\n- refactor eeprom routines to make it possible to modify the value of a single parameter\n- calculate eeprom parameter addresses based on previous param address plus sizeof(type)\n- add 0 C point in Thermistortable 7\n\n Version 1.3.21T\n- M301 set PID Parameter, and Store to EEPROM\n- If no PID is used, deaktivate Variables for PID settings\n\n Version 1.3.22T\n- Error in JERK calculation after G92 command is send, make problems \n  with Z-Lift function in Slic3r\n- Add homing values can shown with M206 D\n\n*/\n\n#include <avr/pgmspace.h>\n#include <math.h>\n\n#include \"fastio.h\"\n#include \"Configuration.h\"\n#include \"pins.h\"\n#include \"Sprinter.h\"\n#include \"speed_lookuptable.h\"\n#include \"heater.h\"\n\n#ifdef USE_ARC_FUNCTION\n  #include \"arc_func.h\"\n#endif\n\n#ifdef SDSUPPORT\n  #include \"SdFat.h\"\n#endif\n\n#ifdef USE_EEPROM_SETTINGS\n  #include \"store_eeprom.h\"\n#endif\n\n#ifndef CRITICAL_SECTION_START\n#define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli()\n#define CRITICAL_SECTION_END    SREG = _sreg\n#endif //CRITICAL_SECTION_START\n\nvoid __cxa_pure_virtual(){};\n\n// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html\n// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes\n\n//Implemented Codes\n//-------------------\n// G0  -> G1\n// G1  - Coordinated Movement X Y Z E\n// G2  - CW ARC\n// G3  - CCW ARC\n// G4  - Dwell S<seconds> or P<milliseconds>\n// G28 - Home all Axis\n// G90 - Use Absolute Coordinates\n// G91 - Use Relative Coordinates\n// G92 - Set current position to cordinates given\n\n//RepRap M Codes\n// M104 - Set extruder target temp\n// M105 - Read current temp\n// M106 - Fan on\n// M107 - Fan off\n// M109 - Wait for extruder current temp to reach target temp.\n// M114 - Display current position\n\n//Custom M Codes\n// M20  - List SD card\n// M21  - Init SD card\n// M22  - Release SD card\n// M23  - Select SD file (M23 filename.g)\n// M24  - Start/resume SD print\n// M25  - Pause SD print\n// M26  - Set SD position in bytes (M26 S12345)\n// M27  - Report SD print status\n// M28  - Start SD write (M28 filename.g)\n// M29  - Stop SD write\n//   -  <filename> - Delete file on sd card\n// M42  - Set output on free pins, on a non pwm pin (over pin 13 on an arduino mega) use S255 to turn it on and S0 to turn it off. Use P to decide the pin (M42 P23 S255) would turn pin 23 on\n// M80  - Turn on Power Supply\n// M81  - Turn off Power Supply\n// M82  - Set E codes absolute (default)\n// M83  - Set E codes relative while in Absolute Coordinates (G90) mode\n// M84  - Disable steppers until next move, \n//        or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled.  S0 to disable the timeout.\n// M85  - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)\n// M92  - Set axis_steps_per_unit - same syntax as G92\n// M93  - Send axis_steps_per_unit\n// M115\t- Capabilities string\n// M119 - Show Endstopper State \n// M140 - Set bed target temp\n// M190 - Wait for bed current temp to reach target temp.\n// M201 - Set maximum acceleration in units/s^2 for print moves (M201 X1000 Y1000)\n// M202 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec\n// M203 - Set temperture monitor to Sx\n// M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) in mm/sec^2\n// M205 - advanced settings:  minimum travel speed S=while printing T=travel only,  X=maximum xy jerk, Z=maximum Z jerk\n// M206 - set additional homing offset\n\n// M220 - set speed factor override percentage S=factor in percent \n// M221 - set extruder multiply factor S100 --> original Extrude Speed \n\n// M301 - Set PID parameters P I and D\n// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)\n\n// M400 - Finish all moves\n\n// M500 - stores paramters in EEPROM\n// M501 - reads parameters from EEPROM (if you need to reset them after you changed them temporarily).\n// M502 - reverts to the default \"factory settings\". You still need to store them in EEPROM afterwards if you want to.\n// M503 - Print settings\n\n// Debug feature / Testing the PID for Hotend\n// M601 - Show Temp jitter from Extruder (min / max value from Hotend Temperature while printing)\n// M602 - Reset Temp jitter from Extruder (min / max val) --> Don't use it while Printing\n// M603 - Show Free Ram\n\n\n#define _VERSION_TEXT \"1.3.22T / 20.08.2012\"\n\n//Stepper Movement Variables\nchar axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};\nfloat axis_steps_per_unit[4] = _AXIS_STEP_PER_UNIT; \n\nfloat max_feedrate[4] = _MAX_FEEDRATE;\nfloat homing_feedrate[] = _HOMING_FEEDRATE;\nbool axis_relative_modes[] = _AXIS_RELATIVE_MODES;\n\nfloat move_acceleration = _ACCELERATION;         // Normal acceleration mm/s^2\nfloat retract_acceleration = _RETRACT_ACCELERATION; // Normal acceleration mm/s^2\nfloat max_xy_jerk = _MAX_XY_JERK;\nfloat max_z_jerk = _MAX_Z_JERK;\nfloat max_e_jerk = _MAX_E_JERK;\nunsigned long min_seg_time = _MIN_SEG_TIME;\n#ifdef PIDTEMP\n unsigned int PID_Kp = PID_PGAIN, PID_Ki = PID_IGAIN, PID_Kd = PID_DGAIN;\n#endif\n\nlong  max_acceleration_units_per_sq_second[4] = _MAX_ACCELERATION_UNITS_PER_SQ_SECOND; // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts\n\n//float max_start_speed_units_per_second[] = _MAX_START_SPEED_UNITS_PER_SECOND;\n//long  max_travel_acceleration_units_per_sq_second[] = _MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND; // X, Y, Z max acceleration in mm/s^2 for travel moves\n\nfloat mintravelfeedrate = DEFAULT_MINTRAVELFEEDRATE;\nfloat minimumfeedrate = DEFAULT_MINIMUMFEEDRATE;\n\nunsigned long axis_steps_per_sqr_second[NUM_AXIS];\nunsigned long plateau_steps;  \n\n//unsigned long axis_max_interval[NUM_AXIS];\n//unsigned long axis_travel_steps_per_sqr_second[NUM_AXIS];\n//unsigned long max_interval;\n//unsigned long steps_per_sqr_second;\n\n\n//adjustable feed factor for online tuning printer speed\nvolatile int feedmultiply=100; //100->original / 200 -> Factor 2 / 50 -> Factor 0.5\nint saved_feedmultiply;\nvolatile bool feedmultiplychanged=false;\nvolatile int extrudemultiply=100; //100->1 200->2\n\n//boolean acceleration_enabled = false, accelerating = false;\n//unsigned long interval;\nfloat destination[NUM_AXIS] = {0.0, 0.0, 0.0, 0.0};\nfloat current_position[NUM_AXIS] = {0.0, 0.0, 0.0, 0.0};\nfloat add_homing[3]={0,0,0};\n\nstatic unsigned short virtual_steps_x = 0;\nstatic unsigned short virtual_steps_y = 0;\nstatic unsigned short virtual_steps_z = 0;\n\nbool home_all_axis = true;\n//unsigned ?? ToDo: Check\nint feedrate = 1500, next_feedrate, saved_feedrate;\n\nlong gcode_N, gcode_LastN;\nbool relative_mode = false;  //Determines Absolute or Relative Coordinates\n\n//unsigned long steps_taken[NUM_AXIS];\n//long axis_interval[NUM_AXIS]; // for speed delay\n//float time_for_move;\n//bool relative_mode_e = false;  //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode.\n//long timediff = 0;\n\nbool is_homing = false;\n\n//experimental feedrate calc\n//float d = 0;\n//float axis_diff[NUM_AXIS] = {0, 0, 0, 0};\n\n\n#ifdef USE_ARC_FUNCTION\n//For arc center point coordinates, sent by commands G2/G3\nfloat offset[3] = {0.0, 0.0, 0.0};\n#endif\n\n#ifdef STEP_DELAY_RATIO\n  long long_step_delay_ratio = STEP_DELAY_RATIO * 100;\n#endif\n\n///oscillation reduction\n#ifdef RAPID_OSCILLATION_REDUCTION\n  float cumm_wait_time_in_dir[NUM_AXIS]={0.0,0.0,0.0,0.0};\n  bool prev_move_direction[NUM_AXIS]={1,1,1,1};\n  float osc_wait_remainder = 0.0;\n#endif\n\n#if (MINIMUM_FAN_START_SPEED > 0)\n  unsigned char fan_last_speed = 0;\n  unsigned char fan_org_start_speed = 0;\n  unsigned long previous_millis_fan_start = 0;\n#endif\n\n// comm variables and Commandbuffer\n// BUFSIZE is reduced from 8 to 6 to free more RAM for the PLANNER\n#define MAX_CMD_SIZE 96\n#define BUFSIZE 6 //8\nchar cmdbuffer[BUFSIZE][MAX_CMD_SIZE];\nbool fromsd[BUFSIZE];\n\n//Need 1kb Ram --> only work with Atmega1284\n#ifdef SD_FAST_XFER_AKTIV\n  char fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE + 1];\n  int lastxferchar;\n  long xferbytes;\n#endif\n\nunsigned char bufindr = 0;\nunsigned char bufindw = 0;\nunsigned char buflen = 0;\nchar serial_char;\nint serial_count = 0;\nboolean comment_mode = false;\nchar *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc\n\n//Send Temperature in °C to Host\nint hotendtC = 0, bedtempC = 0;\n       \n//Inactivity shutdown variables\nunsigned long previous_millis_cmd = 0;\nunsigned long max_inactive_time = 0;\nunsigned long stepper_inactive_time = 0;\n\n//Temp Monitor for repetier\nunsigned char manage_monitor = 255;\n\n\n//------------------------------------------------\n//Init the SD card \n//------------------------------------------------\n#ifdef SDSUPPORT\n  Sd2Card card;\n  SdVolume volume;\n  SdFile root;\n  SdFile file;\n  uint32_t filesize = 0;\n  uint32_t sdpos = 0;\n  bool sdmode = false;\n  bool sdactive = false;\n  bool savetosd = false;\n  int16_t read_char_int;\n  \n  void initsd()\n  {\n  sdactive = false;\n  #if SDSS >- 1\n    if(root.isOpen())\n        root.close();\n\n    if (!card.init(SPI_FULL_SPEED,SDSS)){\n        //if (!card.init(SPI_HALF_SPEED,SDSS))\n          showString(PSTR(\"SD init fail\\r\\n\"));\n    }\n    else if (!volume.init(&card))\n          showString(PSTR(\"volume.init failed\\r\\n\"));\n    else if (!root.openRoot(&volume)) \n          showString(PSTR(\"openRoot failed\\r\\n\"));\n    else{\n          sdactive = true;\n          print_disk_info();\n\n          #ifdef SDINITFILE\n            file.close();\n            if(file.open(&root, \"init.g\", O_READ)){\n                sdpos = 0;\n                filesize = file.fileSize();\n                sdmode = true;\n            }\n          #endif\n    }\n    \n  #endif\n  }\n  \n  #ifdef SD_FAST_XFER_AKTIV\n  \n  #ifdef PIDTEMP\n    extern volatile unsigned char g_heater_pwm_val;\n  #endif\n  \n  void fast_xfer()\n  {\n    char *pstr;\n    boolean done = false;\n    \n    //force heater pins low\n    if(HEATER_0_PIN > -1) WRITE(HEATER_0_PIN,LOW);\n    if(HEATER_1_PIN > -1) WRITE(HEATER_1_PIN,LOW);\n    \n  #ifdef PIDTEMP\n    g_heater_pwm_val = 0;\n  #endif\n    \n    lastxferchar = 1;\n    xferbytes = 0;\n    \n    pstr = strstr(strchr_pointer+4, \" \");\n    \n    if(pstr == NULL)\n    {\n      showString(PSTR(\"invalid command\\r\\n\"));\n      return;\n    }\n    \n    *pstr = '\\0';\n    \n    //check mode (currently only RAW is supported\n    if(strcmp(strchr_pointer+4, \"RAW\") != 0)\n    {\n      showString(PSTR(\"Invalid transfer codec\\r\\n\"));\n      return;\n    }else{\n      showString(PSTR(\"Selected codec: \"));\n      Serial.println(strchr_pointer+4);\n    }\n    \n    if (!file.open(&root, pstr+1, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))\n    {\n      showString(PSTR(\"open failed, File: \"));\n      Serial.print(pstr+1);\n      showString(PSTR(\".\"));\n    }else{\n      showString(PSTR(\"Writing to file: \"));\n      Serial.println(pstr+1);\n    }\n        \n    showString(PSTR(\"ok\\r\\n\"));\n    \n    //RAW transfer codec\n    //Host sends \\0 then up to SD_FAST_XFER_CHUNK_SIZE then \\0\n    //when host is done, it sends \\0\\0.\n    //if a non \\0 character is recieved at the beginning, host has failed somehow, kill the transfer.\n    \n    //read SD_FAST_XFER_CHUNK_SIZE bytes (or until \\0 is recieved)\n    while(!done)\n    {\n      while(!Serial.available())\n      {\n      }\n      if(Serial.read() != 0)\n      {\n        //host has failed, this isn't a RAW chunk, it's an actual command\n        file.sync();\n        file.close();\n        return;\n      }\n\n      for(int i=0;i<SD_FAST_XFER_CHUNK_SIZE+1;i++)\n      {\n        while(!Serial.available())\n        {\n        }\n        lastxferchar = Serial.read();\n        //buffer the data...\n        fastxferbuffer[i] = lastxferchar;\n        \n        xferbytes++;\n        \n        if(lastxferchar == 0)\n          break;\n      }\n      \n      if(fastxferbuffer[0] != 0)\n      {\n        fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE] = 0;\n        file.write(fastxferbuffer);\n        showString(PSTR(\"ok\\r\\n\"));\n      }else{\n        showString(PSTR(\"Wrote \"));\n        Serial.print(xferbytes);\n        showString(PSTR(\" bytes.\\r\\n\"));\n        done = true;\n      }\n    }\n\n    file.sync();\n    file.close();\n  }\n  #endif\n    \n\n void print_disk_info(void)\n {\n\n   // print the type of card\n    showString(PSTR(\"\\nCard type: \"));\n    switch(card.type()) \n    {\n      case SD_CARD_TYPE_SD1:\n        showString(PSTR(\"SD1\\r\\n\"));\n        break;\n      case SD_CARD_TYPE_SD2:\n        showString(PSTR(\"SD2\\r\\n\"));\n        break;\n      case SD_CARD_TYPE_SDHC:\n        showString(PSTR(\"SDHC\\r\\n\"));\n        break;\n      default:\n        showString(PSTR(\"Unknown\\r\\n\"));\n    }\n  \n    //uint64_t freeSpace = volume.clusterCount()*volume.blocksPerCluster()*512;\n    //uint64_t occupiedSpace = (card.cardSize()*512) - freeSpace;\n    // print the type and size of the first FAT-type volume\n    uint32_t volumesize;\n    showString(PSTR(\"\\nVolume type is FAT\"));\n    Serial.println(volume.fatType(), DEC);\n    \n    volumesize = volume.blocksPerCluster(); // clusters are collections of blocks\n    volumesize *= volume.clusterCount(); // we'll have a lot of clusters\n    volumesize *= 512; // SD card blocks are always 512 bytes\n    volumesize /= 1024; //kbytes\n    volumesize /= 1024; //Mbytes\n    showString(PSTR(\"Volume size (Mbytes): \"));\n    Serial.println(volumesize);\n   \n    // list all files in the card with date and size\n    //root.ls(LS_R | LS_DATE | LS_SIZE);\n }\n\n    \n    \n \n  \n  FORCE_INLINE void write_command(char *buf)\n  {\n      char* begin = buf;\n      char* npos = 0;\n      char* end = buf + strlen(buf) - 1;\n      \n      file.writeError = false;\n      \n      if((npos = strchr(buf, 'N')) != NULL)\n      {\n          begin = strchr(npos, ' ') + 1;\n          end = strchr(npos, '*') - 1;\n      }\n      \n      end[1] = '\\r';\n      end[2] = '\\n';\n      end[3] = '\\0';\n      \n      //Serial.println(begin);\n      file.write(begin);\n      \n      if (file.writeError)\n      {\n          showString(PSTR(\"error writing to file\\r\\n\"));\n      }\n  }\n\n#endif\n\n\nint FreeRam1(void)\n{\n  extern int  __bss_end;\n  extern int* __brkval;\n  int free_memory;\n\n  if (reinterpret_cast<int>(__brkval) == 0)\n  {\n    // if no heap use from end of bss section\n    free_memory = reinterpret_cast<int>(&free_memory) - reinterpret_cast<int>(&__bss_end);\n  }\n  else\n  {\n    // use from top of stack to heap\n    free_memory = reinterpret_cast<int>(&free_memory) - reinterpret_cast<int>(__brkval);\n  }\n  \n  return free_memory;\n}\n\n//------------------------------------------------\n//Function the check the Analog OUT pin for not using the Timer1\n//------------------------------------------------\nvoid analogWrite_check(uint8_t check_pin, int val)\n{\n  #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) \n  //Atmega168/328 can't use OCR1A and OCR1B\n  //These are pins PB1/PB2 or on Arduino D9/D10\n    if((check_pin != 9) && (check_pin != 10))\n    {\n        analogWrite(check_pin, val);\n    }\n  #endif\n  \n  #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) \n  //Atmega664P/1284P can't use OCR1A and OCR1B\n  //These are pins PD4/PD5 or on Arduino D12/D13\n    if((check_pin != 12) && (check_pin != 13))\n    {\n        analogWrite(check_pin, val);\n    }\n  #endif\n\n  #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \n  //Atmega1280/2560 can't use OCR1A, OCR1B and OCR1C\n  //These are pins PB5,PB6,PB7 or on Arduino D11,D12 and D13\n    if((check_pin != 11) && (check_pin != 12) && (check_pin != 13))\n    {\n        analogWrite(check_pin, val);\n    }\n  #endif  \n}\n\n//------------------------------------------------\n//Print a String from Flash to Serial (save RAM)\n//------------------------------------------------\nvoid showString (PGM_P s) \n{\n  char c;\n  \n  while ((c = pgm_read_byte(s++)) != 0)\n    Serial.print(c);\n}\n\n\n//------------------------------------------------\n// Init \n//------------------------------------------------\nvoid setup()\n{ \n  \n  Serial.begin(BAUDRATE);\n  showString(PSTR(\"Sprinter\\r\\n\"));\n  showString(PSTR(_VERSION_TEXT));\n  showString(PSTR(\"\\r\\n\"));\n  showString(PSTR(\"start\\r\\n\"));\n\n  for(int i = 0; i < BUFSIZE; i++)\n  {\n      fromsd[i] = false;\n  }\n  \n\n  \n  //Initialize Dir Pins\n  #if X_DIR_PIN > -1\n    SET_OUTPUT(X_DIR_PIN);\n  #endif\n  #if Y_DIR_PIN > -1 \n    SET_OUTPUT(Y_DIR_PIN);\n  #endif\n  #if Z_DIR_PIN > -1 \n    SET_OUTPUT(Z_DIR_PIN);\n  #endif\n  #if E_DIR_PIN > -1 \n    SET_OUTPUT(E_DIR_PIN);\n  #endif\n  \n  //Initialize Enable Pins - steppers default to disabled.\n  \n  #if (X_ENABLE_PIN > -1)\n    SET_OUTPUT(X_ENABLE_PIN);\n  if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);\n  #endif\n  #if (Y_ENABLE_PIN > -1)\n    SET_OUTPUT(Y_ENABLE_PIN);\n  if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);\n  #endif\n  #if (Z_ENABLE_PIN > -1)\n    SET_OUTPUT(Z_ENABLE_PIN);\n  if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH);\n  #endif\n  #if (E_ENABLE_PIN > -1)\n    SET_OUTPUT(E_ENABLE_PIN);\n  if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH);\n  #endif\n\n  #ifdef CONTROLLERFAN_PIN\n    SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan\n  #endif\n  \n  #ifdef EXTRUDERFAN_PIN\n    SET_OUTPUT(EXTRUDERFAN_PIN); //Set pin used for extruder cooling fan\n  #endif\n  \n  //endstops and pullups\n  #ifdef ENDSTOPPULLUPS\n  #if X_MIN_PIN > -1\n    SET_INPUT(X_MIN_PIN); \n    WRITE(X_MIN_PIN,HIGH);\n  #endif\n  #if X_MAX_PIN > -1\n    SET_INPUT(X_MAX_PIN); \n    WRITE(X_MAX_PIN,HIGH);\n  #endif\n  #if Y_MIN_PIN > -1\n    SET_INPUT(Y_MIN_PIN); \n    WRITE(Y_MIN_PIN,HIGH);\n  #endif\n  #if Y_MAX_PIN > -1\n    SET_INPUT(Y_MAX_PIN); \n    WRITE(Y_MAX_PIN,HIGH);\n  #endif\n  #if Z_MIN_PIN > -1\n    SET_INPUT(Z_MIN_PIN); \n    WRITE(Z_MIN_PIN,HIGH);\n  #endif\n  #if Z_MAX_PIN > -1\n    SET_INPUT(Z_MAX_PIN); \n    WRITE(Z_MAX_PIN,HIGH);\n  #endif\n  #else\n  #if X_MIN_PIN > -1\n    SET_INPUT(X_MIN_PIN); \n  #endif\n  #if X_MAX_PIN > -1\n    SET_INPUT(X_MAX_PIN); \n  #endif\n  #if Y_MIN_PIN > -1\n    SET_INPUT(Y_MIN_PIN); \n  #endif\n  #if Y_MAX_PIN > -1\n    SET_INPUT(Y_MAX_PIN); \n  #endif\n  #if Z_MIN_PIN > -1\n    SET_INPUT(Z_MIN_PIN); \n  #endif\n  #if Z_MAX_PIN > -1\n    SET_INPUT(Z_MAX_PIN); \n  #endif\n  #endif\n  \n  #if (HEATER_0_PIN > -1) \n    SET_OUTPUT(HEATER_0_PIN);\n    WRITE(HEATER_0_PIN,LOW);\n  #endif  \n  #if (HEATER_1_PIN > -1) \n    SET_OUTPUT(HEATER_1_PIN);\n    WRITE(HEATER_1_PIN,LOW);\n  #endif  \n  \n  //Initialize Fan Pin\n  #if (FAN_PIN > -1) \n    SET_OUTPUT(FAN_PIN);\n  #endif\n  \n  //Initialize Alarm Pin\n  #if (ALARM_PIN > -1) \n    SET_OUTPUT(ALARM_PIN);\n    WRITE(ALARM_PIN,LOW);\n  #endif\n\n  //Initialize LED Pin\n  #if (LED_PIN > -1) \n    SET_OUTPUT(LED_PIN);\n    WRITE(LED_PIN,LOW);\n  #endif \n  \n//Initialize Step Pins\n  #if (X_STEP_PIN > -1) \n    SET_OUTPUT(X_STEP_PIN);\n  #endif  \n  #if (Y_STEP_PIN > -1) \n    SET_OUTPUT(Y_STEP_PIN);\n  #endif  \n  #if (Z_STEP_PIN > -1) \n    SET_OUTPUT(Z_STEP_PIN);\n  #endif  \n  #if (E_STEP_PIN > -1) \n    SET_OUTPUT(E_STEP_PIN);\n  #endif  \n\n  \n\n//  for(int i=0; i < NUM_AXIS; i++){\n//      axis_max_interval[i] = 100000000.0 / (max_start_speed_units_per_second[i] * axis_steps_per_unit[i]);\n//      axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];\n//      axis_travel_steps_per_sqr_second[i] = max_travel_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];\n//  }\n    \n#ifdef HEATER_USES_MAX6675\n  SET_OUTPUT(SCK_PIN);\n  WRITE(SCK_PIN,0);\n  \n  SET_OUTPUT(MOSI_PIN);\n  WRITE(MOSI_PIN,1);\n  \n  SET_INPUT(MISO_PIN);\n  WRITE(MISO_PIN,1);\n  \n  SET_OUTPUT(MAX6675_SS);\n  WRITE(MAX6675_SS,1);\n#endif  \n \n#ifdef SDSUPPORT\n\n  //power to SD reader\n  #if SDPOWER > -1\n    SET_OUTPUT(SDPOWER); \n    WRITE(SDPOWER,HIGH);\n  #endif\n  \n  showString(PSTR(\"SD Start\\r\\n\"));\n  initsd();\n\n#endif\n\n  #if defined(PID_SOFT_PWM) || (defined(FAN_SOFT_PWM) && (FAN_PIN > -1))\n  showString(PSTR(\"Soft PWM Init\\r\\n\"));\n  init_Timer2_softpwm();\n  #endif\n  \n  showString(PSTR(\"Planner Init\\r\\n\"));\n  plan_init();  // Initialize planner;\n\n  showString(PSTR(\"Stepper Timer init\\r\\n\"));\n  st_init();    // Initialize stepper\n\n  #ifdef USE_EEPROM_SETTINGS\n  //first Value --> Init with default\n  //second value --> Print settings to UART\n  EEPROM_RetrieveSettings(false,false);\n  #endif\n  \n  #ifdef PIDTEMP\n  updatePID();\n  #endif\n\n  //Free Ram\n  showString(PSTR(\"Free Ram: \"));\n  Serial.println(FreeRam1());\n  \n  //Planner Buffer Size\n  showString(PSTR(\"Plan Buffer Size:\"));\n  Serial.print((int)sizeof(block_t)*BLOCK_BUFFER_SIZE);\n  showString(PSTR(\" / \"));\n  Serial.println(BLOCK_BUFFER_SIZE);\n  \n  for(int8_t i=0; i < NUM_AXIS; i++)\n  {\n    axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];\n  }\n\n}\n\n\n\n//------------------------------------------------\n//MAIN LOOP\n//------------------------------------------------\nvoid loop()\n{\n  if(buflen < (BUFSIZE-1))\n    get_command();\n  \n  if(buflen)\n  {\n#ifdef SDSUPPORT\n    if(savetosd)\n    {\n        if(strstr(cmdbuffer[bufindr],\"M29\") == NULL)\n        {\n            write_command(cmdbuffer[bufindr]);\n            showString(PSTR(\"ok\\r\\n\"));\n        }\n        else\n        {\n            file.sync();\n            file.close();\n            savetosd = false;\n            showString(PSTR(\"Done saving file.\\r\\n\"));\n        }\n    }\n    else\n    {\n        process_commands();\n    }\n#else\n    process_commands();\n#endif\n\n    buflen = (buflen-1);\n    //bufindr = (bufindr + 1)%BUFSIZE;\n    //Removed modulo (%) operator, which uses an expensive divide and multiplication\n    bufindr++;\n    if(bufindr == BUFSIZE) bufindr = 0;\n  }\n  \n  //check heater every n milliseconds\n  manage_heater();\n  manage_inactivity(1);\n  #if (MINIMUM_FAN_START_SPEED > 0)\n    manage_fan_start_speed();\n  #endif\n  \n}\n\n//------------------------------------------------\n//Check Uart buffer while arc function ist calc a circle\n//------------------------------------------------\n\nvoid check_buffer_while_arc()\n{\n  if(buflen < (BUFSIZE-1))\n  {\n    get_command();\n  }\n}\n\n//------------------------------------------------\n//READ COMMAND FROM UART\n//------------------------------------------------\nvoid get_command() \n{ \n  while( Serial.available() > 0 && buflen < BUFSIZE)\n  {\n    serial_char = Serial.read();\n    if(serial_char == '\\n' || serial_char == '\\r' || (serial_char == ':' && comment_mode == false) || serial_count >= (MAX_CMD_SIZE - 1) ) \n    {\n      if(!serial_count) { //if empty line\n        comment_mode = false; // for new command\n        return;\n      }\n      cmdbuffer[bufindw][serial_count] = 0; //terminate string\n\n        fromsd[bufindw] = false;\n        if(strstr(cmdbuffer[bufindw], \"N\") != NULL)\n        {\n          strchr_pointer = strchr(cmdbuffer[bufindw], 'N');\n          gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));\n          if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], \"M110\") == NULL) )\n          {\n            showString(PSTR(\"Serial Error: Line Number is not Last Line Number+1, Last Line:\"));\n            Serial.println(gcode_LastN);\n            //Serial.println(gcode_N);\n            FlushSerialRequestResend();\n            serial_count = 0;\n            return;\n          }\n    \n          if(strstr(cmdbuffer[bufindw], \"*\") != NULL)\n          {\n            byte checksum = 0;\n            byte count = 0;\n            while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++];\n            strchr_pointer = strchr(cmdbuffer[bufindw], '*');\n  \n            if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum)\n            {\n              showString(PSTR(\"Error: checksum mismatch, Last Line:\"));\n              Serial.println(gcode_LastN);\n              FlushSerialRequestResend();\n              serial_count = 0;\n              return;\n            }\n            //if no errors, continue parsing\n          }\n          else \n          {\n            showString(PSTR(\"Error: No Checksum with line number, Last Line:\"));\n            Serial.println(gcode_LastN);\n            FlushSerialRequestResend();\n            serial_count = 0;\n            return;\n          }\n    \n          gcode_LastN = gcode_N;\n          //if no errors, continue parsing\n        }\n        else  // if we don't receive 'N' but still see '*'\n        {\n          if((strstr(cmdbuffer[bufindw], \"*\") != NULL))\n          {\n            showString(PSTR(\"Error: No Line Number with checksum, Last Line:\"));\n            Serial.println(gcode_LastN);\n            serial_count = 0;\n            return;\n          }\n        }\n        \n\tif((strstr(cmdbuffer[bufindw], \"G\") != NULL))\n        {\n          strchr_pointer = strchr(cmdbuffer[bufindw], 'G');\n          switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL))))\n          {\n            case 0:\n            case 1:\n            #ifdef USE_ARC_FUNCTION\n            case 2:  //G2\n            case 3:  //G3 arc func\n            #endif\n              #ifdef SDSUPPORT\n              if(savetosd)\n                break;\n              #endif\n              showString(PSTR(\"ok\\r\\n\"));\n              //Serial.println(\"ok\"); \n            break;\n            \n            default:\n            break;\n          }\n        }\n        //Removed modulo (%) operator, which uses an expensive divide and multiplication\n        //bufindw = (bufindw + 1)%BUFSIZE;\n        bufindw++;\n        if(bufindw == BUFSIZE) bufindw = 0;\n        buflen += 1;\n\n      comment_mode = false; //for new command\n      serial_count = 0; //clear buffer\n    }\n    else\n    {\n      if(serial_char == ';') comment_mode = true;\n      if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;\n    }\n  }\n#ifdef SDSUPPORT\n  if(!sdmode || serial_count!=0)\n  {\n    return;\n  }\n  while( filesize > sdpos && buflen < BUFSIZE)\n  {\n    serial_char = file.read();\n    read_char_int = (int)serial_char;\n    \n    if(serial_char == '\\n' || serial_char == '\\r' || (serial_char == ':' && comment_mode == false) || serial_count >= (MAX_CMD_SIZE - 1) || read_char_int == -1) \n    {\n        sdpos = file.curPosition();\n        if(sdpos >= filesize)\n        {\n            sdmode = false;\n            showString(PSTR(\"Done printing file\\r\\n\"));\n        }\n       \n        if(!serial_count) { //if empty line\n          comment_mode = false; // for new command\n          return;\n        }\n        \n        cmdbuffer[bufindw][serial_count] = 0; //terminate string\n\n          fromsd[bufindw] = true;\n          buflen += 1;\n          //Removed modulo (%) operator, which uses an expensive divide and multiplication\t\n          //bufindw = (bufindw + 1)%BUFSIZE;\n          bufindw++;\n          if(bufindw == BUFSIZE) bufindw = 0;\n\n        comment_mode = false; //for new command\n        serial_count = 0; //clear buffer\n    }\n    else\n    {\n      if(serial_char == ';') comment_mode = true;\n      if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;\n    }\n  }\n#endif\n\n}\n\nstatic bool check_endstops = true;\n\nvoid enable_endstops(bool check)\n{\n  check_endstops = check;\n}\n\nFORCE_INLINE float code_value() { return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); }\nFORCE_INLINE long code_value_long() { return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); }\nFORCE_INLINE bool code_seen(char code_string[]) { return (strstr(cmdbuffer[bufindr], code_string) != NULL); }  //Return True if the string was found\n\nFORCE_INLINE bool code_seen(char code)\n{\n  strchr_pointer = strchr(cmdbuffer[bufindr], code);\n  return (strchr_pointer != NULL);  //Return True if a character was found\n}\n\nFORCE_INLINE void homing_routine(char axis)\n{\n  int min_pin, max_pin, home_dir, max_length, home_bounce;\n\n  switch(axis){\n    case X_AXIS:\n      min_pin = X_MIN_PIN;\n      max_pin = X_MAX_PIN;\n      home_dir = X_HOME_DIR;\n      max_length = X_MAX_LENGTH;\n      home_bounce = 10;\n      break;\n    case Y_AXIS:\n      min_pin = Y_MIN_PIN;\n      max_pin = Y_MAX_PIN;\n      home_dir = Y_HOME_DIR;\n      max_length = Y_MAX_LENGTH;\n      home_bounce = 10;\n      break;\n    case Z_AXIS:\n      min_pin = Z_MIN_PIN;\n      max_pin = Z_MAX_PIN;\n      home_dir = Z_HOME_DIR;\n      max_length = Z_MAX_LENGTH;\n      home_bounce = 4;\n      break;\n    default:\n      //never reached\n      break;\n  }\n\n  if ((min_pin > -1 && home_dir==-1) || (max_pin > -1 && home_dir==1))\n  {\n    current_position[axis] = -1.5 * max_length * home_dir;\n    plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\n    destination[axis] = 0;\n    feedrate = homing_feedrate[axis];\n    prepare_move();\n    st_synchronize();\n\n    current_position[axis] = home_bounce/2 * home_dir;\n    plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\n    destination[axis] = 0;\n    prepare_move();\n    st_synchronize();\n\n    current_position[axis] = -home_bounce * home_dir;\n    plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\n    destination[axis] = 0;\n    feedrate = homing_feedrate[axis]/2;\n    prepare_move();\n    st_synchronize();\n\n    current_position[axis] = (home_dir == -1) ? 0 : max_length;\n    current_position[axis] += add_homing[axis];\n    plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\n    destination[axis] = current_position[axis];\n    feedrate = 0;\n  }\n}\n\n//------------------------------------------------\n// CHECK COMMAND AND CONVERT VALUES\n//------------------------------------------------\nFORCE_INLINE void process_commands()\n{\n  unsigned long codenum; //throw away variable\n  char *starpos = NULL;\n\n  if(code_seen('G'))\n  {\n    switch((int)code_value())\n    {\n      case 0: // G0 -> G1\n      case 1: // G1\n        #if (defined DISABLE_CHECK_DURING_ACC) || (defined DISABLE_CHECK_DURING_MOVE) || (defined DISABLE_CHECK_DURING_TRAVEL)\n          manage_heater();\n        #endif\n        get_coordinates(); // For X Y Z E F\n        prepare_move();\n        previous_millis_cmd = millis();\n        //ClearToSend();\n        return;\n        //break;\n      #ifdef USE_ARC_FUNCTION\n      case 2: // G2  - CW ARC\n        get_arc_coordinates();\n        prepare_arc_move(true);\n        previous_millis_cmd = millis();\n        //break;\n        return;\n      case 3: // G3  - CCW ARC\n        get_arc_coordinates();\n        prepare_arc_move(false);\n        previous_millis_cmd = millis();\n        //break;\n        return;  \n      #endif  \n      case 4: // G4 dwell\n        codenum = 0;\n        if(code_seen('P')) codenum = code_value(); // milliseconds to wait\n        if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait\n        codenum += millis();  // keep track of when we started waiting\n        st_synchronize();  // wait for all movements to finish\n        while(millis()  < codenum ){\n          manage_heater();\n        }\n        break;\n      case 28: //G28 Home all Axis one at a time\n        saved_feedrate = feedrate;\n        saved_feedmultiply = feedmultiply;\n        previous_millis_cmd = millis();\n        \n        feedmultiply = 100;    \n      \n        enable_endstops(true);\n      \n        for(int i=0; i < NUM_AXIS; i++) \n        {\n          destination[i] = current_position[i];\n        }\n        feedrate = 0;\n        is_homing = true;\n\n        home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2])));\n\n        if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) \n          homing_routine(X_AXIS);\n\n        if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) \n          homing_routine(Y_AXIS);\n\n        if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) \n          homing_routine(Z_AXIS);\n        \n        #ifdef ENDSTOPS_ONLY_FOR_HOMING\n            enable_endstops(false);\n      \t#endif\n      \n        is_homing = false;\n        feedrate = saved_feedrate;\n        feedmultiply = saved_feedmultiply;\n      \n        previous_millis_cmd = millis();\n        break;\n      case 90: // G90\n        relative_mode = false;\n        break;\n      case 91: // G91\n        relative_mode = true;\n        break;\n      case 92: // G92\n        if(!code_seen(axis_codes[E_AXIS])) \n          st_synchronize();\n          \n        for(int i=0; i < NUM_AXIS; i++)\n        {\n          if(code_seen(axis_codes[i])) current_position[i] = code_value();  \n        }\n        plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\n        break;\n      default:\n            #ifdef SEND_WRONG_CMD_INFO\n              showString(PSTR(\"Unknown G-COM:\"));\n              Serial.println(cmdbuffer[bufindr]);\n            #endif\n      break;\n    }\n  }\n\n  else if(code_seen('M'))\n  {\n    \n    switch( (int)code_value() ) \n    {\n#ifdef SDSUPPORT\n        \n      case 20: // M20 - list SD card\n        showString(PSTR(\"Begin file list\\r\\n\"));\n        root.ls();\n        showString(PSTR(\"End file list\\r\\n\"));\n        break;\n      case 21: // M21 - init SD card\n        sdmode = false;\n        initsd();\n        break;\n      case 22: //M22 - release SD card\n        sdmode = false;\n        sdactive = false;\n        break;\n      case 23: //M23 - Select file\n        if(sdactive)\n        {\n            sdmode = false;\n            file.close();\n            starpos = (strchr(strchr_pointer + 4,'*'));\n            \n            if(starpos!=NULL)\n                *(starpos-1)='\\0';\n            \n            if (file.open(&root, strchr_pointer + 4, O_READ)) \n            {\n                showString(PSTR(\"File opened:\"));\n                Serial.print(strchr_pointer + 4);\n                showString(PSTR(\" Size:\"));\n                Serial.println(file.fileSize());\n                sdpos = 0;\n                filesize = file.fileSize();\n                showString(PSTR(\"File selected\\r\\n\"));\n            }\n            else\n            {\n                showString(PSTR(\"file.open failed\\r\\n\"));\n            }\n        }\n        break;\n      case 24: //M24 - Start SD print\n        if(sdactive)\n        {\n            sdmode = true;\n        }\n        break;\n      case 25: //M25 - Pause SD print\n        if(sdmode)\n        {\n            sdmode = false;\n        }\n        break;\n      case 26: //M26 - Set SD index\n        if(sdactive && code_seen('S'))\n        {\n            sdpos = code_value_long();\n            file.seekSet(sdpos);\n        }\n        break;\n      case 27: //M27 - Get SD status\n        if(sdactive)\n        {\n            showString(PSTR(\"SD printing byte \"));\n            Serial.print(sdpos);\n            showString(PSTR(\"/\"));\n            Serial.println(filesize);\n        }\n        else\n        {\n            showString(PSTR(\"Not SD printing\\r\\n\"));\n        }\n        break;\n      case 28: //M28 - Start SD write\n        if(sdactive)\n        {\n          char* npos = 0;\n            file.close();\n            sdmode = false;\n            starpos = (strchr(strchr_pointer + 4,'*'));\n            if(starpos != NULL)\n            {\n              npos = strchr(cmdbuffer[bufindr], 'N');\n              strchr_pointer = strchr(npos,' ') + 1;\n              *(starpos-1) = '\\0';\n            }\n            \n            if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))\n            {\n              showString(PSTR(\"open failed, File: \"));\n              Serial.print(strchr_pointer + 4);\n              showString(PSTR(\".\"));\n            }\n            else\n            {\n              savetosd = true;\n              showString(PSTR(\"Writing to file: \"));\n              Serial.println(strchr_pointer + 4);\n            }\n        }\n        break;\n      case 29: //M29 - Stop SD write\n        //processed in write to file routine above\n        //savetosd = false;\n        break;\n  #ifndef SD_FAST_XFER_AKTIV\n      case 30: // M30 filename - Delete file\n        if(sdactive)\n        {\n            sdmode = false;\n            file.close();\n            \n            starpos = (strchr(strchr_pointer + 4,'*'));\n            \n            if(starpos!=NULL)\n                *(starpos-1)='\\0';\n            \n            if(file.remove(&root, strchr_pointer + 4))\n            {\n              showString(PSTR(\"File deleted\\r\\n\"));\n            }\n            else\n            {\n              showString(PSTR(\"Deletion failed\\r\\n\"));\n            }\n        }\n        break;  \n   #else     \n      case 30: //M30 - fast SD transfer\n        fast_xfer();\n        break;\n      case 31: //M31 - high speed xfer capabilities\n        showString(PSTR(\"RAW:\"));\n        Serial.println(SD_FAST_XFER_CHUNK_SIZE);\n        break;\n   #endif\n        \n#endif\n      case 42: //M42 -Change pin status via gcode\n        if (code_seen('S'))\n        {\n#ifdef CHAIN_OF_COMMAND\n          st_synchronize(); // wait for all movements to finish\n#endif\n          int pin_status = code_value();\n          if (code_seen('P') && pin_status >= 0 && pin_status <= 255)\n          {\n            int pin_number = code_value();\n            for(int i = 0; i < sizeof(sensitive_pins) / sizeof(int); i++)\n            {\n              if (sensitive_pins[i] == pin_number)\n              {\n                pin_number = -1;\n                break;\n              }\n            }\n            \n            if (pin_number > -1)\n            {              \n              pinMode(pin_number, OUTPUT);\n              digitalWrite(pin_number, pin_status);\n              //analogWrite(pin_number, pin_status);\n            }\n          }\n        }\n        break;\n      case 104: // M104\n#ifdef CHAIN_OF_COMMAND\n          st_synchronize(); // wait for all movements to finish\n#endif\n        if (code_seen('S')) target_raw = temp2analogh(target_temp = code_value());\n        #ifdef WATCHPERIOD\n            if(target_raw > current_raw)\n            {\n                watchmillis = max(1,millis());\n                watch_raw = current_raw;\n            }\n            else\n            {\n                watchmillis = 0;\n            }\n        #endif\n        break;\n      case 140: // M140 set bed temp\n#ifdef CHAIN_OF_COMMAND\n          st_synchronize(); // wait for all movements to finish\n#endif\n        #if TEMP_1_PIN > -1 || defined BED_USES_AD595\n            if (code_seen('S')) target_bed_raw = temp2analogBed(code_value());\n        #endif\n        break;\n      case 105: // M105\n        #if (TEMP_0_PIN > -1) || defined (HEATER_USES_MAX6675)|| defined HEATER_USES_AD595\n          hotendtC = analog2temp(current_raw);\n        #endif\n        #if TEMP_1_PIN > -1 || defined BED_USES_AD595\n          bedtempC = analog2tempBed(current_bed_raw);\n        #endif\n        #if (TEMP_0_PIN > -1) || defined (HEATER_USES_MAX6675) || defined HEATER_USES_AD595\n            showString(PSTR(\"ok T:\"));\n            Serial.print(hotendtC); \n          #ifdef PIDTEMP\n            showString(PSTR(\" @:\"));\n            Serial.print(heater_duty); \n            /*\n            showString(PSTR(\",P:\"));\n            Serial.print(pTerm);\n            showString(PSTR(\",I:\"));\n            Serial.print(iTerm);\n            showString(PSTR(\",D:\"));\n            Serial.print(dTerm);\n            */\n            #ifdef AUTOTEMP\n              showString(PSTR(\",AU:\"));\n              Serial.print(autotemp_setpoint);\n            #endif\n          #endif\n          #if TEMP_1_PIN > -1 || defined BED_USES_AD595\n            showString(PSTR(\" B:\"));\n            Serial.println(bedtempC); \n          #else\n            Serial.println();\n          #endif\n        #else\n          #error No temperature source available\n        #endif\n        return;\n        //break;\n      case 109: { // M109 - Wait for extruder heater to reach target.\n#ifdef CHAIN_OF_COMMAND\n          st_synchronize(); // wait for all movements to finish\n#endif\n        if (code_seen('S')) target_raw = temp2analogh(target_temp = code_value());\n        #ifdef WATCHPERIOD\n            if(target_raw>current_raw)\n            {\n                watchmillis = max(1,millis());\n                watch_raw = current_raw;\n            }\n            else\n            {\n                watchmillis = 0;\n            }\n        #endif\n        codenum = millis(); \n        \n        /* See if we are heating up or cooling down */\n        bool target_direction = (current_raw < target_raw);  // true if heating, false if cooling\n        \n      #ifdef TEMP_RESIDENCY_TIME\n        long residencyStart;\n        residencyStart = -1;\n        /* continue to loop until we have reached the target temp   \n           _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */\n        while( (target_direction ? (current_raw < target_raw) : (current_raw > target_raw))\n            || (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) {\n      #else\n        while ( target_direction ? (current_raw < target_raw) : (current_raw > target_raw) ) {\n      #endif\n          if( (millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up/cooling down\n          {\n            showString(PSTR(\"T:\"));\n            Serial.println( analog2temp(current_raw) );\n            codenum = millis();\n          }\n          manage_heater();\n          #if (MINIMUM_FAN_START_SPEED > 0)\n            manage_fan_start_speed();\n          #endif\n          #ifdef TEMP_RESIDENCY_TIME\n            /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time\n               or when current temp falls outside the hysteresis after target temp was reached */\n            if (   (residencyStart == -1 &&  target_direction && current_raw >= target_raw)\n                || (residencyStart == -1 && !target_direction && current_raw <= target_raw)\n                || (residencyStart > -1 && labs(analog2temp(current_raw) - analog2temp(target_raw)) > TEMP_HYSTERESIS) ) {\n              residencyStart = millis();\n            }\n          #endif\n\t    }\n      }\n      break;\n      case 190: // M190 - Wait for bed heater to reach target temperature.\n#ifdef CHAIN_OF_COMMAND\n          st_synchronize(); // wait for all movements to finish\n#endif\n      #if TEMP_1_PIN > -1\n        if (code_seen('S')) target_bed_raw = temp2analogBed(code_value());\n        codenum = millis(); \n        while(current_bed_raw < target_bed_raw) \n        {\n          if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.\n          {\n            hotendtC=analog2temp(current_raw);\n            showString(PSTR(\"T:\"));\n            Serial.print( hotendtC );\n            showString(PSTR(\" B:\"));\n            Serial.println( analog2tempBed(current_bed_raw) ); \n            codenum = millis(); \n          }\n          manage_heater();\n          #if (MINIMUM_FAN_START_SPEED > 0)\n            manage_fan_start_speed();\n          #endif\n        }\n      #endif\n      break;\n      #if FAN_PIN > -1\n      case 106: //M106 Fan On\n#ifdef CHAIN_OF_COMMAND\n          st_synchronize(); // wait for all movements to finish\n#endif\n        if (code_seen('S'))\n        {\n            unsigned char l_fan_code_val = constrain(code_value(),0,255);\n            \n            #if (MINIMUM_FAN_START_SPEED > 0)\n              if(l_fan_code_val > 0 && fan_last_speed == 0)\n              {\n                 if(l_fan_code_val < MINIMUM_FAN_START_SPEED)\n                 {\n                   fan_org_start_speed = l_fan_code_val;\n                   l_fan_code_val = MINIMUM_FAN_START_SPEED;\n                   previous_millis_fan_start = millis();\n                 }\n                 fan_last_speed = l_fan_code_val;  \n              }  \n              else\n              {\n                fan_last_speed = l_fan_code_val;\n                fan_org_start_speed = 0;\n              }  \n            #endif\n          \n            #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n              g_fan_pwm_val = l_fan_code_val;\n            #else\n              WRITE(FAN_PIN, HIGH);\n              analogWrite_check(FAN_PIN, l_fan_code_val;\n            #endif\n            \n        }\n        else \n        {\n            #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n              g_fan_pwm_val = 255;\n            #else\n              WRITE(FAN_PIN, HIGH);\n              analogWrite_check(FAN_PIN, 255 );\n            #endif\n        }\n        break;\n      case 107: //M107 Fan Off\n          #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n            g_fan_pwm_val = 0;\n          #else\n            analogWrite_check(FAN_PIN, 0);\n            WRITE(FAN_PIN, LOW);\n          #endif\n        break;\n      #endif\n      #if (PS_ON_PIN > -1)\n      case 80: // M81 - ATX Power On\n        SET_OUTPUT(PS_ON_PIN); //GND\n        break;\n      case 81: // M81 - ATX Power Off\n#ifdef CHAIN_OF_COMMAND\n          st_synchronize(); // wait for all movements to finish\n#endif\n        SET_INPUT(PS_ON_PIN); //Floating\n        break;\n      #endif\n      case 82:\n        axis_relative_modes[3] = false;\n        break;\n      case 83:\n        axis_relative_modes[3] = true;\n        break;\n      case 84:\n        st_synchronize(); // wait for all movements to finish\n        if(code_seen('S'))\n        {\n          stepper_inactive_time = code_value() * 1000; \n        }\n        else if(code_seen('T'))\n        {\n          enable_x(); \n          enable_y(); \n          enable_z(); \n          enable_e(); \n        }\n        else\n        { \n          disable_x(); \n          disable_y(); \n          disable_z(); \n          disable_e(); \n        }\n        break;\n      case 85: // M85\n        code_seen('S');\n        max_inactive_time = code_value() * 1000; \n        break;\n      case 92: // M92\n        for(int i=0; i < NUM_AXIS; i++) \n        {\n          if(code_seen(axis_codes[i])) \n          {\n            axis_steps_per_unit[i] = code_value();\n            axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];\n          }\n        }\n        \n          // Update start speed intervals and axis order. TODO: refactor axis_max_interval[] calculation into a function, as it\n          // should also be used in setup() as well\n//        long temp_max_intervals[NUM_AXIS];\n//        for(int i=0; i < NUM_AXIS; i++) \n//        {\n//          axis_max_interval[i] = 100000000.0 / (max_start_speed_units_per_second[i] * axis_steps_per_unit[i]);//TODO: do this for\n//          all steps_per_unit related variables\n//        }\n        break;\n      case 93: // M93 show current axis steps.\n\tshowString(PSTR(\"ok \"));\n\tshowString(PSTR(\"X:\"));\n        Serial.print(axis_steps_per_unit[0]);\n\tshowString(PSTR(\"Y:\"));\n        Serial.print(axis_steps_per_unit[1]);\n\tshowString(PSTR(\"Z:\"));\n        Serial.print(axis_steps_per_unit[2]);\n\tshowString(PSTR(\"E:\"));\n        Serial.println(axis_steps_per_unit[3]);\n        break;\n      case 115: // M115\n        showString(PSTR(\"FIRMWARE_NAME: Sprinter Experimental PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\\r\\n\"));\n        //Serial.println(uuid);\n        showString(PSTR(_DEF_CHAR_UUID));\n        showString(PSTR(\"\\r\\n\"));\n        break;\n      case 114: // M114\n\tshowString(PSTR(\"X:\"));\n        Serial.print(current_position[0]);\n\tshowString(PSTR(\"Y:\"));\n        Serial.print(current_position[1]);\n\tshowString(PSTR(\"Z:\"));\n        Serial.print(current_position[2]);\n\tshowString(PSTR(\"E:\"));\n        Serial.println(current_position[3]);\n        break;\n      case 119: // M119\n      \n      \t#if (X_MIN_PIN > -1)\n          showString(PSTR(\"x_min:\"));\n          Serial.print((READ(X_MIN_PIN)^X_ENDSTOP_INVERT)?\"H \":\"L \");\n      \t#endif\n      \t#if (X_MAX_PIN > -1)\n          showString(PSTR(\"x_max:\"));\n          Serial.print((READ(X_MAX_PIN)^X_ENDSTOP_INVERT)?\"H \":\"L \");\n      \t#endif\n      \t#if (Y_MIN_PIN > -1)\n      \t  showString(PSTR(\"y_min:\"));\n          Serial.print((READ(Y_MIN_PIN)^Y_ENDSTOP_INVERT)?\"H \":\"L \");\n      \t#endif\n      \t#if (Y_MAX_PIN > -1)\n      \t  showString(PSTR(\"y_max:\"));\n          Serial.print((READ(Y_MAX_PIN)^Y_ENDSTOP_INVERT)?\"H \":\"L \");\n      \t#endif\n      \t#if (Z_MIN_PIN > -1)\n      \t  showString(PSTR(\"z_min:\"));\n          Serial.print((READ(Z_MIN_PIN)^Z_ENDSTOP_INVERT)?\"H \":\"L \");\n      \t#endif\n      \t#if (Z_MAX_PIN > -1)\n      \t  showString(PSTR(\"z_max:\"));\n          Serial.print((READ(Z_MAX_PIN)^Z_ENDSTOP_INVERT)?\"H \":\"L \");\n      \t#endif\n      \n        showString(PSTR(\"\\r\\n\"));\n      \tbreak;\n      case 201: // M201  Set maximum acceleration in units/s^2 for print moves (M201 X1000 Y1000)\n\n        for(int8_t i=0; i < NUM_AXIS; i++) \n        {\n          if(code_seen(axis_codes[i]))\n          {\n            max_acceleration_units_per_sq_second[i] = code_value();\n            axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];\n          }\n        }\n        break;\n      #if 0 // Not used for Sprinter/grbl gen6\n      case 202: // M202\n        for(int i=0; i < NUM_AXIS; i++) \n        {\n          if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];\n        }\n        break;\n      #else  \n      case 202: // M202 max feedrate mm/sec\n        for(int8_t i=0; i < NUM_AXIS; i++) \n        {\n          if(code_seen(axis_codes[i])) max_feedrate[i] = code_value();\n        }\n      break;\n      #endif\n      case 203: // M203 Temperature monitor\n          if(code_seen('S')) manage_monitor = code_value();\n          if(manage_monitor==100) manage_monitor=1; // Set 100 to heated bed\n      break;\n      case 204: // M204 acceleration S normal moves T filmanent only moves\n          if(code_seen('S')) move_acceleration = code_value() ;\n          if(code_seen('T')) retract_acceleration = code_value() ;\n      break;\n      case 205: //M205 advanced settings:  minimum travel speed S=while printing T=travel only,  B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk, E= max E jerk\n        if(code_seen('S')) minimumfeedrate = code_value();\n        if(code_seen('T')) mintravelfeedrate = code_value();\n      //if(code_seen('B')) minsegmenttime = code_value() ;\n        if(code_seen('X')) max_xy_jerk = code_value() ;\n        if(code_seen('Z')) max_z_jerk = code_value() ;\n        if(code_seen('E')) max_e_jerk = code_value() ;\n      break;\n      case 206: // M206 additional homing offset\n        if(code_seen('D'))\n        {\n          showString(PSTR(\"Addhome X:\")); Serial.print(add_homing[0]);\n          showString(PSTR(\" Y:\")); Serial.print(add_homing[1]);\n          showString(PSTR(\" Z:\")); Serial.println(add_homing[2]);\n        }\n\n        for(int8_t cnt_i=0; cnt_i < 3; cnt_i++) \n        {\n          if(code_seen(axis_codes[cnt_i])) add_homing[cnt_i] = code_value();\n        }\n      break;  \n      case 220: // M220 S<factor in percent>- set speed factor override percentage\n      {\n        if(code_seen('S')) \n        {\n          feedmultiply = code_value() ;\n          feedmultiply = constrain(feedmultiply, 20, 200);\n          feedmultiplychanged=true;\n        }\n      }\n      break;\n      case 221: // M221 S<factor in percent>- set extrude factor override percentage\n      {\n        if(code_seen('S')) \n        {\n          extrudemultiply = code_value() ;\n          extrudemultiply = constrain(extrudemultiply, 40, 200);\n        }\n      }\n      break;\n#ifdef PIDTEMP\n      case 301: // M301\n      {\n        if(code_seen('P')) PID_Kp = code_value();\n        if(code_seen('I')) PID_Ki = code_value();\n        if(code_seen('D')) PID_Kd = code_value();\n        updatePID();\n      }\n      break;\n#endif //PIDTEMP      \n#ifdef PID_AUTOTUNE\n      case 303: // M303 PID autotune\n      {\n        float help_temp = 150.0;\n        if (code_seen('S')) help_temp=code_value();\n        PID_autotune(help_temp);\n      }\n      break;\n#endif\n      case 400: // M400 finish all moves\n      {\n      \tst_synchronize();\t\n      }\n      break;\n#ifdef USE_EEPROM_SETTINGS\n      case 500: // Store settings in EEPROM\n      {\n        EEPROM_StoreSettings();\n      }\n      break;\n      case 501: // Read settings from EEPROM\n      {\n        EEPROM_RetrieveSettings(false,true);\n        for(int8_t i=0; i < NUM_AXIS; i++)\n        {\n          axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];\n        }\n      }\n      break;\n      case 502: // Revert to default settings\n      {\n        EEPROM_RetrieveSettings(true,true);\n        for(int8_t i=0; i < NUM_AXIS; i++)\n        {\n          axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];\n        }\n      }\n      break;\n      case 503: // print settings currently in memory\n      {\n        EEPROM_printSettings();\n      }\n      break;  \n#endif      \n#ifdef DEBUG_HEATER_TEMP\n      case 601: // M601  show Extruder Temp jitter\n        #if (TEMP_0_PIN > -1) || defined (HEATER_USES_MAX6675)|| defined HEATER_USES_AD595\n          if(current_raw_maxval > 0)\n            tt_maxval = analog2temp(current_raw_maxval);\n          if(current_raw_minval < 10000)  \n            tt_minval = analog2temp(current_raw_minval);\n        #endif\n        \n            showString(PSTR(\"Tmin:\"));\n            Serial.print(tt_minval); \n            showString(PSTR(\" / Tmax:\"));\n            Serial.print(tt_maxval); \n            showString(PSTR(\" \"));\n      break;\n      case 602: // M602  reset Extruder Temp jitter\n            current_raw_minval = 32000;\n            current_raw_maxval = -32000;\n        \n            showString(PSTR(\"T Minmax Reset \"));\n      break;\n#endif\n      case 603: // M603  Free RAM\n            showString(PSTR(\"Free Ram: \"));\n            Serial.println(FreeRam1()); \n      break;\n      default:\n            #ifdef SEND_WRONG_CMD_INFO\n              showString(PSTR(\"Unknown M-COM:\"));\n              Serial.println(cmdbuffer[bufindr]);\n            #endif\n      break;\n\n    }\n    \n  }\n  else{\n      showString(PSTR(\"Unknown command:\\r\\n\"));\n      Serial.println(cmdbuffer[bufindr]);\n  }\n  \n  ClearToSend();\n      \n}\n\n\n\nvoid FlushSerialRequestResend()\n{\n  //char cmdbuffer[bufindr][100]=\"Resend:\";\n  Serial.flush();\n  showString(PSTR(\"Resend:\"));\n  Serial.println(gcode_LastN + 1);\n  ClearToSend();\n}\n\nvoid ClearToSend()\n{\n  previous_millis_cmd = millis();\n  #ifdef SDSUPPORT\n  if(fromsd[bufindr])\n    return;\n  #endif\n  showString(PSTR(\"ok\\r\\n\"));\n  //Serial.println(\"ok\");\n}\n\nFORCE_INLINE void get_coordinates()\n{\n  for(int i=0; i < NUM_AXIS; i++)\n  {\n    if(code_seen(axis_codes[i])) destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i];\n    else destination[i] = current_position[i];                                                       //Are these else lines really needed?\n  }\n  \n  if(code_seen('F'))\n  {\n    next_feedrate = code_value();\n    if(next_feedrate > 0.0) feedrate = next_feedrate;\n  }\n}\n\n#ifdef USE_ARC_FUNCTION\nvoid get_arc_coordinates()\n{\n   get_coordinates();\n   if(code_seen('I')) {\n     offset[0] = code_value();\n   } \n   else {\n     offset[0] = 0.0;\n   }\n   if(code_seen('J')) {\n     offset[1] = code_value();\n   }\n   else {\n     offset[1] = 0.0;\n   }\n}\n#endif\n\n\n\nvoid prepare_move()\n{\n  long help_feedrate = 0;\n\n  if(!is_homing){\n    if (min_software_endstops) \n    {\n      if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0;\n      if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0;\n      if (destination[Z_AXIS] < 0) destination[Z_AXIS] = 0.0;\n    }\n\n    if (max_software_endstops) \n    {\n      if (destination[X_AXIS] > X_MAX_LENGTH) destination[X_AXIS] = X_MAX_LENGTH;\n      if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH;\n      if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH;\n    }\n  }\n\n  if(destination[E_AXIS] > current_position[E_AXIS])\n  {\n    help_feedrate = ((long)feedrate*(long)feedmultiply);\n  }\n  else\n  {\n    help_feedrate = ((long)feedrate*(long)100);\n  }\n  \n  plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], help_feedrate/6000.0);\n  \n  for(int i=0; i < NUM_AXIS; i++)\n  {\n    current_position[i] = destination[i];\n  } \n}\n\n\n#ifdef USE_ARC_FUNCTION\nvoid prepare_arc_move(char isclockwise) \n{\n\n  float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc\n  long help_feedrate = 0;\n\n  if(destination[E_AXIS] > current_position[E_AXIS])\n  {\n    help_feedrate = ((long)feedrate*(long)feedmultiply);\n  }\n  else\n  {\n    help_feedrate = ((long)feedrate*(long)100);\n  }\n\n  // Trace the arc\n  mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, help_feedrate/6000.0, r, isclockwise);\n  \n  // As far as the parser is concerned, the position is now == target. In reality the\n  // motion control system might still be processing the action and the real tool position\n  // in any intermediate location.\n  for(int8_t i=0; i < NUM_AXIS; i++) \n  {\n    current_position[i] = destination[i];\n  }\n}\n#endif\n\nFORCE_INLINE void kill()\n{\n  #if TEMP_0_PIN > -1\n    target_raw=0;\n    WRITE(HEATER_0_PIN,LOW);\n  #endif\n  \n  #if TEMP_1_PIN > -1\n    target_bed_raw=0;\n    if(HEATER_1_PIN > -1) WRITE(HEATER_1_PIN,LOW);\n  #endif\n\n  disable_x();\n  disable_y();\n  disable_z();\n  disable_e();\n  \n  if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT);\n  \n}\n\nFORCE_INLINE void manage_inactivity(byte debug) \n{ \n  if( (millis()-previous_millis_cmd) >  max_inactive_time ) if(max_inactive_time) kill(); \n  \n  if( (millis()-previous_millis_cmd) >  stepper_inactive_time ) if(stepper_inactive_time) \n  { \n    disable_x(); \n    disable_y(); \n    disable_z(); \n    disable_e(); \n  }\n  check_axes_activity();\n}\n\n#if (MINIMUM_FAN_START_SPEED > 0)\nvoid manage_fan_start_speed(void)\n{\n  if(fan_org_start_speed > 0)\n  {\n     if((millis() - previous_millis_fan_start) > MINIMUM_FAN_START_TIME )\n     { \n       #if FAN_PIN > -1\n         #if defined(FAN_SOFT_PWM)\n           g_fan_pwm_val = fan_org_start_speed;\n         #else\n           WRITE(FAN_PIN, HIGH);\n           analogWrite_check(FAN_PIN, fan_org_start_speed;\n         #endif  \n       #endif\n       \n       fan_org_start_speed = 0;\n     }  \n  }\n}\n#endif\n\n// Planner with Interrupt for Stepper\n\n/*  \n Reasoning behind the mathematics in this module (in the key of 'Mathematica'):\n \n s == speed, a == acceleration, t == time, d == distance\n \n Basic definitions:\n \n Speed[s_, a_, t_] := s + (a*t) \n Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t]\n \n Distance to reach a specific speed with a constant acceleration:\n \n Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t]\n d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance()\n \n Speed after a given distance of travel with constant acceleration:\n \n Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t]\n m -> Sqrt[2 a d + s^2]    \n \n DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2]\n \n When to start braking (di) to reach a specified destionation speed (s2) after accelerating\n from initial speed s1 without ever stopping at a plateau:\n \n Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di]\n di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance()\n \n IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a)\n */\n\n\nstatic block_t block_buffer[BLOCK_BUFFER_SIZE];            // A ring buffer for motion instructions\nstatic volatile unsigned char block_buffer_head;           // Index of the next block to be pushed\nstatic volatile unsigned char block_buffer_tail;           // Index of the block to process now\n\n//===========================================================================\n//=============================private variables ============================\n//===========================================================================\n\n// Returns the index of the next block in the ring buffer\n// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication.\nstatic int8_t next_block_index(int8_t block_index) {\n  block_index++;\n  if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; }\n  return(block_index);\n}\n\n\n// Returns the index of the previous block in the ring buffer\nstatic int8_t prev_block_index(int8_t block_index) {\n  if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; }\n  block_index--;\n  return(block_index);\n}\n\n// The current position of the tool in absolute steps\nstatic long position[4];   \nstatic float previous_speed[4]; // Speed of previous path line segment\nstatic float previous_nominal_speed; // Nominal speed of previous path line segment\nstatic unsigned char G92_reset_previous_speed = 0;\n\n\n// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the \n// given acceleration:\nFORCE_INLINE float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration)\n{\n  if (acceleration!=0) {\n  return((target_rate*target_rate-initial_rate*initial_rate)/\n         (2.0*acceleration));\n  }\n  else {\n    return 0.0;  // acceleration was 0, set acceleration distance to 0\n  }\n}\n\n// This function gives you the point at which you must start braking (at the rate of -acceleration) if \n// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after\n// a total travel of distance. This can be used to compute the intersection point between acceleration and\n// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed)\n\nFORCE_INLINE float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) \n{\n if (acceleration!=0) {\n  return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/\n         (4.0*acceleration) );\n  }\n  else {\n    return 0.0;  // acceleration was 0, set intersection distance to 0\n  }\n}\n\n// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors.\n\nvoid calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) {\n  unsigned long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min)\n  unsigned long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min)\n\n  // Limit minimal step rate (Otherwise the timer will overflow.)\n  if(initial_rate <120) {initial_rate=120; }\n  if(final_rate < 120) {final_rate=120;  }\n  \n  long acceleration = block->acceleration_st;\n  int32_t accelerate_steps =\n    ceil(estimate_acceleration_distance(block->initial_rate, block->nominal_rate, acceleration));\n  int32_t decelerate_steps =\n    floor(estimate_acceleration_distance(block->nominal_rate, block->final_rate, -acceleration));\n    \n  // Calculate the size of Plateau of Nominal Rate.\n  int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps;\n  \n  // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will\n  // have to use intersection_distance() to calculate when to abort acceleration and start breaking\n  // in order to reach the final_rate exactly at the end of this block.\n  if (plateau_steps < 0) {\n    accelerate_steps = ceil(\n      intersection_distance(block->initial_rate, block->final_rate, acceleration, block->step_event_count));\n    accelerate_steps = max(accelerate_steps,0); // Check limits due to numerical round-off\n    accelerate_steps = min(accelerate_steps,block->step_event_count);\n    plateau_steps = 0;\n  }\n\n  #ifdef ADVANCE\n    volatile long initial_advance = block->advance*entry_factor*entry_factor; \n    volatile long final_advance = block->advance*exit_factor*exit_factor;\n  #endif // ADVANCE\n  \n // block->accelerate_until = accelerate_steps;\n // block->decelerate_after = accelerate_steps+plateau_steps;\n  CRITICAL_SECTION_START;  // Fill variables used by the stepper in a critical section\n  if(block->busy == false) { // Don't update variables if block is busy.\n    block->accelerate_until = accelerate_steps;\n    block->decelerate_after = accelerate_steps+plateau_steps;\n    block->initial_rate = initial_rate;\n    block->final_rate = final_rate;\n  #ifdef ADVANCE\n      block->initial_advance = initial_advance;\n      block->final_advance = final_advance;\n  #endif //ADVANCE\n  }\n  CRITICAL_SECTION_END;\n}                    \n\n// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the \n// acceleration within the allotted distance.\nFORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) {\n  return  sqrt(target_velocity*target_velocity-2*acceleration*distance);\n}\n\n// \"Junction jerk\" in this context is the immediate change in speed at the junction of two blocks.\n// This method will calculate the junction jerk as the euclidean distance between the nominal \n// velocities of the respective blocks.\n//inline float junction_jerk(block_t *before, block_t *after) {\n//  return sqrt(\n//    pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2));\n//}\n\n\n\n// The kernel called by planner_recalculate() when scanning the plan from last to first entry.\nvoid planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) {\n  if(!current) { return; }\n  \n    if (next) {\n    // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.\n    // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and\n    // check for maximum allowable speed reductions to ensure maximum possible planned speed.\n    if (current->entry_speed != current->max_entry_speed) {\n    \n      // If nominal length true, max junction speed is guaranteed to be reached. Only compute\n      // for max allowable speed if block is decelerating and nominal length is false.\n      if ((!current->nominal_length_flag) && (current->max_entry_speed > next->entry_speed)) {\n        current->entry_speed = min( current->max_entry_speed,\n          max_allowable_speed(-current->acceleration,next->entry_speed,current->millimeters));\n      } else {\n        current->entry_speed = current->max_entry_speed;\n      }\n      current->recalculate_flag = true;\n    \n    }\n  } // Skip last block. Already initialized and set for recalculation.\n}\n\n// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This \n// implements the reverse pass.\nvoid planner_reverse_pass() {\n  uint8_t block_index = block_buffer_head;\n  \n  //Make a local copy of block_buffer_tail, because the interrupt can alter it\n  CRITICAL_SECTION_START;\n  unsigned char tail = block_buffer_tail;\n  CRITICAL_SECTION_END;\n  \n  if(((block_buffer_head-tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) \n  {\n    block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1);\n    block_t *block[3] = { NULL, NULL, NULL };\n    while(block_index != tail) { \n      block_index = prev_block_index(block_index); \n      block[2]= block[1];\n      block[1]= block[0];\n      block[0] = &block_buffer[block_index];\n      planner_reverse_pass_kernel(block[0], block[1], block[2]);\n    }\n  }\n}\n\n\n// The kernel called by planner_recalculate() when scanning the plan from first to last entry.\nvoid planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) {\n  if(!previous) { return; }\n  \n  // If the previous block is an acceleration block, but it is not long enough to complete the\n  // full speed change within the block, we need to adjust the entry speed accordingly. Entry\n  // speeds have already been reset, maximized, and reverse planned by reverse planner.\n  // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck.\n  if (!previous->nominal_length_flag) {\n    if (previous->entry_speed < current->entry_speed) {\n      double entry_speed = min( current->entry_speed,\n        max_allowable_speed(-previous->acceleration,previous->entry_speed,previous->millimeters) );\n\n      // Check for junction speed change\n      if (current->entry_speed != entry_speed) {\n        current->entry_speed = entry_speed;\n        current->recalculate_flag = true;\n      }\n    }\n  }\n}\n\n// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This \n// implements the forward pass.\nvoid planner_forward_pass() {\n  uint8_t block_index = block_buffer_tail;\n  block_t *block[3] = { NULL, NULL, NULL };\n\n  while(block_index != block_buffer_head) {\n    block[0] = block[1];\n    block[1] = block[2];\n    block[2] = &block_buffer[block_index];\n    planner_forward_pass_kernel(block[0],block[1],block[2]);\n    block_index = next_block_index(block_index);\n  }\n  planner_forward_pass_kernel(block[1], block[2], NULL);\n}\n\n// Recalculates the trapezoid speed profiles for all blocks in the plan according to the \n// entry_factor for each junction. Must be called by planner_recalculate() after \n// updating the blocks.\nvoid planner_recalculate_trapezoids() {\n  int8_t block_index = block_buffer_tail;\n  block_t *current;\n  block_t *next = NULL;\n  \n  while(block_index != block_buffer_head) {\n    current = next;\n    next = &block_buffer[block_index];\n    if (current) {\n      // Recalculate if current block entry or exit junction speed has changed.\n      if (current->recalculate_flag || next->recalculate_flag) {\n        // NOTE: Entry and exit factors always > 0 by all previous logic operations.\n        calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed,\n          next->entry_speed/current->nominal_speed);\n        current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed\n      }\n    }\n    block_index = next_block_index( block_index );\n  }\n  // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated.\n  if(next != NULL) {\n    calculate_trapezoid_for_block(next, next->entry_speed/next->nominal_speed,\n      MINIMUM_PLANNER_SPEED/next->nominal_speed);\n    next->recalculate_flag = false;\n  }\n}\n\n// Recalculates the motion plan according to the following algorithm:\n//\n//   1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) \n//      so that:\n//     a. The junction jerk is within the set limit\n//     b. No speed reduction within one block requires faster deceleration than the one, true constant \n//        acceleration.\n//   2. Go over every block in chronological order and dial down junction speed reduction values if \n//     a. The speed increase within one block would require faster accelleration than the one, true \n//        constant acceleration.\n//\n// When these stages are complete all blocks have an entry_factor that will allow all speed changes to \n// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than \n// the set limit. Finally it will:\n//\n//   3. Recalculate trapezoids for all blocks.\n\nvoid planner_recalculate() {   \n  planner_reverse_pass();\n  planner_forward_pass();\n  planner_recalculate_trapezoids();\n}\n\nvoid plan_init() {\n  block_buffer_head = 0;\n  block_buffer_tail = 0;\n  memset(position, 0, sizeof(position)); // clear position\n  previous_speed[0] = 0.0;\n  previous_speed[1] = 0.0;\n  previous_speed[2] = 0.0;\n  previous_speed[3] = 0.0;\n  previous_nominal_speed = 0.0;\n}\n\n\n\nFORCE_INLINE void plan_discard_current_block() {\n  if (block_buffer_head != block_buffer_tail) {\n    block_buffer_tail = (block_buffer_tail + 1) & BLOCK_BUFFER_MASK;  \n  }\n}\n\nFORCE_INLINE block_t *plan_get_current_block() {\n  if (block_buffer_head == block_buffer_tail) { \n    return(NULL); \n  }\n  block_t *block = &block_buffer[block_buffer_tail];\n  block->busy = true;\n  return(block);\n}\n\n// Gets the current block. Returns NULL if buffer empty\nFORCE_INLINE bool blocks_queued() \n{\n  if (block_buffer_head == block_buffer_tail) { \n    return false; \n  }\n  else\n    return true;\n}\n\nvoid check_axes_activity() {\n  unsigned char x_active = 0;\n  unsigned char y_active = 0;  \n  unsigned char z_active = 0;\n  unsigned char e_active = 0;\n  block_t *block;\n\n  if(block_buffer_tail != block_buffer_head) {\n    uint8_t block_index = block_buffer_tail;\n    while(block_index != block_buffer_head) {\n      block = &block_buffer[block_index];\n      if(block->steps_x != 0) x_active++;\n      if(block->steps_y != 0) y_active++;\n      if(block->steps_z != 0) z_active++;\n      if(block->steps_e != 0) e_active++;\n      block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1);\n    }\n  }\n  if((DISABLE_X) && (x_active == 0)) disable_x();\n  if((DISABLE_Y) && (y_active == 0)) disable_y();\n  if((DISABLE_Z) && (z_active == 0)) disable_z();\n  if((DISABLE_E) && (e_active == 0)) disable_e();\n}\n\n\nfloat junction_deviation = 0.1;\nfloat max_E_feedrate_calc = MAX_RETRACT_FEEDRATE;\nbool retract_feedrate_aktiv = false;\n\n// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in \n// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration\n// calculation the caller must also provide the physical length of the line in millimeters.\nvoid plan_buffer_line(float x, float y, float z, float e, float feed_rate)\n{\n  // Calculate the buffer head after we push this byte\n  int next_buffer_head = next_block_index(block_buffer_head);\n\n  // If the buffer is full: good! That means we are well ahead of the robot. \n  // Rest here until there is room in the buffer.\n  while(block_buffer_tail == next_buffer_head) { \n    manage_heater(); \n    manage_inactivity(1); \n    #if (MINIMUM_FAN_START_SPEED > 0)\n      manage_fan_start_speed();\n    #endif \n  }\n\n  // The target position of the tool in absolute steps\n  // Calculate target position in absolute steps\n  //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow\n  long target[4];\n  target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]);\n  target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]);\n  target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);     \n  target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);\n  \n  // Prepare to set up new block\n  block_t *block = &block_buffer[block_buffer_head];\n  \n  // Mark block as not busy (Not executed by the stepper interrupt)\n  block->busy = false;\n\n  // Number of steps for each axis\n  block->steps_x = labs(target[X_AXIS]-position[X_AXIS]);\n  block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]);\n  block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]);\n  block->steps_e = labs(target[E_AXIS]-position[E_AXIS]);\n  block->steps_e *= extrudemultiply;\n  block->steps_e /= 100;\n  block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e)));\n\n  // Bail if this is a zero-length block\n  if (block->step_event_count <=dropsegments) { return; };\n\n  // Compute direction bits for this block \n  block->direction_bits = 0;\n  if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<<X_AXIS); }\n  if (target[Y_AXIS] < position[Y_AXIS]) { block->direction_bits |= (1<<Y_AXIS); }\n  if (target[Z_AXIS] < position[Z_AXIS]) { block->direction_bits |= (1<<Z_AXIS); }\n  if (target[E_AXIS] < position[E_AXIS]) \n  { \n    block->direction_bits |= (1<<E_AXIS); \n    //High Feedrate for retract\n    max_E_feedrate_calc = MAX_RETRACT_FEEDRATE;\n    retract_feedrate_aktiv = true;\n  }\n  else\n  {\n     if(retract_feedrate_aktiv)\n     {\n       if(block->steps_e > 0)\n         retract_feedrate_aktiv = false;\n     }\n     else\n     {\n       max_E_feedrate_calc = max_feedrate[E_AXIS]; \n     }\n  }\n  \n\n #ifdef DELAY_ENABLE\n  if(block->steps_x != 0)\n  {\n    enable_x();\n    delayMicroseconds(DELAY_ENABLE);\n  }\n  if(block->steps_y != 0)\n  {\n    enable_y();\n    delayMicroseconds(DELAY_ENABLE);\n  }\n  if(block->steps_z != 0)\n  {\n    enable_z();\n    delayMicroseconds(DELAY_ENABLE);\n  }\n  if(block->steps_e != 0)\n  {\n    enable_e();\n    delayMicroseconds(DELAY_ENABLE);\n  }\n #else\n  //enable active axes\n  if(block->steps_x != 0) enable_x();\n  if(block->steps_y != 0) enable_y();\n  if(block->steps_z != 0) enable_z();\n  if(block->steps_e != 0) enable_e();\n #endif \n \n  if (block->steps_e == 0) {\n        if(feed_rate<mintravelfeedrate) feed_rate=mintravelfeedrate;\n  }\n  else {\n    \tif(feed_rate<minimumfeedrate) feed_rate=minimumfeedrate;\n  } \n\n  // slow down when the buffer starts to empty, rather than wait at the corner for a buffer refill\n  int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1);\n#ifdef SLOWDOWN  \n  if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); \n#endif\n\n  float delta_mm[4];\n  delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS];\n  delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS];\n  delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS];\n  //delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS];\n  delta_mm[E_AXIS] = ((target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS])*extrudemultiply/100.0;\n  \n  if ( block->steps_x <= dropsegments && block->steps_y <= dropsegments && block->steps_z <= dropsegments ) {\n    block->millimeters = fabs(delta_mm[E_AXIS]);\n  } else {\n    block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS]));\n  }\n  \n  float inverse_millimeters = 1.0/block->millimeters;  // Inverse millimeters to remove multiple divides \n  \n  // Calculate speed in mm/second for each axis. No divide by zero due to previous checks.\n  float inverse_second = feed_rate * inverse_millimeters;\n  \n  block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0\n  block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0\n\n  \n \n\n  \n/*\n  //  segment time im micro seconds\n  long segment_time = lround(1000000.0/inverse_second);\n  if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) {\n    if (segment_time<minsegmenttime)  { // buffer is draining, add extra time.  The amount of time added increases if the buffer is still emptied more.\n        segment_time=segment_time+lround(2*(minsegmenttime-segment_time)/blockcount);\n    }\n  }\n  else {\n    if (segment_time<minsegmenttime) segment_time=minsegmenttime;\n  }\n  //  END OF SLOW DOWN SECTION    \n*/\n\n\n // Calculate and limit speed in mm/sec for each axis\n  float current_speed[4];\n  float speed_factor = 1.0; //factor <=1 do decrease speed\n  for(int i=0; i < 3; i++) \n  {\n    current_speed[i] = delta_mm[i] * inverse_second;\n    if(fabs(current_speed[i]) > max_feedrate[i])\n      speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i]));\n  }\n  \n  current_speed[E_AXIS] = delta_mm[E_AXIS] * inverse_second;\n  if(fabs(current_speed[E_AXIS]) > max_E_feedrate_calc)\n    speed_factor = min(speed_factor, max_E_feedrate_calc / fabs(current_speed[E_AXIS]));\n\n\n  // Correct the speed  \n  if( speed_factor < 1.0) \n  {\n    for(unsigned char i=0; i < 4; i++) {\n      current_speed[i] *= speed_factor;\n    }\n    block->nominal_speed *= speed_factor;\n    block->nominal_rate *= speed_factor;\n  }\n\n  // Compute and limit the acceleration rate for the trapezoid generator.  \n  float steps_per_mm = block->step_event_count/block->millimeters;\n  if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) {\n    block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2\n  }\n  else {\n    block->acceleration_st = ceil(move_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2\n    // Limit acceleration per axis\n    if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS])\n      block->acceleration_st = axis_steps_per_sqr_second[X_AXIS];\n    if(((float)block->acceleration_st * (float)block->steps_y / (float)block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS])\n      block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS];\n    if(((float)block->acceleration_st * (float)block->steps_e / (float)block->step_event_count) > axis_steps_per_sqr_second[E_AXIS])\n      block->acceleration_st = axis_steps_per_sqr_second[E_AXIS];\n    if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS])\n      block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS];\n  }\n  block->acceleration = block->acceleration_st / steps_per_mm;\n  block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608);\n  \n#if 0  // Use old jerk for now\n  // Compute path unit vector\n  double unit_vec[3];\n\n  unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters;\n  unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters;\n  unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters;\n  \n  // Compute maximum allowable entry speed at junction by centripetal acceleration approximation.\n  // Let a circle be tangent to both previous and current path line segments, where the junction\n  // deviation is defined as the distance from the junction to the closest edge of the circle,\n  // colinear with the circle center. The circular segment joining the two paths represents the\n  // path of centripetal acceleration. Solve for max velocity based on max acceleration about the\n  // radius of the circle, defined indirectly by junction deviation. This may be also viewed as\n  // path width or max_jerk in the previous grbl version. This approach does not actually deviate\n  // from path, but used as a robust way to compute cornering speeds, as it takes into account the\n  // nonlinearities of both the junction angle and junction velocity.\n  double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed\n\n  // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.\n  if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) {\n    // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)\n    // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.\n    double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]\n                       - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]\n                       - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ;\n                           \n    // Skip and use default max junction speed for 0 degree acute junction.\n    if (cos_theta < 0.95) {\n      vmax_junction = min(previous_nominal_speed,block->nominal_speed);\n      // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.\n      if (cos_theta > -0.95) {\n        // Compute maximum junction velocity based on maximum acceleration and junction deviation\n        double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive.\n        vmax_junction = min(vmax_junction,\n          sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) );\n      }\n    }\n  }\n#endif\n  // Start with a safe speed\n  float vmax_junction = max_xy_jerk/2; \n  float vmax_junction_factor = 1.0; \n\n  if(fabs(current_speed[Z_AXIS]) > max_z_jerk/2) \n    vmax_junction = min(vmax_junction, max_z_jerk/2);\n\n  if(fabs(current_speed[E_AXIS]) > max_e_jerk/2) \n    vmax_junction = min(vmax_junction, max_e_jerk/2);\n\n  if(G92_reset_previous_speed == 1)\n  {\n    vmax_junction = 0.1;\n    G92_reset_previous_speed = 0;  \n  }\n\n  vmax_junction = min(vmax_junction, block->nominal_speed);\n  float safe_speed = vmax_junction;\n\n  if ((moves_queued > 1) && (previous_nominal_speed > 0.0001)) {\n    float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2));\n    //    if((fabs(previous_speed[X_AXIS]) > 0.0001) || (fabs(previous_speed[Y_AXIS]) > 0.0001)) {\n    vmax_junction = block->nominal_speed;\n    //    }\n    if (jerk > max_xy_jerk) {\n      vmax_junction_factor = (max_xy_jerk/jerk);\n    } \n    if(fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) {\n      vmax_junction_factor= min(vmax_junction_factor, (max_z_jerk/fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])));\n    } \n    if(fabs(current_speed[E_AXIS] - previous_speed[E_AXIS]) > max_e_jerk) {\n      vmax_junction_factor = min(vmax_junction_factor, (max_e_jerk/fabs(current_speed[E_AXIS] - previous_speed[E_AXIS])));\n    } \n    vmax_junction = min(previous_nominal_speed, vmax_junction * vmax_junction_factor); // Limit speed to max previous speed\n  }\n  block->max_entry_speed = vmax_junction;\n\n  // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED.\n  double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters);\n  block->entry_speed = min(vmax_junction, v_allowable);\n\n  // Initialize planner efficiency flags\n  // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds.\n  // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then\n  // the current block and next block junction speeds are guaranteed to always be at their maximum\n  // junction speeds in deceleration and acceleration, respectively. This is due to how the current\n  // block nominal speed limits both the current and next maximum junction speeds. Hence, in both\n  // the reverse and forward planners, the corresponding block junction speed will always be at the\n  // the maximum junction speed and may always be ignored for any speed reduction checks.\n  if (block->nominal_speed <= v_allowable) { \n    block->nominal_length_flag = true; \n  }\n  else { \n    block->nominal_length_flag = false; \n  }\n  block->recalculate_flag = true; // Always calculate trapezoid for new block\n\n  // Update previous path unit_vector and nominal speed\n  memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[]\n  previous_nominal_speed = block->nominal_speed;\n  \n  #ifdef ADVANCE\n    // Calculate advance rate\n    if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) {\n      block->advance_rate = 0;\n      block->advance = 0;\n    }\n    else {\n      long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st);\n      float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * \n        (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUTION_AREA * EXTRUTION_AREA)*256;\n      block->advance = advance;\n      if(acc_dist == 0) {\n        block->advance_rate = 0;\n      } \n      else {\n        block->advance_rate = advance / (float)acc_dist;\n      }\n    }\n\n  #endif // ADVANCE\n\n\n  calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed,\n    safe_speed/block->nominal_speed);\n    \n  // Move buffer head\n  block_buffer_head = next_buffer_head;\n  \n  // Update position\n  memcpy(position, target, sizeof(target)); // position[] = target[]\n\n  planner_recalculate();\n  #ifdef AUTOTEMP\n    getHighESpeed();\n  #endif\n  st_wake_up();\n}\n\nint calc_plannerpuffer_fill(void)\n{\n  int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1);\n  return(moves_queued);\n}\n\nvoid plan_set_position(float x, float y, float z, float e)\n{\n  position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]);\n  position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]);\n  position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);     \n  position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]);  \n\n  virtual_steps_x = 0;\n  virtual_steps_y = 0;\n  virtual_steps_z = 0;\n\n  previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.\n  previous_speed[0] = 0.0;\n  previous_speed[1] = 0.0;\n  previous_speed[2] = 0.0;\n  previous_speed[3] = 0.0;\n  \n  G92_reset_previous_speed = 1;\n}\n\n#ifdef AUTOTEMP\nvoid getHighESpeed()\n{\n  static float oldt=0;\n  if(!autotemp_enabled)\n    return;\n  if((target_temp+2) < autotemp_min)  //probably temperature set to zero.\n    return; //do nothing\n  \n  float high=0.0;\n  uint8_t block_index = block_buffer_tail;\n  \n  while(block_index != block_buffer_head) {\n    if((block_buffer[block_index].steps_x != 0) ||\n       (block_buffer[block_index].steps_y != 0) ||\n       (block_buffer[block_index].steps_z != 0)) {\n      float se=(float(block_buffer[block_index].steps_e)/float(block_buffer[block_index].step_event_count))*block_buffer[block_index].nominal_speed;\n      //se; units steps/sec;\n      if(se>high)\n      {\n        high=se;\n      }\n    }\n    block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1);\n  }\n   \n  float t=autotemp_min+high*autotemp_factor;\n  \n  if(t<autotemp_min)\n    t=autotemp_min;\n  \n  if(t>autotemp_max)\n    t=autotemp_max;\n  \n  if(oldt>t)\n  {\n    t=AUTOTEMP_OLDWEIGHT*oldt+(1-AUTOTEMP_OLDWEIGHT)*t;\n  }\n  oldt=t;\n  autotemp_setpoint = (int)t;\n\n}\n#endif\n\n\n\n// Stepper\n\n// intRes = intIn1 * intIn2 >> 16\n// uses:\n// r26 to store 0\n// r27 to store the byte 1 of the 24 bit result\n#define MultiU16X8toH16(intRes, charIn1, intIn2) \\\nasm volatile ( \\\n\"clr r26 \\n\\t\" \\\n\"mul %A1, %B2 \\n\\t\" \\\n\"movw %A0, r0 \\n\\t\" \\\n\"mul %A1, %A2 \\n\\t\" \\\n\"add %A0, r1 \\n\\t\" \\\n\"adc %B0, r26 \\n\\t\" \\\n\"lsr r0 \\n\\t\" \\\n\"adc %A0, r26 \\n\\t\" \\\n\"adc %B0, r26 \\n\\t\" \\\n\"clr r1 \\n\\t\" \\\n: \\\n\"=&r\" (intRes) \\\n: \\\n\"d\" (charIn1), \\\n\"d\" (intIn2) \\\n: \\\n\"r26\" \\\n)\n\n// intRes = longIn1 * longIn2 >> 24\n// uses:\n// r26 to store 0\n// r27 to store the byte 1 of the 48bit result\n#define MultiU24X24toH16(intRes, longIn1, longIn2) \\\nasm volatile ( \\\n\"clr r26 \\n\\t\" \\\n\"mul %A1, %B2 \\n\\t\" \\\n\"mov r27, r1 \\n\\t\" \\\n\"mul %B1, %C2 \\n\\t\" \\\n\"movw %A0, r0 \\n\\t\" \\\n\"mul %C1, %C2 \\n\\t\" \\\n\"add %B0, r0 \\n\\t\" \\\n\"mul %C1, %B2 \\n\\t\" \\\n\"add %A0, r0 \\n\\t\" \\\n\"adc %B0, r1 \\n\\t\" \\\n\"mul %A1, %C2 \\n\\t\" \\\n\"add r27, r0 \\n\\t\" \\\n\"adc %A0, r1 \\n\\t\" \\\n\"adc %B0, r26 \\n\\t\" \\\n\"mul %B1, %B2 \\n\\t\" \\\n\"add r27, r0 \\n\\t\" \\\n\"adc %A0, r1 \\n\\t\" \\\n\"adc %B0, r26 \\n\\t\" \\\n\"mul %C1, %A2 \\n\\t\" \\\n\"add r27, r0 \\n\\t\" \\\n\"adc %A0, r1 \\n\\t\" \\\n\"adc %B0, r26 \\n\\t\" \\\n\"mul %B1, %A2 \\n\\t\" \\\n\"add r27, r1 \\n\\t\" \\\n\"adc %A0, r26 \\n\\t\" \\\n\"adc %B0, r26 \\n\\t\" \\\n\"lsr r27 \\n\\t\" \\\n\"adc %A0, r26 \\n\\t\" \\\n\"adc %B0, r26 \\n\\t\" \\\n\"clr r1 \\n\\t\" \\\n: \\\n\"=&r\" (intRes) \\\n: \\\n\"d\" (longIn1), \\\n\"d\" (longIn2) \\\n: \\\n\"r26\" , \"r27\" \\\n)\n\n// Some useful constants\n\n#define ENABLE_STEPPER_DRIVER_INTERRUPT()  TIMSK1 |= (1<<OCIE1A)\n#define DISABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 &= ~(1<<OCIE1A)\n\n#ifdef ENDSTOPS_ONLY_FOR_HOMING\n  #define CHECK_ENDSTOPS  if(check_endstops)\n#else\n  #define CHECK_ENDSTOPS\n#endif\n\nstatic block_t *current_block;  // A pointer to the block currently being traced\n\n// Variables used by The Stepper Driver Interrupt\nstatic unsigned char out_bits;        // The next stepping-bits to be output\nstatic long counter_x,       // Counter variables for the bresenham line tracer\n            counter_y, \n            counter_z,       \n            counter_e;\nstatic unsigned long step_events_completed; // The number of step events executed in the current block\n#ifdef ADVANCE\n  static long advance_rate, advance, final_advance = 0;\n  static short old_advance = 0;\n#endif\nstatic short e_steps;\nstatic unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler.\nstatic long acceleration_time, deceleration_time;\nstatic unsigned short acc_step_rate; // needed for deceleration start point\nstatic char step_loops;\nstatic unsigned short OCR1A_nominal;\n\nstatic volatile bool endstop_x_hit=false;\nstatic volatile bool endstop_y_hit=false;\nstatic volatile bool endstop_z_hit=false;\n\nstatic bool old_x_min_endstop=false;\nstatic bool old_x_max_endstop=false;\nstatic bool old_y_min_endstop=false;\nstatic bool old_y_max_endstop=false;\nstatic bool old_z_min_endstop=false;\nstatic bool old_z_max_endstop=false;\n\n\n\n//         __________________________\n//        /|                        |\\     _________________         ^\n//       / |                        | \\   /|               |\\        |\n//      /  |                        |  \\ / |               | \\       s\n//     /   |                        |   |  |               |  \\      p\n//    /    |                        |   |  |               |   \\     e\n//   +-----+------------------------+---+--+---------------+----+    e\n//   |               BLOCK 1            |      BLOCK 2          |    d\n//\n//                           time ----->\n// \n//  The trapezoid is the shape of the speed curve over time. It starts at block->initial_rate, accelerates \n//  first block->accelerate_until step_events_completed, then keeps going at constant speed until \n//  step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.\n//  The slope of acceleration is calculated with the leib ramp alghorithm.\n\nvoid st_wake_up() \n{\n  //  TCNT1 = 0;\n  if(busy == false) \n  ENABLE_STEPPER_DRIVER_INTERRUPT();  \n}\n\nFORCE_INLINE unsigned short calc_timer(unsigned short step_rate)\n{\n  unsigned short timer;\n  if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY;\n  \n  if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times\n    step_rate = (step_rate >> 2)&0x3fff;\n    step_loops = 4;\n  }\n  else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times\n    step_rate = (step_rate >> 1)&0x7fff;\n    step_loops = 2;\n  }\n  else {\n    step_loops = 1;\n  } \n  \n  if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000);\n  step_rate -= (F_CPU/500000); // Correct for minimal speed\n  \n  if(step_rate >= (8*256)) // higher step rate \n  { // higher step rate \n    unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];\n    unsigned char tmp_step_rate = (step_rate & 0x00ff);\n    unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2);\n    MultiU16X8toH16(timer, tmp_step_rate, gain);\n    timer = (unsigned short)pgm_read_word_near(table_address) - timer;\n  }\n  else \n  { // lower step rates\n    unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0];\n    table_address += ((step_rate)>>1) & 0xfffc;\n    timer = (unsigned short)pgm_read_word_near(table_address);\n    timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3);\n  }\n  if(timer < 100) { timer = 100; }//(20kHz this should never happen)\n  return timer;\n}\n\n// Initializes the trapezoid generator from the current block. Called whenever a new \n// block begins.\nFORCE_INLINE void trapezoid_generator_reset()\n{\n  #ifdef ADVANCE\n    advance = current_block->initial_advance;\n    final_advance = current_block->final_advance;\n    // Do E steps + advance steps\n    e_steps += ((advance >>8) - old_advance);\n    old_advance = advance >>8;  \n  #endif\n  deceleration_time = 0;\n  \n  \n  // step_rate to timer interval\n  acc_step_rate = current_block->initial_rate;\n  acceleration_time = calc_timer(acc_step_rate);\n  OCR1A = acceleration_time;\n  OCR1A_nominal = calc_timer(current_block->nominal_rate);\n    \n}\n\n// \"The Stepper Driver Interrupt\" - This timer interrupt is the workhorse.  \n// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. \nISR(TIMER1_COMPA_vect)\n{        \n  // If there is no current block, attempt to pop one from the buffer\n  if (current_block == NULL) {\n    // Anything in the buffer?\n    current_block = plan_get_current_block();\n    if (current_block != NULL) {\n      trapezoid_generator_reset();\n      counter_x = -(current_block->step_event_count >> 1);\n      counter_y = counter_x;\n      counter_z = counter_x;\n      counter_e = counter_x;\n      step_events_completed = 0;\n//      #ifdef ADVANCE\n//      e_steps = 0;\n//      #endif\n    } \n    else {\n        OCR1A=2000; // 1kHz.\n    }    \n  } \n\n  if (current_block != NULL) {\n    // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt\n    out_bits = current_block->direction_bits;\n\n    // Set direction and check limit switches\n    if ((out_bits & (1<<X_AXIS)) != 0) {   // -direction\n      WRITE(X_DIR_PIN, INVERT_X_DIR);\n      CHECK_ENDSTOPS\n      {\n        #if X_MIN_PIN > -1\n          bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOP_INVERT);\n          if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {\n            if(!is_homing)\n              endstop_x_hit=true;\n            else  \n              step_events_completed = current_block->step_event_count;\n          }\n          else\n          {\n            endstop_x_hit=false;\n          }\n          old_x_min_endstop = x_min_endstop;\n        #else\n          endstop_x_hit=false;\n        #endif\n      }\n    }\n    else { // +direction \n      WRITE(X_DIR_PIN,!INVERT_X_DIR);\n      CHECK_ENDSTOPS \n      {\n        #if X_MAX_PIN > -1\n          bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOP_INVERT);\n          if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){\n            if(!is_homing)\n              endstop_x_hit=true;\n            else    \n              step_events_completed = current_block->step_event_count;\n          }\n          else\n          {\n            endstop_x_hit=false;\n          }\n          old_x_max_endstop = x_max_endstop;\n        #else\n          endstop_x_hit=false;\n        #endif\n      }\n    }\n\n    if ((out_bits & (1<<Y_AXIS)) != 0) {   // -direction\n      WRITE(Y_DIR_PIN,INVERT_Y_DIR);\n      CHECK_ENDSTOPS\n      {\n        #if Y_MIN_PIN > -1\n          bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOP_INVERT);\n          if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {\n            if(!is_homing)\n              endstop_y_hit=true;\n            else\n              step_events_completed = current_block->step_event_count;\n          }\n          else\n          {\n            endstop_y_hit=false;\n          }\n          old_y_min_endstop = y_min_endstop;\n        #else\n          endstop_y_hit=false;  \n        #endif\n      }\n    }\n    else { // +direction\n      WRITE(Y_DIR_PIN,!INVERT_Y_DIR);\n      CHECK_ENDSTOPS\n      {\n        #if Y_MAX_PIN > -1\n          bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOP_INVERT);\n          if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){\n            if(!is_homing)\n              endstop_y_hit=true;\n            else  \n              step_events_completed = current_block->step_event_count;\n          }\n          else\n          {\n            endstop_y_hit=false;\n          }\n          old_y_max_endstop = y_max_endstop;\n        #else\n          endstop_y_hit=false;  \n        #endif\n      }\n    }\n\n    if ((out_bits & (1<<Z_AXIS)) != 0) {   // -direction\n      WRITE(Z_DIR_PIN,INVERT_Z_DIR);\n      CHECK_ENDSTOPS\n      {\n        #if Z_MIN_PIN > -1\n          bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOP_INVERT);\n          if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) {\n            if(!is_homing)  \n              endstop_z_hit=true;\n            else  \n              step_events_completed = current_block->step_event_count;\n          }\n          else\n          {\n            endstop_z_hit=false;\n          }\n          old_z_min_endstop = z_min_endstop;\n        #else\n          endstop_z_hit=false;  \n        #endif\n      }\n    }\n    else { // +direction\n      WRITE(Z_DIR_PIN,!INVERT_Z_DIR);\n      CHECK_ENDSTOPS\n      {\n        #if Z_MAX_PIN > -1\n          bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOP_INVERT);\n          if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) {\n            if(!is_homing)\n              endstop_z_hit=true;\n            else  \n              step_events_completed = current_block->step_event_count;\n          }\n          else\n          {\n            endstop_z_hit=false;\n          }\n          old_z_max_endstop = z_max_endstop;\n        #else\n          endstop_z_hit=false;  \n        #endif\n      }\n    }\n\n    #ifndef ADVANCE\n      if ((out_bits & (1<<E_AXIS)) != 0) {  // -direction\n        WRITE(E_DIR_PIN,INVERT_E_DIR);\n      }\n      else { // +direction\n        WRITE(E_DIR_PIN,!INVERT_E_DIR);\n      }\n    #endif //!ADVANCE\n    \n\n    \n    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) \n      \n      #ifdef ADVANCE\n      counter_e += current_block->steps_e;\n      if (counter_e > 0) {\n        counter_e -= current_block->step_event_count;\n        if ((out_bits & (1<<E_AXIS)) != 0) { // - direction\n          e_steps--;\n        }\n        else {\n          e_steps++;\n        }\n      }    \n      #endif //ADVANCE\n\n\n      counter_x += current_block->steps_x;\n      if (counter_x > 0) {\n        if(!endstop_x_hit)\n        {\n          if(virtual_steps_x)\n            virtual_steps_x--;\n          else\n            WRITE(X_STEP_PIN, HIGH);\n        }\n        else\n          virtual_steps_x++;\n          \n        counter_x -= current_block->step_event_count;\n        WRITE(X_STEP_PIN, LOW);\n      }\n\n      counter_y += current_block->steps_y;\n      if (counter_y > 0) {\n        if(!endstop_y_hit)\n        {\n          if(virtual_steps_y)\n            virtual_steps_y--;\n          else\n            WRITE(Y_STEP_PIN, HIGH);\n        }\n        else\n          virtual_steps_y++;\n            \n        counter_y -= current_block->step_event_count;\n        WRITE(Y_STEP_PIN, LOW);\n      }\n\n      counter_z += current_block->steps_z;\n      if (counter_z > 0) {\n        if(!endstop_z_hit)\n        {\n          if(virtual_steps_z)\n            virtual_steps_z--;\n          else\n            WRITE(Z_STEP_PIN, HIGH);\n        }\n        else\n          virtual_steps_z++;\n          \n        counter_z -= current_block->step_event_count;\n        WRITE(Z_STEP_PIN, LOW);\n      }\n\n      #ifndef ADVANCE\n        counter_e += current_block->steps_e;\n        if (counter_e > 0) {\n          WRITE(E_STEP_PIN, HIGH);\n          counter_e -= current_block->step_event_count;\n          WRITE(E_STEP_PIN, LOW);\n        }\n      #endif //!ADVANCE\n\n      step_events_completed += 1;  \n      if(step_events_completed >= current_block->step_event_count) break;\n      \n    }\n    // Calculare new timer value\n    unsigned short timer;\n    unsigned short step_rate;\n    if (step_events_completed <= (unsigned long int)current_block->accelerate_until) {\n      \n      MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);\n      acc_step_rate += current_block->initial_rate;\n      \n      // upper limit\n      if(acc_step_rate > current_block->nominal_rate)\n        acc_step_rate = current_block->nominal_rate;\n\n      // step_rate to timer interval\n      timer = calc_timer(acc_step_rate);\n      OCR1A = timer;\n      acceleration_time += timer;\n      #ifdef ADVANCE\n        for(int8_t i=0; i < step_loops; i++) {\n          advance += advance_rate;\n        }\n        //if(advance > current_block->advance) advance = current_block->advance;\n        // Do E steps + advance steps\n        e_steps += ((advance >>8) - old_advance);\n        old_advance = advance >>8;  \n        \n      #endif\n    } \n    else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {   \n      MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);\n      \n      if(step_rate > acc_step_rate) { // Check step_rate stays positive\n        step_rate = current_block->final_rate;\n      }\n      else {\n        step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point.\n      }\n\n      // lower limit\n      if(step_rate < current_block->final_rate)\n        step_rate = current_block->final_rate;\n\n      // step_rate to timer interval\n      timer = calc_timer(step_rate);\n      OCR1A = timer;\n      deceleration_time += timer;\n      #ifdef ADVANCE\n        for(int8_t i=0; i < step_loops; i++) {\n          advance -= advance_rate;\n        }\n        if(advance < final_advance) advance = final_advance;\n        // Do E steps + advance steps\n        e_steps += ((advance >>8) - old_advance);\n        old_advance = advance >>8;  \n      #endif //ADVANCE\n    }\n    else {\n      OCR1A = OCR1A_nominal;\n    }\n\n    // If current block is finished, reset pointer \n    if (step_events_completed >= current_block->step_event_count) {\n      current_block = NULL;\n      plan_discard_current_block();\n    }   \n  } \n}\n\n#ifdef ADVANCE\n\nunsigned char old_OCR0A;\n// Timer interrupt for E. e_steps is set in the main routine;\n// Timer 0 is shared with millies\nISR(TIMER0_COMPA_vect)\n{\n    old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz)\n    OCR0A = old_OCR0A;\n  // Set E direction (Depends on E direction + advance)\n  for(unsigned char i=0; i<4;i++) \n  {\n      if (e_steps != 0)\n      {\n        WRITE(E0_STEP_PIN, LOW);\n        if (e_steps < 0) {\n          WRITE(E0_DIR_PIN, INVERT_E0_DIR);\n          e_steps++;\n          WRITE(E0_STEP_PIN, HIGH);\n        } \n        else if (e_steps > 0) {\n          WRITE(E0_DIR_PIN, !INVERT_E0_DIR);\n       \t  e_steps--;\n    \t  WRITE(E0_STEP_PIN, HIGH);\n  \t    }\n      }\n    }\n  }\n#endif // ADVANCE\n\nvoid st_init()\n{\n  // waveform generation = 0100 = CTC\n  TCCR1B &= ~(1<<WGM13);\n  TCCR1B |=  (1<<WGM12);\n  TCCR1A &= ~(1<<WGM11); \n  TCCR1A &= ~(1<<WGM10);\n\n  // output mode = 00 (disconnected)\n  TCCR1A &= ~(3<<COM1A0); \n  TCCR1A &= ~(3<<COM1B0); \n\n  // Set the timer pre-scaler\n  // Generally we use a divider of 8, resulting in a 2MHz timer\n  // frequency on a 16MHz MCU. If you are going to change this, be\n  // sure to regenerate speed_lookuptable.h with\n  // create_speed_lookuptable.py\n  TCCR1B = (TCCR1B & ~(0x07<<CS10)) | (2<<CS10); // 2MHz timer\n\n  OCR1A = 0x4000;\n  TCNT1 = 0;\n  ENABLE_STEPPER_DRIVER_INTERRUPT();\n\n#ifdef ADVANCE\n  #if defined(TCCR0A) && defined(WGM01)\n    TCCR0A &= ~(1<<WGM01);\n    TCCR0A &= ~(1<<WGM00);\n  #endif  \n  e_steps = 0;\n  TIMSK0 |= (1<<OCIE0A);\n#endif //ADVANCE\n\n  #ifdef ENDSTOPS_ONLY_FOR_HOMING\n    enable_endstops(false);\n  #else\n    enable_endstops(true);\n  #endif\n  \n  sei();\n}\n\n// Block until all buffered steps are executed\nvoid st_synchronize()\n{\n  while(blocks_queued()) {\n    manage_heater();\n    manage_inactivity(1);\n    #if (MINIMUM_FAN_START_SPEED > 0)\n      manage_fan_start_speed();\n    #endif\n  }   \n}\n\n\n#ifdef DEBUG\nvoid log_message(char*   message) {\n  Serial.print(\"DEBUG\"); Serial.println(message);\n}\n\nvoid log_bool(char* message, bool value) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": \"); Serial.println(value);\n}\n\nvoid log_int(char* message, int value) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": \"); Serial.println(value);\n}\n\nvoid log_long(char* message, long value) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": \"); Serial.println(value);\n}\n\nvoid log_float(char* message, float value) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": \"); Serial.println(value);\n}\n\nvoid log_uint(char* message, unsigned int value) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": \"); Serial.println(value);\n}\n\nvoid log_ulong(char* message, unsigned long value) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": \"); Serial.println(value);\n}\n\nvoid log_int_array(char* message, int value[], int array_lenght) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": {\");\n  for(int i=0; i < array_lenght; i++){\n    Serial.print(value[i]);\n    if(i != array_lenght-1) Serial.print(\", \");\n  }\n  Serial.println(\"}\");\n}\n\nvoid log_long_array(char* message, long value[], int array_lenght) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": {\");\n  for(int i=0; i < array_lenght; i++){\n    Serial.print(value[i]);\n    if(i != array_lenght-1) Serial.print(\", \");\n  }\n  Serial.println(\"}\");\n}\n\nvoid log_float_array(char* message, float value[], int array_lenght) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": {\");\n  for(int i=0; i < array_lenght; i++){\n    Serial.print(value[i]);\n    if(i != array_lenght-1) Serial.print(\", \");\n  }\n  Serial.println(\"}\");\n}\n\nvoid log_uint_array(char* message, unsigned int value[], int array_lenght) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": {\");\n  for(int i=0; i < array_lenght; i++){\n    Serial.print(value[i]);\n    if(i != array_lenght-1) Serial.print(\", \");\n  }\n  Serial.println(\"}\");\n}\n\nvoid log_ulong_array(char* message, unsigned long value[], int array_lenght) {\n  Serial.print(\"DEBUG\"); Serial.print(message); Serial.print(\": {\");\n  for(int i=0; i < array_lenght; i++){\n    Serial.print(value[i]);\n    if(i != array_lenght-1) Serial.print(\", \");\n  }\n  Serial.println(\"}\");\n}\n#endif\n"
  },
  {
    "path": "Sprinter/arc_func.cpp",
    "content": "/*\n  arc_func.c - high level interface for issuing motion commands\n  Part of Grbl\n\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  Copyright (c) 2011 Sungeun K. Jeon\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include <avr/pgmspace.h>\n#include <math.h>\n\n#include \"Configuration.h\"\n#include \"Sprinter.h\"\n\n#ifdef USE_ARC_FUNCTION\n// The arc is approximated by generating a huge number of tiny, linear segments. The length of each \n// segment is configured in settings.mm_per_arc_segment.  \nvoid mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, \n  uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise)\n{      \n  //   int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();\n  //   plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc\n  float center_axis0 = position[axis_0] + offset[axis_0];\n  float center_axis1 = position[axis_1] + offset[axis_1];\n  float linear_travel = target[axis_linear] - position[axis_linear];\n  float extruder_travel = target[E_AXIS] - position[E_AXIS];\n  float r_axis0 = -offset[axis_0];  // Radius vector from center to current location\n  float r_axis1 = -offset[axis_1];\n  float rt_axis0 = target[axis_0] - center_axis0;\n  float rt_axis1 = target[axis_1] - center_axis1;\n  \n  // CCW angle between position and target from circle center. Only one atan2() trig computation required.\n  float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);\n  if (angular_travel < 0) { angular_travel += 2*M_PI; }\n  if (isclockwise) { angular_travel -= 2*M_PI; }\n  \n  float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));\n  if (millimeters_of_travel < 0.001) { return; }\n  uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT);\n  if(segments == 0) segments = 1;\n\n  /*  \n    // Multiply inverse feed_rate to compensate for the fact that this movement is approximated\n    // by a number of discrete segments. The inverse feed_rate should be correct for the sum of \n    // all segments.\n    if (invert_feed_rate) { feed_rate *= segments; }\n  */\n  float theta_per_segment = angular_travel/segments;\n  float linear_per_segment = linear_travel/segments;\n  float extruder_per_segment = extruder_travel/segments;\n  \n  /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,\n     and phi is the angle of rotation. Based on the solution approach by Jens Geisler.\n         r_T = [cos(phi) -sin(phi);\n                sin(phi)  cos(phi] * r ;\n     \n     For arc generation, the center of the circle is the axis of rotation and the radius vector is \n     defined from the circle center to the initial position. Each line segment is formed by successive\n     vector rotations. This requires only two cos() and sin() computations to form the rotation\n     matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since\n     all double numbers are single precision on the Arduino. (True double precision will not have\n     round off issues for CNC applications.) Single precision error can accumulate to be greater than\n     tool precision in some cases. Therefore, arc path correction is implemented. \n\n     Small angle approximation may be used to reduce computation overhead further. This approximation\n     holds for everything, but very small circles and large mm_per_arc_segment values. In other words,\n     theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large\n     to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for \n     numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an\n     issue for CNC machines with the single precision Arduino calculations.\n     \n     This approximation also allows mc_arc to immediately insert a line segment into the planner \n     without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied\n     a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead. \n     This is important when there are successive arc motions. \n  */\n  // Vector rotation matrix values\n  float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation\n  float sin_T = theta_per_segment;\n  \n  float arc_target[4];\n  float sin_Ti;\n  float cos_Ti;\n  float r_axisi;\n  uint16_t i;\n  int8_t count = 0;\n\n  // Initialize the linear axis\n  arc_target[axis_linear] = position[axis_linear];\n  \n  // Initialize the extruder axis\n  arc_target[E_AXIS] = position[E_AXIS];\n\n  for (i = 1; i<segments; i++) \n  { // Increment (segments-1)\n    \n    if((count == 10) || (count == 15))\n    {\n\t  //Read the next two Commands while arc is calculating\n      check_buffer_while_arc();\n    }\n\n    if (count < N_ARC_CORRECTION)  //25 pieces\n    {\n      // Apply vector rotation matrix \n      r_axisi = r_axis0*sin_T + r_axis1*cos_T;\n      r_axis0 = r_axis0*cos_T - r_axis1*sin_T;\n      r_axis1 = r_axisi;\n      count++;\n    }\n    else\n    {\n      // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.\n      // Compute exact location by applying transformation matrix from initial radius vector(=-offset).\n      cos_Ti  = cos(i*theta_per_segment);\n      sin_Ti  = sin(i*theta_per_segment);\n      r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;\n      r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;\n      count = 0;\n    }\n\n    // Update arc_target location\n    arc_target[axis_0] = center_axis0 + r_axis0;\n    arc_target[axis_1] = center_axis1 + r_axis1;\n    arc_target[axis_linear] += linear_per_segment;\n    arc_target[E_AXIS] += extruder_per_segment;\n    \n    plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate);\n    \n  }\n  // Ensure last segment arrives at target location.\n  plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate);\n\n  //   plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled);\n}\n#endif\n"
  },
  {
    "path": "Sprinter/arc_func.h",
    "content": "/*\n  arc_func.h - high level interface for issuing motion commands\n  Part of Grbl\n\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  Copyright (c) 2011 Sungeun K. Jeon\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef arc_func_h\n#define arc_func_h\n\n// Execute an arc in offset mode format. position == current xyz, target == target xyz, \n// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is\n// the direction of helical travel, radius == circle radius, isclockwise boolean. Used\n// for vector transformation direction.\nvoid mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1,\n  unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise);\n  \n#endif\n"
  },
  {
    "path": "Sprinter/createTemperatureLookup.py",
    "content": "#!/usr/bin/python\n#\n# Creates a C code lookup table for doing ADC to temperature conversion\n# on a microcontroller\n# based on: http://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html\n\"\"\"Thermistor Value Lookup Table Generator\n\nGenerates lookup to temperature values for use in a microcontroller in C format based on: \nhttp://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html\n\nThe main use is for Arduino programs that read data from the circuit board described here:\nhttp://make.rrrf.org/ts-1.0\n\nUsage: python createTemperatureLookup.py [options]\n\nOptions:\n  -h, --help            show this help\n  --r0=...          thermistor rating where # is the ohm rating of the thermistor at t0 (eg: 10K = 10000)\n  --t0=...          thermistor temp rating where # is the temperature in Celsuis to get r0 (from your datasheet)\n  --beta=...            thermistor beta rating.\u0010 see http://reprap.org/bin/view/Main/MeasuringThermistorBeta\n  --r1=...          R1 rating where # is the ohm rating of R1 (eg: 10K = 10000)\n  --r2=...          R2 rating where # is the ohm rating of R2 (eg: 10K = 10000)\n  --num-temps=...   the number of temperature points to calculate (default: 20)\n  --max-adc=...     the max ADC reading to use.  if you use R1, it limits the top value for the thermistor circuit, and thus the possible range of ADC values\n\"\"\"\n\nfrom math import *\nimport sys\nimport getopt\n\nclass Thermistor:\n    \"Class to do the thermistor maths\"\n    def __init__(self, r0, t0, beta, r1, r2):\n        self.r0 = r0                        # stated resistance, e.g. 10K\n        self.t0 = t0 + 273.15               # temperature at stated resistance, e.g. 25C\n        self.beta = beta                    # stated beta, e.g. 3500\n        self.vadc = 5.0                     # ADC reference\n        self.vcc = 5.0                      # supply voltage to potential divider\n        self.k = r0 * exp(-beta / self.t0)   # constant part of calculation\n\n        if r1 > 0:\n            self.vs = r1 * self.vcc / (r1 + r2) # effective bias voltage\n            self.rs = r1 * r2 / (r1 + r2)       # effective bias impedance\n        else:\n            self.vs = self.vcc                   # effective bias voltage\n            self.rs = r2                         # effective bias impedance\n\n    def temp(self,adc):\n        \"Convert ADC reading into a temperature in Celcius\"\n        v = adc * self.vadc / 1024          # convert the 10 bit ADC value to a voltage\n        r = self.rs * v / (self.vs - v)     # resistance of thermistor\n        return (self.beta / log(r / self.k)) - 273.15        # temperature\n\n    def setting(self, t):\n        \"Convert a temperature into a ADC value\"\n        r = self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0)) # resistance of the thermistor\n        v = self.vs * r / (self.rs + r)     # the voltage at the potential divider\n        return round(v / self.vadc * 1024)  # the ADC reading\n\ndef main(argv):\n\n    r0 = 10000;\n    t0 = 25;\n    beta = 3947;\n    r1 = 680;\n    r2 = 1600;\n    num_temps = int(20);\n    \n    try:\n        opts, args = getopt.getopt(argv, \"h\", [\"help\", \"r0=\", \"t0=\", \"beta=\", \"r1=\", \"r2=\"])\n    except getopt.GetoptError:\n        usage()\n        sys.exit(2)\n        \n    for opt, arg in opts:\n        if opt in (\"-h\", \"--help\"):\n            usage()\n            sys.exit()\n        elif opt == \"--r0\":\n            r0 = int(arg)\n        elif opt == \"--t0\":\n            t0 = int(arg)\n        elif opt == \"--beta\":\n            beta = int(arg)\n        elif opt == \"--r1\":\n            r1 = int(arg)\n        elif opt == \"--r2\":\n            r2 = int(arg)\n\n    if r1:\n        max_adc = int(1023 * r1 / (r1 + r2));\n    else:\n        max_adc = 1023\n    increment = int(max_adc/(num_temps-1));\n            \n    t = Thermistor(r0, t0, beta, r1, r2)\n\n    adcs = range(1, max_adc, increment);\n#   adcs = [1, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100, 110, 130, 150, 190, 220,  250, 300]\n    first = 1\n\n    print \"// Thermistor lookup table for RepRap Temperature Sensor Boards (http://make.rrrf.org/ts)\"\n    print \"// Made with createTemperatureLookup.py (http://svn.reprap.org/trunk/reprap/firmware/Arduino/utilities/createTemperatureLookup.py)\"\n    print \"// ./createTemperatureLookup.py --r0=%s --t0=%s --r1=%s --r2=%s --beta=%s --max-adc=%s\" % (r0, t0, r1, r2, beta, max_adc)\n    print \"// r0: %s\" % (r0)\n    print \"// t0: %s\" % (t0)\n    print \"// r1: %s\" % (r1)\n    print \"// r2: %s\" % (r2)\n    print \"// beta: %s\" % (beta)\n    print \"// max adc: %s\" % (max_adc)\n    print \"#define NUMTEMPS %s\" % (len(adcs))\n    print \"short temptable[NUMTEMPS][2] = {\"\n\n    counter = 0\n    for adc in adcs:\n        counter = counter +1\n        if counter == len(adcs):\n            print \"   {%s, %s}\" % (adc, int(t.temp(adc)))\n        else:\n            print \"   {%s, %s},\" % (adc, int(t.temp(adc)))\n    print \"};\"\n    \ndef usage():\n    print __doc__\n\nif __name__ == \"__main__\":\n    main(sys.argv[1:])\n"
  },
  {
    "path": "Sprinter/fastio.h",
    "content": "/*\n\tThis code contibuted by Triffid_Hunter and modified by Kliment\n\twhy double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html\n*/\n\n#ifndef\t_ARDUINO_H\n#define\t_ARDUINO_H\n\n#include\t<avr/io.h>\n\n/*\n\tutility functions\n*/\n\n#ifndef\t\tMASK\n/// MASKING- returns \\f$2^PIN\\f$\n\t#define\t\tMASK(PIN)\t\t\t\t(1 << PIN)\n#endif\n\n/*\n\tmagic I/O routines\n\n\tnow you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0);\n*/\n\n/// Read a pin\n#define\t\t_READ(IO)\t\t\t\t\t((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))\n/// write to a pin\n#define\t\t_WRITE(IO, v)\t\t\tdo { if (v) {DIO ##  IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ##  IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0)\n/// toggle a pin\n#define\t\t_TOGGLE(IO)\t\t\t\tdo {DIO ##  IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0)\n\n/// set pin as input\n#define\t\t_SET_INPUT(IO)\t\tdo {DIO ##  IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0)\n/// set pin as output\n#define\t\t_SET_OUTPUT(IO)\t\tdo {DIO ##  IO ## _DDR |=  MASK(DIO ## IO ## _PIN); } while (0)\n\n/// check if pin is an input\n#define\t\t_GET_INPUT(IO)\t\t((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0)\n/// check if pin is an output\n#define\t\t_GET_OUTPUT(IO)\t\t((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)\n\n//\twhy double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html\n\n/// Read a pin wrapper\n#define\t\tREAD(IO)\t\t\t\t\t_READ(IO)\n/// Write to a pin wrapper\n#define\t\tWRITE(IO, v)\t\t\t_WRITE(IO, v)\n/// toggle a pin wrapper\n#define\t\tTOGGLE(IO)\t\t\t\t_TOGGLE(IO)\n\n/// set pin as input wrapper\n#define\t\tSET_INPUT(IO)\t\t\t_SET_INPUT(IO)\n/// set pin as output wrapper\n#define\t\tSET_OUTPUT(IO)\t\t_SET_OUTPUT(IO)\n\n/// check if pin is an input wrapper\n#define\t\tGET_INPUT(IO)\t\t\t_GET_INPUT(IO)\n/// check if pin is an output wrapper\n#define\t\tGET_OUTPUT(IO)\t\t_GET_OUTPUT(IO)\n\n/*\n\tports and functions\n\n\tadded as necessary or if I feel like it- not a comprehensive list!\n*/\n\n#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__)\n// UART\n#define\tRXD\t\t\t\t\tDIO0\n#define\tTXD\t\t\t\t\tDIO1\n\n// SPI\n#define\tSCK\t\t\t\t\tDIO13\n#define\tMISO\t\t\t\tDIO12\n#define\tMOSI\t\t\t\tDIO11\n#define\tSS\t\t\t\t\tDIO10\n\n// TWI (I2C)\n#define\tSCL\t\t\t\t\tAIO5\n#define\tSDA\t\t\t\t\tAIO4\n\n// timers and PWM\n#define\tOC0A\t\t\t\tDIO6\n#define\tOC0B\t\t\t\tDIO5\n#define\tOC1A\t\t\t\tDIO9\n#define\tOC1B\t\t\t\tDIO10\n#define\tOC2A\t\t\t\tDIO11\n#define\tOC2B\t\t\t\tDIO3\n\n#define\tDEBUG_LED\t\tAIO5\n\n/*\npins\n*/\n\n#define DIO0_PIN\t\tPIND0\n#define DIO0_RPORT\tPIND\n#define DIO0_WPORT\tPORTD\n#define DIO0_DDR\t\tDDRD\n#define DIO0_PWM\t\tNULL\n\n#define DIO1_PIN\t\tPIND1\n#define DIO1_RPORT\tPIND\n#define DIO1_WPORT\tPORTD\n#define DIO1_DDR\t\tDDRD\n#define DIO1_PWM\t\tNULL\n\n#define DIO2_PIN\t\tPIND2\n#define DIO2_RPORT\tPIND\n#define DIO2_WPORT\tPORTD\n#define DIO2_DDR\t\tDDRD\n#define DIO2_PWM\t\tNULL\n\n#define DIO3_PIN\t\tPIND3\n#define DIO3_RPORT\tPIND\n#define DIO3_WPORT\tPORTD\n#define DIO3_DDR\t\tDDRD\n#define DIO3_PWM\t\t&OCR2B\n\n#define DIO4_PIN\t\tPIND4\n#define DIO4_RPORT\tPIND\n#define DIO4_WPORT\tPORTD\n#define DIO4_DDR\t\tDDRD\n#define DIO4_PWM\t\tNULL\n\n#define DIO5_PIN\t\tPIND5\n#define DIO5_RPORT\tPIND\n#define DIO5_WPORT\tPORTD\n#define DIO5_DDR\t\tDDRD\n#define DIO5_PWM\t\t&OCR0B\n\n#define DIO6_PIN\t\tPIND6\n#define DIO6_RPORT\tPIND\n#define DIO6_WPORT\tPORTD\n#define DIO6_DDR\t\tDDRD\n#define DIO6_PWM\t\t&OCR0A\n\n#define DIO7_PIN\t\tPIND7\n#define DIO7_RPORT\tPIND\n#define DIO7_WPORT\tPORTD\n#define DIO7_DDR\t\tDDRD\n#define DIO7_PWM\t\tNULL\n\n#define DIO8_PIN\t\tPINB0\n#define DIO8_RPORT\tPINB\n#define DIO8_WPORT\tPORTB\n#define DIO8_DDR\t\tDDRB\n#define DIO8_PWM\t\tNULL\n\n#define DIO9_PIN\t\tPINB1\n#define DIO9_RPORT\tPINB\n#define DIO9_WPORT\tPORTB\n#define DIO9_DDR\t\tDDRB\n#define DIO9_PWM\t\tNULL\n\n#define DIO10_PIN\t\tPINB2\n#define DIO10_RPORT\tPINB\n#define DIO10_WPORT\tPORTB\n#define DIO10_DDR\t\tDDRB\n#define DIO10_PWM\t\tNULL\n\n#define DIO11_PIN\t\tPINB3\n#define DIO11_RPORT\tPINB\n#define DIO11_WPORT\tPORTB\n#define DIO11_DDR\t\tDDRB\n#define DIO11_PWM\t\t&OCR2A\n\n#define DIO12_PIN\t\tPINB4\n#define DIO12_RPORT\tPINB\n#define DIO12_WPORT\tPORTB\n#define DIO12_DDR\t\tDDRB\n#define DIO12_PWM\t\tNULL\n\n#define DIO13_PIN\t\tPINB5\n#define DIO13_RPORT\tPINB\n#define DIO13_WPORT\tPORTB\n#define DIO13_DDR\t\tDDRB\n#define DIO13_PWM\t\tNULL\n\n\n#define DIO14_PIN\t\tPINC0\n#define DIO14_RPORT\tPINC\n#define DIO14_WPORT\tPORTC\n#define DIO14_DDR\t\tDDRC\n#define DIO14_PWM\t\tNULL\n\n#define DIO15_PIN\t\tPINC1\n#define DIO15_RPORT\tPINC\n#define DIO15_WPORT\tPORTC\n#define DIO15_DDR\t\tDDRC\n#define DIO15_PWM\t\tNULL\n\n#define DIO16_PIN\t\tPINC2\n#define DIO16_RPORT\tPINC\n#define DIO16_WPORT\tPORTC\n#define DIO16_DDR\t\tDDRC\n#define DIO16_PWM\t\tNULL\n\n#define DIO17_PIN\t\tPINC3\n#define DIO17_RPORT\tPINC\n#define DIO17_WPORT\tPORTC\n#define DIO17_DDR\t\tDDRC\n#define DIO17_PWM\t\tNULL\n\n#define DIO18_PIN\t\tPINC4\n#define DIO18_RPORT\tPINC\n#define DIO18_WPORT\tPORTC\n#define DIO18_DDR\t\tDDRC\n#define DIO18_PWM\t\tNULL\n\n#define DIO19_PIN\t\tPINC5\n#define DIO19_RPORT\tPINC\n#define DIO19_WPORT\tPORTC\n#define DIO19_DDR\t\tDDRC\n#define DIO19_PWM\t\tNULL\n\n#define DIO20_PIN\t\tPINC6\n#define DIO20_RPORT\tPINC\n#define DIO20_WPORT\tPORTC\n#define DIO20_DDR\t\tDDRC\n#define DIO20_PWM\t\tNULL\n\n#define DIO21_PIN\t\tPINC7\n#define DIO21_RPORT\tPINC\n#define DIO21_WPORT\tPORTC\n#define DIO21_DDR\t\tDDRC\n#define DIO21_PWM\t\tNULL\n\n\n\n#undef PB0\n#define PB0_PIN\t\t\tPINB0\n#define PB0_RPORT\t\tPINB\n#define PB0_WPORT\t\tPORTB\n#define PB0_DDR\t\t\tDDRB\n#define PB0_PWM\t\t\tNULL\n\n#undef PB1\n#define PB1_PIN\t\t\tPINB1\n#define PB1_RPORT\t\tPINB\n#define PB1_WPORT\t\tPORTB\n#define PB1_DDR\t\t\tDDRB\n#define PB1_PWM\t\t\tNULL\n\n#undef PB2\n#define PB2_PIN\t\t\tPINB2\n#define PB2_RPORT\t\tPINB\n#define PB2_WPORT\t\tPORTB\n#define PB2_DDR\t\t\tDDRB\n#define PB2_PWM\t\t\tNULL\n\n#undef PB3\n#define PB3_PIN\t\t\tPINB3\n#define PB3_RPORT\t\tPINB\n#define PB3_WPORT\t\tPORTB\n#define PB3_DDR\t\t\tDDRB\n#define PB3_PWM\t\t\t&OCR2A\n\n#undef PB4\n#define PB4_PIN\t\t\tPINB4\n#define PB4_RPORT\t\tPINB\n#define PB4_WPORT\t\tPORTB\n#define PB4_DDR\t\t\tDDRB\n#define PB4_PWM\t\t\tNULL\n\n#undef PB5\n#define PB5_PIN\t\t\tPINB5\n#define PB5_RPORT\t\tPINB\n#define PB5_WPORT\t\tPORTB\n#define PB5_DDR\t\t\tDDRB\n#define PB5_PWM\t\t\tNULL\n\n#undef PB6\n#define PB6_PIN\t\t\tPINB6\n#define PB6_RPORT\t\tPINB\n#define PB6_WPORT\t\tPORTB\n#define PB6_DDR\t\t\tDDRB\n#define PB6_PWM\t\t\tNULL\n\n#undef PB7\n#define PB7_PIN\t\t\tPINB7\n#define PB7_RPORT\t\tPINB\n#define PB7_WPORT\t\tPORTB\n#define PB7_DDR\t\t\tDDRB\n#define PB7_PWM\t\t\tNULL\n\n\n#undef PC0\n#define PC0_PIN\t\t\tPINC0\n#define PC0_RPORT\t\tPINC\n#define PC0_WPORT\t\tPORTC\n#define PC0_DDR\t\t\tDDRC\n#define PC0_PWM\t\t\tNULL\n\n#undef PC1\n#define PC1_PIN\t\t\tPINC1\n#define PC1_RPORT\t\tPINC\n#define PC1_WPORT\t\tPORTC\n#define PC1_DDR\t\t\tDDRC\n#define PC1_PWM\t\t\tNULL\n\n#undef PC2\n#define PC2_PIN\t\t\tPINC2\n#define PC2_RPORT\t\tPINC\n#define PC2_WPORT\t\tPORTC\n#define PC2_DDR\t\t\tDDRC\n#define PC2_PWM\t\t\tNULL\n\n#undef PC3\n#define PC3_PIN\t\t\tPINC3\n#define PC3_RPORT\t\tPINC\n#define PC3_WPORT\t\tPORTC\n#define PC3_DDR\t\t\tDDRC\n#define PC3_PWM\t\t\tNULL\n\n#undef PC4\n#define PC4_PIN\t\t\tPINC4\n#define PC4_RPORT\t\tPINC\n#define PC4_WPORT\t\tPORTC\n#define PC4_DDR\t\t\tDDRC\n#define PC4_PWM\t\t\tNULL\n\n#undef PC5\n#define PC5_PIN\t\t\tPINC5\n#define PC5_RPORT\t\tPINC\n#define PC5_WPORT\t\tPORTC\n#define PC5_DDR\t\t\tDDRC\n#define PC5_PWM\t\t\tNULL\n\n#undef PC6\n#define PC6_PIN\t\t\tPINC6\n#define PC6_RPORT\t\tPINC\n#define PC6_WPORT\t\tPORTC\n#define PC6_DDR\t\t\tDDRC\n#define PC6_PWM\t\t\tNULL\n\n#undef PC7\n#define PC7_PIN\t\t\tPINC7\n#define PC7_RPORT\t\tPINC\n#define PC7_WPORT\t\tPORTC\n#define PC7_DDR\t\t\tDDRC\n#define PC7_PWM\t\t\tNULL\n\n\n#undef PD0\n#define PD0_PIN\t\t\tPIND0\n#define PD0_RPORT\t\tPIND\n#define PD0_WPORT\t\tPORTD\n#define PD0_DDR\t\t\tDDRD\n#define PD0_PWM\t\t\tNULL\n\n#undef PD1\n#define PD1_PIN\t\t\tPIND1\n#define PD1_RPORT\t\tPIND\n#define PD1_WPORT\t\tPORTD\n#define PD1_DDR\t\t\tDDRD\n#define PD1_PWM\t\t\tNULL\n\n#undef PD2\n#define PD2_PIN\t\t\tPIND2\n#define PD2_RPORT\t\tPIND\n#define PD2_WPORT\t\tPORTD\n#define PD2_DDR\t\t\tDDRD\n#define PD2_PWM\t\t\tNULL\n\n#undef PD3\n#define PD3_PIN\t\t\tPIND3\n#define PD3_RPORT\t\tPIND\n#define PD3_WPORT\t\tPORTD\n#define PD3_DDR\t\t\tDDRD\n#define PD3_PWM\t\t\t&OCR2B\n\n#undef PD4\n#define PD4_PIN\t\t\tPIND4\n#define PD4_RPORT\t\tPIND\n#define PD4_WPORT\t\tPORTD\n#define PD4_DDR\t\t\tDDRD\n#define PD4_PWM\t\t\tNULL\n\n#undef PD5\n#define PD5_PIN\t\t\tPIND5\n#define PD5_RPORT\t\tPIND\n#define PD5_WPORT\t\tPORTD\n#define PD5_DDR\t\t\tDDRD\n#define PD5_PWM\t\t\t&OCR0B\n\n#undef PD6\n#define PD6_PIN\t\t\tPIND6\n#define PD6_RPORT\t\tPIND\n#define PD6_WPORT\t\tPORTD\n#define PD6_DDR\t\t\tDDRD\n#define PD6_PWM\t\t\t&OCR0A\n\n#undef PD7\n#define PD7_PIN\t\t\tPIND7\n#define PD7_RPORT\t\tPIND\n#define PD7_WPORT\t\tPORTD\n#define PD7_DDR\t\t\tDDRD\n#define PD7_PWM\t\t\tNULL\n#endif\t/*\t_AVR_ATmega{168,328,328P}__ */\n\n#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)\n// UART\n#define\tRXD\t\t\t\t\tDIO8\n#define\tTXD\t\t\t\t\tDIO9\n#define\tRXD0\t\t\t\tDIO8\n#define\tTXD0\t\t\t\tDIO9\n\n#define\tRXD1\t\t\t\tDIO10\n#define\tTXD1\t\t\t\tDIO11\n\n// SPI\n#define\tSCK\t\t\t\t\tDIO7\n#define\tMISO\t\t\t\tDIO6\n#define\tMOSI\t\t\t\tDIO5\n#define\tSS\t\t\t\t\tDIO4\n\n// TWI (I2C)\n#define\tSCL\t\t\t\t\tDIO16\n#define\tSDA\t\t\t\t\tDIO17\n\n// timers and PWM\n#define\tOC0A\t\t\t\tDIO3\n#define\tOC0B\t\t\t\tDIO4\n#define\tOC1A\t\t\t\tDIO13\n#define\tOC1B\t\t\t\tDIO12\n#define\tOC2A\t\t\t\tDIO15\n#define\tOC2B\t\t\t\tDIO14\n\n#define\tDEBUG_LED\t\tDIO0\n/*\npins\n*/\n\n#define DIO0_PIN\t\tPINB0\n#define DIO0_RPORT\tPINB\n#define DIO0_WPORT\tPORTB\n#define DIO0_DDR\t\tDDRB\n#define DIO0_PWM\t\tNULL\n\n#define DIO1_PIN\t\tPINB1\n#define DIO1_RPORT\tPINB\n#define DIO1_WPORT\tPORTB\n#define DIO1_DDR\t\tDDRB\n#define DIO1_PWM\t\tNULL\n\n#define DIO2_PIN\t\tPINB2\n#define DIO2_RPORT\tPINB\n#define DIO2_WPORT\tPORTB\n#define DIO2_DDR\t\tDDRB\n#define DIO2_PWM\t\tNULL\n\n#define DIO3_PIN\t\tPINB3\n#define DIO3_RPORT\tPINB\n#define DIO3_WPORT\tPORTB\n#define DIO3_DDR\t\tDDRB\n#define DIO3_PWM\t\t&OCR0A\n\n#define DIO4_PIN\t\tPINB4\n#define DIO4_RPORT\tPINB\n#define DIO4_WPORT\tPORTB\n#define DIO4_DDR\t\tDDRB\n#define DIO4_PWM\t\t&OCR0B\n\n#define DIO5_PIN\t\tPINB5\n#define DIO5_RPORT\tPINB\n#define DIO5_WPORT\tPORTB\n#define DIO5_DDR\t\tDDRB\n#define DIO5_PWM\t\tNULL\n\n#define DIO6_PIN\t\tPINB6\n#define DIO6_RPORT\tPINB\n#define DIO6_WPORT\tPORTB\n#define DIO6_DDR\t\tDDRB\n#define DIO6_PWM\t\tNULL\n\n#define DIO7_PIN\t\tPINB7\n#define DIO7_RPORT\tPINB\n#define DIO7_WPORT\tPORTB\n#define DIO7_DDR\t\tDDRB\n#define DIO7_PWM\t\tNULL\n\n#define DIO8_PIN\t\tPIND0\n#define DIO8_RPORT\tPIND\n#define DIO8_WPORT\tPORTD\n#define DIO8_DDR\t\tDDRD\n#define DIO8_PWM\t\tNULL\n\n#define DIO9_PIN\t\tPIND1\n#define DIO9_RPORT\tPIND\n#define DIO9_WPORT\tPORTD\n#define DIO9_DDR\t\tDDRD\n#define DIO9_PWM\t\tNULL\n\n#define DIO10_PIN\t\tPIND2\n#define DIO10_RPORT\tPIND\n#define DIO10_WPORT\tPORTD\n#define DIO10_DDR\t\tDDRD\n#define DIO10_PWM\t\tNULL\n\n#define DIO11_PIN\t\tPIND3\n#define DIO11_RPORT\tPIND\n#define DIO11_WPORT\tPORTD\n#define DIO11_DDR\t\tDDRD\n#define DIO11_PWM\t\tNULL\n\n#define DIO12_PIN\t\tPIND4\n#define DIO12_RPORT\tPIND\n#define DIO12_WPORT\tPORTD\n#define DIO12_DDR\t\tDDRD\n#define DIO12_PWM\t\tNULL\n\n#define DIO13_PIN\t\tPIND5\n#define DIO13_RPORT\tPIND\n#define DIO13_WPORT\tPORTD\n#define DIO13_DDR\t\tDDRD\n#define DIO13_PWM\t\tNULL\n\n#define DIO14_PIN\t\tPIND6\n#define DIO14_RPORT\tPIND\n#define DIO14_WPORT\tPORTD\n#define DIO14_DDR\t\tDDRD\n#define DIO14_PWM\t\t&OCR2B\n\n#define DIO15_PIN\t\tPIND7\n#define DIO15_RPORT\tPIND\n#define DIO15_WPORT\tPORTD\n#define DIO15_DDR\t\tDDRD\n#define DIO15_PWM\t\t&OCR2A\n\n#define DIO16_PIN\t\tPINC0\n#define DIO16_RPORT\tPINC\n#define DIO16_WPORT\tPORTC\n#define DIO16_DDR\t\tDDRC\n#define DIO16_PWM\t\tNULL\n\n#define DIO17_PIN\t\tPINC1\n#define DIO17_RPORT\tPINC\n#define DIO17_WPORT\tPORTC\n#define DIO17_DDR\t\tDDRC\n#define DIO17_PWM\t\tNULL\n\n#define DIO18_PIN\t\tPINC2\n#define DIO18_RPORT\tPINC\n#define DIO18_WPORT\tPORTC\n#define DIO18_DDR\t\tDDRC\n#define DIO18_PWM\t\tNULL\n\n#define DIO19_PIN\t\tPINC3\n#define DIO19_RPORT\tPINC\n#define DIO19_WPORT\tPORTC\n#define DIO19_DDR\t\tDDRC\n#define DIO19_PWM\t\tNULL\n\n#define DIO20_PIN\t\tPINC4\n#define DIO20_RPORT\tPINC\n#define DIO20_WPORT\tPORTC\n#define DIO20_DDR\t\tDDRC\n#define DIO20_PWM\t\tNULL\n\n#define DIO21_PIN\t\tPINC5\n#define DIO21_RPORT\tPINC\n#define DIO21_WPORT\tPORTC\n#define DIO21_DDR\t\tDDRC\n#define DIO21_PWM\t\tNULL\n\n#define DIO22_PIN\t\tPINC6\n#define DIO22_RPORT\tPINC\n#define DIO22_WPORT\tPORTC\n#define DIO22_DDR\t\tDDRC\n#define DIO22_PWM\t\tNULL\n\n#define DIO23_PIN\t\tPINC7\n#define DIO23_RPORT\tPINC\n#define DIO23_WPORT\tPORTC\n#define DIO23_DDR\t\tDDRC\n#define DIO23_PWM\t\tNULL\n\n#define DIO24_PIN\t\tPINA7\n#define DIO24_RPORT\tPINA\n#define DIO24_WPORT\tPORTA\n#define DIO24_DDR\t\tDDRA\n#define DIO24_PWM\t\tNULL\n\n#define DIO25_PIN\t\tPINA6\n#define DIO25_RPORT\tPINA\n#define DIO25_WPORT\tPORTA\n#define DIO25_DDR\t\tDDRA\n#define DIO25_PWM\t\tNULL\n\n#define DIO26_PIN\t\tPINA5\n#define DIO26_RPORT\tPINA\n#define DIO26_WPORT\tPORTA\n#define DIO26_DDR\t\tDDRA\n#define DIO26_PWM\t\tNULL\n\n#define DIO27_PIN\t\tPINA4\n#define DIO27_RPORT\tPINA\n#define DIO27_WPORT\tPORTA\n#define DIO27_DDR\t\tDDRA\n#define DIO27_PWM\t\tNULL\n\n#define DIO28_PIN\t\tPINA3\n#define DIO28_RPORT\tPINA\n#define DIO28_WPORT\tPORTA\n#define DIO28_DDR\t\tDDRA\n#define DIO28_PWM\t\tNULL\n\n#define DIO29_PIN\t\tPINA2\n#define DIO29_RPORT\tPINA\n#define DIO29_WPORT\tPORTA\n#define DIO29_DDR\t\tDDRA\n#define DIO29_PWM\t\tNULL\n\n#define DIO30_PIN\t\tPINA1\n#define DIO30_RPORT\tPINA\n#define DIO30_WPORT\tPORTA\n#define DIO30_DDR\t\tDDRA\n#define DIO30_PWM\t\tNULL\n\n#define DIO31_PIN\t\tPINA0\n#define DIO31_RPORT\tPINA\n#define DIO31_WPORT\tPORTA\n#define DIO31_DDR\t\tDDRA\n#define DIO31_PWM\t\tNULL\n\n#define AIO0_PIN\t\tPINA0\n#define AIO0_RPORT\tPINA\n#define AIO0_WPORT\tPORTA\n#define AIO0_DDR\t\tDDRA\n#define AIO0_PWM\t\tNULL\n\n#define AIO1_PIN\t\tPINA1\n#define AIO1_RPORT\tPINA\n#define AIO1_WPORT\tPORTA\n#define AIO1_DDR\t\tDDRA\n#define AIO1_PWM\t\tNULL\n\n#define AIO2_PIN\t\tPINA2\n#define AIO2_RPORT\tPINA\n#define AIO2_WPORT\tPORTA\n#define AIO2_DDR\t\tDDRA\n#define AIO2_PWM\t\tNULL\n\n#define AIO3_PIN\t\tPINA3\n#define AIO3_RPORT\tPINA\n#define AIO3_WPORT\tPORTA\n#define AIO3_DDR\t\tDDRA\n#define AIO3_PWM\t\tNULL\n\n#define AIO4_PIN\t\tPINA4\n#define AIO4_RPORT\tPINA\n#define AIO4_WPORT\tPORTA\n#define AIO4_DDR\t\tDDRA\n#define AIO4_PWM\t\tNULL\n\n#define AIO5_PIN\t\tPINA5\n#define AIO5_RPORT\tPINA\n#define AIO5_WPORT\tPORTA\n#define AIO5_DDR\t\tDDRA\n#define AIO5_PWM\t\tNULL\n\n#define AIO6_PIN\t\tPINA6\n#define AIO6_RPORT\tPINA\n#define AIO6_WPORT\tPORTA\n#define AIO6_DDR\t\tDDRA\n#define AIO6_PWM\t\tNULL\n\n#define AIO7_PIN\t\tPINA7\n#define AIO7_RPORT\tPINA\n#define AIO7_WPORT\tPORTA\n#define AIO7_DDR\t\tDDRA\n#define AIO7_PWM\t\tNULL\n\n\n\n#undef PA0\n#define PA0_PIN\t\t\tPINA0\n#define PA0_RPORT\t\tPINA\n#define PA0_WPORT\t\tPORTA\n#define PA0_DDR\t\t\tDDRA\n#define PA0_PWM\t\t\tNULL\n\n#undef PA1\n#define PA1_PIN\t\t\tPINA1\n#define PA1_RPORT\t\tPINA\n#define PA1_WPORT\t\tPORTA\n#define PA1_DDR\t\t\tDDRA\n#define PA1_PWM\t\t\tNULL\n\n#undef PA2\n#define PA2_PIN\t\t\tPINA2\n#define PA2_RPORT\t\tPINA\n#define PA2_WPORT\t\tPORTA\n#define PA2_DDR\t\t\tDDRA\n#define PA2_PWM\t\t\tNULL\n\n#undef PA3\n#define PA3_PIN\t\t\tPINA3\n#define PA3_RPORT\t\tPINA\n#define PA3_WPORT\t\tPORTA\n#define PA3_DDR\t\t\tDDRA\n#define PA3_PWM\t\t\tNULL\n\n#undef PA4\n#define PA4_PIN\t\t\tPINA4\n#define PA4_RPORT\t\tPINA\n#define PA4_WPORT\t\tPORTA\n#define PA4_DDR\t\t\tDDRA\n#define PA4_PWM\t\t\tNULL\n\n#undef PA5\n#define PA5_PIN\t\t\tPINA5\n#define PA5_RPORT\t\tPINA\n#define PA5_WPORT\t\tPORTA\n#define PA5_DDR\t\t\tDDRA\n#define PA5_PWM\t\t\tNULL\n\n#undef PA6\n#define PA6_PIN\t\t\tPINA6\n#define PA6_RPORT\t\tPINA\n#define PA6_WPORT\t\tPORTA\n#define PA6_DDR\t\t\tDDRA\n#define PA6_PWM\t\t\tNULL\n\n#undef PA7\n#define PA7_PIN\t\t\tPINA7\n#define PA7_RPORT\t\tPINA\n#define PA7_WPORT\t\tPORTA\n#define PA7_DDR\t\t\tDDRA\n#define PA7_PWM\t\t\tNULL\n\n\n#undef PB0\n#define PB0_PIN\t\t\tPINB0\n#define PB0_RPORT\t\tPINB\n#define PB0_WPORT\t\tPORTB\n#define PB0_DDR\t\t\tDDRB\n#define PB0_PWM\t\t\tNULL\n\n#undef PB1\n#define PB1_PIN\t\t\tPINB1\n#define PB1_RPORT\t\tPINB\n#define PB1_WPORT\t\tPORTB\n#define PB1_DDR\t\t\tDDRB\n#define PB1_PWM\t\t\tNULL\n\n#undef PB2\n#define PB2_PIN\t\t\tPINB2\n#define PB2_RPORT\t\tPINB\n#define PB2_WPORT\t\tPORTB\n#define PB2_DDR\t\t\tDDRB\n#define PB2_PWM\t\t\tNULL\n\n#undef PB3\n#define PB3_PIN\t\t\tPINB3\n#define PB3_RPORT\t\tPINB\n#define PB3_WPORT\t\tPORTB\n#define PB3_DDR\t\t\tDDRB\n#define PB3_PWM\t\t\t&OCR0A\n\n#undef PB4\n#define PB4_PIN\t\t\tPINB4\n#define PB4_RPORT\t\tPINB\n#define PB4_WPORT\t\tPORTB\n#define PB4_DDR\t\t\tDDRB\n#define PB4_PWM\t\t\t&OCR0B\n\n#undef PB5\n#define PB5_PIN\t\t\tPINB5\n#define PB5_RPORT\t\tPINB\n#define PB5_WPORT\t\tPORTB\n#define PB5_DDR\t\t\tDDRB\n#define PB5_PWM\t\t\tNULL\n\n#undef PB6\n#define PB6_PIN\t\t\tPINB6\n#define PB6_RPORT\t\tPINB\n#define PB6_WPORT\t\tPORTB\n#define PB6_DDR\t\t\tDDRB\n#define PB6_PWM\t\t\tNULL\n\n#undef PB7\n#define PB7_PIN\t\t\tPINB7\n#define PB7_RPORT\t\tPINB\n#define PB7_WPORT\t\tPORTB\n#define PB7_DDR\t\t\tDDRB\n#define PB7_PWM\t\t\tNULL\n\n\n#undef PC0\n#define PC0_PIN\t\t\tPINC0\n#define PC0_RPORT\t\tPINC\n#define PC0_WPORT\t\tPORTC\n#define PC0_DDR\t\t\tDDRC\n#define PC0_PWM\t\t\tNULL\n\n#undef PC1\n#define PC1_PIN\t\t\tPINC1\n#define PC1_RPORT\t\tPINC\n#define PC1_WPORT\t\tPORTC\n#define PC1_DDR\t\t\tDDRC\n#define PC1_PWM\t\t\tNULL\n\n#undef PC2\n#define PC2_PIN\t\t\tPINC2\n#define PC2_RPORT\t\tPINC\n#define PC2_WPORT\t\tPORTC\n#define PC2_DDR\t\t\tDDRC\n#define PC2_PWM\t\t\tNULL\n\n#undef PC3\n#define PC3_PIN\t\t\tPINC3\n#define PC3_RPORT\t\tPINC\n#define PC3_WPORT\t\tPORTC\n#define PC3_DDR\t\t\tDDRC\n#define PC3_PWM\t\t\tNULL\n\n#undef PC4\n#define PC4_PIN\t\t\tPINC4\n#define PC4_RPORT\t\tPINC\n#define PC4_WPORT\t\tPORTC\n#define PC4_DDR\t\t\tDDRC\n#define PC4_PWM\t\t\tNULL\n\n#undef PC5\n#define PC5_PIN\t\t\tPINC5\n#define PC5_RPORT\t\tPINC\n#define PC5_WPORT\t\tPORTC\n#define PC5_DDR\t\t\tDDRC\n#define PC5_PWM\t\t\tNULL\n\n#undef PC6\n#define PC6_PIN\t\t\tPINC6\n#define PC6_RPORT\t\tPINC\n#define PC6_WPORT\t\tPORTC\n#define PC6_DDR\t\t\tDDRC\n#define PC6_PWM\t\t\tNULL\n\n#undef PC7\n#define PC7_PIN\t\t\tPINC7\n#define PC7_RPORT\t\tPINC\n#define PC7_WPORT\t\tPORTC\n#define PC7_DDR\t\t\tDDRC\n#define PC7_PWM\t\t\tNULL\n\n\n#undef PD0\n#define PD0_PIN\t\t\tPIND0\n#define PD0_RPORT\t\tPIND\n#define PD0_WPORT\t\tPORTD\n#define PD0_DDR\t\t\tDDRD\n#define PD0_PWM\t\t\tNULL\n\n#undef PD1\n#define PD1_PIN\t\t\tPIND1\n#define PD1_RPORT\t\tPIND\n#define PD1_WPORT\t\tPORTD\n#define PD1_DDR\t\t\tDDRD\n#define PD1_PWM\t\t\tNULL\n\n#undef PD2\n#define PD2_PIN\t\t\tPIND2\n#define PD2_RPORT\t\tPIND\n#define PD2_WPORT\t\tPORTD\n#define PD2_DDR\t\t\tDDRD\n#define PD2_PWM\t\t\tNULL\n\n#undef PD3\n#define PD3_PIN\t\t\tPIND3\n#define PD3_RPORT\t\tPIND\n#define PD3_WPORT\t\tPORTD\n#define PD3_DDR\t\t\tDDRD\n#define PD3_PWM\t\t\tNULL\n\n#undef PD4\n#define PD4_PIN\t\t\tPIND4\n#define PD4_RPORT\t\tPIND\n#define PD4_WPORT\t\tPORTD\n#define PD4_DDR\t\t\tDDRD\n#define PD4_PWM\t\t\tNULL\n\n#undef PD5\n#define PD5_PIN\t\t\tPIND5\n#define PD5_RPORT\t\tPIND\n#define PD5_WPORT\t\tPORTD\n#define PD5_DDR\t\t\tDDRD\n#define PD5_PWM\t\t\tNULL\n\n#undef PD6\n#define PD6_PIN\t\t\tPIND6\n#define PD6_RPORT\t\tPIND\n#define PD6_WPORT\t\tPORTD\n#define PD6_DDR\t\t\tDDRD\n#define PD6_PWM\t\t\t&OCR2B\n\n#undef PD7\n#define PD7_PIN\t\t\tPIND7\n#define PD7_RPORT\t\tPIND\n#define PD7_WPORT\t\tPORTD\n#define PD7_DDR\t\t\tDDRD\n#define PD7_PWM\t\t\t&OCR2A\n#endif\t/*\t_AVR_ATmega{644,644P,644PA,1284P}__ */\n\n#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__)\n// UART\n#define\tRXD\t\t\t\t\tDIO0\n#define\tTXD\t\t\t\t\tDIO1\n\n// SPI\n#define\tSCK\t\t\t\t\tDIO52\n#define\tMISO\t\t\t\tDIO50\n#define\tMOSI\t\t\t\tDIO51\n#define\tSS\t\t\t\t\tDIO53\n\n// TWI (I2C)\n#define\tSCL\t\t\t\t\tDIO21\n#define\tSDA\t\t\t\t\tDIO20\n\n// timers and PWM\n#define\tOC0A\t\t\t\tDIO13\n#define\tOC0B\t\t\t\tDIO4\n#define\tOC1A\t\t\t\tDIO11\n#define\tOC1B\t\t\t\tDIO12\n#define\tOC2A\t\t\t\tDIO10\n#define\tOC2B\t\t\t\tDIO9\n#define\tOC3A\t\t\t\tDIO5\n#define\tOC3B\t\t\t\tDIO2\n#define\tOC3C\t\t\t\tDIO3\n#define\tOC4A\t\t\t\tDIO6\n#define\tOC4B\t\t\t\tDIO7\n#define\tOC4C\t\t\t\tDIO8\n#define\tOC5A\t\t\t\tDIO46\n#define\tOC5B\t\t\t\tDIO45\n#define\tOC5C\t\t\t\tDIO44\n\n// change for your board\n#define\tDEBUG_LED\t\tDIO21\n\n/*\npins\n*/\n#define\tDIO0_PIN\t\tPINE0\n#define\tDIO0_RPORT\tPINE\n#define\tDIO0_WPORT\tPORTE\n#define\tDIO0_DDR\t\tDDRE\n#define DIO0_PWM\t\tNULL\n\n#define\tDIO1_PIN\t\tPINE1\n#define\tDIO1_RPORT\tPINE\n#define\tDIO1_WPORT\tPORTE\n#define\tDIO1_DDR\t\tDDRE\n#define DIO1_PWM\t\tNULL\n\n#define\tDIO2_PIN\t\tPINE4\n#define\tDIO2_RPORT\tPINE\n#define\tDIO2_WPORT\tPORTE\n#define\tDIO2_DDR\t\tDDRE\n#define DIO2_PWM\t\t&OCR3BL\n\n#define\tDIO3_PIN\t\tPINE5\n#define\tDIO3_RPORT\tPINE\n#define\tDIO3_WPORT\tPORTE\n#define\tDIO3_DDR\t\tDDRE\n#define DIO3_PWM\t\t&OCR3CL\n\n#define\tDIO4_PIN\t\tPING5\n#define\tDIO4_RPORT\tPING\n#define\tDIO4_WPORT\tPORTG\n#define\tDIO4_DDR\t\tDDRG\n#define DIO4_PWM\t\t&OCR0B\n\n#define\tDIO5_PIN\t\tPINE3\n#define\tDIO5_RPORT\tPINE\n#define\tDIO5_WPORT\tPORTE\n#define\tDIO5_DDR\t\tDDRE\n#define DIO5_PWM\t\t&OCR3AL\n\n#define\tDIO6_PIN\t\tPINH3\n#define\tDIO6_RPORT\tPINH\n#define\tDIO6_WPORT\tPORTH\n#define\tDIO6_DDR\t\tDDRH\n#define DIO6_PWM\t\t&OCR4AL\n\n#define\tDIO7_PIN\t\tPINH4\n#define\tDIO7_RPORT\tPINH\n#define\tDIO7_WPORT\tPORTH\n#define\tDIO7_DDR\t\tDDRH\n#define DIO7_PWM\t\t&OCR4BL\n\n#define\tDIO8_PIN\t\tPINH5\n#define\tDIO8_RPORT\tPINH\n#define\tDIO8_WPORT\tPORTH\n#define\tDIO8_DDR\t\tDDRH\n#define DIO8_PWM\t\t&OCR4CL\n\n#define\tDIO9_PIN\t\tPINH6\n#define\tDIO9_RPORT\tPINH\n#define\tDIO9_WPORT\tPORTH\n#define\tDIO9_DDR\t\tDDRH\n#define DIO9_PWM\t\t&OCR2B\n\n#define\tDIO10_PIN\t\tPINB4\n#define\tDIO10_RPORT\tPINB\n#define\tDIO10_WPORT\tPORTB\n#define\tDIO10_DDR\t\tDDRB\n#define DIO10_PWM\t\t&OCR2A\n\n#define\tDIO11_PIN\t\tPINB5\n#define\tDIO11_RPORT\tPINB\n#define\tDIO11_WPORT\tPORTB\n#define\tDIO11_DDR\t\tDDRB\n#define DIO11_PWM\t\tNULL\n\n#define\tDIO12_PIN\t\tPINB6\n#define\tDIO12_RPORT\tPINB\n#define\tDIO12_WPORT\tPORTB\n#define\tDIO12_DDR\t\tDDRB\n#define DIO12_PWM\t\tNULL\n\n#define\tDIO13_PIN\t\tPINB7\n#define\tDIO13_RPORT\tPINB\n#define\tDIO13_WPORT\tPORTB\n#define\tDIO13_DDR\t\tDDRB\n#define DIO13_PWM\t\t&OCR0A\n\n#define\tDIO14_PIN\t\tPINJ1\n#define\tDIO14_RPORT\tPINJ\n#define\tDIO14_WPORT\tPORTJ\n#define\tDIO14_DDR\t\tDDRJ\n#define DIO14_PWM\t\tNULL\n\n#define\tDIO15_PIN\t\tPINJ0\n#define\tDIO15_RPORT\tPINJ\n#define\tDIO15_WPORT\tPORTJ\n#define\tDIO15_DDR\t\tDDRJ\n#define DIO15_PWM\t\tNULL\n\n#define\tDIO16_PIN\t\tPINH1\n#define\tDIO16_RPORT\tPINH\n#define\tDIO16_WPORT\tPORTH\n#define\tDIO16_DDR\t\tDDRH\n#define DIO16_PWM\t\tNULL\n\n#define\tDIO17_PIN\t\tPINH0\n#define\tDIO17_RPORT\tPINH\n#define\tDIO17_WPORT\tPORTH\n#define\tDIO17_DDR\t\tDDRH\n#define DIO17_PWM\t\tNULL\n\n#define\tDIO18_PIN\t\tPIND3\n#define\tDIO18_RPORT\tPIND\n#define\tDIO18_WPORT\tPORTD\n#define\tDIO18_DDR\t\tDDRD\n#define DIO18_PWM\t\tNULL\n\n#define\tDIO19_PIN\t\tPIND2\n#define\tDIO19_RPORT\tPIND\n#define\tDIO19_WPORT\tPORTD\n#define\tDIO19_DDR\t\tDDRD\n#define DIO19_PWM\t\tNULL\n\n#define\tDIO20_PIN\t\tPIND1\n#define\tDIO20_RPORT\tPIND\n#define\tDIO20_WPORT\tPORTD\n#define\tDIO20_DDR\t\tDDRD\n#define DIO20_PWM\t\tNULL\n\n#define\tDIO21_PIN\t\tPIND0\n#define\tDIO21_RPORT\tPIND\n#define\tDIO21_WPORT\tPORTD\n#define\tDIO21_DDR\t\tDDRD\n#define DIO21_PWM\t\tNULL\n\n#define\tDIO22_PIN\t\tPINA0\n#define\tDIO22_RPORT\tPINA\n#define\tDIO22_WPORT\tPORTA\n#define\tDIO22_DDR\t\tDDRA\n#define DIO22_PWM\t\tNULL\n\n#define\tDIO23_PIN\t\tPINA1\n#define\tDIO23_RPORT\tPINA\n#define\tDIO23_WPORT\tPORTA\n#define\tDIO23_DDR\t\tDDRA\n#define DIO23_PWM\t\tNULL\n\n#define\tDIO24_PIN\t\tPINA2\n#define\tDIO24_RPORT\tPINA\n#define\tDIO24_WPORT\tPORTA\n#define\tDIO24_DDR\t\tDDRA\n#define DIO24_PWM\t\tNULL\n\n#define\tDIO25_PIN\t\tPINA3\n#define\tDIO25_RPORT\tPINA\n#define\tDIO25_WPORT\tPORTA\n#define\tDIO25_DDR\t\tDDRA\n#define DIO25_PWM\t\tNULL\n\n#define\tDIO26_PIN\t\tPINA4\n#define\tDIO26_RPORT\tPINA\n#define\tDIO26_WPORT\tPORTA\n#define\tDIO26_DDR\t\tDDRA\n#define DIO26_PWM\t\tNULL\n\n#define\tDIO27_PIN\t\tPINA5\n#define\tDIO27_RPORT\tPINA\n#define\tDIO27_WPORT\tPORTA\n#define\tDIO27_DDR\t\tDDRA\n#define DIO27_PWM\t\tNULL\n\n#define\tDIO28_PIN\t\tPINA6\n#define\tDIO28_RPORT\tPINA\n#define\tDIO28_WPORT\tPORTA\n#define\tDIO28_DDR\t\tDDRA\n#define DIO28_PWM\t\tNULL\n\n#define\tDIO29_PIN\t\tPINA7\n#define\tDIO29_RPORT\tPINA\n#define\tDIO29_WPORT\tPORTA\n#define\tDIO29_DDR\t\tDDRA\n#define DIO29_PWM\t\tNULL\n\n#define\tDIO30_PIN\t\tPINC7\n#define\tDIO30_RPORT\tPINC\n#define\tDIO30_WPORT\tPORTC\n#define\tDIO30_DDR\t\tDDRC\n#define DIO30_PWM\t\tNULL\n\n#define\tDIO31_PIN\t\tPINC6\n#define\tDIO31_RPORT\tPINC\n#define\tDIO31_WPORT\tPORTC\n#define\tDIO31_DDR\t\tDDRC\n#define DIO31_PWM\t\tNULL\n\n#define\tDIO32_PIN\t\tPINC5\n#define\tDIO32_RPORT\tPINC\n#define\tDIO32_WPORT\tPORTC\n#define\tDIO32_DDR\t\tDDRC\n#define DIO32_PWM\t\tNULL\n\n#define\tDIO33_PIN\t\tPINC4\n#define\tDIO33_RPORT\tPINC\n#define\tDIO33_WPORT\tPORTC\n#define\tDIO33_DDR\t\tDDRC\n#define DIO33_PWM\t\tNULL\n\n#define\tDIO34_PIN\t\tPINC3\n#define\tDIO34_RPORT\tPINC\n#define\tDIO34_WPORT\tPORTC\n#define\tDIO34_DDR\t\tDDRC\n#define DIO34_PWM\t\tNULL\n\n#define\tDIO35_PIN\t\tPINC2\n#define\tDIO35_RPORT\tPINC\n#define\tDIO35_WPORT\tPORTC\n#define\tDIO35_DDR\t\tDDRC\n#define DIO35_PWM\t\tNULL\n\n#define\tDIO36_PIN\t\tPINC1\n#define\tDIO36_RPORT\tPINC\n#define\tDIO36_WPORT\tPORTC\n#define\tDIO36_DDR\t\tDDRC\n#define DIO36_PWM\t\tNULL\n\n#define\tDIO37_PIN\t\tPINC0\n#define\tDIO37_RPORT\tPINC\n#define\tDIO37_WPORT\tPORTC\n#define\tDIO37_DDR\t\tDDRC\n#define DIO37_PWM\t\tNULL\n\n#define\tDIO38_PIN\t\tPIND7\n#define\tDIO38_RPORT\tPIND\n#define\tDIO38_WPORT\tPORTD\n#define\tDIO38_DDR\t\tDDRD\n#define DIO38_PWM\t\tNULL\n\n#define\tDIO39_PIN\t\tPING2\n#define\tDIO39_RPORT\tPING\n#define\tDIO39_WPORT\tPORTG\n#define\tDIO39_DDR\t\tDDRG\n#define DIO39_PWM\t\tNULL\n\n#define\tDIO40_PIN\t\tPING1\n#define\tDIO40_RPORT\tPING\n#define\tDIO40_WPORT\tPORTG\n#define\tDIO40_DDR\t\tDDRG\n#define DIO40_PWM\t\tNULL\n\n#define\tDIO41_PIN\t\tPING0\n#define\tDIO41_RPORT\tPING\n#define\tDIO41_WPORT\tPORTG\n#define\tDIO41_DDR\t\tDDRG\n#define DIO41_PWM\t\tNULL\n\n#define\tDIO42_PIN\t\tPINL7\n#define\tDIO42_RPORT\tPINL\n#define\tDIO42_WPORT\tPORTL\n#define\tDIO42_DDR\t\tDDRL\n#define DIO42_PWM\t\tNULL\n\n#define\tDIO43_PIN\t\tPINL6\n#define\tDIO43_RPORT\tPINL\n#define\tDIO43_WPORT\tPORTL\n#define\tDIO43_DDR\t\tDDRL\n#define DIO43_PWM\t\tNULL\n\n#define\tDIO44_PIN\t\tPINL5\n#define\tDIO44_RPORT\tPINL\n#define\tDIO44_WPORT\tPORTL\n#define\tDIO44_DDR\t\tDDRL\n#define DIO44_PWM\t\t&OCR5CL\n\n#define\tDIO45_PIN\t\tPINL4\n#define\tDIO45_RPORT\tPINL\n#define\tDIO45_WPORT\tPORTL\n#define\tDIO45_DDR\t\tDDRL\n#define DIO45_PWM\t\t&OCR5BL\n\n#define\tDIO46_PIN\t\tPINL3\n#define\tDIO46_RPORT\tPINL\n#define\tDIO46_WPORT\tPORTL\n#define\tDIO46_DDR\t\tDDRL\n#define DIO46_PWM\t\t&OCR5AL\n\n#define\tDIO47_PIN\t\tPINL2\n#define\tDIO47_RPORT\tPINL\n#define\tDIO47_WPORT\tPORTL\n#define\tDIO47_DDR\t\tDDRL\n#define DIO47_PWM\t\tNULL\n\n#define\tDIO48_PIN\t\tPINL1\n#define\tDIO48_RPORT\tPINL\n#define\tDIO48_WPORT\tPORTL\n#define\tDIO48_DDR\t\tDDRL\n#define DIO48_PWM\t\tNULL\n\n#define\tDIO49_PIN\t\tPINL0\n#define\tDIO49_RPORT\tPINL\n#define\tDIO49_WPORT\tPORTL\n#define\tDIO49_DDR\t\tDDRL\n#define DIO49_PWM\t\tNULL\n\n#define\tDIO50_PIN\t\tPINB3\n#define\tDIO50_RPORT\tPINB\n#define\tDIO50_WPORT\tPORTB\n#define\tDIO50_DDR\t\tDDRB\n#define DIO50_PWM\t\tNULL\n\n#define\tDIO51_PIN\t\tPINB2\n#define\tDIO51_RPORT\tPINB\n#define\tDIO51_WPORT\tPORTB\n#define\tDIO51_DDR\t\tDDRB\n#define DIO51_PWM\t\tNULL\n\n#define\tDIO52_PIN\t\tPINB1\n#define\tDIO52_RPORT\tPINB\n#define\tDIO52_WPORT\tPORTB\n#define\tDIO52_DDR\t\tDDRB\n#define DIO52_PWM\t\tNULL\n\n#define\tDIO53_PIN\t\tPINB0\n#define\tDIO53_RPORT\tPINB\n#define\tDIO53_WPORT\tPORTB\n#define\tDIO53_DDR\t\tDDRB\n#define DIO53_PWM\t\tNULL\n\n#define DIO54_PIN\t\tPINF0\n#define DIO54_RPORT\tPINF\n#define DIO54_WPORT\tPORTF\n#define DIO54_DDR\t\tDDRF\n#define DIO54_PWM\t\tNULL\n\n#define DIO55_PIN\t\tPINF1\n#define DIO55_RPORT\tPINF\n#define DIO55_WPORT\tPORTF\n#define DIO55_DDR\t\tDDRF\n#define DIO55_PWM\t\tNULL\n\n#define DIO56_PIN\t\tPINF2\n#define DIO56_RPORT\tPINF\n#define DIO56_WPORT\tPORTF\n#define DIO56_DDR\t\tDDRF\n#define DIO56_PWM\t\tNULL\n\n#define DIO57_PIN\t\tPINF3\n#define DIO57_RPORT\tPINF\n#define DIO57_WPORT\tPORTF\n#define DIO57_DDR\t\tDDRF\n#define DIO57_PWM\t\tNULL\n\n#define DIO58_PIN\t\tPINF4\n#define DIO58_RPORT\tPINF\n#define DIO58_WPORT\tPORTF\n#define DIO58_DDR\t\tDDRF\n#define DIO58_PWM\t\tNULL\n\n#define DIO59_PIN\t\tPINF5\n#define DIO59_RPORT\tPINF\n#define DIO59_WPORT\tPORTF\n#define DIO59_DDR\t\tDDRF\n#define DIO59_PWM\t\tNULL\n\n#define DIO60_PIN\t\tPINF6\n#define DIO60_RPORT\tPINF\n#define DIO60_WPORT\tPORTF\n#define DIO60_DDR\t\tDDRF\n#define DIO60_PWM\t\tNULL\n\n#define DIO61_PIN\t\tPINF7\n#define DIO61_RPORT\tPINF\n#define DIO61_WPORT\tPORTF\n#define DIO61_DDR\t\tDDRF\n#define DIO61_PWM\t\tNULL\n\n#define DIO62_PIN\t\tPINK0\n#define DIO62_RPORT\tPINK\n#define DIO62_WPORT\tPORTK\n#define DIO62_DDR\t\tDDRK\n#define DIO62_PWM\t\tNULL\n\n#define DIO63_PIN\t\tPINK1\n#define DIO63_RPORT\tPINK\n#define DIO63_WPORT\tPORTK\n#define DIO63_DDR\t\tDDRK\n#define DIO63_PWM\t\tNULL\n\n#define DIO64_PIN\t\tPINK2\n#define DIO64_RPORT\tPINK\n#define DIO64_WPORT\tPORTK\n#define DIO64_DDR\t\tDDRK\n#define DIO64_PWM\t\tNULL\n\n#define DIO65_PIN\t\tPINK3\n#define DIO65_RPORT\tPINK\n#define DIO65_WPORT\tPORTK\n#define DIO65_DDR\t\tDDRK\n#define DIO65_PWM\t\tNULL\n\n#define DIO66_PIN\t\tPINK4\n#define DIO66_RPORT\tPINK\n#define DIO66_WPORT\tPORTK\n#define DIO66_DDR\t\tDDRK\n#define DIO66_PWM\t\tNULL\n\n#define DIO67_PIN\t\tPINK5\n#define DIO67_RPORT\tPINK\n#define DIO67_WPORT\tPORTK\n#define DIO67_DDR\t\tDDRK\n#define DIO67_PWM\t\tNULL\n\n#define DIO68_PIN\t\tPINK6\n#define DIO68_RPORT\tPINK\n#define DIO68_WPORT\tPORTK\n#define DIO68_DDR\t\tDDRK\n#define DIO68_PWM\t\tNULL\n\n#define DIO69_PIN\t\tPINK7\n#define DIO69_RPORT\tPINK\n#define DIO69_WPORT\tPORTK\n#define DIO69_DDR\t\tDDRK\n#define DIO69_PWM\t\tNULL\n\n\n\n#undef PA0\n#define PA0_PIN\t\t\tPINA0\n#define PA0_RPORT\t\tPINA\n#define PA0_WPORT\t\tPORTA\n#define PA0_DDR\t\t\tDDRA\n#define PA0_PWM\t\t\tNULL\n#undef PA1\n#define PA1_PIN\t\t\tPINA1\n#define PA1_RPORT\t\tPINA\n#define PA1_WPORT\t\tPORTA\n#define PA1_DDR\t\t\tDDRA\n#define PA1_PWM\t\t\tNULL\n#undef PA2\n#define PA2_PIN\t\t\tPINA2\n#define PA2_RPORT\t\tPINA\n#define PA2_WPORT\t\tPORTA\n#define PA2_DDR\t\t\tDDRA\n#define PA2_PWM\t\t\tNULL\n#undef PA3\n#define PA3_PIN\t\t\tPINA3\n#define PA3_RPORT\t\tPINA\n#define PA3_WPORT\t\tPORTA\n#define PA3_DDR\t\t\tDDRA\n#define PA3_PWM\t\t\tNULL\n#undef PA4\n#define PA4_PIN\t\t\tPINA4\n#define PA4_RPORT\t\tPINA\n#define PA4_WPORT\t\tPORTA\n#define PA4_DDR\t\t\tDDRA\n#define PA4_PWM\t\t\tNULL\n#undef PA5\n#define PA5_PIN\t\t\tPINA5\n#define PA5_RPORT\t\tPINA\n#define PA5_WPORT\t\tPORTA\n#define PA5_DDR\t\t\tDDRA\n#define PA5_PWM\t\t\tNULL\n#undef PA6\n#define PA6_PIN\t\t\tPINA6\n#define PA6_RPORT\t\tPINA\n#define PA6_WPORT\t\tPORTA\n#define PA6_DDR\t\t\tDDRA\n#define PA6_PWM\t\t\tNULL\n#undef PA7\n#define PA7_PIN\t\t\tPINA7\n#define PA7_RPORT\t\tPINA\n#define PA7_WPORT\t\tPORTA\n#define PA7_DDR\t\t\tDDRA\n#define PA7_PWM\t\t\tNULL\n\n#undef PB0\n#define PB0_PIN\t\t\tPINB0\n#define PB0_RPORT\t\tPINB\n#define PB0_WPORT\t\tPORTB\n#define PB0_DDR\t\t\tDDRB\n#define PB0_PWM\t\t\tNULL\n#undef PB1\n#define PB1_PIN\t\t\tPINB1\n#define PB1_RPORT\t\tPINB\n#define PB1_WPORT\t\tPORTB\n#define PB1_DDR\t\t\tDDRB\n#define PB1_PWM\t\t\tNULL\n#undef PB2\n#define PB2_PIN\t\t\tPINB2\n#define PB2_RPORT\t\tPINB\n#define PB2_WPORT\t\tPORTB\n#define PB2_DDR\t\t\tDDRB\n#define PB2_PWM\t\t\tNULL\n#undef PB3\n#define PB3_PIN\t\t\tPINB3\n#define PB3_RPORT\t\tPINB\n#define PB3_WPORT\t\tPORTB\n#define PB3_DDR\t\t\tDDRB\n#define PB3_PWM\t\t\tNULL\n#undef PB4\n#define PB4_PIN\t\t\tPINB4\n#define PB4_RPORT\t\tPINB\n#define PB4_WPORT\t\tPORTB\n#define PB4_DDR\t\t\tDDRB\n#define PB4_PWM\t\t\t&OCR2A\n#undef PB5\n#define PB5_PIN\t\t\tPINB5\n#define PB5_RPORT\t\tPINB\n#define PB5_WPORT\t\tPORTB\n#define PB5_DDR\t\t\tDDRB\n#define PB5_PWM\t\t\tNULL\n#undef PB6\n#define PB6_PIN\t\t\tPINB6\n#define PB6_RPORT\t\tPINB\n#define PB6_WPORT\t\tPORTB\n#define PB6_DDR\t\t\tDDRB\n#define PB6_PWM\t\t\tNULL\n#undef PB7\n#define PB7_PIN\t\t\tPINB7\n#define PB7_RPORT\t\tPINB\n#define PB7_WPORT\t\tPORTB\n#define PB7_DDR\t\t\tDDRB\n#define PB7_PWM\t\t\t&OCR0A\n\n#undef PC0\n#define PC0_PIN\t\t\tPINC0\n#define PC0_RPORT\t\tPINC\n#define PC0_WPORT\t\tPORTC\n#define PC0_DDR\t\t\tDDRC\n#define PC0_PWM\t\t\tNULL\n#undef PC1\n#define PC1_PIN\t\t\tPINC1\n#define PC1_RPORT\t\tPINC\n#define PC1_WPORT\t\tPORTC\n#define PC1_DDR\t\t\tDDRC\n#define PC1_PWM\t\t\tNULL\n#undef PC2\n#define PC2_PIN\t\t\tPINC2\n#define PC2_RPORT\t\tPINC\n#define PC2_WPORT\t\tPORTC\n#define PC2_DDR\t\t\tDDRC\n#define PC2_PWM\t\t\tNULL\n#undef PC3\n#define PC3_PIN\t\t\tPINC3\n#define PC3_RPORT\t\tPINC\n#define PC3_WPORT\t\tPORTC\n#define PC3_DDR\t\t\tDDRC\n#define PC3_PWM\t\t\tNULL\n#undef PC4\n#define PC4_PIN\t\t\tPINC4\n#define PC4_RPORT\t\tPINC\n#define PC4_WPORT\t\tPORTC\n#define PC4_DDR\t\t\tDDRC\n#define PC4_PWM\t\t\tNULL\n#undef PC5\n#define PC5_PIN\t\t\tPINC5\n#define PC5_RPORT\t\tPINC\n#define PC5_WPORT\t\tPORTC\n#define PC5_DDR\t\t\tDDRC\n#define PC5_PWM\t\t\tNULL\n#undef PC6\n#define PC6_PIN\t\t\tPINC6\n#define PC6_RPORT\t\tPINC\n#define PC6_WPORT\t\tPORTC\n#define PC6_DDR\t\t\tDDRC\n#define PC6_PWM\t\t\tNULL\n#undef PC7\n#define PC7_PIN\t\t\tPINC7\n#define PC7_RPORT\t\tPINC\n#define PC7_WPORT\t\tPORTC\n#define PC7_DDR\t\t\tDDRC\n#define PC7_PWM\t\t\tNULL\n\n#undef PD0\n#define PD0_PIN\t\t\tPIND0\n#define PD0_RPORT\t\tPIND\n#define PD0_WPORT\t\tPORTD\n#define PD0_DDR\t\t\tDDRD\n#define PD0_PWM\t\t\tNULL\n#undef PD1\n#define PD1_PIN\t\t\tPIND1\n#define PD1_RPORT\t\tPIND\n#define PD1_WPORT\t\tPORTD\n#define PD1_DDR\t\t\tDDRD\n#define PD1_PWM\t\t\tNULL\n#undef PD2\n#define PD2_PIN\t\t\tPIND2\n#define PD2_RPORT\t\tPIND\n#define PD2_WPORT\t\tPORTD\n#define PD2_DDR\t\t\tDDRD\n#define PD2_PWM\t\t\tNULL\n#undef PD3\n#define PD3_PIN\t\t\tPIND3\n#define PD3_RPORT\t\tPIND\n#define PD3_WPORT\t\tPORTD\n#define PD3_DDR\t\t\tDDRD\n#define PD3_PWM\t\t\tNULL\n#undef PD4\n#define PD4_PIN\t\t\tPIND4\n#define PD4_RPORT\t\tPIND\n#define PD4_WPORT\t\tPORTD\n#define PD4_DDR\t\t\tDDRD\n#define PD4_PWM\t\t\tNULL\n#undef PD5\n#define PD5_PIN\t\t\tPIND5\n#define PD5_RPORT\t\tPIND\n#define PD5_WPORT\t\tPORTD\n#define PD5_DDR\t\t\tDDRD\n#define PD5_PWM\t\t\tNULL\n#undef PD6\n#define PD6_PIN\t\t\tPIND6\n#define PD6_RPORT\t\tPIND\n#define PD6_WPORT\t\tPORTD\n#define PD6_DDR\t\t\tDDRD\n#define PD6_PWM\t\t\tNULL\n#undef PD7\n#define PD7_PIN\t\t\tPIND7\n#define PD7_RPORT\t\tPIND\n#define PD7_WPORT\t\tPORTD\n#define PD7_DDR\t\t\tDDRD\n#define PD7_PWM\t\t\tNULL\n\n#undef PE0\n#define PE0_PIN\t\t\tPINE0\n#define PE0_RPORT\t\tPINE\n#define PE0_WPORT\t\tPORTE\n#define PE0_DDR\t\t\tDDRE\n#define PE0_PWM\t\t\tNULL\n#undef PE1\n#define PE1_PIN\t\t\tPINE1\n#define PE1_RPORT\t\tPINE\n#define PE1_WPORT\t\tPORTE\n#define PE1_DDR\t\t\tDDRE\n#define PE1_PWM\t\t\tNULL\n#undef PE2\n#define PE2_PIN\t\t\tPINE2\n#define PE2_RPORT\t\tPINE\n#define PE2_WPORT\t\tPORTE\n#define PE2_DDR\t\t\tDDRE\n#define PE2_PWM\t\t\tNULL\n#undef PE3\n#define PE3_PIN\t\t\tPINE3\n#define PE3_RPORT\t\tPINE\n#define PE3_WPORT\t\tPORTE\n#define PE3_DDR\t\t\tDDRE\n#define PE3_PWM\t\t\t&OCR3AL\n#undef PE4\n#define PE4_PIN\t\t\tPINE4\n#define PE4_RPORT\t\tPINE\n#define PE4_WPORT\t\tPORTE\n#define PE4_DDR\t\t\tDDRE\n#define PE4_PWM\t\t\t&OCR3BL\n#undef PE5\n#define PE5_PIN\t\t\tPINE5\n#define PE5_RPORT\t\tPINE\n#define PE5_WPORT\t\tPORTE\n#define PE5_DDR\t\t\tDDRE\n#define PE5_PWM\t\t\t&OCR3CL\n#undef PE6\n#define PE6_PIN\t\t\tPINE6\n#define PE6_RPORT\t\tPINE\n#define PE6_WPORT\t\tPORTE\n#define PE6_DDR\t\t\tDDRE\n#define PE6_PWM\t\t\tNULL\n#undef PE7\n#define PE7_PIN\t\t\tPINE7\n#define PE7_RPORT\t\tPINE\n#define PE7_WPORT\t\tPORTE\n#define PE7_DDR\t\t\tDDRE\n#define PE7_PWM\t\t\tNULL\n\n#undef PF0\n#define PF0_PIN\t\t\tPINF0\n#define PF0_RPORT\t\tPINF\n#define PF0_WPORT\t\tPORTF\n#define PF0_DDR\t\t\tDDRF\n#define PF0_PWM\t\t\tNULL\n#undef PF1\n#define PF1_PIN\t\t\tPINF1\n#define PF1_RPORT\t\tPINF\n#define PF1_WPORT\t\tPORTF\n#define PF1_DDR\t\t\tDDRF\n#define PF1_PWM\t\t\tNULL\n#undef PF2\n#define PF2_PIN\t\t\tPINF2\n#define PF2_RPORT\t\tPINF\n#define PF2_WPORT\t\tPORTF\n#define PF2_DDR\t\t\tDDRF\n#define PF2_PWM\t\t\tNULL\n#undef PF3\n#define PF3_PIN\t\t\tPINF3\n#define PF3_RPORT\t\tPINF\n#define PF3_WPORT\t\tPORTF\n#define PF3_DDR\t\t\tDDRF\n#define PF3_PWM\t\t\tNULL\n#undef PF4\n#define PF4_PIN\t\t\tPINF4\n#define PF4_RPORT\t\tPINF\n#define PF4_WPORT\t\tPORTF\n#define PF4_DDR\t\t\tDDRF\n#define PF4_PWM\t\t\tNULL\n#undef PF5\n#define PF5_PIN\t\t\tPINF5\n#define PF5_RPORT\t\tPINF\n#define PF5_WPORT\t\tPORTF\n#define PF5_DDR\t\t\tDDRF\n#define PF5_PWM\t\t\tNULL\n#undef PF6\n#define PF6_PIN\t\t\tPINF6\n#define PF6_RPORT\t\tPINF\n#define PF6_WPORT\t\tPORTF\n#define PF6_DDR\t\t\tDDRF\n#define PF6_PWM\t\t\tNULL\n#undef PF7\n#define PF7_PIN\t\t\tPINF7\n#define PF7_RPORT\t\tPINF\n#define PF7_WPORT\t\tPORTF\n#define PF7_DDR\t\t\tDDRF\n#define PF7_PWM\t\t\tNULL\n\n#undef PG0\n#define PG0_PIN\t\t\tPING0\n#define PG0_RPORT\t\tPING\n#define PG0_WPORT\t\tPORTG\n#define PG0_DDR\t\t\tDDRG\n#define PG0_PWM\t\t\tNULL\n#undef PG1\n#define PG1_PIN\t\t\tPING1\n#define PG1_RPORT\t\tPING\n#define PG1_WPORT\t\tPORTG\n#define PG1_DDR\t\t\tDDRG\n#define PG1_PWM\t\t\tNULL\n#undef PG2\n#define PG2_PIN\t\t\tPING2\n#define PG2_RPORT\t\tPING\n#define PG2_WPORT\t\tPORTG\n#define PG2_DDR\t\t\tDDRG\n#define PG2_PWM\t\t\tNULL\n#undef PG3\n#define PG3_PIN\t\t\tPING3\n#define PG3_RPORT\t\tPING\n#define PG3_WPORT\t\tPORTG\n#define PG3_DDR\t\t\tDDRG\n#define PG3_PWM\t\t\tNULL\n#undef PG4\n#define PG4_PIN\t\t\tPING4\n#define PG4_RPORT\t\tPING\n#define PG4_WPORT\t\tPORTG\n#define PG4_DDR\t\t\tDDRG\n#define PG4_PWM\t\t\tNULL\n#undef PG5\n#define PG5_PIN\t\t\tPING5\n#define PG5_RPORT\t\tPING\n#define PG5_WPORT\t\tPORTG\n#define PG5_DDR\t\t\tDDRG\n#define PG5_PWM\t\t\t&OCR0B\n#undef PG6\n#define PG6_PIN\t\t\tPING6\n#define PG6_RPORT\t\tPING\n#define PG6_WPORT\t\tPORTG\n#define PG6_DDR\t\t\tDDRG\n#define PG6_PWM\t\t\tNULL\n#undef PG7\n#define PG7_PIN\t\t\tPING7\n#define PG7_RPORT\t\tPING\n#define PG7_WPORT\t\tPORTG\n#define PG7_DDR\t\t\tDDRG\n#define PG7_PWM\t\t\tNULL\n\n#undef PH0\n#define PH0_PIN\t\t\tPINH0\n#define PH0_RPORT\t\tPINH\n#define PH0_WPORT\t\tPORTH\n#define PH0_DDR\t\t\tDDRH\n#define PH0_PWM\t\t\tNULL\n#undef PH1\n#define PH1_PIN\t\t\tPINH1\n#define PH1_RPORT\t\tPINH\n#define PH1_WPORT\t\tPORTH\n#define PH1_DDR\t\t\tDDRH\n#define PH1_PWM\t\t\tNULL\n#undef PH2\n#define PH2_PIN\t\t\tPINH2\n#define PH2_RPORT\t\tPINH\n#define PH2_WPORT\t\tPORTH\n#define PH2_DDR\t\t\tDDRH\n#define PH2_PWM\t\t\tNULL\n#undef PH3\n#define PH3_PIN\t\t\tPINH3\n#define PH3_RPORT\t\tPINH\n#define PH3_WPORT\t\tPORTH\n#define PH3_DDR\t\t\tDDRH\n#define PH3_PWM\t\t\t&OCR4AL\n#undef PH4\n#define PH4_PIN\t\t\tPINH4\n#define PH4_RPORT\t\tPINH\n#define PH4_WPORT\t\tPORTH\n#define PH4_DDR\t\t\tDDRH\n#define PH4_PWM\t\t\t&OCR4BL\n#undef PH5\n#define PH5_PIN\t\t\tPINH5\n#define PH5_RPORT\t\tPINH\n#define PH5_WPORT\t\tPORTH\n#define PH5_DDR\t\t\tDDRH\n#define PH5_PWM\t\t\t&OCR4CL\n#undef PH6\n#define PH6_PIN\t\t\tPINH6\n#define PH6_RPORT\t\tPINH\n#define PH6_WPORT\t\tPORTH\n#define PH6_DDR\t\t\tDDRH\n#define PH6_PWM\t\t\t&OCR2B\n#undef PH7\n#define PH7_PIN\t\t\tPINH7\n#define PH7_RPORT\t\tPINH\n#define PH7_WPORT\t\tPORTH\n#define PH7_DDR\t\t\tDDRH\n#define PH7_PWM\t\t\tNULL\n\n#undef PJ0\n#define PJ0_PIN\t\t\tPINJ0\n#define PJ0_RPORT\t\tPINJ\n#define PJ0_WPORT\t\tPORTJ\n#define PJ0_DDR\t\t\tDDRJ\n#define PJ0_PWM\t\t\tNULL\n#undef PJ1\n#define PJ1_PIN\t\t\tPINJ1\n#define PJ1_RPORT\t\tPINJ\n#define PJ1_WPORT\t\tPORTJ\n#define PJ1_DDR\t\t\tDDRJ\n#define PJ1_PWM\t\t\tNULL\n#undef PJ2\n#define PJ2_PIN\t\t\tPINJ2\n#define PJ2_RPORT\t\tPINJ\n#define PJ2_WPORT\t\tPORTJ\n#define PJ2_DDR\t\t\tDDRJ\n#define PJ2_PWM\t\t\tNULL\n#undef PJ3\n#define PJ3_PIN\t\t\tPINJ3\n#define PJ3_RPORT\t\tPINJ\n#define PJ3_WPORT\t\tPORTJ\n#define PJ3_DDR\t\t\tDDRJ\n#define PJ3_PWM\t\t\tNULL\n#undef PJ4\n#define PJ4_PIN\t\t\tPINJ4\n#define PJ4_RPORT\t\tPINJ\n#define PJ4_WPORT\t\tPORTJ\n#define PJ4_DDR\t\t\tDDRJ\n#define PJ4_PWM\t\t\tNULL\n#undef PJ5\n#define PJ5_PIN\t\t\tPINJ5\n#define PJ5_RPORT\t\tPINJ\n#define PJ5_WPORT\t\tPORTJ\n#define PJ5_DDR\t\t\tDDRJ\n#define PJ5_PWM\t\t\tNULL\n#undef PJ6\n#define PJ6_PIN\t\t\tPINJ6\n#define PJ6_RPORT\t\tPINJ\n#define PJ6_WPORT\t\tPORTJ\n#define PJ6_DDR\t\t\tDDRJ\n#define PJ6_PWM\t\t\tNULL\n#undef PJ7\n#define PJ7_PIN\t\t\tPINJ7\n#define PJ7_RPORT\t\tPINJ\n#define PJ7_WPORT\t\tPORTJ\n#define PJ7_DDR\t\t\tDDRJ\n#define PJ7_PWM\t\t\tNULL\n\n#undef PK0\n#define PK0_PIN\t\t\tPINK0\n#define PK0_RPORT\t\tPINK\n#define PK0_WPORT\t\tPORTK\n#define PK0_DDR\t\t\tDDRK\n#define PK0_PWM\t\t\tNULL\n#undef PK1\n#define PK1_PIN\t\t\tPINK1\n#define PK1_RPORT\t\tPINK\n#define PK1_WPORT\t\tPORTK\n#define PK1_DDR\t\t\tDDRK\n#define PK1_PWM\t\t\tNULL\n#undef PK2\n#define PK2_PIN\t\t\tPINK2\n#define PK2_RPORT\t\tPINK\n#define PK2_WPORT\t\tPORTK\n#define PK2_DDR\t\t\tDDRK\n#define PK2_PWM\t\t\tNULL\n#undef PK3\n#define PK3_PIN\t\t\tPINK3\n#define PK3_RPORT\t\tPINK\n#define PK3_WPORT\t\tPORTK\n#define PK3_DDR\t\t\tDDRK\n#define PK3_PWM\t\t\tNULL\n#undef PK4\n#define PK4_PIN\t\t\tPINK4\n#define PK4_RPORT\t\tPINK\n#define PK4_WPORT\t\tPORTK\n#define PK4_DDR\t\t\tDDRK\n#define PK4_PWM\t\t\tNULL\n#undef PK5\n#define PK5_PIN\t\t\tPINK5\n#define PK5_RPORT\t\tPINK\n#define PK5_WPORT\t\tPORTK\n#define PK5_DDR\t\t\tDDRK\n#define PK5_PWM\t\t\tNULL\n#undef PK6\n#define PK6_PIN\t\t\tPINK6\n#define PK6_RPORT\t\tPINK\n#define PK6_WPORT\t\tPORTK\n#define PK6_DDR\t\t\tDDRK\n#define PK6_PWM\t\t\tNULL\n#undef PK7\n#define PK7_PIN\t\t\tPINK7\n#define PK7_RPORT\t\tPINK\n#define PK7_WPORT\t\tPORTK\n#define PK7_DDR\t\t\tDDRK\n#define PK7_PWM\t\t\tNULL\n\n#undef PL0\n#define PL0_PIN\t\t\tPINL0\n#define PL0_RPORT\t\tPINL\n#define PL0_WPORT\t\tPORTL\n#define PL0_DDR\t\t\tDDRL\n#define PL0_PWM\t\t\tNULL\n#undef PL1\n#define PL1_PIN\t\t\tPINL1\n#define PL1_RPORT\t\tPINL\n#define PL1_WPORT\t\tPORTL\n#define PL1_DDR\t\t\tDDRL\n#define PL1_PWM\t\t\tNULL\n#undef PL2\n#define PL2_PIN\t\t\tPINL2\n#define PL2_RPORT\t\tPINL\n#define PL2_WPORT\t\tPORTL\n#define PL2_DDR\t\t\tDDRL\n#define PL2_PWM\t\t\tNULL\n#undef PL3\n#define PL3_PIN\t\t\tPINL3\n#define PL3_RPORT\t\tPINL\n#define PL3_WPORT\t\tPORTL\n#define PL3_DDR\t\t\tDDRL\n#define PL3_PWM\t\t\t&OCR5AL\n#undef PL4\n#define PL4_PIN\t\t\tPINL4\n#define PL4_RPORT\t\tPINL\n#define PL4_WPORT\t\tPORTL\n#define PL4_DDR\t\t\tDDRL\n#define PL4_PWM\t\t\t&OCR5BL\n#undef PL5\n#define PL5_PIN\t\t\tPINL5\n#define PL5_RPORT\t\tPINL\n#define PL5_WPORT\t\tPORTL\n#define PL5_DDR\t\t\tDDRL\n#define PL5_PWM\t\t\t&OCR5CL\n#undef PL6\n#define PL6_PIN\t\t\tPINL6\n#define PL6_RPORT\t\tPINL\n#define PL6_WPORT\t\tPORTL\n#define PL6_DDR\t\t\tDDRL\n#define PL6_PWM\t\t\tNULL\n#undef PL7\n#define PL7_PIN\t\t\tPINL7\n#define PL7_RPORT\t\tPINL\n#define PL7_WPORT\t\tPORTL\n#define PL7_DDR\t\t\tDDRL\n#define PL7_PWM\t\t\tNULL\n\n#endif\n\n#if defined (__AVR_AT90USB646__)\n// SPI\n#define\tSCK\t\t\t\t\tDIO9\n#define\tMISO\t\t\t\tDIO11\n#define\tMOSI\t\t\t\tDIO10\n#define\tSS\t\t\t\t\tDIO8\n\n// change for your board\n#define\tDEBUG_LED\t\tDIO31 /* led D5 red */\n\n/*\npins\n*/\n#define DIO0_PIN        PINA0\n#define DIO0_RPORT      PINA\n#define DIO0_WPORT      PORTA\n#define DIO0_PWM\t\t\tNULL\n#define DIO0_DDR        DDRA\n\n#define DIO1_PIN        PINA1\n#define DIO1_RPORT      PINA\n#define DIO1_WPORT      PORTA\n#define DIO1_PWM\t\t\tNULL\n#define DIO1_DDR        DDRA\n\n#define DIO2_PIN        PINA2\n#define DIO2_RPORT      PINA\n#define DIO2_WPORT      PORTA\n#define DIO2_PWM\t\t\tNULL\n#define DIO2_DDR        DDRA\n\n#define DIO3_PIN        PINA3\n#define DIO3_RPORT      PINA\n#define DIO3_WPORT      PORTA\n#define DIO3_PWM\t\t\tNULL\n#define DIO3_DDR        DDRA\n\n#define DIO4_PIN        PINA4\n#define DIO4_RPORT      PINA\n#define DIO4_WPORT      PORTA\n#define DIO4_PWM\t\t\tNULL\n#define DIO4_DDR        DDRA\n\n#define DIO5_PIN        PINA5\n#define DIO5_RPORT      PINA\n#define DIO5_WPORT      PORTA\n#define DIO5_PWM\t\t\tNULL\n#define DIO5_DDR        DDRA\n\n#define DIO6_PIN        PINA6\n#define DIO6_RPORT      PINA\n#define DIO6_WPORT      PORTA\n#define DIO6_PWM\t\t\tNULL\n#define DIO6_DDR        DDRA\n\n#define DIO7_PIN        PINA7\n#define DIO7_RPORT      PINA\n#define DIO7_WPORT      PORTA\n#define DIO7_PWM\t\t\tNULL\n#define DIO7_DDR        DDRA\n\n#define DIO8_PIN        PINB0\n#define DIO8_RPORT      PINB\n#define DIO8_WPORT      PORTB\n#define DIO8_PWM\t\t\tNULL\n#define DIO8_DDR        DDRB\n\n#define DIO9_PIN        PINB1\n#define DIO9_RPORT      PINB\n#define DIO9_WPORT      PORTB\n#define DIO9_PWM\t\t\tNULL\n#define DIO9_DDR        DDRB\n\n#define DIO10_PIN       PINB2\n#define DIO10_RPORT     PINB\n#define DIO10_WPORT     PORTB\n#define DIO10_PWM\t\t\tNULL\n#define DIO10_DDR       DDRB\n\n#define DIO11_PIN       PINB3\n#define DIO11_RPORT     PINB\n#define DIO11_WPORT     PORTB\n#define DIO11_PWM\t\t\tNULL\n#define DIO11_DDR       DDRB\n\n#define DIO12_PIN       PINB4\n#define DIO12_RPORT     PINB\n#define DIO12_WPORT     PORTB\n#define DIO12_PWM\t\t\tNULL\n#define DIO12_DDR       DDRB\n\n#define DIO13_PIN       PINB5\n#define DIO13_RPORT     PINB\n#define DIO13_WPORT     PORTB\n#define DIO13_PWM\t\t\tNULL\n#define DIO13_DDR       DDRB\n\n#define DIO14_PIN       PINB6\n#define DIO14_RPORT     PINB\n#define DIO14_WPORT     PORTB\n#define DIO14_PWM\t\t\tNULL\n#define DIO14_DDR       DDRB\n\n#define DIO15_PIN       PINB7\n#define DIO15_RPORT     PINB\n#define DIO15_WPORT     PORTB\n#define DIO15_PWM\t\t\tNULL\n#define DIO15_DDR       DDRB\n\n#define DIO16_PIN       PINC0\n#define DIO16_RPORT     PINC\n#define DIO16_WPORT     PORTC\n#define DIO16_PWM\t\t\tNULL\n#define DIO16_DDR       DDRC\n\n#define DIO17_PIN       PINC1\n#define DIO17_RPORT     PINC\n#define DIO17_WPORT     PORTC\n#define DIO17_PWM\t\t\tNULL\n#define DIO17_DDR       DDRC\n\n#define DIO18_PIN       PINC2\n#define DIO18_RPORT     PINC\n#define DIO18_WPORT     PORTC\n#define DIO18_PWM\t\t\tNULL\n#define DIO18_DDR       DDRC\n\n#define DIO19_PIN       PINC3\n#define DIO19_RPORT     PINC\n#define DIO19_WPORT     PORTC\n#define DIO19_PWM\t\t\tNULL\n#define DIO19_DDR       DDRC\n\n#define DIO20_PIN       PINC4\n#define DIO20_RPORT     PINC\n#define DIO20_WPORT     PORTC\n#define DIO20_PWM\t\t\tNULL\n#define DIO20_DDR       DDRC\n\n#define DIO21_PIN       PINC5\n#define DIO21_RPORT     PINC\n#define DIO21_WPORT     PORTC\n#define DIO21_PWM\t\t\tNULL\n#define DIO21_DDR       DDRC\n\n#define DIO22_PIN       PINC6\n#define DIO22_RPORT     PINC\n#define DIO22_WPORT     PORTC\n#define DIO22_PWM\t\t\tNULL\n#define DIO22_DDR       DDRC\n\n#define DIO23_PIN       PINC7\n#define DIO23_RPORT     PINC\n#define DIO23_WPORT     PORTC\n#define DIO23_PWM\t\t\tNULL\n#define DIO23_DDR       DDRC\n\n#define DIO24_PIN       PIND0\n#define DIO24_RPORT     PIND\n#define DIO24_WPORT     PORTD\n#define DIO24_PWM\t\t\tNULL\n#define DIO24_DDR       DDRD\n\n#define DIO25_PIN       PIND1\n#define DIO25_RPORT     PIND\n#define DIO25_WPORT     PORTD\n#define DIO25_PWM\t\t\tNULL\n#define DIO25_DDR       DDRD\n\n#define DIO26_PIN       PIND2\n#define DIO26_RPORT     PIND\n#define DIO26_WPORT     PORTD\n#define DIO26_PWM\t\t\tNULL\n#define DIO26_DDR       DDRD\n\n#define DIO27_PIN       PIND3\n#define DIO27_RPORT     PIND\n#define DIO27_WPORT     PORTD\n#define DIO27_PWM\t\t\tNULL\n#define DIO27_DDR       DDRD\n\n#define DIO28_PIN       PIND4\n#define DIO28_RPORT     PIND\n#define DIO28_WPORT     PORTD\n#define DIO28_PWM\t\t\tNULL\n#define DIO28_DDR       DDRD\n\n#define DIO29_PIN       PIND5\n#define DIO29_RPORT     PIND\n#define DIO29_WPORT     PORTD\n#define DIO29_PWM\t\t\tNULL\n#define DIO29_DDR       DDRD\n\n#define DIO30_PIN       PIND6\n#define DIO30_RPORT     PIND\n#define DIO30_WPORT     PORTD\n#define DIO30_PWM\t\t\tNULL\n#define DIO30_DDR       DDRD\n\n#define DIO31_PIN       PIND7\n#define DIO31_RPORT     PIND\n#define DIO31_WPORT     PORTD\n#define DIO31_PWM\t\t\tNULL\n#define DIO31_DDR       DDRD\n\n\n#define DIO32_PIN       PINE0\n#define DIO32_RPORT     PINE\n#define DIO32_WPORT     PORTE\n#define DIO32_PWM\t\t\tNULL\n#define DIO32_DDR       DDRE\n\n#define DIO33_PIN       PINE1\n#define DIO33_RPORT     PINE\n#define DIO33_WPORT     PORTE\n#define DIO33_PWM\t\t\tNULL\n#define DIO33_DDR       DDRE\n\n#define DIO34_PIN       PINE2\n#define DIO34_RPORT     PINE\n#define DIO34_WPORT     PORTE\n#define DIO34_PWM\t\t\tNULL\n#define DIO34_DDR       DDRE\n\n#define DIO35_PIN       PINE3\n#define DIO35_RPORT     PINE\n#define DIO35_WPORT     PORTE\n#define DIO35_PWM\t\t\tNULL\n#define DIO35_DDR       DDRE\n\n#define DIO36_PIN       PINE4\n#define DIO36_RPORT     PINE\n#define DIO36_WPORT     PORTE\n#define DIO36_PWM\t\t\tNULL\n#define DIO36_DDR       DDRE\n\n#define DIO37_PIN       PINE5\n#define DIO37_RPORT     PINE\n#define DIO37_WPORT     PORTE\n#define DIO37_PWM\t\t\tNULL\n#define DIO37_DDR       DDRE\n\n#define DIO38_PIN       PINE6\n#define DIO38_RPORT     PINE\n#define DIO38_WPORT     PORTE\n#define DIO38_PWM\t\t\tNULL\n#define DIO38_DDR       DDRE\n\n#define DIO39_PIN       PINE7\n#define DIO39_RPORT     PINE\n#define DIO39_WPORT     PORTE\n#define DIO39_PWM\t\t\tNULL\n#define DIO39_DDR       DDRE\n\n#define AIO0_PIN PINF0\n#define AIO0_RPORT PINF\n#define AIO0_WPORT PORTF\n#define AIO0_PWM\t\t\tNULL\n#define AIO0_DDR DDRF\n\n#define AIO1_PIN PINF1\n#define AIO1_RPORT PINF\n#define AIO1_WPORT PORTF\n#define AIO1_PWM\t\t\tNULL\n#define AIO1_DDR DDRF\n\n#define AIO2_PIN PINF2\n#define AIO2_RPORT PINF\n#define AIO2_WPORT PORTF\n#define AIO2_PWM\t\t\tNULL\n#define AIO2_DDR DDRF\n\n#define AIO3_PIN PINF3\n#define AIO3_RPORT PINF\n#define AIO3_WPORT PORTF\n#define AIO3_PWM\t\t\tNULL\n#define AIO3_DDR DDRF\n\n#define AIO4_PIN PINF4\n#define AIO4_RPORT PINF\n#define AIO4_WPORT PORTF\n#define AIO4_PWM\t\t\tNULL\n#define AIO4_DDR DDRF\n\n#define AIO5_PIN PINF5\n#define AIO5_RPORT PINF\n#define AIO5_WPORT PORTF\n#define AIO5_PWM\t\t\tNULL\n#define AIO5_DDR DDRF\n\n#define AIO6_PIN PINF6\n#define AIO6_RPORT PINF\n#define AIO6_WPORT PORTF\n#define AIO6_PWM\t\t\tNULL\n#define AIO6_DDR DDRF\n\n#define AIO7_PIN PINF7\n#define AIO7_RPORT PINF\n#define AIO7_WPORT PORTF\n#define AIO7_PWM\t\t\tNULL\n#define AIO7_DDR DDRF\n\n#define DIO40_PIN       PINF0\n#define DIO40_RPORT     PINF\n#define DIO40_WPORT     PORTF\n#define DIO40_PWM\t\t\tNULL\n#define DIO40_DDR       DDRF\n\n#define DIO41_PIN       PINF1\n#define DIO41_RPORT     PINF\n#define DIO41_WPORT     PORTF\n#define DIO41_PWM\t\t\tNULL\n#define DIO41_DDR       DDRF\n\n#define DIO42_PIN       PINF2\n#define DIO42_RPORT     PINF\n#define DIO42_WPORT     PORTF\n#define DIO42_PWM\t\t\tNULL\n#define DIO42_DDR       DDRF\n\n#define DIO43_PIN       PINF3\n#define DIO43_RPORT     PINF\n#define DIO43_WPORT     PORTF\n#define DIO43_PWM\t\t\tNULL\n#define DIO43_DDR       DDRF\n\n#define DIO44_PIN       PINF4\n#define DIO44_RPORT     PINF\n#define DIO44_WPORT     PORTF\n#define DIO44_PWM\t\t\tNULL\n#define DIO44_DDR       DDRF\n\n#define DIO45_PIN       PINF5\n#define DIO45_RPORT     PINF\n#define DIO45_WPORT     PORTF\n#define DIO45_PWM\t\t\tNULL\n#define DIO45_DDR       DDRF\n\n#define DIO46_PIN       PINF6\n#define DIO46_RPORT     PINF\n#define DIO46_WPORT     PORTF\n#define DIO46_PWM\t\t\tNULL\n#define DIO46_DDR       DDRF\n\n#define DIO47_PIN       PINF7\n#define DIO47_RPORT     PINF\n#define DIO47_WPORT     PORTF\n#define DIO47_PWM\t\t\tNULL\n#define DIO47_DDR       DDRF\n\n\n\n#undef PA0\n#define PA0_PIN\t\t\tPINA0\n#define PA0_RPORT\t\tPINA\n#define PA0_WPORT\t\tPORTA\n#define PA0_PWM\t\t\tNULL\n#define PA0_DDR\t\t\tDDRA\n#undef PA1\n#define PA1_PIN\t\t\tPINA1\n#define PA1_RPORT\t\tPINA\n#define PA1_WPORT\t\tPORTA\n#define PA1_PWM\t\t\tNULL\n#define PA1_DDR\t\t\tDDRA\n#undef PA2\n#define PA2_PIN\t\t\tPINA2\n#define PA2_RPORT\t\tPINA\n#define PA2_WPORT\t\tPORTA\n#define PA2_PWM\t\t\tNULL\n#define PA2_DDR\t\t\tDDRA\n#undef PA3\n#define PA3_PIN\t\t\tPINA3\n#define PA3_RPORT\t\tPINA\n#define PA3_WPORT\t\tPORTA\n#define PA3_PWM\t\t\tNULL\n#define PA3_DDR\t\t\tDDRA\n#undef PA4\n#define PA4_PIN\t\t\tPINA4\n#define PA4_RPORT\t\tPINA\n#define PA4_WPORT\t\tPORTA\n#define PA4_PWM\t\t\tNULL\n#define PA4_DDR\t\t\tDDRA\n#undef PA5\n#define PA5_PIN\t\t\tPINA5\n#define PA5_RPORT\t\tPINA\n#define PA5_WPORT\t\tPORTA\n#define PA5_PWM\t\t\tNULL\n#define PA5_DDR\t\t\tDDRA\n#undef PA6\n#define PA6_PIN\t\t\tPINA6\n#define PA6_RPORT\t\tPINA\n#define PA6_WPORT\t\tPORTA\n#define PA6_PWM\t\t\tNULL\n#define PA6_DDR\t\t\tDDRA\n#undef PA7\n#define PA7_PIN\t\t\tPINA7\n#define PA7_RPORT\t\tPINA\n#define PA7_WPORT\t\tPORTA\n#define PA7_PWM\t\t\tNULL\n#define PA7_DDR\t\t\tDDRA\n\n#undef PB0\n#define PB0_PIN\t\t\tPINB0\n#define PB0_RPORT\t\tPINB\n#define PB0_WPORT\t\tPORTB\n#define PB0_PWM\t\t\tNULL\n#define PB0_DDR\t\t\tDDRB\n#undef PB1\n#define PB1_PIN\t\t\tPINB1\n#define PB1_RPORT\t\tPINB\n#define PB1_WPORT\t\tPORTB\n#define PB1_PWM\t\t\tNULL\n#define PB1_DDR\t\t\tDDRB\n#undef PB2\n#define PB2_PIN\t\t\tPINB2\n#define PB2_RPORT\t\tPINB\n#define PB2_WPORT\t\tPORTB\n#define PB2_PWM\t\t\tNULL\n#define PB2_DDR\t\t\tDDRB\n#undef PB3\n#define PB3_PIN\t\t\tPINB3\n#define PB3_RPORT\t\tPINB\n#define PB3_WPORT\t\tPORTB\n#define PB3_PWM\t\t\tNULL\n#define PB3_DDR\t\t\tDDRB\n#undef PB4\n#define PB4_PIN\t\t\tPINB4\n#define PB4_RPORT\t\tPINB\n#define PB4_WPORT\t\tPORTB\n#define PB4_PWM\t\t\tNULL\n#define PB4_DDR\t\t\tDDRB\n#undef PB5\n#define PB5_PIN\t\t\tPINB5\n#define PB5_RPORT\t\tPINB\n#define PB5_WPORT\t\tPORTB\n#define PB5_PWM\t\t\tNULL\n#define PB5_DDR\t\t\tDDRB\n#undef PB6\n#define PB6_PIN\t\t\tPINB6\n#define PB6_RPORT\t\tPINB\n#define PB6_WPORT\t\tPORTB\n#define PB6_PWM\t\t\tNULL\n#define PB6_DDR\t\t\tDDRB\n#undef PB7\n#define PB7_PIN\t\t\tPINB7\n#define PB7_RPORT\t\tPINB\n#define PB7_WPORT\t\tPORTB\n#define PB7_PWM\t\t\tNULL\n#define PB7_DDR\t\t\tDDRB\n\n#undef PC0\n#define PC0_PIN\t\t\tPINC0\n#define PC0_RPORT\t\tPINC\n#define PC0_WPORT\t\tPORTC\n#define PC0_PWM\t\t\tNULL\n#define PC0_DDR\t\t\tDDRC\n#undef PC1\n#define PC1_PIN\t\t\tPINC1\n#define PC1_RPORT\t\tPINC\n#define PC1_WPORT\t\tPORTC\n#define PC1_PWM\t\t\tNULL\n#define PC1_DDR\t\t\tDDRC\n#undef PC2\n#define PC2_PIN\t\t\tPINC2\n#define PC2_RPORT\t\tPINC\n#define PC2_WPORT\t\tPORTC\n#define PC2_PWM\t\t\tNULL\n#define PC2_DDR\t\t\tDDRC\n#undef PC3\n#define PC3_PIN\t\t\tPINC3\n#define PC3_RPORT\t\tPINC\n#define PC3_WPORT\t\tPORTC\n#define PC3_PWM\t\t\tNULL\n#define PC3_DDR\t\t\tDDRC\n#undef PC4\n#define PC4_PIN\t\t\tPINC4\n#define PC4_RPORT\t\tPINC\n#define PC4_WPORT\t\tPORTC\n#define PC4_PWM\t\t\tNULL\n#define PC4_DDR\t\t\tDDRC\n#undef PC5\n#define PC5_PIN\t\t\tPINC5\n#define PC5_RPORT\t\tPINC\n#define PC5_WPORT\t\tPORTC\n#define PC5_PWM\t\t\tNULL\n#define PC5_DDR\t\t\tDDRC\n#undef PC6\n#define PC6_PIN\t\t\tPINC6\n#define PC6_RPORT\t\tPINC\n#define PC6_WPORT\t\tPORTC\n#define PC6_PWM\t\t\tNULL\n#define PC6_DDR\t\t\tDDRC\n#undef PC7\n#define PC7_PIN\t\t\tPINC7\n#define PC7_RPORT\t\tPINC\n#define PC7_WPORT\t\tPORTC\n#define PC7_PWM\t\t\tNULL\n#define PC7_DDR\t\t\tDDRC\n\n#undef PD0\n#define PD0_PIN\t\t\tPIND0\n#define PD0_RPORT\t\tPIND\n#define PD0_WPORT\t\tPORTD\n#define PD0_PWM\t\t\tNULL\n#define PD0_DDR\t\t\tDDRD\n#undef PD1\n#define PD1_PIN\t\t\tPIND1\n#define PD1_RPORT\t\tPIND\n#define PD1_WPORT\t\tPORTD\n#define PD1_PWM\t\t\tNULL\n#define PD1_DDR\t\t\tDDRD\n#undef PD2\n#define PD2_PIN\t\t\tPIND2\n#define PD2_RPORT\t\tPIND\n#define PD2_WPORT\t\tPORTD\n#define PD2_PWM\t\t\tNULL\n#define PD2_DDR\t\t\tDDRD\n#undef PD3\n#define PD3_PIN\t\t\tPIND3\n#define PD3_RPORT\t\tPIND\n#define PD3_WPORT\t\tPORTD\n#define PD3_PWM\t\t\tNULL\n#define PD3_DDR\t\t\tDDRD\n#undef PD4\n#define PD4_PIN\t\t\tPIND4\n#define PD4_RPORT\t\tPIND\n#define PD4_WPORT\t\tPORTD\n#define PD4_PWM\t\t\tNULL\n#define PD4_DDR\t\t\tDDRD\n#undef PD5\n#define PD5_PIN\t\t\tPIND5\n#define PD5_RPORT\t\tPIND\n#define PD5_WPORT\t\tPORTD\n#define PD5_PWM\t\t\tNULL\n#define PD5_DDR\t\t\tDDRD\n#undef PD6\n#define PD6_PIN\t\t\tPIND6\n#define PD6_RPORT\t\tPIND\n#define PD6_WPORT\t\tPORTD\n#define PD6_PWM\t\t\tNULL\n#define PD6_DDR\t\t\tDDRD\n#undef PD7\n#define PD7_PIN\t\t\tPIND7\n#define PD7_RPORT\t\tPIND\n#define PD7_WPORT\t\tPORTD\n#define PD7_PWM\t\t\tNULL\n#define PD7_DDR\t\t\tDDRD\n\n#undef PE0\n#define PE0_PIN\t\t\tPINE0\n#define PE0_RPORT\t\tPINE\n#define PE0_WPORT\t\tPORTE\n#define PE0_PWM\t\t\tNULL\n#define PE0_DDR\t\t\tDDRE\n#undef PE1\n#define PE1_PIN\t\t\tPINE1\n#define PE1_RPORT\t\tPINE\n#define PE1_WPORT\t\tPORTE\n#define PE1_PWM\t\t\tNULL\n#define PE1_DDR\t\t\tDDRE\n#undef PE2\n#define PE2_PIN\t\t\tPINE2\n#define PE2_RPORT\t\tPINE\n#define PE2_WPORT\t\tPORTE\n#define PE2_PWM\t\t\tNULL\n#define PE2_DDR\t\t\tDDRE\n#undef PE3\n#define PE3_PIN\t\t\tPINE3\n#define PE3_RPORT\t\tPINE\n#define PE3_WPORT\t\tPORTE\n#define PE3_PWM\t\t\tNULL\n#define PE3_DDR\t\t\tDDRE\n#undef PE4\n#define PE4_PIN\t\t\tPINE4\n#define PE4_RPORT\t\tPINE\n#define PE4_WPORT\t\tPORTE\n#define PE4_PWM\t\t\tNULL\n#define PE4_DDR\t\t\tDDRE\n#undef PE5\n#define PE5_PIN\t\t\tPINE5\n#define PE5_RPORT\t\tPINE\n#define PE5_WPORT\t\tPORTE\n#define PE5_PWM\t\t\tNULL\n#define PE5_DDR\t\t\tDDRE\n#undef PE6\n#define PE6_PIN\t\t\tPINE6\n#define PE6_RPORT\t\tPINE\n#define PE6_WPORT\t\tPORTE\n#define PE6_PWM\t\t\tNULL\n#define PE6_DDR\t\t\tDDRE\n#undef PE7\n#define PE7_PIN\t\t\tPINE7\n#define PE7_RPORT\t\tPINE\n#define PE7_WPORT\t\tPORTE\n#define PE7_PWM\t\t\tNULL\n#define PE7_DDR\t\t\tDDRE\n\n#undef PF0\n#define PF0_PIN\t\t\tPINF0\n#define PF0_RPORT\t\tPINF\n#define PF0_WPORT\t\tPORTF\n#define PF0_PWM\t\t\tNULL\n#define PF0_DDR\t\t\tDDRF\n#undef PF1\n#define PF1_PIN\t\t\tPINF1\n#define PF1_RPORT\t\tPINF\n#define PF1_WPORT\t\tPORTF\n#define PF1_PWM\t\t\tNULL\n#define PF1_DDR\t\t\tDDRF\n#undef PF2\n#define PF2_PIN\t\t\tPINF2\n#define PF2_RPORT\t\tPINF\n#define PF2_WPORT\t\tPORTF\n#define PF2_PWM\t\t\tNULL\n#define PF2_DDR\t\t\tDDRF\n#undef PF3\n#define PF3_PIN\t\t\tPINF3\n#define PF3_RPORT\t\tPINF\n#define PF3_WPORT\t\tPORTF\n#define PF3_PWM\t\t\tNULL\n#define PF3_DDR\t\t\tDDRF\n#undef PF4\n#define PF4_PIN\t\t\tPINF4\n#define PF4_RPORT\t\tPINF\n#define PF4_WPORT\t\tPORTF\n#define PF4_PWM\t\t\tNULL\n#define PF4_DDR\t\t\tDDRF\n#undef PF5\n#define PF5_PIN\t\t\tPINF5\n#define PF5_RPORT\t\tPINF\n#define PF5_WPORT\t\tPORTF\n#define PF5_PWM\t\t\tNULL\n#define PF5_DDR\t\t\tDDRF\n#undef PF6\n#define PF6_PIN\t\t\tPINF6\n#define PF6_RPORT\t\tPINF\n#define PF6_WPORT\t\tPORTF\n#define PF6_PWM\t\t\tNULL\n#define PF6_DDR\t\t\tDDRF\n#undef PF7\n#define PF7_PIN\t\t\tPINF7\n#define PF7_RPORT\t\tPINF\n#define PF7_WPORT\t\tPORTF\n#define PF7_PWM\t\t\tNULL\n#define PF7_DDR\t\t\tDDRF\n#endif\n\n#if defined (__AVR_AT90USB1287__) || defined (__AVR_AT90USB1286__)\n// SPI\n#define\tSCK\t\t\t\t\tDIO9\n#define\tMISO\t\t\t\tDIO11\n#define\tMOSI\t\t\t\tDIO10\n#define\tSS\t\t\t\t\tDIO8\n\n// change for your board\n#define\tDEBUG_LED\t\tDIO31 /* led D5 red */\n\n/*\npins\n*/\n#define DIO0_PIN        PIND0\n#define DIO0_RPORT      PIND\n#define DIO0_WPORT      PORTD\n#define DIO0_PWM\t\t\tNULL\n#define DIO0_DDR        DDRD\n\n#define DIO1_PIN        PIND1\n#define DIO1_RPORT      PIND\n#define DIO1_WPORT      PORTD\n#define DIO1_PWM\t\t\tNULL\n#define DIO1_DDR        DDRD\n\n#define DIO2_PIN        PIND2\n#define DIO2_RPORT      PIND\n#define DIO2_WPORT      PORTD\n#define DIO2_PWM\t\t\tNULL\n#define DIO2_DDR        DDRD\n\n#define DIO3_PIN        PIND3\n#define DIO3_RPORT      PIND\n#define DIO3_WPORT      PORTD\n#define DIO3_PWM\t\t\tNULL\n#define DIO3_DDR        DDRD\n\n#define DIO4_PIN        PIND4\n#define DIO4_RPORT      PIND\n#define DIO4_WPORT      PORTD\n#define DIO4_PWM\t\t\tNULL\n#define DIO4_DDR        DDRD\n\n#define DIO5_PIN        PIND5\n#define DIO5_RPORT      PIND\n#define DIO5_WPORT      PORTD\n#define DIO5_PWM\t\t\tNULL\n#define DIO5_DDR        DDRD\n\n#define DIO6_PIN        PIND6\n#define DIO6_RPORT      PIND\n#define DIO6_WPORT      PORTD\n#define DIO6_PWM\t\t\tNULL\n#define DIO6_DDR        DDRD\n\n#define DIO7_PIN        PIND7\n#define DIO7_RPORT      PIND\n#define DIO7_WPORT      PORTD\n#define DIO7_PWM\t\t\tNULL\n#define DIO7_DDR        DDRD\n\n#define DIO8_PIN        PINE0\n#define DIO8_RPORT      PINE\n#define DIO8_WPORT      PORTE\n#define DIO8_PWM\t\t\tNULL\n#define DIO8_DDR        DDRE\n\n#define DIO9_PIN        PINE1\n#define DIO9_RPORT      PINE\n#define DIO9_WPORT      PORTE\n#define DIO9_PWM\t\t\tNULL\n#define DIO9_DDR        DDRE\n\n#define DIO10_PIN       PINC0\n#define DIO10_RPORT     PINC\n#define DIO10_WPORT     PORTC\n#define DIO10_PWM\t\t\tNULL\n#define DIO10_DDR       DDRC\n\n#define DIO11_PIN       PINC1\n#define DIO11_RPORT     PINC\n#define DIO11_WPORT     PORTC\n#define DIO11_PWM\t\t\tNULL\n#define DIO11_DDR       DDRC\n\n#define DIO12_PIN       PINC2\n#define DIO12_RPORT     PINC\n#define DIO12_WPORT     PORTC\n#define DIO12_PWM\t\t\tNULL\n#define DIO12_DDR       DDRC\n\n#define DIO13_PIN       PINC3\n#define DIO13_RPORT     PINC\n#define DIO13_WPORT     PORTC\n#define DIO13_PWM\t\t\tNULL\n#define DIO13_DDR       DDRC\n\n#define DIO14_PIN       PINC4\n#define DIO14_RPORT     PINC\n#define DIO14_WPORT     PORTC\n#define DIO14_PWM\t\t\tNULL\n#define DIO14_DDR       DDRC\n\n#define DIO15_PIN       PINC5\n#define DIO15_RPORT     PINC\n#define DIO15_WPORT     PORTC\n#define DIO15_PWM\t\t\tNULL\n#define DIO15_DDR       DDRC\n\n#define DIO16_PIN       PINC6\n#define DIO16_RPORT     PINC\n#define DIO16_WPORT     PORTC\n#define DIO16_PWM\t\t\tNULL\n#define DIO16_DDR       DDRC\n\n#define DIO17_PIN       PINC7\n#define DIO17_RPORT     PINC\n#define DIO17_WPORT     PORTC\n#define DIO17_PWM\t\t\tNULL\n#define DIO17_DDR       DDRC\n\n#define DIO18_PIN       PINE6\n#define DIO18_RPORT     PINE\n#define DIO18_WPORT     PORTE\n#define DIO18_PWM\t\t\tNULL\n#define DIO18_DDR       DDRE\n\n#define DIO19_PIN       PINE7\n#define DIO19_RPORT     PINE\n#define DIO19_WPORT     PORTE\n#define DIO19_PWM\t\t\tNULL\n#define DIO19_DDR       DDRE\n\n#define DIO20_PIN       PINB0\n#define DIO20_RPORT     PINB\n#define DIO20_WPORT     PORTB\n#define DIO20_PWM\t\t\tNULL\n#define DIO20_DDR       DDRB\n\n#define DIO21_PIN       PINB1\n#define DIO21_RPORT     PINB\n#define DIO21_WPORT     PORTB\n#define DIO21_PWM\t\t\tNULL\n#define DIO21_DDR       DDRB\n\n#define DIO22_PIN       PINB2\n#define DIO22_RPORT     PINB\n#define DIO22_WPORT     PORTB\n#define DIO22_PWM\t\t\tNULL\n#define DIO22_DDR       DDRB\n\n#define DIO23_PIN       PINB3\n#define DIO23_RPORT     PINB\n#define DIO23_WPORT     PORTB\n#define DIO23_PWM\t\t\tNULL\n#define DIO23_DDR       DDRB\n\n#define DIO24_PIN       PINB4\n#define DIO24_RPORT     PINB\n#define DIO24_WPORT     PORTB\n#define DIO24_PWM\t\t\tNULL\n#define DIO24_DDR       DDRB\n\n#define DIO25_PIN       PINB5\n#define DIO25_RPORT     PINB\n#define DIO25_WPORT     PORTB\n#define DIO25_PWM\t\t\tNULL\n#define DIO25_DDR       DDRB\n\n#define DIO26_PIN       PINB6\n#define DIO26_RPORT     PINB\n#define DIO26_WPORT     PORTB\n#define DIO26_PWM\t\t\tNULL\n#define DIO26_DDR       DDRB\n\n#define DIO27_PIN       PINB7\n#define DIO27_RPORT     PINB\n#define DIO27_WPORT     PORTB\n#define DIO27_PWM\t\t\tNULL\n#define DIO27_DDR       DDRB\n\n#define DIO28_PIN       PINA0\n#define DIO28_RPORT     PINA\n#define DIO28_WPORT     PORTA\n#define DIO28_PWM\t\t\tNULL\n#define DIO28_DDR       DDRA\n\n#define DIO29_PIN       PINA1\n#define DIO29_RPORT     PINA\n#define DIO29_WPORT     PORTA\n#define DIO29_PWM\t\t\tNULL\n#define DIO29_DDR       DDRA\n\n#define DIO30_PIN       PINA2\n#define DIO30_RPORT     PINA\n#define DIO30_WPORT     PORTA\n#define DIO30_PWM\t\t\tNULL\n#define DIO30_DDR       DDRA\n\n#define DIO31_PIN       PINA3\n#define DIO31_RPORT     PINA\n#define DIO31_WPORT     PORTA\n#define DIO31_PWM\t\t\tNULL\n#define DIO31_DDR       DDRA\n\n\n#define DIO32_PIN       PINA4\n#define DIO32_RPORT     PINA\n#define DIO32_WPORT     PORTA\n#define DIO32_PWM\t\t\tNULL\n#define DIO32_DDR       DDRA\n\n#define DIO33_PIN       PINA5\n#define DIO33_RPORT     PINA\n#define DIO33_WPORT     PORTA\n#define DIO33_PWM\t\t\tNULL\n#define DIO33_DDR       DDRA\n\n#define DIO34_PIN       PINA6\n#define DIO34_RPORT     PINA\n#define DIO34_WPORT     PORTA\n#define DIO34_PWM\t\t\tNULL\n#define DIO34_DDR       DDRA\n\n#define DIO35_PIN       PINA7\n#define DIO35_RPORT     PINA\n#define DIO35_WPORT     PORTA\n#define DIO35_PWM\t\t\tNULL\n#define DIO35_DDR       DDRA\n\n#define DIO36_PIN       PINE4\n#define DIO36_RPORT     PINE\n#define DIO36_WPORT     PORTE\n#define DIO36_PWM\t\t\tNULL\n#define DIO36_DDR       DDRE\n\n#define DIO37_PIN       PINE5\n#define DIO37_RPORT     PINE\n#define DIO37_WPORT     PORTE\n#define DIO37_PWM\t\t\tNULL\n#define DIO37_DDR       DDRE\n\n#define DIO38_PIN       PINF0\n#define DIO38_RPORT     PINF\n#define DIO38_WPORT     PORTF\n#define DIO38_PWM\t\t\tNULL\n#define DIO38_DDR       DDRF\n\n#define DIO39_PIN       PINF1\n#define DIO39_RPORT     PINF\n#define DIO39_WPORT     PORTF\n#define DIO39_PWM\t\t\tNULL\n#define DIO39_DDR       DDRF\n\n#define DIO40_PIN       PINF2\n#define DIO40_RPORT     PINF\n#define DIO40_WPORT     PORTF\n#define DIO40_PWM\t\t\tNULL\n#define DIO40_DDR       DDRF\n\n#define DIO41_PIN       PINF3\n#define DIO41_RPORT     PINF\n#define DIO41_WPORT     PORTF\n#define DIO41_PWM\t\t\tNULL\n#define DIO41_DDR       DDRF\n\n#define DIO42_PIN       PINF4\n#define DIO42_RPORT     PINF\n#define DIO42_WPORT     PORTF\n#define DIO42_PWM\t\t\tNULL\n#define DIO42_DDR       DDRF\n\n#define DIO43_PIN       PINF5\n#define DIO43_RPORT     PINF\n#define DIO43_WPORT     PORTF\n#define DIO43_PWM\t\t\tNULL\n#define DIO43_DDR       DDRF\n\n#define DIO44_PIN       PINF6\n#define DIO44_RPORT     PINF\n#define DIO44_WPORT     PORTF\n#define DIO44_PWM\t\t\tNULL\n#define DIO44_DDR       DDRF\n\n#define DIO45_PIN       PINF7\n#define DIO45_RPORT     PINF\n#define DIO45_WPORT     PORTF\n#define DIO45_PWM\t\t\tNULL\n#define DIO45_DDR       DDRF\n\n#define AIO0_PIN PINF0\n#define AIO0_RPORT PINF\n#define AIO0_WPORT PORTF\n#define AIO0_PWM\t\t\tNULL\n#define AIO0_DDR DDRF\n\n#define AIO1_PIN PINF1\n#define AIO1_RPORT PINF\n#define AIO1_WPORT PORTF\n#define AIO1_PWM\t\t\tNULL\n#define AIO1_DDR DDRF\n\n#define AIO2_PIN PINF2\n#define AIO2_RPORT PINF\n#define AIO2_WPORT PORTF\n#define AIO2_PWM\t\t\tNULL\n#define AIO2_DDR DDRF\n\n#define AIO3_PIN PINF3\n#define AIO3_RPORT PINF\n#define AIO3_WPORT PORTF\n#define AIO3_PWM\t\t\tNULL\n#define AIO3_DDR DDRF\n\n#define AIO4_PIN PINF4\n#define AIO4_RPORT PINF\n#define AIO4_WPORT PORTF\n#define AIO4_PWM\t\t\tNULL\n#define AIO4_DDR DDRF\n\n#define AIO5_PIN PINF5\n#define AIO5_RPORT PINF\n#define AIO5_WPORT PORTF\n#define AIO5_PWM\t\t\tNULL\n#define AIO5_DDR DDRF\n\n#define AIO6_PIN PINF6\n#define AIO6_RPORT PINF\n#define AIO6_WPORT PORTF\n#define AIO6_PWM\t\t\tNULL\n#define AIO6_DDR DDRF\n\n#define AIO7_PIN PINF7\n#define AIO7_RPORT PINF\n#define AIO7_WPORT PORTF\n#define AIO7_PWM\t\t\tNULL\n#define AIO7_DDR DDRF\n\n//-- Begin not supported by Teensyduino\n//-- don't use Arduino functions on these pins pinMode/digitalWrite/etc\n#define DIO46_PIN       PINE2\n#define DIO46_RPORT     PINE\n#define DIO46_WPORT     PORTE\n#define DIO46_PWM\t\t\tNULL\n#define DIO46_DDR       DDRE\n\n#define DIO47_PIN       PINE3\n#define DIO47_RPORT     PINE\n#define DIO47_WPORT     PORTE\n#define DIO47_PWM\t\t\tNULL\n#define DIO47_DDR       DDRE\n//-- end not supported by Teensyduino\n\n\n\n#undef PA0\n#define PA0_PIN\t\t\tPINA0\n#define PA0_RPORT\t\tPINA\n#define PA0_WPORT\t\tPORTA\n#define PA0_PWM\t\t\tNULL\n#define PA0_DDR\t\t\tDDRA\n#undef PA1\n#define PA1_PIN\t\t\tPINA1\n#define PA1_RPORT\t\tPINA\n#define PA1_WPORT\t\tPORTA\n#define PA1_PWM\t\t\tNULL\n#define PA1_DDR\t\t\tDDRA\n#undef PA2\n#define PA2_PIN\t\t\tPINA2\n#define PA2_RPORT\t\tPINA\n#define PA2_WPORT\t\tPORTA\n#define PA2_PWM\t\t\tNULL\n#define PA2_DDR\t\t\tDDRA\n#undef PA3\n#define PA3_PIN\t\t\tPINA3\n#define PA3_RPORT\t\tPINA\n#define PA3_WPORT\t\tPORTA\n#define PA3_PWM\t\t\tNULL\n#define PA3_DDR\t\t\tDDRA\n#undef PA4\n#define PA4_PIN\t\t\tPINA4\n#define PA4_RPORT\t\tPINA\n#define PA4_WPORT\t\tPORTA\n#define PA4_PWM\t\t\tNULL\n#define PA4_DDR\t\t\tDDRA\n#undef PA5\n#define PA5_PIN\t\t\tPINA5\n#define PA5_RPORT\t\tPINA\n#define PA5_WPORT\t\tPORTA\n#define PA5_PWM\t\t\tNULL\n#define PA5_DDR\t\t\tDDRA\n#undef PA6\n#define PA6_PIN\t\t\tPINA6\n#define PA6_RPORT\t\tPINA\n#define PA6_WPORT\t\tPORTA\n#define PA6_PWM\t\t\tNULL\n#define PA6_DDR\t\t\tDDRA\n#undef PA7\n#define PA7_PIN\t\t\tPINA7\n#define PA7_RPORT\t\tPINA\n#define PA7_WPORT\t\tPORTA\n#define PA7_PWM\t\t\tNULL\n#define PA7_DDR\t\t\tDDRA\n\n#undef PB0\n#define PB0_PIN\t\t\tPINB0\n#define PB0_RPORT\t\tPINB\n#define PB0_WPORT\t\tPORTB\n#define PB0_PWM\t\t\tNULL\n#define PB0_DDR\t\t\tDDRB\n#undef PB1\n#define PB1_PIN\t\t\tPINB1\n#define PB1_RPORT\t\tPINB\n#define PB1_WPORT\t\tPORTB\n#define PB1_PWM\t\t\tNULL\n#define PB1_DDR\t\t\tDDRB\n#undef PB2\n#define PB2_PIN\t\t\tPINB2\n#define PB2_RPORT\t\tPINB\n#define PB2_WPORT\t\tPORTB\n#define PB2_PWM\t\t\tNULL\n#define PB2_DDR\t\t\tDDRB\n#undef PB3\n#define PB3_PIN\t\t\tPINB3\n#define PB3_RPORT\t\tPINB\n#define PB3_WPORT\t\tPORTB\n#define PB3_PWM\t\t\tNULL\n#define PB3_DDR\t\t\tDDRB\n#undef PB4\n#define PB4_PIN\t\t\tPINB4\n#define PB4_RPORT\t\tPINB\n#define PB4_WPORT\t\tPORTB\n#define PB4_PWM\t\t\tNULL\n#define PB4_DDR\t\t\tDDRB\n#undef PB5\n#define PB5_PIN\t\t\tPINB5\n#define PB5_RPORT\t\tPINB\n#define PB5_WPORT\t\tPORTB\n#define PB5_PWM\t\t\tNULL\n#define PB5_DDR\t\t\tDDRB\n#undef PB6\n#define PB6_PIN\t\t\tPINB6\n#define PB6_RPORT\t\tPINB\n#define PB6_WPORT\t\tPORTB\n#define PB6_PWM\t\t\tNULL\n#define PB6_DDR\t\t\tDDRB\n#undef PB7\n#define PB7_PIN\t\t\tPINB7\n#define PB7_RPORT\t\tPINB\n#define PB7_WPORT\t\tPORTB\n#define PB7_PWM\t\t\tNULL\n#define PB7_DDR\t\t\tDDRB\n\n#undef PC0\n#define PC0_PIN\t\t\tPINC0\n#define PC0_RPORT\t\tPINC\n#define PC0_WPORT\t\tPORTC\n#define PC0_PWM\t\t\tNULL\n#define PC0_DDR\t\t\tDDRC\n#undef PC1\n#define PC1_PIN\t\t\tPINC1\n#define PC1_RPORT\t\tPINC\n#define PC1_WPORT\t\tPORTC\n#define PC1_PWM\t\t\tNULL\n#define PC1_DDR\t\t\tDDRC\n#undef PC2\n#define PC2_PIN\t\t\tPINC2\n#define PC2_RPORT\t\tPINC\n#define PC2_WPORT\t\tPORTC\n#define PC2_PWM\t\t\tNULL\n#define PC2_DDR\t\t\tDDRC\n#undef PC3\n#define PC3_PIN\t\t\tPINC3\n#define PC3_RPORT\t\tPINC\n#define PC3_WPORT\t\tPORTC\n#define PC3_PWM\t\t\tNULL\n#define PC3_DDR\t\t\tDDRC\n#undef PC4\n#define PC4_PIN\t\t\tPINC4\n#define PC4_RPORT\t\tPINC\n#define PC4_WPORT\t\tPORTC\n#define PC4_PWM\t\t\tNULL\n#define PC4_DDR\t\t\tDDRC\n#undef PC5\n#define PC5_PIN\t\t\tPINC5\n#define PC5_RPORT\t\tPINC\n#define PC5_WPORT\t\tPORTC\n#define PC5_PWM\t\t\tNULL\n#define PC5_DDR\t\t\tDDRC\n#undef PC6\n#define PC6_PIN\t\t\tPINC6\n#define PC6_RPORT\t\tPINC\n#define PC6_WPORT\t\tPORTC\n#define PC6_PWM\t\t\tNULL\n#define PC6_DDR\t\t\tDDRC\n#undef PC7\n#define PC7_PIN\t\t\tPINC7\n#define PC7_RPORT\t\tPINC\n#define PC7_WPORT\t\tPORTC\n#define PC7_PWM\t\t\tNULL\n#define PC7_DDR\t\t\tDDRC\n\n#undef PD0\n#define PD0_PIN\t\t\tPIND0\n#define PD0_RPORT\t\tPIND\n#define PD0_WPORT\t\tPORTD\n#define PD0_PWM\t\t\tNULL\n#define PD0_DDR\t\t\tDDRD\n#undef PD1\n#define PD1_PIN\t\t\tPIND1\n#define PD1_RPORT\t\tPIND\n#define PD1_WPORT\t\tPORTD\n#define PD1_PWM\t\t\tNULL\n#define PD1_DDR\t\t\tDDRD\n#undef PD2\n#define PD2_PIN\t\t\tPIND2\n#define PD2_RPORT\t\tPIND\n#define PD2_WPORT\t\tPORTD\n#define PD2_PWM\t\t\tNULL\n#define PD2_DDR\t\t\tDDRD\n#undef PD3\n#define PD3_PIN\t\t\tPIND3\n#define PD3_RPORT\t\tPIND\n#define PD3_WPORT\t\tPORTD\n#define PD3_PWM\t\t\tNULL\n#define PD3_DDR\t\t\tDDRD\n#undef PD4\n#define PD4_PIN\t\t\tPIND4\n#define PD4_RPORT\t\tPIND\n#define PD4_WPORT\t\tPORTD\n#define PD4_PWM\t\t\tNULL\n#define PD4_DDR\t\t\tDDRD\n#undef PD5\n#define PD5_PIN\t\t\tPIND5\n#define PD5_RPORT\t\tPIND\n#define PD5_WPORT\t\tPORTD\n#define PD5_PWM\t\t\tNULL\n#define PD5_DDR\t\t\tDDRD\n#undef PD6\n#define PD6_PIN\t\t\tPIND6\n#define PD6_RPORT\t\tPIND\n#define PD6_WPORT\t\tPORTD\n#define PD6_PWM\t\t\tNULL\n#define PD6_DDR\t\t\tDDRD\n#undef PD7\n#define PD7_PIN\t\t\tPIND7\n#define PD7_RPORT\t\tPIND\n#define PD7_WPORT\t\tPORTD\n#define PD7_PWM\t\t\tNULL\n#define PD7_DDR\t\t\tDDRD\n\n#undef PE0\n#define PE0_PIN\t\t\tPINE0\n#define PE0_RPORT\t\tPINE\n#define PE0_WPORT\t\tPORTE\n#define PE0_PWM\t\t\tNULL\n#define PE0_DDR\t\t\tDDRE\n#undef PE1\n#define PE1_PIN\t\t\tPINE1\n#define PE1_RPORT\t\tPINE\n#define PE1_WPORT\t\tPORTE\n#define PE1_PWM\t\t\tNULL\n#define PE1_DDR\t\t\tDDRE\n#undef PE2\n#define PE2_PIN\t\t\tPINE2\n#define PE2_RPORT\t\tPINE\n#define PE2_WPORT\t\tPORTE\n#define PE2_PWM\t\t\tNULL\n#define PE2_DDR\t\t\tDDRE\n#undef PE3\n#define PE3_PIN\t\t\tPINE3\n#define PE3_RPORT\t\tPINE\n#define PE3_WPORT\t\tPORTE\n#define PE3_PWM\t\t\tNULL\n#define PE3_DDR\t\t\tDDRE\n#undef PE4\n#define PE4_PIN\t\t\tPINE4\n#define PE4_RPORT\t\tPINE\n#define PE4_WPORT\t\tPORTE\n#define PE4_PWM\t\t\tNULL\n#define PE4_DDR\t\t\tDDRE\n#undef PE5\n#define PE5_PIN\t\t\tPINE5\n#define PE5_RPORT\t\tPINE\n#define PE5_WPORT\t\tPORTE\n#define PE5_PWM\t\t\tNULL\n#define PE5_DDR\t\t\tDDRE\n#undef PE6\n#define PE6_PIN\t\t\tPINE6\n#define PE6_RPORT\t\tPINE\n#define PE6_WPORT\t\tPORTE\n#define PE6_PWM\t\t\tNULL\n#define PE6_DDR\t\t\tDDRE\n#undef PE7\n#define PE7_PIN\t\t\tPINE7\n#define PE7_RPORT\t\tPINE\n#define PE7_WPORT\t\tPORTE\n#define PE7_PWM\t\t\tNULL\n#define PE7_DDR\t\t\tDDRE\n\n#undef PF0\n#define PF0_PIN\t\t\tPINF0\n#define PF0_RPORT\t\tPINF\n#define PF0_WPORT\t\tPORTF\n#define PF0_PWM\t\t\tNULL\n#define PF0_DDR\t\t\tDDRF\n#undef PF1\n#define PF1_PIN\t\t\tPINF1\n#define PF1_RPORT\t\tPINF\n#define PF1_WPORT\t\tPORTF\n#define PF1_PWM\t\t\tNULL\n#define PF1_DDR\t\t\tDDRF\n#undef PF2\n#define PF2_PIN\t\t\tPINF2\n#define PF2_RPORT\t\tPINF\n#define PF2_WPORT\t\tPORTF\n#define PF2_PWM\t\t\tNULL\n#define PF2_DDR\t\t\tDDRF\n#undef PF3\n#define PF3_PIN\t\t\tPINF3\n#define PF3_RPORT\t\tPINF\n#define PF3_WPORT\t\tPORTF\n#define PF3_PWM\t\t\tNULL\n#define PF3_DDR\t\t\tDDRF\n#undef PF4\n#define PF4_PIN\t\t\tPINF4\n#define PF4_RPORT\t\tPINF\n#define PF4_WPORT\t\tPORTF\n#define PF4_PWM\t\t\tNULL\n#define PF4_DDR\t\t\tDDRF\n#undef PF5\n#define PF5_PIN\t\t\tPINF5\n#define PF5_RPORT\t\tPINF\n#define PF5_WPORT\t\tPORTF\n#define PF5_PWM\t\t\tNULL\n#define PF5_DDR\t\t\tDDRF\n#undef PF6\n#define PF6_PIN\t\t\tPINF6\n#define PF6_RPORT\t\tPINF\n#define PF6_WPORT\t\tPORTF\n#define PF6_PWM\t\t\tNULL\n#define PF6_DDR\t\t\tDDRF\n#undef PF7\n#define PF7_PIN\t\t\tPINF7\n#define PF7_RPORT\t\tPINF\n#define PF7_WPORT\t\tPORTF\n#define PF7_PWM\t\t\tNULL\n#define PF7_DDR\t\t\tDDRF\n#endif\n\n\n#ifndef\tDIO0_PIN\n#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request\n#endif\n\n#endif /* _ARDUINO_H */\n"
  },
  {
    "path": "Sprinter/heater.cpp",
    "content": "/*\n Reprap heater funtions based on Sprinter\n\n \n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n \n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n \n You should have received a copy of the GNU General Public License\n along with this program.  If not, see <http://www.gnu.org/licenses/>. */\n\n/*\n This softwarepart for Heatercontrol is based on Sprinter\n big thanks to kliment (https://github.com/kliment/Sprinter)\n*/\n\n\n#include <avr/pgmspace.h>\n\n#include \"heater.h\"\n#include \"fastio.h\"\n#include \"pins.h\"\n#include \"Sprinter.h\"\n\n#ifdef CONTROLLERFAN_PIN\n  void controllerFan(void);\n#endif\n\n#ifdef EXTRUDERFAN_PIN\n  void extruderFan(void);\n#endif\n\n// Manage heater variables. For a thermistor or AD595 thermocouple, raw values refer to the \n// reading from the analog pin. For a MAX6675 thermocouple, the raw value is the temperature in 0.25 \n// degree increments (i.e. 100=25 deg). \n\nint target_raw = 0;\nint target_temp = 0;\nint current_raw = 0;\nint current_raw_maxval = -32000;\nint current_raw_minval = 32000;\nint tt_maxval;\nint tt_minval;\nint target_bed_raw = 0;\nint current_bed_raw = 0;\nunsigned long previous_millis_heater, previous_millis_bed_heater, previous_millis_monitor;\n\n#ifdef PIDTEMP\n  volatile unsigned char g_heater_pwm_val = 0;\n \n  //unsigned char PWM_off_time = 0;\n  //unsigned char PWM_out_on = 0;\n  \n  int temp_iState = 0;\n  int temp_dState = 0;\n  int prev_temp = 0;\n  int pTerm;\n  int iTerm;\n  int dTerm;\n      //int output;\n  int error;\n  int heater_duty = 0;\n  int temp_iState_min = 256L * -PID_INTEGRAL_DRIVE_MAX / PID_IGAIN;\n  int temp_iState_max = 256L * PID_INTEGRAL_DRIVE_MAX / PID_IGAIN;\n#endif\n\n\n#if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n  volatile unsigned char g_fan_pwm_val = 0;\n#endif\n\n#ifdef AUTOTEMP\n    float autotemp_max=AUTO_TEMP_MAX;\n    float autotemp_min=AUTO_TEMP_MIN;\n    float autotemp_factor=AUTO_TEMP_FACTOR;\n    int   autotemp_setpoint=0;\n    bool autotemp_enabled=true;\n#endif\n\n#ifndef HEATER_CURRENT\n  #define HEATER_CURRENT 255\n#endif\n\n#ifdef SMOOTHING\n  uint32_t nma = 0;\n#endif\n\n#ifdef WATCHPERIOD\n  int watch_raw = -1000;\n  unsigned long watchmillis = 0;\n#endif\n\n#ifdef MINTEMP\n  int minttemp = temp2analogh(MINTEMP);\n#endif\n\n#ifdef MAXTEMP\n  int maxttemp = temp2analogh(MAXTEMP);\n#endif\n\n\n\n#define HEAT_INTERVAL 250\n#ifdef HEATER_USES_MAX6675\nunsigned long max6675_previous_millis = 0;\nint max6675_temp = 2000;\n\nint read_max6675()\n{\n  if (millis() - max6675_previous_millis < HEAT_INTERVAL) \n    return max6675_temp;\n  \n  max6675_previous_millis = millis();\n\n  max6675_temp = 0;\n    \n  #ifdef\tPRR\n    PRR &= ~(1<<PRSPI);\n  #elif defined PRR0\n    PRR0 &= ~(1<<PRSPI);\n  #endif\n  \n  SPCR = (1<<MSTR) | (1<<SPE) | (1<<SPR0);\n  \n  // enable TT_MAX6675\n  WRITE(MAX6675_SS, 0);\n  \n  // ensure 100ns delay - a bit extra is fine\n  delay(1);\n  \n  // read MSB\n  SPDR = 0;\n  for (;(SPSR & (1<<SPIF)) == 0;);\n  max6675_temp = SPDR;\n  max6675_temp <<= 8;\n  \n  // read LSB\n  SPDR = 0;\n  for (;(SPSR & (1<<SPIF)) == 0;);\n  max6675_temp |= SPDR;\n  \n  // disable TT_MAX6675\n  WRITE(MAX6675_SS, 1);\n\n  if (max6675_temp & 4) \n  {\n    // thermocouple open\n    max6675_temp = 2000;\n  }\n  else \n  {\n    max6675_temp = max6675_temp >> 3;\n  }\n\n  return max6675_temp;\n}\n#endif\n\n\n//------------------------------------------------------------------------\n// Soft PWM for Heater and FAN\n//------------------------------------------------------------------------\n\n#if defined(PID_SOFT_PWM) || (defined(FAN_SOFT_PWM) && (FAN_PIN > -1))\n void init_Timer2_softpwm(void)\n {\n  // This is a simple SOFT PWM with 500 Hz for Extruder Heating\n\n  TIFR2 = (1 << TOV2);          // clear interrupt flag\n  TCCR2B = (1 << CS22) | (1 << CS20);         // start timer (ck/128 prescalar)\n  TCCR2A = 0;//(1 << WGM21);        // Normal mode\n  \n   TIMSK2 |= (1 << TOIE2);\n  \n  #ifdef PID_SOFT_PWM\n   OCR2A = 128;                  // We want to have at least 500Hz or else it gets choppy\n   TIMSK2 |= (1 << OCIE2A);       // enable timer2 output compare match interrupt\n  #endif\n  \n  #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n   OCR2B = 128;                  // We want to have at least 500Hz or else it gets choppy\n   TIMSK2 |= (1 << OCIE2B);       // enable timer2 output compare match interrupt\n  #endif\n \n }\n#endif\n\n#if defined(PID_SOFT_PWM) || (defined(FAN_SOFT_PWM) && (FAN_PIN > -1))\nISR(TIMER2_OVF_vect)\n{\n  \n  //--------------------------------------\n  // Soft PWM, Heater, start PWM cycle\n  //--------------------------------------\n  #ifdef PID_SOFT_PWM\n    if(g_heater_pwm_val >= 2)\n    {\n      #if LED_PIN > -1\n        WRITE(LED_PIN,HIGH);\n      #endif\n      WRITE(HEATER_0_PIN,HIGH);\n\n      if(g_heater_pwm_val <= 253)\n        OCR2A = g_heater_pwm_val; \n      else\n        OCR2A = 192; \n    }\n    else\n    {\n      #if LED_PIN > -1\n        WRITE(LED_PIN,LOW);\n      #endif\n      WRITE(HEATER_0_PIN,LOW);\n      OCR2A = 192; \n    }\n  #endif\n  \n  //--------------------------------------\n  // Soft PWM, Fan, start PWM cycle\n  //--------------------------------------\n  #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n    if(g_fan_pwm_val >= 2)\n    {\n      #if (FAN_PIN > -1) \n        WRITE(FAN_PIN,HIGH);\n      #endif  \n      \n      if(g_fan_pwm_val <= 253)\n        OCR2B = g_fan_pwm_val; \n      else\n        OCR2B = 128; \n    }\n    else\n    {\n      #if (FAN_PIN > -1) \n        WRITE(FAN_PIN,LOW);\n      #endif  \n      \n      OCR2B = 128; \n    }\n  #endif\n  \n\n}\n#endif\n\n\n #ifdef PID_SOFT_PWM\n ISR(TIMER2_COMPA_vect)\n {\n\n\n   if(g_heater_pwm_val > 253)\n   {\n     #if LED_PIN > -1\n       WRITE(LED_PIN,HIGH);\n     #endif\n     WRITE(HEATER_0_PIN,HIGH);\n   }\n   else\n   {\n     #if LED_PIN > -1\n       WRITE(LED_PIN,LOW);\n     #endif\n     WRITE(HEATER_0_PIN,LOW);\n   }\n   \n\n }\n #endif\n \n\n #if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n ISR(TIMER2_COMPB_vect)\n {\n\n   \n   if(g_fan_pwm_val > 253)\n   {\n     #if (FAN_PIN > -1) \n       WRITE(FAN_PIN,HIGH);\n     #endif\n   }\n   else\n   {\n     #if (FAN_PIN > -1) \n       WRITE(FAN_PIN,LOW);\n     #endif\n   }  \n\n\n }  \n #endif\n //--------------------END SOFT PWM---------------------------\n\n//-------------------- START PID AUTOTUNE ---------------------------\n// Based on PID relay test \n// Thanks to Erik van der Zalm for this idea to use it for Marlin\n// Some information see:\n// http://brettbeauregard.com/blog/2012/01/arduino-pid-autotune-library/\n//------------------------------------------------------------------\n#ifdef PID_AUTOTUNE\nvoid PID_autotune(int PIDAT_test_temp)\n{\n  float PIDAT_input = 0;\n  int PIDAT_input_help = 0;\n  unsigned char PIDAT_count_input = 0;\n\n  float PIDAT_max, PIDAT_min;\n \n  unsigned char PIDAT_PWM_val = HEATER_CURRENT;\n  \n  unsigned char PIDAT_cycles=0;\n  bool PIDAT_heating = true;\n\n  unsigned long PIDAT_temp_millis = millis();\n  unsigned long PIDAT_t1=PIDAT_temp_millis;\n  unsigned long PIDAT_t2=PIDAT_temp_millis;\n  unsigned long PIDAT_T_check_AI_val = PIDAT_temp_millis;\n\n  unsigned char PIDAT_cycle_cnt = 0;\n  \n  long PIDAT_t_high;\n  long PIDAT_t_low;\n\n  long PIDAT_bias= HEATER_CURRENT/2;\n  long PIDAT_d  =  HEATER_CURRENT/2;\n  \n  float PIDAT_Ku, PIDAT_Tu;\n  float PIDAT_Kp, PIDAT_Ki, PIDAT_Kd;\n  \n  #define PIDAT_TIME_FACTOR ((HEATER_CHECK_INTERVAL*256.0) / 1000.0)\n  \n  showString(PSTR(\"PID Autotune start\\r\\n\"));\n\n  target_temp = PIDAT_test_temp;\n  \n  #ifdef BED_USES_THERMISTOR\n   WRITE(HEATER_1_PIN,LOW);\n  #endif\n  \n  for(;;) \n  {\n \n    if((millis() - PIDAT_T_check_AI_val) > 100 )\n    {\n      PIDAT_T_check_AI_val = millis();\n      PIDAT_cycle_cnt++;\n      \n      #ifdef HEATER_USES_THERMISTOR\n        current_raw = analogRead(TEMP_0_PIN); \n        current_raw = 1023 - current_raw;\n        PIDAT_input_help += analog2temp(current_raw);\n        PIDAT_count_input++;\n      #elif defined HEATER_USES_AD595\n        current_raw = analogRead(TEMP_0_PIN);    \n        PIDAT_input_help += analog2temp(current_raw);\n        PIDAT_count_input++;\n      #elif defined HEATER_USES_MAX6675\n        current_raw = read_max6675();\n        PIDAT_input_help += analog2temp(current_raw);\n        PIDAT_count_input++;\n      #endif\n    }\n    \n    if(PIDAT_cycle_cnt >= 10 )\n    {\n      \n      PIDAT_cycle_cnt = 0;\n      \n      PIDAT_input = (float)PIDAT_input_help / (float)PIDAT_count_input;\n      PIDAT_input_help = 0;\n      PIDAT_count_input = 0;\n      \n      PIDAT_max=max(PIDAT_max,PIDAT_input);\n      PIDAT_min=min(PIDAT_min,PIDAT_input);\n      \n      if(PIDAT_heating == true && PIDAT_input > PIDAT_test_temp) \n      {\n        if(millis() - PIDAT_t2 > 5000) \n        { \n          PIDAT_heating = false;\n          PIDAT_PWM_val = (PIDAT_bias - PIDAT_d);\n          PIDAT_t1 = millis();\n          PIDAT_t_high = PIDAT_t1 - PIDAT_t2;\n          PIDAT_max = PIDAT_test_temp;\n        }\n      }\n      \n      if(PIDAT_heating == false && PIDAT_input < PIDAT_test_temp) \n      {\n        if(millis() - PIDAT_t1 > 5000) \n        {\n          PIDAT_heating = true;\n          PIDAT_t2 = millis();\n          PIDAT_t_low = PIDAT_t2 - PIDAT_t1;\n          \n          if(PIDAT_cycles > 0) \n          {\n            PIDAT_bias += (PIDAT_d*(PIDAT_t_high - PIDAT_t_low))/(PIDAT_t_low + PIDAT_t_high);\n            PIDAT_bias = constrain(PIDAT_bias, 20 ,HEATER_CURRENT - 20);\n            if(PIDAT_bias > (HEATER_CURRENT/2)) PIDAT_d = (HEATER_CURRENT - 1) - PIDAT_bias;\n            else PIDAT_d = PIDAT_bias;\n\n            showString(PSTR(\" bias: \")); Serial.print(PIDAT_bias);\n            showString(PSTR(\" d: \"));    Serial.print(PIDAT_d);\n            showString(PSTR(\" min: \"));  Serial.print(PIDAT_min);\n            showString(PSTR(\" max: \"));  Serial.println(PIDAT_max);\n            \n            if(PIDAT_cycles > 2) \n            {\n              PIDAT_Ku = (4.0*PIDAT_d)/(3.14159*(PIDAT_max-PIDAT_min));\n              PIDAT_Tu = ((float)(PIDAT_t_low + PIDAT_t_high)/1000.0);\n              \n              showString(PSTR(\" Ku: \")); Serial.print(PIDAT_Ku);\n              showString(PSTR(\" Tu: \")); Serial.println(PIDAT_Tu);\n\n              PIDAT_Kp = 0.60*PIDAT_Ku;\n              PIDAT_Ki = 2*PIDAT_Kp/PIDAT_Tu;\n              PIDAT_Kd = PIDAT_Kp*PIDAT_Tu/8;\n              showString(PSTR(\" Clasic PID \\r\\n\"));\n              //showString(PSTR(\" Kp: \")); Serial.println(PIDAT_Kp);\n              //showString(PSTR(\" Ki: \")); Serial.println(PIDAT_Ki);\n              //showString(PSTR(\" Kd: \")); Serial.println(PIDAT_Kd);\n              showString(PSTR(\" CFG Kp: \")); Serial.println((unsigned int)(PIDAT_Kp*256));\n              showString(PSTR(\" CFG Ki: \")); Serial.println((unsigned int)(PIDAT_Ki*PIDAT_TIME_FACTOR));\n              showString(PSTR(\" CFG Kd: \")); Serial.println((unsigned int)(PIDAT_Kd*PIDAT_TIME_FACTOR));\n              \n              PIDAT_Kp = 0.30*PIDAT_Ku;\n              PIDAT_Ki = PIDAT_Kp/PIDAT_Tu;\n              PIDAT_Kd = PIDAT_Kp*PIDAT_Tu/3;\n              showString(PSTR(\" Some overshoot \\r\\n\"));\n              showString(PSTR(\" CFG Kp: \")); Serial.println((unsigned int)(PIDAT_Kp*256));\n              showString(PSTR(\" CFG Ki: \")); Serial.println((unsigned int)(PIDAT_Ki*PIDAT_TIME_FACTOR));\n              showString(PSTR(\" CFG Kd: \")); Serial.println((unsigned int)(PIDAT_Kd*PIDAT_TIME_FACTOR));\n              /*\n              PIDAT_Kp = 0.20*PIDAT_Ku;\n              PIDAT_Ki = 2*PIDAT_Kp/PIDAT_Tu;\n              PIDAT_Kd = PIDAT_Kp*PIDAT_Tu/3;\n              showString(PSTR(\" No overshoot \\r\\n\"));\n              showString(PSTR(\" CFG Kp: \")); Serial.println((unsigned int)(PIDAT_Kp*256));\n              showString(PSTR(\" CFG Ki: \")); Serial.println((unsigned int)(PIDAT_Ki*PIDAT_TIME_FACTOR));\n              showString(PSTR(\" CFG Kd: \")); Serial.println((unsigned int)(PIDAT_Kd*PIDAT_TIME_FACTOR));\n              */\n            }\n          }\n          PIDAT_PWM_val = (PIDAT_bias + PIDAT_d);\n          PIDAT_cycles++;\n          PIDAT_min = PIDAT_test_temp;\n        }\n      } \n      \n      #ifdef PID_SOFT_PWM\n        g_heater_pwm_val = PIDAT_PWM_val;\n      #else\n        analogWrite_check(HEATER_0_PIN, PIDAT_PWM_val);\n        #if LED_PIN>-1\n          analogWrite_check(LED_PIN, PIDAT_PWM_val);\n        #endif\n      #endif  \n    }\n    \n    if((PIDAT_input > (PIDAT_test_temp + 55)) || (PIDAT_input > 255))\n    {\n      showString(PSTR(\"PID Autotune failed! Temperature to high\\r\\n\"));\n      target_temp = 0;\n      return;\n    }\n    \n    if(millis() - PIDAT_temp_millis > 2000) \n    {\n      PIDAT_temp_millis = millis();\n      showString(PSTR(\"ok T:\"));\n      Serial.print(PIDAT_input);   \n      showString(PSTR(\" @:\"));\n      Serial.println((unsigned char)PIDAT_PWM_val*1);       \n    }\n    \n    if(((millis() - PIDAT_t1) + (millis() - PIDAT_t2)) > (10L*60L*1000L*2L)) \n    {\n      showString(PSTR(\"PID Autotune failed! timeout\\r\\n\"));\n      return;\n    }\n    \n    if(PIDAT_cycles > 5) \n    {\n      showString(PSTR(\"PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h\\r\\n\"));\n      return;\n    }\n  }\n}\n#endif  \n//---------------- END AUTOTUNE PID ------------------------------\n\n void updatePID()\n {\n   #ifdef PIDTEMP\n    temp_iState_min = (256L * -PID_INTEGRAL_DRIVE_MAX) / PID_Ki;\n    temp_iState_max = (256L * PID_INTEGRAL_DRIVE_MAX) / PID_Ki;\n   #endif\n }\n \n void manage_heater()\n {\n\n  //Temperatur Monitor for repetier\n  if((millis() - previous_millis_monitor) > 250 )\n  {\n    previous_millis_monitor = millis();\n\n\n    if(manage_monitor <= 1)\n    {\n      showString(PSTR(\"MTEMP:\"));\n      Serial.print(millis());\n      if(manage_monitor<1)\n      {\n        showString(PSTR(\" \"));\n        Serial.print(analog2temp(current_raw));\n        showString(PSTR(\" \"));\n        Serial.print(target_temp);\n        showString(PSTR(\" \"));\n        #ifdef PIDTEMP\n        Serial.println(heater_duty);\n        #else \n          #if (HEATER_0_PIN > -1)\n          if(READ(HEATER_0_PIN))\n            Serial.println(255);\n          else\n            Serial.println(0);\n          #else\n          Serial.println(0);\n          #endif\n        #endif\n      }\n      #if THERMISTORBED!=0\n      else\n      {\n        showString(PSTR(\" \"));\n        Serial.print(analog2tempBed(current_bed_raw));\n        showString(PSTR(\" \"));\n        Serial.print(analog2tempBed(target_bed_raw));\n        showString(PSTR(\" \"));\n        #if (HEATER_1_PIN > -1)\n          if(READ(HEATER_1_PIN))\n            Serial.println(255);\n          else\n            Serial.println(0);\n        #else\n          Serial.println(0);\n        #endif  \n      }\n      #endif\n      \n    }\n  \n  }\n  // ENDE Temperatur Monitor for repetier\n \n  if((millis() - previous_millis_heater) < HEATER_CHECK_INTERVAL )\n    return;\n    \n  previous_millis_heater = millis();\n  \n  #ifdef HEATER_USES_THERMISTOR\n    current_raw = analogRead(TEMP_0_PIN); \n    #ifdef DEBUG_HEAT_MGMT\n      log_int(\"_HEAT_MGMT - analogRead(TEMP_0_PIN)\", current_raw);\n      log_int(\"_HEAT_MGMT - NUMTEMPS\", NUMTEMPS);\n    #endif\n    // When using thermistor, when the heater is colder than targer temp, we get a higher analog reading than target, \n    // this switches it up so that the reading appears lower than target for the control logic.\n    current_raw = 1023 - current_raw;\n  #elif defined HEATER_USES_AD595\n    current_raw = analogRead(TEMP_0_PIN);    \n  #elif defined HEATER_USES_MAX6675\n    current_raw = read_max6675();\n  #endif\n  \n  //MIN / MAX save to display the jitter of Heaterbarrel\n  if(current_raw > current_raw_maxval)\n    current_raw_maxval = current_raw;\n    \n  if(current_raw < current_raw_minval)\n    current_raw_minval = current_raw;\n \n  #ifdef SMOOTHING\n    if (!nma) nma = SMOOTHFACTOR * current_raw;\n    nma = (nma + current_raw) - (nma / SMOOTHFACTOR);\n    current_raw = nma / SMOOTHFACTOR;\n  #endif\n  \n  #ifdef WATCHPERIOD\n    if(watchmillis && millis() - watchmillis > WATCHPERIOD)\n    {\n        if(watch_raw + 1 >= current_raw)\n        {\n            target_temp = target_raw = 0;\n            WRITE(HEATER_0_PIN,LOW);\n\n            #ifdef PID_SOFT_PWM\n              g_heater_pwm_val = 0;           \n            #else\n              analogWrite(HEATER_0_PIN, 0);\n              #if LED_PIN>-1\n                WRITE(LED_PIN,LOW);\n              #endif\n            #endif\n        }\n        else\n        {\n            watchmillis = 0;\n        }\n    }\n  #endif\n  \n  //If tmp is lower then MINTEMP stop the Heater\n  //or it os better to deaktivate the uutput PIN or PWM ?\n  #ifdef MINTEMP\n    if(current_raw <= minttemp)\n        target_temp = target_raw = 0;\n  #endif\n  \n  #ifdef MAXTEMP\n    if(current_raw >= maxttemp)\n    {\n        target_temp = target_raw = 0;\n    \n        #if (ALARM_PIN > -1) \n          WRITE(ALARM_PIN,HIGH);\n        #endif\n    }\n  #endif\n\n  #if (TEMP_0_PIN > -1) || defined (HEATER_USES_MAX6675) || defined (HEATER_USES_AD595)\n    #ifdef PIDTEMP\n      \n      int current_temp = analog2temp(current_raw);\n      error = target_temp - current_temp;\n      int delta_temp = current_temp - prev_temp;\n      \n      prev_temp = current_temp;\n      pTerm = ((long)PID_Kp * error) / 256;\n      const int H0 = min(HEATER_DUTY_FOR_SETPOINT(target_temp),HEATER_CURRENT);\n      heater_duty = H0 + pTerm;\n      \n      if(error < 30)\n      {\n        temp_iState += error;\n        temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max);\n        iTerm = ((long)PID_Ki * temp_iState) / 256;\n        heater_duty += iTerm;\n      }\n      \n      int prev_error = abs(target_temp - prev_temp);\n      int log3 = 1; // discrete logarithm base 3, plus 1\n      \n      if(prev_error > 81){ prev_error /= 81; log3 += 4; }\n      if(prev_error >  9){ prev_error /=  9; log3 += 2; }\n      if(prev_error >  3){ prev_error /=  3; log3 ++;   }\n      \n      dTerm = ((long)PID_Kd * delta_temp) / (256*log3);\n      heater_duty += dTerm;\n      heater_duty = constrain(heater_duty, 0, HEATER_CURRENT);\n\n      #ifdef PID_SOFT_PWM\n        if(target_raw != 0)\n          g_heater_pwm_val = (unsigned char)heater_duty;\n        else\n          g_heater_pwm_val = 0;\n      #else\n        if(target_raw != 0)\n          analogWrite(HEATER_0_PIN, heater_duty);\n        else\n          analogWrite(HEATER_0_PIN, 0);\n    \n        #if LED_PIN>-1\n          if(target_raw != 0)\n            analogWrite(LED_PIN, constrain(LED_PWM_FOR_BRIGHTNESS(heater_duty),0,255));\n          else\n            analogWrite(LED_PIN, 0);\n        #endif\n      #endif\n  \n    #else\n    \n      if(current_raw >= target_raw)\n      {\n        WRITE(HEATER_0_PIN,LOW);\n        #if LED_PIN>-1\n            WRITE(LED_PIN,LOW);\n        #endif\n      }\n      else \n      {\n        if(target_raw != 0)\n        {\n          WRITE(HEATER_0_PIN,HIGH);\n          #if LED_PIN > -1\n              WRITE(LED_PIN,HIGH);\n          #endif\n        }\n      }\n    #endif\n  #endif\n    \n  if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)\n    return;\n  \n  previous_millis_bed_heater = millis();\n\n  #ifndef TEMP_1_PIN\n    return;\n  #endif\n\n  #if TEMP_1_PIN == -1\n    return;\n  #else\n  \n  #ifdef BED_USES_THERMISTOR\n  \n    current_bed_raw = analogRead(TEMP_1_PIN);   \n  \n    #ifdef DEBUG_HEAT_MGMT\n      log_int(\"_HEAT_MGMT - analogRead(TEMP_1_PIN)\", current_bed_raw);\n      log_int(\"_HEAT_MGMT - BNUMTEMPS\", BNUMTEMPS);\n    #endif               \n  \n    // If using thermistor, when the heater is colder than targer temp, we get a higher analog reading than target, \n    // this switches it up so that the reading appears lower than target for the control logic.\n    current_bed_raw = 1023 - current_bed_raw;\n  #elif defined BED_USES_AD595\n    current_bed_raw = analogRead(TEMP_1_PIN);                  \n\n  #endif\n  \n  \n  #ifdef MINTEMP\n    if(current_bed_raw >= target_bed_raw || current_bed_raw < minttemp)\n  #else\n    if(current_bed_raw >= target_bed_raw)\n  #endif\n    {\n      WRITE(HEATER_1_PIN,LOW);\n    }\n    else \n    {\n      WRITE(HEATER_1_PIN,HIGH);\n    }\n    #endif\n    \n#ifdef CONTROLLERFAN_PIN\n  controllerFan(); //Check if fan should be turned on to cool stepper drivers down\n#endif\n\n#ifdef EXTRUDERFAN_PIN\n  extruderFan(); //Check if fan should be turned on to cool extruder down\n#endif\n\n}\n\n#if defined (HEATER_USES_THERMISTOR) || defined (BED_USES_THERMISTOR)\nint temp2analog_thermistor(int celsius, const short table[][2], int numtemps) \n{\n    int raw = 0;\n    byte i;\n    \n    for (i=1; i<numtemps; i++)\n    {\n      if (table[i][1] < celsius)\n      {\n        raw = table[i-1][0] + \n          (celsius - table[i-1][1]) * \n          (table[i][0] - table[i-1][0]) /\n          (table[i][1] - table[i-1][1]);\n      \n        break;\n      }\n    }\n\n    // Overflow: Set to last value in the table\n    if (i == numtemps) raw = table[i-1][0];\n\n    return 1023 - raw;\n}\n#endif\n\n#if defined (HEATER_USES_AD595) || defined (BED_USES_AD595)\nint temp2analog_ad595(int celsius) \n{\n    return (celsius * 1024.0) / (500.0);\n}\n#endif\n\n#if defined (HEATER_USES_MAX6675) || defined (BED_USES_MAX6675)\nint temp2analog_max6675(int celsius) \n{\n    return celsius * 4;\n}\n#endif\n\n#if defined (HEATER_USES_THERMISTOR) || defined (BED_USES_THERMISTOR)\nint analog2temp_thermistor(int raw,const short table[][2], int numtemps) {\n    int celsius = 0;\n    byte i;\n    \n    raw = 1023 - raw;\n\n    for (i=1; i<numtemps; i++)\n    {\n      if (table[i][0] > raw)\n      {\n        celsius  = table[i-1][1] + \n          (raw - table[i-1][0]) * \n          (table[i][1] - table[i-1][1]) /\n          (table[i][0] - table[i-1][0]);\n\n        break;\n      }\n    }\n\n    // Overflow: Set to last value in the table\n    if (i == numtemps) celsius = table[i-1][1];\n\n    return celsius;\n}\n#endif\n\n#if defined (HEATER_USES_AD595) || defined (BED_USES_AD595)\nint analog2temp_ad595(int raw)\n{\n        return (raw * 500.0) / 1024.0;\n}\n#endif\n\n#if defined (HEATER_USES_MAX6675) || defined (BED_USES_MAX6675)\nint analog2temp_max6675(int raw)\n{\n    return raw / 4;\n}\n#endif\n\n#ifdef CONTROLLERFAN_PIN\nunsigned long lastMotor = 0; //Save the time for when a motor was turned on last\nunsigned long lastMotorCheck = 0;\n\nvoid controllerFan()\n{  \n  if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms\n  {\n    lastMotorCheck = millis();\n    \n    if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) || !READ(E_ENABLE_PIN)) //If any of the drivers are enabled...\n    {\n      lastMotor = millis(); //... set time to NOW so the fan will turn on\n    }\n    \n    if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC...\n    {\n      WRITE(CONTROLLERFAN_PIN, LOW); //... turn the fan off\n    }\n    else\n    {\n      WRITE(CONTROLLERFAN_PIN, HIGH); //... turn the fan on\n    }\n  }\n}\n#endif\n\n#ifdef EXTRUDERFAN_PIN\nunsigned long lastExtruderCheck = 0;\n\nvoid extruderFan()\n{\n  if ((millis() - lastExtruderCheck) >= 2500) //Not a time critical function, so we only check every 2500ms\n  {\n    lastExtruderCheck = millis();\n           \n    if (analog2temp(current_raw) < EXTRUDERFAN_DEC)\n    {\n      WRITE(EXTRUDERFAN_PIN, LOW); //... turn the fan off\n    }\n    else\n    {\n      WRITE(EXTRUDERFAN_PIN, HIGH); //... turn the fan on\n    }\n  }\n}\n#endif\n\n"
  },
  {
    "path": "Sprinter/heater.h",
    "content": "/*\n Reprap heater funtions based on Sprinter\n \n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n \n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n \n You should have received a copy of the GNU General Public License\n along with this program.  If not, see <http://www.gnu.org/licenses/>. */\n\n/*\n This softwarepart for Heatercontrol is based on Sprinter\n big thanks to kliment (https://github.com/kliment/Sprinter)\n \n*/\n\n\n#include \"Configuration.h\"\n#include \"thermistortables.h\"\n\n#if defined HEATER_USES_THERMISTOR\n#define temp2analogh( c ) temp2analog_thermistor(c,temptable,NUMTEMPS)\n#define analog2temp( c ) analog2temp_thermistor(c,temptable,NUMTEMPS)\n#elif defined HEATER_USES_AD595\n#define temp2analogh( c ) temp2analog_ad595(c)\n#define analog2temp( c ) analog2temp_ad595(c)\n#elif defined HEATER_USES_MAX6675\n#define temp2analogh( c ) temp2analog_max6675(c)\n#define analog2temp( c ) analog2temp_max6675(c)\n#endif\n\n#if defined BED_USES_THERMISTOR\n#define temp2analogBed( c ) temp2analog_thermistor((c),bedtemptable,BNUMTEMPS)\n#define analog2tempBed( c ) analog2temp_thermistor((c),bedtemptable,BNUMTEMPS)\n#elif defined BED_USES_AD595\n#define temp2analogBed( c ) temp2analog_ad595(c)\n#define analog2tempBed( c ) analog2temp_ad595(c)\n#elif defined BED_USES_MAX6675\n#define temp2analogBed( c ) temp2analog_max6675(c)\n#define analog2tempBed( c ) analog2temp_max6675(c)\n#endif\n\n#if defined (HEATER_USES_THERMISTOR) || defined (BED_USES_THERMISTOR)\nint temp2analog_thermistor(int celsius, const short table[][2], int numtemps);\nint analog2temp_thermistor(int raw,const short table[][2], int numtemps);\n#endif\n\n#if defined (HEATER_USES_AD595) || defined (BED_USES_AD595)\nint temp2analog_ad595(int celsius);\nint analog2temp_ad595(int raw);\n#endif\n\n#if defined (HEATER_USES_MAX6675) || defined (BED_USES_MAX6675)\nint temp2analog_max6675(int celsius);\nint analog2temp_max6675(int raw);\n#endif\n\n\nextern int target_raw;\nextern int target_temp;\nextern int current_raw;\nextern int current_raw_maxval;\nextern int current_raw_minval;\nextern int tt_maxval;\nextern int tt_minval;\nextern int target_bed_raw;\nextern int current_bed_raw;\nextern unsigned long previous_millis_heater, previous_millis_bed_heater;\nextern unsigned char manage_monitor;\n\n#ifdef PIDTEMP\n  extern volatile unsigned char g_heater_pwm_val;\n \n  extern unsigned char PWM_off_time;\n  extern unsigned char PWM_out_on;\n  \n  extern int temp_iState;\n  extern int temp_dState;\n  extern int prev_temp;\n  extern int pTerm;\n  extern int iTerm;\n  extern int dTerm;\n  extern int error;\n  extern int heater_duty;\n  \n  extern unsigned int PID_Kp, PID_Ki, PID_Kd;\n#endif\n\n#if defined(FAN_SOFT_PWM) && (FAN_PIN > -1)\n  extern volatile unsigned char g_fan_pwm_val;\n#endif\n\n#ifdef AUTOTEMP\n    extern float autotemp_max;\n    extern float autotemp_min;\n    extern float autotemp_factor;\n    extern int   autotemp_setpoint;\n    extern bool autotemp_enabled;\n#endif\n\n\n#ifdef SMOOTHING\n  extern uint32_t nma;\n#endif\n\n#ifdef WATCHPERIOD\n  extern int watch_raw;\n  extern unsigned long watchmillis;\n#endif\n\n\n\n\n#if defined(PID_SOFT_PWM) || (defined(FAN_SOFT_PWM) && (FAN_PIN > -1))\n void init_Timer2_softpwm(void);\n#endif\n\n#ifdef PID_AUTOTUNE\n void PID_autotune(int PIDAT_test_temp);\n#endif\n\n#ifdef PIDTEMP\n void updatePID();\n#endif\n\nvoid manage_heater();\n"
  },
  {
    "path": "Sprinter/pins.h",
    "content": "#ifndef PINS_H\n#define PINS_H\n#define ALARM_PIN          -1\n\n/****************************************************************************************\n* Arduino pin assignment\n*\n*                  ATMega168\n*                   +-\\/-+\n*             PC6  1|    |28  PC5 (AI 5 / D19)\n*       (D 0) PD0  2|    |27  PC4 (AI 4 / D18)\n*       (D 1) PD1  3|    |26  PC3 (AI 3 / D17)\n*       (D 2) PD2  4|    |25  PC2 (AI 2 / D16)\n*  PWM+ (D 3) PD3  5|    |24  PC1 (AI 1 / D15)\n*       (D 4) PD4  6|    |23  PC0 (AI 0 / D14)\n*             VCC  7|    |22  GND\n*             GND  8|    |21  AREF\n*             PB6  9|    |20  AVCC\n*             PB7 10|    |19  PB5 (D 13)\n*  PWM+ (D 5) PD5 11|    |18  PB4 (D 12)\n*  PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM\n*       (D 7) PD7 13|    |16  PB2 (D 10) PWM\n*       (D 8) PB0 14|    |15  PB1 (D 9)  PWM\n*                   +----+\n****************************************************************************************/\n#if MOTHERBOARD == 0\n#define KNOWN_BOARD 1\n\n#ifndef __AVR_ATmega168__\n#error Oops!  Make sure you have 'Arduino Diecimila' selected from the boards menu.\n#endif\n\n#define X_STEP_PIN          2\n#define X_DIR_PIN           3\n#define X_ENABLE_PIN       -1\n#define X_MIN_PIN           4\n#define X_MAX_PIN           9\n\n#define Y_STEP_PIN         10\n#define Y_DIR_PIN           7\n#define Y_ENABLE_PIN       -1\n#define Y_MIN_PIN           8\n#define Y_MAX_PIN          13\n\n#define Z_STEP_PIN         19\n#define Z_DIR_PIN          18\n#define Z_ENABLE_PIN        5\n#define Z_MIN_PIN          17\n#define Z_MAX_PIN          16\n\n#define E_STEP_PIN         11\n#define E_DIR_PIN          12\n#define E_ENABLE_PIN       -1\n\n#define SDPOWER          -1\n#define SDSS          -1\n#define LED_PIN            -1\n#define FAN_PIN            -1\n#define PS_ON_PIN          15\n#define KILL_PIN           -1\n#define ALARM_PIN          -1\n\n#define HEATER_0_PIN        6\n#define TEMP_0_PIN          0    // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!!\n\n\n#endif\n\n\n\n/****************************************************************************************\n* Sanguino/RepRap Motherboard with direct-drive extruders\n*\n*                        ATMega644P\n*\n*                        +---\\/---+\n*            (D 0) PB0  1|        |40  PA0 (AI 0 / D31)\n*            (D 1) PB1  2|        |39  PA1 (AI 1 / D30)\n*       INT2 (D 2) PB2  3|        |38  PA2 (AI 2 / D29)\n*        PWM (D 3) PB3  4|        |37  PA3 (AI 3 / D28)\n*        PWM (D 4) PB4  5|        |36  PA4 (AI 4 / D27)\n*       MOSI (D 5) PB5  6|        |35  PA5 (AI 5 / D26)\n*       MISO (D 6) PB6  7|        |34  PA6 (AI 6 / D25)\n*        SCK (D 7) PB7  8|        |33  PA7 (AI 7 / D24)\n*                  RST  9|        |32  AREF\n*                  VCC 10|        |31  GND \n*                  GND 11|        |30  AVCC\n*                XTAL2 12|        |29  PC7 (D 23)\n*                XTAL1 13|        |28  PC6 (D 22)\n*       RX0 (D 8)  PD0 14|        |27  PC5 (D 21) TDI\n*       TX0 (D 9)  PD1 15|        |26  PC4 (D 20) TDO\n*  INT0 RX1 (D 10) PD2 16|        |25  PC3 (D 19) TMS\n*  INT1 TX1 (D 11) PD3 17|        |24  PC2 (D 18) TCK\n*       PWM (D 12) PD4 18|        |23  PC1 (D 17) SDA\n*       PWM (D 13) PD5 19|        |22  PC0 (D 16) SCL\n*       PWM (D 14) PD6 20|        |21  PD7 (D 15) PWM\n*                        +--------+\n*\n****************************************************************************************\n*\n*                     ATMega644P (SMD)\n*\n*                        +--------+\n*       MOSI (D 5) PB5  1| O      |44  PB4 (D 4)  PWM  \n*       MISO (D 6) PB6  2|        |43  PB3 (D 3)  PWM  \n*       SCK  (D 7) PB7  3|        |42  PB2 (D 2)  INT2   \n*                  RST  4|        |41  PB1 (D 1)\n*                  Vcc  5|        |40  PB0 (D 0)  \n*                  GND  6|        |39  GND\n*                XTAL2  7|        |38  Vcc\n*                XTAL1  8|        |37  PA0 (AI 0 / D31)\n*       RX0 (D 8)  PD0  9|        |36  PA1 (AI 1 / D30)\n*       TX0 (D 9)  PD1 10|        |35  PA2 (AI 2 / D29)\n*  INT0 RX1 (D 10) PD2 11|        |34  PA3 (AI 3 / D28)\n*                        +        +\n*  INT1 TX1 (D 11) PD3 12|        |33  PA4 (AI 4 / D27)\n*       PWM (D 12) PD4 13|        |32  PA5 (AI 5 / D26)\n*       PWM (D 13) PD5 14|        |31  PA6 (AI 6 / D25)\n*       PWM (D 14) PD6 15|        |30  PA7 (AI 7 / D24)\n*       PWM (D 15) PD7 16|        |29  AREF\n*                  Vcc 17|        |28  GND\n*                  GND 18|        |27  AVCC\n*           (D 16) PC0 19|        |26  PC7 (D 23)      \n*           (D 17) PC1 20|        |25  PC6 (D 22)      \n*           (D 18) PC2 21|        |24  PC5 (D 21) TDI  \n*           (D 19) PC3 22|        |23  PC4 (D 20) TDO  \n*                        +--------+\n*\n****************************************************************************************/\n#if MOTHERBOARD == 1\n#define KNOWN_BOARD 1\n\n#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) \n#error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n#define X_STEP_PIN         15\n#define X_DIR_PIN          18\n#define X_ENABLE_PIN       19\n#define X_MIN_PIN          20\n#define X_MAX_PIN          21\n\n#define Y_STEP_PIN         23\n#define Y_DIR_PIN          22\n#define Y_ENABLE_PIN       19\n#define Y_MIN_PIN          25\n#define Y_MAX_PIN          26\n\n#define Z_STEP_PIN         29\n#define Z_DIR_PIN          30\n#define Z_ENABLE_PIN       31\n#define Z_MIN_PIN           2\n#define Z_MAX_PIN           1\n\n#define E_STEP_PIN         12\n#define E_DIR_PIN          16\n#define E_ENABLE_PIN        3\n\n#define SDPOWER          -1\n#define SDSS          -1\n#define LED_PIN             0\n#define FAN_PIN            -1\n#define PS_ON_PIN          -1\n#define KILL_PIN           -1\n#define ALARM_PIN          -1\n\n#define HEATER_0_PIN       14\n#define TEMP_0_PIN          4 //D27   // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!!\n\n/*  Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31)  */\n\n\n\n#endif\n\n\n/****************************************************************************************\n* RepRap Motherboard  ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---*******\n*\n****************************************************************************************/\n#if MOTHERBOARD == 2\n#define KNOWN_BOARD 1\n\n#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) && !defined(__ATmega644P__) && !defined(__ATmega1284P__)  \n#error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n#define X_STEP_PIN      15\n#define X_DIR_PIN       18\n#define X_ENABLE_PIN    19\n#define X_MIN_PIN       20\n#define X_MAX_PIN       21\n\n#define Y_STEP_PIN      23\n#define Y_DIR_PIN       22\n#define Y_ENABLE_PIN    24\n#define Y_MIN_PIN       25\n#define Y_MAX_PIN       26\n\n#define Z_STEP_PINN     27\n#define Z_DIR_PINN      28\n#define Z_ENABLE_PIN    29\n#define Z_MIN_PIN       30\n#define Z_MAX_PIN       31\n\n#define E_STEP_PIN      17\n#define E_DIR_PIN       16\n#define E_ENABLE_PIN    -1\n\n#define SDPOWER          -1\n#define SDSS          4\n#define LED_PIN          0\n\n#define SD_CARD_WRITE    2\n#define SD_CARD_DETECT   3\n#define SD_CARD_SELECT   4\n\n//our RS485 pins\n#define TX_ENABLE_PIN\t12\n#define RX_ENABLE_PIN\t13\n\n//pin for controlling the PSU.\n#define PS_ON_PIN       14\n\n#define FAN_PIN         -1\n#define KILL_PIN        -1\n#define ALARM_PIN          -1\n\n#define HEATER_0_PIN    -1\n#define TEMP_0_PIN      -1    // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!!\n\n\n\n\n#endif\n\n/****************************************************************************************\n* Gen3 PLUS for RepRap Motherboard V1.2\n*\n****************************************************************************************/\n#if MOTHERBOARD == 21\n#define KNOWN_BOARD 1\n\n#ifndef __AVR_ATmega644P__\n    #error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n\n//x axis pins\n#define X_STEP_PIN      15\n#define X_DIR_PIN       18\n#define X_ENABLE_PIN    19\n#define X_MIN_PIN       20\n#define X_MAX_PIN       -1\n\n//y axis pins\n#define Y_STEP_PIN      23\n#define Y_DIR_PIN       22\n#define Y_ENABLE_PIN    24\n#define Y_MIN_PIN       25\n#define Y_MAX_PIN       -1\n\n//z axis pins\n#define Z_STEP_PIN      27\n#define Z_DIR_PIN       28\n#define Z_ENABLE_PIN    29\n#define Z_MIN_PIN       30\n#define Z_MAX_PIN       -1\n\n#define E_DIR_PIN       21\n#define E_STEP_PIN\t17\n#define E_ENABLE_PIN\t13\n\n//heaters\n\n//pin for hot end heater\n#define HEATER_0_PIN\t12\n\n//Pin for heated bed heater\n#define HEATER_1_PIN\t 16\n\n\n//pin for debugging.\n#define DEBUG_PIN        -1\n\n//SD card pin\n\n#define SDSS\t\t  4\n\n#define SDPOWER          -1\n#define FAN_PIN          -1\n#define TEMP_0_PIN        0\n#define TEMP_1_PIN        5\n#define LED_PIN          -1\n\n//pin for controlling the PSU.\n#define PS_ON_PIN       14\n\n#endif\n\n/****************************************************************************************\n* Gen3  Monolithic Electronics \n*\n****************************************************************************************/\n#if MOTHERBOARD == 22\n#define KNOWN_BOARD 1\n\n#ifndef __AVR_ATmega644P__\n    #error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n#define DEBUG_PIN 0\n\n\n// x axis\n#define X_STEP_PIN 15\n#define X_DIR_PIN 18\n#define X_MIN_PIN 20\n#define X_ENABLE_PIN 24 //actually uses Y_enable_pin\n#define X_MAX_PIN -1\n\n// y axes\n#define Y_STEP_PIN 23\n#define Y_DIR_PIN 22\n#define Y_MIN_PIN 25\n#define Y_ENABLE_PIN 24 //shared with X_enable_pin \n#define Y_MAX_PIN -1\n\n// z axes\n#define Z_STEP_PIN 27\n#define Z_DIR_PIN 28\n#define Z_MIN_PIN 30\n#define Z_ENABLE_PIN 29\n#define Z_MAX_PIN -1\n\n//extruder pins\n#define E_STEP_PIN 12 \n#define E_DIR_PIN 17\n#define E_ENABLE_PIN 3\n#define HEATER_0_PIN 16\n#define TEMP_0_PIN 0\n\n#define FAN_PIN -1\n\n//bed pins\n#define HEATER_1_PIN -1\n#define TEMP_1_PIN -1\n\n\n#define SDSS\t\t -1\n#define SDPOWER          -1\n#define LED_PIN          -1\n\n//pin for controlling the PSU.\n#define PS_ON_PIN       14\n\n#endif\n\n\n/****************************************************************************************\n* Gen3 PLUS for TechZone Gen3 Remix Motherboard\n*\n****************************************************************************************/\n#if MOTHERBOARD == 23\n#define KNOWN_BOARD 1\n\n#ifndef __AVR_ATmega644P__\n    #error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n\n//x axis pins\n#define X_STEP_PIN      15\n#define X_DIR_PIN       18\n#define X_ENABLE_PIN    24 //same as E/Y_enable_pin\n#define X_MIN_PIN       20\n#define X_MAX_PIN       -1\n\n//y axis pins\n#define Y_STEP_PIN      23\n#define Y_DIR_PIN       22\n#define Y_ENABLE_PIN    24 //same as E/X_enable_pin\n#define Y_MIN_PIN       25\n#define Y_MAX_PIN       -1\n\n//z axis pins\n#define Z_STEP_PIN      27\n#define Z_DIR_PIN       28\n#define Z_ENABLE_PIN    29\n#define Z_MIN_PIN       30\n#define Z_MAX_PIN       -1\n\n#define E_DIR_PIN        21\n#define E_STEP_PIN\t19\n#define E_ENABLE_PIN\t24 //same as X/Y_enable_pin\n\n//heaters\n\n//pin for hot end heater\n#define HEATER_0_PIN\t16\n\n//Pin for heated bed heater\n#define HEATER_1_PIN\t17\n\n\n//pin for debugging.\n#define DEBUG_PIN        -1\n\n//SD card pin\n\n#define SDSS\t\t  4\n\n#define SDPOWER          -1\n#define FAN_PIN          -1\n#define TEMP_0_PIN        0\n#define TEMP_1_PIN        5\n#define LED_PIN          -1\n\n//pin for controlling the PSU.\n#define PS_ON_PIN       14\n\n#endif\n\n\n/****************************************************************************************\n* Arduino Mega pin assignment\n*\n****************************************************************************************/\n#if MOTHERBOARD == 33\n#define MOTHERBOARD 3\n#define RAMPS_V_1_3\n#endif\n#if MOTHERBOARD == 3\n#define KNOWN_BOARD 1\n\n//////////////////FIX THIS//////////////\n#ifndef __AVR_ATmega1280__\n #ifndef __AVR_ATmega2560__\n #error Oops!  Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu.\n #endif\n#endif\n\n// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1\n// #define RAMPS_V_1_3\n// #define RAMPS_V_1_0\n\n#ifdef RAMPS_V_1_3\n\n#define X_STEP_PIN         54\n#define X_DIR_PIN          55\n#define X_ENABLE_PIN       38\n#define X_MIN_PIN           3\n#define X_MAX_PIN          -1   //2 //Max endstops default to disabled \"-1\", set to commented value to enable.\n\n#define Y_STEP_PIN         60\n#define Y_DIR_PIN          61\n#define Y_ENABLE_PIN       56\n#define Y_MIN_PIN          14\n#define Y_MAX_PIN          -1   //15\n\n#define Z_STEP_PIN         46\n#define Z_DIR_PIN          48\n#define Z_ENABLE_PIN       62\n#define Z_MIN_PIN          18\n#define Z_MAX_PIN          -1   //19\n\n#define E_STEP_PIN         26\n#define E_DIR_PIN          28\n#define E_ENABLE_PIN       24\n\n#define E_1_STEP_PIN         36\n#define E_1_DIR_PIN          34\n#define E_1_ENABLE_PIN       30\n\n#define SDPOWER            -1\n#define SDSS               53\n#define LED_PIN            13\n#define FAN_PIN            9\n#define PS_ON_PIN          12\n#define KILL_PIN           -1\n#define ALARM_PIN          -1\n\n#define HEATER_0_PIN       10\n#define HEATER_1_PIN       8\n#define TEMP_0_PIN         13   // ANALOG NUMBERING\n#define TEMP_1_PIN         14   // ANALOG NUMBERING\n#define TEMP_2_PIN         15   // ANALOG NUMBERING\n\n#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default\n\n#define X_STEP_PIN         26\n#define X_DIR_PIN          28\n#define X_ENABLE_PIN       24\n#define X_MIN_PIN           3\n#define X_MAX_PIN          -1    //2\n\n#define Y_STEP_PIN         38\n#define Y_DIR_PIN          40\n#define Y_ENABLE_PIN       36\n#define Y_MIN_PIN          16\n#define Y_MAX_PIN          -1    //17\n\n#define Z_STEP_PIN         44\n#define Z_DIR_PIN          46\n#define Z_ENABLE_PIN       42\n#define Z_MIN_PIN          18\n#define Z_MAX_PIN          -1    //19\n\n#define E_STEP_PIN         32\n#define E_DIR_PIN          34\n#define E_ENABLE_PIN       30\n\n#define SDPOWER            48\n#define SDSS               53\n#define LED_PIN            13\n#define PS_ON_PIN          -1\n#define KILL_PIN           -1\n#define ALARM_PIN          -1\n\n\n#ifdef RAMPS_V_1_0 // RAMPS_V_1_0\n  #define HEATER_0_PIN     12    // RAMPS 1.0\n  #define HEATER_1_PIN     -1    // RAMPS 1.0\n  #define FAN_PIN          11    // RAMPS 1.0\n\n#else // RAMPS_V_1_1 or RAMPS_V_1_2\n  #define HEATER_0_PIN     10    // RAMPS 1.1\n  #define HEATER_1_PIN      8    // RAMPS 1.1\n  #define FAN_PIN           9    // RAMPS 1.1\n#endif\n\n#define TEMP_0_PIN          2    // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!!\n#define TEMP_1_PIN          1    // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!!\n#endif\n\n// SPI for Max6675 Thermocouple \n\n#ifndef SDSUPPORT\n// these pins are defined in the SD library if building with SD support  \n  #define SCK_PIN          52\n  #define MISO_PIN         50\n  #define MOSI_PIN         51\n  #define MAX6675_SS       53\n#else\n  #define MAX6675_SS       49\n#endif\n\n\n#endif\n/****************************************************************************************\n* Duemilanove w/ ATMega328P pin assignment\n*\n****************************************************************************************/\n#if MOTHERBOARD == 4\n#define KNOWN_BOARD 1\n\n#ifndef __AVR_ATmega328P__\n#error Oops!  Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu.\n#endif\n\n#define X_STEP_PIN         19\n#define X_DIR_PIN          18\n#define X_ENABLE_PIN       -1\n#define X_MIN_PIN          17\n#define X_MAX_PIN          -1\n\n#define Y_STEP_PIN         10\n#define Y_DIR_PIN           7\n#define Y_ENABLE_PIN       -1\n#define Y_MIN_PIN           8\n#define Y_MAX_PIN          -1\n\n#define Z_STEP_PIN         13\n#define Z_DIR_PIN           3\n#define Z_ENABLE_PIN        2\n#define Z_MIN_PIN           4\n#define Z_MAX_PIN          -1\n\n#define E_STEP_PIN         11\n#define E_DIR_PIN          12\n#define E_ENABLE_PIN       -1\n\n#define SDPOWER          -1\n#define SDSS          -1\n#define LED_PIN            -1\n#define FAN_PIN             5\n#define PS_ON_PIN          -1\n#define KILL_PIN           -1\n#define ALARM_PIN          -1\n\n#define HEATER_0_PIN        6\n#define TEMP_0_PIN          0    // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!!\n\n\n#endif\n\n/****************************************************************************************\n* Gen6 pin assignment\n*\n****************************************************************************************/\n#if MOTHERBOARD == 51\n  #define MOTHERBOARD 5\n  #define GEN6_DELUXE\n#endif\n\n#if MOTHERBOARD == 5\n#define KNOWN_BOARD 1\n\n#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) \n    #error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n//x axis pins\n    #define X_STEP_PIN      15\n    #define X_DIR_PIN       18\n    #define X_ENABLE_PIN    19\n    #define X_MIN_PIN       20\n    #define X_MAX_PIN       -1\n    \n    //y axis pins\n    #define Y_STEP_PIN      23\n    #define Y_DIR_PIN       22\n    #define Y_ENABLE_PIN    24\n    #define Y_MIN_PIN       25\n    #define Y_MAX_PIN       -1\n    \n    //z axis pins\n    #define Z_STEP_PIN      27\n    #define Z_DIR_PIN       28\n    #define Z_ENABLE_PIN    29\n    #define Z_MIN_PIN       30\n    #define Z_MAX_PIN       -1\n    \n    //extruder pins\n    #define E_STEP_PIN      4     //Edited @ EJE Electronics 20100715\n    #define E_DIR_PIN       2     //Edited @ EJE Electronics 20100715\n    #define E_ENABLE_PIN    3     //Added @ EJE Electronics 20100715\n    #define TEMP_0_PIN      5     //changed @ rkoeppl 20110410\n    #define HEATER_0_PIN    14    //changed @ rkoeppl 20110410\n    \n    #ifdef GEN6_DELUXE\n      #define HEATER_1_PIN   1    \n      #define TEMP_1_PIN     0    \n    #else\n      #define HEATER_1_PIN   -1   \n      #define TEMP_1_PIN     -1    \n    #endif\n    \n    #define SDPOWER          -1\n    #define SDSS          17\n    #define LED_PIN         -1    //changed @ rkoeppl 20110410\n    #define FAN_PIN         -1    //changed @ rkoeppl 20110410\n    #define PS_ON_PIN       -1    //changed @ rkoeppl 20110410\n    //our pin for debugging.\n    \n    #define DEBUG_PIN        0\n    \n    //our RS485 pins\n    #define TX_ENABLE_PIN\t12\n    #define RX_ENABLE_PIN\t13\n\n#endif\n/****************************************************************************************\n* Sanguinololu pin assignment\n*\n****************************************************************************************/\n#if MOTHERBOARD == 62\n#define MOTHERBOARD 6\n#define SANGUINOLOLU_V_1_2 \n#endif\n#if MOTHERBOARD == 6\n#define KNOWN_BOARD 1\n#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) \n#error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n#define X_STEP_PIN         15\n#define X_DIR_PIN          21\n#define X_MIN_PIN          18\n#define X_MAX_PIN           -2\n\n#define Y_STEP_PIN         22\n#define Y_DIR_PIN          23\n#define Y_MIN_PIN          19\n#define Y_MAX_PIN          -1\n\n#define Z_STEP_PIN         3\n#define Z_DIR_PIN          2\n#define Z_MIN_PIN          20\n#define Z_MAX_PIN          -1\n\n#define E_STEP_PIN         1\n#define E_DIR_PIN          0\n\n#define LED_PIN            -1\n\n#define FAN_PIN            -1 \n\n#define PS_ON_PIN          -1\n#define KILL_PIN           -1\n#define ALARM_PIN          -1\n\n#define HEATER_0_PIN       13 // (extruder)\n\n#ifdef SANGUINOLOLU_V_1_2\n\n#define HEATER_1_PIN       12 // (bed)\n#define X_ENABLE_PIN       14\n#define Y_ENABLE_PIN       14\n#define Z_ENABLE_PIN       26\n#define E_ENABLE_PIN       14\n#else\n\n#define HEATER_1_PIN       14  // (bed)\n#define X_ENABLE_PIN       -1\n#define Y_ENABLE_PIN       -1\n#define Z_ENABLE_PIN       -1\n#define E_ENABLE_PIN       -1\n\n#endif\n\n#define TEMP_0_PIN          7   // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder)\n#define TEMP_1_PIN          6   // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed)\n#define SDPOWER          -1\n#define SDSS          31\n\n#endif\n\n/****************************************************************************************\n* Gen7 pin assignment\n*\n****************************************************************************************\n* for Gen7 to work properly, you should reset your fuses to lfuse= 0xF7 ; hfuse = 0xD4 ; efuse = FD;\n* else you will always get a \"brown out reset\" loop resetting the firmware\n* you need a programmer to set the fuses\n**/\n#if MOTHERBOARD == 71    //GEN7 with 20 Mhz\n#define MOTHERBOARD 7\n#define QUARZ_20MHZ\n#endif\n\n#if MOTHERBOARD == 7\n#define KNOWN_BOARD 1\n\n#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) && !defined(__AVR_ATmega644__)\n    #error Oops!  Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.\n#endif\n\n//x axis pins\n    #define X_STEP_PIN      19\n    #define X_DIR_PIN       18\n    #define X_ENABLE_PIN    24\n    #define X_MIN_PIN       7\n    #define X_MAX_PIN       -1      //X - Maxpin is 6\n\n    //y axis pins\n    #define Y_STEP_PIN      23\n    #define Y_DIR_PIN       22\n    #define Y_ENABLE_PIN    24\n    #define Y_MIN_PIN       5\n    #define Y_MAX_PIN       -1      //Y - Maxpin is 2\n\n    //z axis pins\n    #define Z_STEP_PIN      26\n    #define Z_DIR_PIN       25\n    #define Z_ENABLE_PIN    24\n    #define Z_MIN_PIN       1\n    #define Z_MAX_PIN       -1      //Z - Maxpin is 0\n\n    //extruder pins\n    #define E_STEP_PIN      28     \n    #define E_DIR_PIN       27     \n    #define E_ENABLE_PIN    24     \n    #define TEMP_0_PIN      1    // Extruder \n    #define HEATER_0_PIN     4    // Extruder\n    #define HEATER_1_PIN     3    // Bed\n\n\n    #define SDPOWER         -1\n    #define SDSS            -1\n    #define LED_PIN         -1    \n    #define TEMP_1_PIN      2    //Bed   \n    #define FAN_PIN         -1    \n    #define PS_ON_PIN       15    \n\n#endif\n\n/****************************************************************************************\n* Teensylu 0.7 pin assingments (ATMEGA90USB)\n* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE!\n****************************************************************************************/\n#if MOTHERBOARD == 8\n#define MOTHERBOARD 8\n#define KNOWN_BOARD 1\n\n\n#define X_STEP_PIN         28\n#define X_DIR_PIN          29\n#define X_ENABLE_PIN       19\n#define X_MIN_PIN          25\n#define X_MAX_PIN          -1    \n\n#define Y_STEP_PIN         30\n#define Y_DIR_PIN          31\n#define Y_ENABLE_PIN       26\n#define Y_MIN_PIN           20\n#define Y_MAX_PIN          -1    \n\n#define Z_STEP_PIN         32\n#define Z_DIR_PIN          33\n#define Z_ENABLE_PIN       17\n#define Z_MIN_PIN          27\n#define Z_MAX_PIN          -1    \n\n#define E_STEP_PIN         34\n#define E_DIR_PIN          35\n#define E_ENABLE_PIN       13\n\n#define HEATER_0_PIN       15  // Extruder\n#define HEATER_1_PIN       14  // Bed\n#define FAN_PIN            16  // Fan   \n\n#define TEMP_0_PIN          7  // Extruder\n#define TEMP_1_PIN          6  // Bed\n\n#define SDPOWER            -1\n#define SDSS                20\n#define LED_PIN            -1\n#define PS_ON_PIN          -1\n#define KILL_PIN           -1 \n#define ALARM_PIN          -1\n\n#ifndef SDSUPPORT\n// these pins are defined in the SD library if building with SD support  \n  #define SCK_PIN          21\n  #define MISO_PIN         22 \n  #define MOSI_PIN         23 \n#endif\n\n#endif\n\n/****************************************************************************************\n* Printrboard Rev. B pin assingments (ATMEGA90USB1286)\n* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE!\n* See http://reprap.org/wiki/Printrboard for more info\n****************************************************************************************/\n#if MOTHERBOARD == 9\n#define MOTHERBOARD 9\n#define KNOWN_BOARD 1\n\n\n#define X_STEP_PIN         28\n#define X_DIR_PIN          29\n#define X_ENABLE_PIN       19\n#define X_MIN_PIN          47\n#define X_MAX_PIN          -1\n\n#define Y_STEP_PIN         30\n#define Y_DIR_PIN          31\n#define Y_ENABLE_PIN       18\n#define Y_MIN_PIN           20\n#define Y_MAX_PIN          -1\n\n#define Z_STEP_PIN         32\n#define Z_DIR_PIN          33\n#define Z_ENABLE_PIN       17\n#define Z_MIN_PIN          36\n#define Z_MAX_PIN          -1\n\n#define E_STEP_PIN         34\n#define E_DIR_PIN          35\n#define E_ENABLE_PIN       13\n\n#define HEATER_0_PIN       15  // Extruder\n#define HEATER_1_PIN       14  // Bed\n#define FAN_PIN            16  // Fan\n\n#define TEMP_0_PIN          1  // Extruder\n#define TEMP_1_PIN          0  // Bed\n\n#define SDPOWER            -1\n#define SDSS                2\n#define LED_PIN            -1\n#define PS_ON_PIN          -1\n#define KILL_PIN           -1\n\n#ifndef SDSUPPORT\n// these pins are defined in the SD library if building with SD support\n  #define SCK_PIN          21\n  #define MISO_PIN         22\n  #define MOSI_PIN         23\n#endif\n\n#endif\n\n#ifndef KNOWN_BOARD\n#error Unknown MOTHERBOARD value in configuration.h\n#endif\n\n\n//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those!\nconst int sensitive_pins[] = {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN};\n\n#endif\n\n\n"
  },
  {
    "path": "Sprinter/speed_lookuptable.h",
    "content": "#ifndef SPEED_LOOKUPTABLE_H\n#define SPEED_LOOKUPTABLE_H\n\n#include <avr/pgmspace.h>\n\n\n #if F_CPU == 16000000\n const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\\\n  { 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, \n  { 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, \n  { 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, \n  { 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8}, \n  { 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5}, \n  { 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3}, \n  { 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2}, \n  { 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2}, \n  { 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1}, \n  { 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1}, \n  { 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1}, \n  { 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1}, \n  { 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0}, \n  { 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1}, \n  { 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0}, \n  { 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1}, \n  { 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0}, \n  { 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0}, \n  { 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0}, \n  { 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1}, \n  { 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0}, \n  { 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0}, \n  { 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0}, \n  { 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0}, \n  { 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0}, \n  { 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0}, \n  { 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0}, \n  { 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1}, \n  { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0}, \n  { 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0}, \n  { 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, \n  { 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0}\n  };\n  \n const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\\\n  { 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, \n  { 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, \n  { 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, \n  { 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198}, \n  { 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132}, \n  { 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94}, \n  { 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71}, \n  { 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55}, \n  { 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44}, \n  { 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36}, \n  { 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30}, \n  { 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25}, \n  { 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22}, \n  { 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18}, \n  { 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16}, \n  { 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15}, \n  { 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13}, \n  { 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11}, \n  { 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10}, \n  { 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9}, \n  { 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8}, \n  { 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8}, \n  { 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7}, \n  { 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7}, \n  { 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6}, \n  { 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5}, \n  { 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5}, \n  { 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5}, \n  { 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4}, \n  { 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4}, \n  { 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4}, \n  { 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3}\n  };\n\n #else\n\n  const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\n   {62500, 54055}, {8445, 3917}, {4528, 1434}, {3094, 745}, {2349, 456}, {1893, 307}, {1586, 222}, {1364, 167},\n   {1197, 131}, {1066, 105}, {961, 86}, {875, 72}, {803, 61}, {742, 53}, {689, 45}, {644, 40},\n   {604, 35}, {569, 32}, {537, 28}, {509, 25}, {484, 23}, {461, 21}, {440, 19}, {421, 17},\n   {404, 16}, {388, 15}, {373, 14}, {359, 13}, {346, 12}, {334, 11}, {323, 10}, {313, 10},\n   {303, 9}, {294, 9}, {285, 8}, {277, 7}, {270, 8}, {262, 7}, {255, 6}, {249, 6},\n   {243, 6}, {237, 6}, {231, 5}, {226, 5}, {221, 5}, {216, 5}, {211, 4}, {207, 5},\n   {202, 4}, {198, 4}, {194, 4}, {190, 3}, {187, 4}, {183, 3}, {180, 3}, {177, 4},\n   {173, 3}, {170, 3}, {167, 2}, {165, 3}, {162, 3}, {159, 2}, {157, 3}, {154, 2},\n   {152, 3}, {149, 2}, {147, 2}, {145, 2}, {143, 2}, {141, 2}, {139, 2}, {137, 2},\n   {135, 2}, {133, 2}, {131, 2}, {129, 1}, {128, 2}, {126, 2}, {124, 1}, {123, 2},\n   {121, 1}, {120, 2}, {118, 1}, {117, 1}, {116, 2}, {114, 1}, {113, 1}, {112, 2},\n   {110, 1}, {109, 1}, {108, 1}, {107, 2}, {105, 1}, {104, 1}, {103, 1}, {102, 1},\n   {101, 1}, {100, 1}, {99, 1}, {98, 1}, {97, 1}, {96, 1}, {95, 1}, {94, 1},\n   {93, 1}, {92, 1}, {91, 0}, {91, 1}, {90, 1}, {89, 1}, {88, 1}, {87, 0},\n   {87, 1}, {86, 1}, {85, 1}, {84, 0}, {84, 1}, {83, 1}, {82, 1}, {81, 0},\n   {81, 1}, {80, 1}, {79, 0}, {79, 1}, {78, 0}, {78, 1}, {77, 1}, {76, 0},\n   {76, 1}, {75, 0}, {75, 1}, {74, 1}, {73, 0}, {73, 1}, {72, 0}, {72, 1},\n   {71, 0}, {71, 1}, {70, 0}, {70, 1}, {69, 0}, {69, 1}, {68, 0}, {68, 1},\n   {67, 0}, {67, 1}, {66, 0}, {66, 1}, {65, 0}, {65, 0}, {65, 1}, {64, 0},\n   {64, 1}, {63, 0}, {63, 1}, {62, 0}, {62, 0}, {62, 1}, {61, 0}, {61, 1},\n   {60, 0}, {60, 0}, {60, 1}, {59, 0}, {59, 0}, {59, 1}, {58, 0}, {58, 0},\n   {58, 1}, {57, 0}, {57, 0}, {57, 1}, {56, 0}, {56, 0}, {56, 1}, {55, 0},\n   {55, 0}, {55, 1}, {54, 0}, {54, 0}, {54, 1}, {53, 0}, {53, 0}, {53, 0},\n   {53, 1}, {52, 0}, {52, 0}, {52, 1}, {51, 0}, {51, 0}, {51, 0}, {51, 1},\n   {50, 0}, {50, 0}, {50, 0}, {50, 1}, {49, 0}, {49, 0}, {49, 0}, {49, 1},\n   {48, 0}, {48, 0}, {48, 0}, {48, 1}, {47, 0}, {47, 0}, {47, 0}, {47, 1},\n   {46, 0}, {46, 0}, {46, 0}, {46, 0}, {46, 1}, {45, 0}, {45, 0}, {45, 0},\n   {45, 1}, {44, 0}, {44, 0}, {44, 0}, {44, 0}, {44, 1}, {43, 0}, {43, 0},\n   {43, 0}, {43, 0}, {43, 1}, {42, 0}, {42, 0}, {42, 0}, {42, 0}, {42, 0},\n   {42, 1}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 1}, {40, 0},\n   {40, 0}, {40, 0}, {40, 0}, {40, 1}, {39, 0}, {39, 0}, {39, 0}, {39, 0},\n   {39, 0}, {39, 0}, {39, 1}, {38, 0}, {38, 0}, {38, 0}, {38, 0}, {38, 0},\n};\n  \n  const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\n   {62500, 10417}, {52083, 7441}, {44642, 5580}, {39062, 4340}, {34722, 3472}, {31250, 2841}, {28409, 2368}, {26041, 2003},\n   {24038, 1717}, {22321, 1488}, {20833, 1302}, {19531, 1149}, {18382, 1021}, {17361, 914}, {16447, 822}, {15625, 745},\n   {14880, 676}, {14204, 618}, {13586, 566}, {13020, 520}, {12500, 481}, {12019, 445}, {11574, 414}, {11160, 385},\n   {10775, 359}, {10416, 336}, {10080, 315}, {9765, 296}, {9469, 278}, {9191, 263}, {8928, 248}, {8680, 235},\n   {8445, 222}, {8223, 211}, {8012, 200}, {7812, 191}, {7621, 181}, {7440, 173}, {7267, 165}, {7102, 158},\n   {6944, 151}, {6793, 145}, {6648, 138}, {6510, 133}, {6377, 127}, {6250, 123}, {6127, 118}, {6009, 113},\n   {5896, 109}, {5787, 106}, {5681, 101}, {5580, 98}, {5482, 95}, {5387, 91}, {5296, 88}, {5208, 86},\n   {5122, 82}, {5040, 80}, {4960, 78}, {4882, 75}, {4807, 73}, {4734, 70}, {4664, 69}, {4595, 67},\n   {4528, 64}, {4464, 63}, {4401, 61}, {4340, 60}, {4280, 58}, {4222, 56}, {4166, 55}, {4111, 53},\n   {4058, 52}, {4006, 51}, {3955, 49}, {3906, 48}, {3858, 48}, {3810, 45}, {3765, 45}, {3720, 44},\n   {3676, 43}, {3633, 42}, {3591, 40}, {3551, 40}, {3511, 39}, {3472, 38}, {3434, 38}, {3396, 36},\n   {3360, 36}, {3324, 35}, {3289, 34}, {3255, 34}, {3221, 33}, {3188, 32}, {3156, 31}, {3125, 31},\n   {3094, 31}, {3063, 30}, {3033, 29}, {3004, 28}, {2976, 28}, {2948, 28}, {2920, 27}, {2893, 27},\n   {2866, 26}, {2840, 25}, {2815, 25}, {2790, 25}, {2765, 24}, {2741, 24}, {2717, 24}, {2693, 23},\n   {2670, 22}, {2648, 22}, {2626, 22}, {2604, 22}, {2582, 21}, {2561, 21}, {2540, 20}, {2520, 20},\n   {2500, 20}, {2480, 20}, {2460, 19}, {2441, 19}, {2422, 19}, {2403, 18}, {2385, 18}, {2367, 18},\n   {2349, 17}, {2332, 18}, {2314, 17}, {2297, 16}, {2281, 17}, {2264, 16}, {2248, 16}, {2232, 16},\n   {2216, 16}, {2200, 15}, {2185, 15}, {2170, 15}, {2155, 15}, {2140, 15}, {2125, 14}, {2111, 14},\n   {2097, 14}, {2083, 14}, {2069, 14}, {2055, 13}, {2042, 13}, {2029, 13}, {2016, 13}, {2003, 13},\n   {1990, 13}, {1977, 12}, {1965, 12}, {1953, 13}, {1940, 11}, {1929, 12}, {1917, 12}, {1905, 12},\n   {1893, 11}, {1882, 11}, {1871, 11}, {1860, 11}, {1849, 11}, {1838, 11}, {1827, 11}, {1816, 10},\n   {1806, 11}, {1795, 10}, {1785, 10}, {1775, 10}, {1765, 10}, {1755, 10}, {1745, 9}, {1736, 10},\n   {1726, 9}, {1717, 10}, {1707, 9}, {1698, 9}, {1689, 9}, {1680, 9}, {1671, 9}, {1662, 9},\n   {1653, 9}, {1644, 8}, {1636, 9}, {1627, 8}, {1619, 9}, {1610, 8}, {1602, 8}, {1594, 8},\n   {1586, 8}, {1578, 8}, {1570, 8}, {1562, 8}, {1554, 7}, {1547, 8}, {1539, 8}, {1531, 7},\n   {1524, 8}, {1516, 7}, {1509, 7}, {1502, 7}, {1495, 7}, {1488, 7}, {1481, 7}, {1474, 7},\n   {1467, 7}, {1460, 7}, {1453, 7}, {1446, 6}, {1440, 7}, {1433, 7}, {1426, 6}, {1420, 6},\n   {1414, 7}, {1407, 6}, {1401, 6}, {1395, 7}, {1388, 6}, {1382, 6}, {1376, 6}, {1370, 6},\n   {1364, 6}, {1358, 6}, {1352, 6}, {1346, 5}, {1341, 6}, {1335, 6}, {1329, 5}, {1324, 6},\n   {1318, 5}, {1313, 6}, {1307, 5}, {1302, 6}, {1296, 5}, {1291, 5}, {1286, 6}, {1280, 5},\n   {1275, 5}, {1270, 5}, {1265, 5}, {1260, 5}, {1255, 5}, {1250, 5}, {1245, 5}, {1240, 5},\n   {1235, 5}, {1230, 5}, {1225, 5}, {1220, 5}, {1215, 4}, {1211, 5}, {1206, 5}, {1201, 5},\n  };\n #endif\n\n#endif\n"
  },
  {
    "path": "Sprinter/store_eeprom.cpp",
    "content": "/*\n EEPROM routines to save Sprinter Settings \n \n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n \n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n \n You should have received a copy of the GNU General Public License\n along with this program.  If not, see <http://www.gnu.org/licenses/>. \n*/\n\n#include <avr/eeprom.h>\n#include <avr/pgmspace.h>\n#include <inttypes.h>\n\n#include \"Sprinter.h\"\n#include \"store_eeprom.h\"\n#include \"Configuration.h\"\n\n#ifdef PIDTEMP\n extern unsigned int PID_Kp, PID_Ki, PID_Kd;\n#endif\n\n\n#ifdef USE_EEPROM_SETTINGS\n\n//======================================================================================\n//========================= Read / Write EEPROM =======================================\ntemplate <class T> int EEPROM_write_setting(int address, const T& value)\n{\n  const byte* p = (const byte*)(const void*)&value;\n  int i;\n  for (i = 0; i < (int)sizeof(value); i++)\n    eeprom_write_byte((unsigned char *)address++, *p++);\n  return i;\n}\n\ntemplate <class T> int EEPROM_read_setting(int address, T& value)\n{\n  byte* p = (byte*)(void*)&value;\n  int i;\n  for (i = 0; i < (int)sizeof(value); i++)\n    *p++ = eeprom_read_byte((unsigned char *)address++);\n  return i;\n}\n//======================================================================================\n\n\nvoid EEPROM_StoreSettings() \n{\n  char ver[4]= \"000\";\n  EEPROM_write_setting(EEPROM_OFFSET, ver); // invalidate data first\n  EEPROM_write_setting(axis_steps_per_unit_address, axis_steps_per_unit);\n  EEPROM_write_setting(max_feedrate_address, max_feedrate);\n  EEPROM_write_setting(max_acceleration_units_per_sq_second_address, max_acceleration_units_per_sq_second);\n  EEPROM_write_setting(move_acceleration_address, move_acceleration);\n  EEPROM_write_setting(retract_acceleration_address, retract_acceleration);\n  EEPROM_write_setting(minimumfeedrate_address, minimumfeedrate);\n  EEPROM_write_setting(mintravelfeedrate_address, mintravelfeedrate);\n  EEPROM_write_setting(min_seg_time_address, min_seg_time);  //Min Segment Time, not used yet\n  EEPROM_write_setting(max_xy_jerk_address, max_xy_jerk);\n  EEPROM_write_setting(max_z_jerk_address, max_z_jerk);\n  EEPROM_write_setting(max_e_jerk_address, max_e_jerk);\n\n  //PID Settings\n  #ifdef PIDTEMP\n   EEPROM_write_setting(Kp_address, PID_Kp);     //Kp\n   EEPROM_write_setting(Ki_address, PID_Ki);     //Ki\n   EEPROM_write_setting(Kd_address, PID_Kd);     //Kd\n  #else\n   EEPROM_write_setting(Kp_address, 2048);     //Kp\n   EEPROM_write_setting(Ki_address, 32);     //Ki\n   EEPROM_write_setting(Kd_address, 2048);     //Kd\n  #endif\n  \n\n  char ver2[4]=EEPROM_VERSION;\n  EEPROM_write_setting(EEPROM_OFFSET, ver2); // validate data\n  showString(PSTR(\"Settings Stored\\r\\n\"));\n \n}\n\n\nvoid EEPROM_printSettings()\n{  \n  #ifdef PRINT_EEPROM_SETTING\n      showString(PSTR(\"Steps per unit:\\r\\n\"));\n      showString(PSTR(\" M92 X\"));\n      Serial.print(axis_steps_per_unit[0]);\n      showString(PSTR(\" Y\"));\n      Serial.print(axis_steps_per_unit[1]);\n      showString(PSTR(\" Z\"));\n      Serial.print(axis_steps_per_unit[2]);\n      showString(PSTR(\" E\"));\n      Serial.println(axis_steps_per_unit[3]);\n      \n      showString(PSTR(\"Maximum feedrates (mm/s):\\r\\n\"));\n      showString(PSTR(\"  M202 X\"));\n      Serial.print(max_feedrate[0]);\n      showString(PSTR(\" Y\"));\n      Serial.print(max_feedrate[1]); \n      showString(PSTR(\" Z\"));\n      Serial.print(max_feedrate[2]); \n      showString(PSTR(\" E\"));\n      Serial.println(max_feedrate[3]);\n\n      showString(PSTR(\"Maximum Acceleration (mm/s2):\\r\\n\"));\n      showString(PSTR(\"  M201 X\"));\n      Serial.print(max_acceleration_units_per_sq_second[0] ); \n      showString(PSTR(\" Y\"));\n      Serial.print(max_acceleration_units_per_sq_second[1] ); \n      showString(PSTR(\" Z\"));\n      Serial.print(max_acceleration_units_per_sq_second[2] );\n      showString(PSTR(\" E\"));\n      Serial.println(max_acceleration_units_per_sq_second[3]);\n\n      showString(PSTR(\"Acceleration: S=acceleration, T=retract acceleration\\r\\n\"));\n      showString(PSTR(\"  M204 S\"));\n      Serial.print(move_acceleration ); \n      showString(PSTR(\" T\"));\n      Serial.println(retract_acceleration);\n\n      showString(PSTR(\"Advanced variables (mm/s): S=Min feedrate, T=Min travel feedrate, X=max xY jerk,  Z=max Z jerk, E=max E jerk\\r\\n\"));\n\n      showString(PSTR(\"  M205 S\"));\n      Serial.print(minimumfeedrate ); \n      showString(PSTR(\" T\" ));\n      Serial.print(mintravelfeedrate ); \n//      showString(PSTR(\" B\"));\n//      Serial.print(min_seg_time ); \n      showString(PSTR(\" X\"));\n      Serial.print(max_xy_jerk ); \n      showString(PSTR(\" Z\"));\n      Serial.print(max_z_jerk);\n      showString(PSTR(\" E\"));\n      Serial.println(max_e_jerk);\n\n      \n    #ifdef PIDTEMP\n    \n      showString(PSTR(\"PID settings:\\r\\n\"));\n      showString(PSTR(\"  M301 P\"));\n      Serial.print(PID_Kp); \n      showString(PSTR(\" I\"));\n      Serial.print(PID_Ki); \n      showString(PSTR(\" D\"));\n      Serial.println(PID_Kd);\n    \n    #endif\n  #endif\n\n} \n\n\nvoid EEPROM_RetrieveSettings(bool def, bool printout)\n{  // if def=true, the default values will be used\n\n    int i=EEPROM_OFFSET;\n    char stored_ver[4];\n    char ver[4]=EEPROM_VERSION;\n    \n    EEPROM_read_setting(EEPROM_OFFSET,stored_ver); //read stored version\n    if ((!def)&&(strncmp(ver,stored_ver,3)==0))\n    {   // version number match\n      EEPROM_read_setting(axis_steps_per_unit_address, axis_steps_per_unit);\n      EEPROM_read_setting(max_feedrate_address, max_feedrate);\n      EEPROM_read_setting(max_acceleration_units_per_sq_second_address, max_acceleration_units_per_sq_second);\n      EEPROM_read_setting(move_acceleration_address, move_acceleration);\n      EEPROM_read_setting(retract_acceleration_address, retract_acceleration);\n      EEPROM_read_setting(minimumfeedrate_address, minimumfeedrate);\n      EEPROM_read_setting(mintravelfeedrate_address, mintravelfeedrate);\n      EEPROM_read_setting(min_seg_time_address, min_seg_time);  //min Segmenttime --> not used yet\n      EEPROM_read_setting(max_xy_jerk_address, max_xy_jerk);\n      EEPROM_read_setting(max_z_jerk_address, max_z_jerk);\n      EEPROM_read_setting(max_e_jerk_address, max_e_jerk);\n\n      #ifdef PIDTEMP\n       EEPROM_read_setting(Kp_address, PID_Kp);\n       EEPROM_read_setting(Ki_address, PID_Ki);\n       EEPROM_read_setting(Kd_address, PID_Kd);\n      #endif\n\n      showString(PSTR(\"Stored settings retreived\\r\\n\"));\n    }\n    else \n    {\n\n      float tmp1[]=_AXIS_STEP_PER_UNIT;\n      float tmp2[]=_MAX_FEEDRATE;\n      long tmp3[]=_MAX_ACCELERATION_UNITS_PER_SQ_SECOND;\n      for (short i=0;i<4;i++) \n      {\n        axis_steps_per_unit[i]=tmp1[i];  \n        max_feedrate[i]=tmp2[i];  \n        max_acceleration_units_per_sq_second[i]=tmp3[i];\n      }\n      move_acceleration=_ACCELERATION;\n      retract_acceleration=_RETRACT_ACCELERATION;\n      minimumfeedrate=DEFAULT_MINIMUMFEEDRATE;\n      mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE;\n      max_xy_jerk=_MAX_XY_JERK;\n      max_z_jerk=_MAX_Z_JERK;\n      max_e_jerk=_MAX_E_JERK;\n      min_seg_time=_MIN_SEG_TIME;\n      \n      #ifdef PIDTEMP\n       PID_Kp = PID_PGAIN;\n       PID_Ki = PID_IGAIN;\n       PID_Kd = PID_DGAIN;\n      #endif\n\n      showString(PSTR(\"Using Default settings\\r\\n\"));\n    }\n    \n    if(printout)\n    {\n      EEPROM_printSettings();\n    }\n}  \n\n#endif\n"
  },
  {
    "path": "Sprinter/store_eeprom.h",
    "content": "/*\n EEPROM routines to save Sprinter Settings \n \n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n \n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n \n You should have received a copy of the GNU General Public License\n along with this program.  If not, see <http://www.gnu.org/licenses/>. \n*/\n\n\n#ifndef __EEPROMH\n#define __EEPROMH\n\n#define EEPROM_OFFSET 100\n\n\n// IMPORTANT:  Whenever there are changes made to the variables stored in EEPROM\n// in the functions below, also increment the version number. This makes sure that\n// the default values are used whenever there is a change to the data, to prevent\n// wrong data being written to the variables.\n// ALSO:  always make sure the variables in the Store and retrieve sections are in the same order.\n#define EEPROM_VERSION \"S03\"\n\n\nextern float axis_steps_per_unit[4]; \nextern float max_feedrate[4];\nextern long  max_acceleration_units_per_sq_second[4];\nextern float move_acceleration;\nextern float retract_acceleration;\nextern float mintravelfeedrate;\nextern float minimumfeedrate;\nextern float max_xy_jerk;\nextern float max_z_jerk;\nextern float max_e_jerk;\nextern unsigned long min_seg_time;\n\n#define axis_steps_per_unit_address (EEPROM_OFFSET + 4*sizeof(char))\n#define max_feedrate_address (axis_steps_per_unit_address + 4*sizeof(float))\n#define max_acceleration_units_per_sq_second_address (max_feedrate_address + 4*sizeof(float))\n#define move_acceleration_address (max_acceleration_units_per_sq_second_address + 4*sizeof(long))\n#define retract_acceleration_address (move_acceleration_address + sizeof(float))\n#define mintravelfeedrate_address (retract_acceleration_address + sizeof(float))\n#define minimumfeedrate_address (mintravelfeedrate_address + sizeof(float))\n#define max_xy_jerk_address (minimumfeedrate_address + sizeof(float))\n#define max_z_jerk_address (max_xy_jerk_address + sizeof(float))\n#define max_e_jerk_address (max_z_jerk_address + sizeof(float))\n#define min_seg_time_address (max_e_jerk_address + sizeof(float))\n#define Kp_address (min_seg_time_address + sizeof(unsigned long))\n#define Ki_address (Kp_address + sizeof(unsigned int))\n#define Kd_address (Ki_address + sizeof(unsigned int))\n\nextern void EEPROM_RetrieveSettings(bool def, bool printout );\nextern void EEPROM_printSettings();\nextern void EEPROM_StoreSettings();\n\n\n#endif\n"
  },
  {
    "path": "Sprinter/thermistortables.h",
    "content": "#ifndef THERMISTORTABLES_H_\n#define THERMISTORTABLES_H_\n\n#if (THERMISTORHEATER == 1) || (THERMISTORBED == 1) //100k bed thermistor\n\n\n#define NUMTEMPS_1 61\nconst short temptable_1[NUMTEMPS_1][2] = {\n{\t23\t,\t300\t},\n{\t25\t,\t295\t},\n{\t27\t,\t290\t},\n{\t28\t,\t285\t},\n{\t31\t,\t280\t},\n{\t33\t,\t275\t},\n{\t35\t,\t270\t},\n{\t38\t,\t265\t},\n{\t41\t,\t260\t},\n{\t44\t,\t255\t},\n{\t48\t,\t250\t},\n{\t52\t,\t245\t},\n{\t56\t,\t240\t},\n{\t61\t,\t235\t},\n{\t66\t,\t230\t},\n{\t71\t,\t225\t},\n{\t78\t,\t220\t},\n{\t84\t,\t215\t},\n{\t92\t,\t210\t},\n{\t100\t,\t205\t},\n{\t109\t,\t200\t},\n{\t120\t,\t195\t},\n{\t131\t,\t190\t},\n{\t143\t,\t185\t},\n{\t156\t,\t180\t},\n{\t171\t,\t175\t},\n{\t187\t,\t170\t},\n{\t205\t,\t165\t},\n{\t224\t,\t160\t},\n{\t245\t,\t155\t},\n{\t268\t,\t150\t},\n{\t293\t,\t145\t},\n{\t320\t,\t140\t},\n{\t348\t,\t135\t},\n{\t379\t,\t130\t},\n{\t411\t,\t125\t},\n{\t445\t,\t120\t},\n{\t480\t,\t115\t},\n{\t516\t,\t110\t},\n{\t553\t,\t105\t},\n{\t591\t,\t100\t},\n{\t628\t,\t95\t},\n{\t665\t,\t90\t},\n{\t702\t,\t85\t},\n{\t737\t,\t80\t},\n{\t770\t,\t75\t},\n{\t801\t,\t70\t},\n{\t830\t,\t65\t},\n{\t857\t,\t60\t},\n{\t881\t,\t55\t},\n{\t903\t,\t50\t},\n{\t922\t,\t45\t},\n{\t939\t,\t40\t},\n{\t954\t,\t35\t},\n{\t966\t,\t30\t},\n{\t977\t,\t25\t},\n{\t985\t,\t20\t},\n{\t993\t,\t15\t},\n{\t999\t,\t10\t},\n{\t1004\t,\t5\t},\n{\t1008\t,\t0\t} //safety\n};\n#endif\n#if (THERMISTORHEATER == 2) || (THERMISTORBED == 2) //200k bed thermistor verified by arcol\n#define NUMTEMPS_2 64\nconst short temptable_2[NUMTEMPS_2][2] = {\n   {  16, 315},\n   {  17, 310},\n   {  18, 305},\n   {  19, 300},\n   {  20, 295},\n   {  21, 290},\n   {  22, 285},\n   {  23, 280},\n   {  24, 275},\n   {  25, 270},\n   {  29, 265},\n   {  30, 260},\n   {  35, 255},\n   {  40, 250},\n   {  45, 245},\n   {  50, 240},\n   {  55, 235},\n   {  60, 230},\n   {  65, 225},\n   {  70, 220},\n   {  90, 215},\n   {  95, 210},\n   { 103, 205},\n   { 105, 200},\n   { 115, 195},\n   { 130, 190},\n   { 150, 185},\n   { 167, 180},\n   { 190, 175},\n   { 200, 170},\n   { 230, 165},\n   { 250, 160},\n   { 270, 155},\n   { 300, 150},\n   { 330, 145},\n   { 360, 140},\n   { 380, 135},\n   { 408, 130},\n   { 450, 125},\n   { 500, 120},\n   { 530, 115},\n   { 550, 110},\n   { 570, 105},\n   { 595, 100},\n   { 615,  95},\n   { 640,  90},\n   { 665,  85},\n   { 700,  80},\n   { 740,  75},\n   { 780,  70},\n   { 810,  65},\n   { 840,  60},\n   { 880,  55},\n   { 920,  50},\n   { 960,  45},\n   { 980,  40},\n   { 990,  35},\n   {1000,  30},\n   {1005,  25},\n   {1006,  20},\n   {1009,  15},\n   {1010,  10},\n   {1020,   5},\n   {1023,   0} //safety\n};\n\n#endif\n#if (THERMISTORHEATER == 3) || (THERMISTORBED == 3) //mendel-parts\n#define NUMTEMPS_3 28\nconst short temptable_3[NUMTEMPS_3][2] = {\n\t\t{1,864},\n\t\t{21,300},\n\t\t{25,290},\n\t\t{29,280},\n\t\t{33,270},\n\t\t{39,260},\n\t\t{46,250},\n\t\t{54,240},\n\t\t{64,230},\n\t\t{75,220},\n\t\t{90,210},\n\t\t{107,200},\n\t\t{128,190},\n\t\t{154,180},\n\t\t{184,170},\n\t\t{221,160},\n\t\t{265,150},\n\t\t{316,140},\n\t\t{375,130},\n\t\t{441,120},\n\t\t{513,110},\n\t\t{588,100},\n\t\t{734,80},\n\t\t{856,60},\n\t\t{938,40},\n\t\t{986,20},\n\t\t{1008,0},\n\t\t{1018,-20}\n\t};\n\n#endif\n#if (THERMISTORHEATER == 4) || (THERMISTORBED == 4) //10k thermistor\n\n#define NUMTEMPS_4 20\nconst short temptable_4[NUMTEMPS_4][2] = {\n   {1, 430},\n   {54, 137},\n   {107, 107},\n   {160, 91},\n   {213, 80},\n   {266, 71},\n   {319, 64},\n   {372, 57},\n   {425, 51},\n   {478, 46},\n   {531, 41},\n   {584, 35},\n   {637, 30},\n   {690, 25},\n   {743, 20},\n   {796, 14},\n   {849, 7},\n   {902, 0},\n   {955, -11},\n   {1008, -35}\n};\n#endif\n\n#if (THERMISTORHEATER == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2)\n\n#define NUMTEMPS_5 61\nconst short temptable_5[NUMTEMPS_5][2] = {\n{1, 713},\n{18, 316},\n{35, 266},\n{52, 239},\n{69, 221},\n{86, 208},\n{103, 197},\n{120, 188},\n{137, 181},\n{154, 174},\n{171, 169},\n{188, 163},\n{205, 159},\n{222, 154},\n{239, 150},\n{256, 147},\n{273, 143},\n{290, 140},\n{307, 136},\n{324, 133},\n{341, 130},\n{358, 128},\n{375, 125},\n{392, 122},\n{409, 120},\n{426, 117},\n{443, 115},\n{460, 112},\n{477, 110},\n{494, 108},\n{511, 106},\n{528, 103},\n{545, 101},\n{562, 99},\n{579, 97},\n{596, 95},\n{613, 92},\n{630, 90},\n{647, 88},\n{664, 86},\n{681, 84},\n{698, 81},\n{715, 79},\n{732, 77},\n{749, 75},\n{766, 72},\n{783, 70},\n{800, 67},\n{817, 64},\n{834, 61},\n{851, 58},\n{868, 55},\n{885, 52},\n{902, 48},\n{919, 44},\n{936, 40},\n{953, 34},\n{970, 28},\n{987, 20},\n{1004, 8},\n{1021, 0}\n};\n#endif\n\n#if (THERMISTORHEATER == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor\n#define NUMTEMPS_6 36\nconst short temptable_6[NUMTEMPS_6][2] = {\n   {28, 250},\n   {31, 245},\n   {35, 240},\n   {39, 235},\n   {42, 230},\n   {44, 225},\n   {49, 220},\n   {53, 215},\n   {62, 210},\n   {71, 205}, //fitted graphically\n   {78, 200}, //fitted graphically\n   {94, 190},\n   {102, 185},\n   {116, 170},\n   {143, 160},\n   {183, 150},\n   {223, 140},\n   {270, 130},\n   {318, 120},\n   {383, 110},\n   {413, 105},\n   {439, 100},\n   {484, 95},\n   {513, 90},\n   {607, 80},\n   {664, 70},\n   {781, 60},\n   {810, 55},\n   {849, 50},\n   {914, 45},\n   {914, 40},\n   {935, 35},\n   {954, 30},\n   {970, 25},\n   {978, 22},\n   {1008, 3}\n};\n#endif\n\n#if (THERMISTORHEATER == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01\n#define NUMTEMPS_7 55\nconst short temptable_7[NUMTEMPS_7][2] = {\n   {46, 270},\n   {50, 265},\n   {54, 260},\n   {58, 255},\n   {62, 250},\n   {67, 245},\n   {72, 240},\n   {79, 235},\n   {85, 230},\n   {91, 225},\n   {99, 220},\n   {107, 215},\n   {116, 210},\n   {126, 205},\n   {136, 200},\n   {149, 195},\n   {160, 190},\n   {175, 185},\n   {191, 180},\n   {209, 175},\n   {224, 170},\n   {246, 165},\n   {267, 160},\n   {293, 155},\n   {316, 150},\n   {340, 145},\n   {364, 140},\n   {396, 135},\n   {425, 130},\n   {460, 125},\n   {489, 120},\n   {526, 115},\n   {558, 110},\n   {591, 105},\n   {628, 100},\n   {660, 95},\n   {696, 90},\n   {733, 85},\n   {761, 80},\n   {794, 75},\n   {819, 70},\n   {847, 65},\n   {870, 60},\n   {892, 55},\n   {911, 50},\n   {929, 45},\n   {944, 40},\n   {959, 35},\n   {971, 30},\n   {981, 25},\n   {989, 20},\n   {994, 15},\n   {1001, 10},\n   {1005, 5},\n   {1021, 0} //safety\n\n};\n#endif\n\n\n\n#if THERMISTORHEATER == 1\n#define NUMTEMPS NUMTEMPS_1\n#define temptable temptable_1\n#elif THERMISTORHEATER == 2\n#define NUMTEMPS NUMTEMPS_2\n#define temptable temptable_2\n#elif THERMISTORHEATER == 3\n#define NUMTEMPS NUMTEMPS_3\n#define temptable temptable_3\n#elif THERMISTORHEATER == 4\n#define NUMTEMPS NUMTEMPS_4\n#define temptable temptable_4\n#elif THERMISTORHEATER == 5\n#define NUMTEMPS NUMTEMPS_5\n#define temptable temptable_5\n#elif THERMISTORHEATER == 6\n#define NUMTEMPS NUMTEMPS_6\n#define temptable temptable_6\n#elif THERMISTORHEATER == 7\n#define NUMTEMPS NUMTEMPS_7\n#define temptable temptable_7\n#elif defined HEATER_USES_THERMISTOR\n#error No heater thermistor table specified\n#endif\n#if THERMISTORBED == 1\n#define BNUMTEMPS NUMTEMPS_1\n#define bedtemptable temptable_1\n#elif THERMISTORBED == 2\n#define BNUMTEMPS NUMTEMPS_2\n#define bedtemptable temptable_2\n#elif THERMISTORBED == 3\n#define BNUMTEMPS NUMTEMPS_3\n#define bedtemptable temptable_3\n#elif THERMISTORBED == 4\n#define BNUMTEMPS NUMTEMPS_4\n#define bedtemptable temptable_4\n#elif THERMISTORBED == 5\n#define BNUMTEMPS NUMTEMPS_5\n#define bedtemptable temptable_5\n#elif THERMISTORBED == 6\n#define BNUMTEMPS NUMTEMPS_6\n#define bedtemptable temptable_6\n#elif THERMISTORBED == 7\n#define BNUMTEMPS NUMTEMPS_7\n#define bedtemptable temptable_7\n#elif defined BED_USES_THERMISTOR\n#error No bed thermistor table specified\n#endif\n\n#endif //THERMISTORTABLES_H_\n"
  }
]