├── Sprinter ├── Sprinter.h ├── SdFatUtil.h ├── createTemperatureLookup.py ├── thermistortables.h ├── SdInfo.h ├── Configuration.h ├── Makefile ├── SdFatmainpage.h ├── Sd2Card.h ├── SdVolume.cpp ├── Sd2PinMap.h ├── FatStructs.h ├── pins.h ├── Sd2Card.cpp ├── SdFat.h └── SdFile.cpp └── README /Sprinter/Sprinter.h: -------------------------------------------------------------------------------- 1 | // Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. 2 | // Licence: GPL 3 | #include 4 | #include "fastio.h" 5 | extern "C" void __cxa_pure_virtual(); 6 | void __cxa_pure_virtual(){}; 7 | void get_command(); 8 | void process_commands(); 9 | 10 | void manage_inactivity(byte debug); 11 | 12 | void manage_heater(); 13 | int temp2analogu(int celsius, const short table[][2], int numtemps, int source); 14 | int analog2tempu(int raw, const short table[][2], int numtemps, int source); 15 | #ifdef HEATER_USES_THERMISTOR 16 | #define HEATERSOURCE 1 17 | #endif 18 | #ifdef HEATER_USES_AD595 19 | #define HEATERSOURCE 2 20 | #endif 21 | #ifdef HEATER_USES_MAX6675 22 | #define HEATERSOURCE 3 23 | #endif 24 | #ifdef BED_USES_THERMISTOR 25 | #define BEDSOURCE 1 26 | #endif 27 | #ifdef BED_USES_AD595 28 | #define BEDSOURCE 2 29 | #endif 30 | #ifdef BED_USES_MAX6675 31 | #define BEDSOURCE 3 32 | #endif 33 | 34 | #define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS,HEATERSOURCE) 35 | #define temp2analogBed( c ) temp2analogu((c),bedtemptable,BNUMTEMPS,BEDSOURCE) 36 | #define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS,HEATERSOURCE) 37 | #define analog2tempBed( c ) analog2tempu((c),bedtemptable,BNUMTEMPS,BEDSOURCE) 38 | #if X_ENABLE_PIN > -1 39 | #define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) 40 | #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) 41 | #else 42 | #define enable_x() ; 43 | #define disable_x() ; 44 | #endif 45 | #if Y_ENABLE_PIN > -1 46 | #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) 47 | #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) 48 | #else 49 | #define enable_y() ; 50 | #define disable_y() ; 51 | #endif 52 | #if Z_ENABLE_PIN > -1 53 | #define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON) 54 | #define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON) 55 | #else 56 | #define enable_z() ; 57 | #define disable_z() ; 58 | #endif 59 | #if E_ENABLE_PIN > -1 60 | #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) 61 | #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) 62 | #else 63 | #define enable_e() ; 64 | #define disable_e() ; 65 | #endif 66 | 67 | void FlushSerialRequestResend(); 68 | void ClearToSend(); 69 | 70 | void get_coordinates(); 71 | void prepare_move(); 72 | void linear_move(unsigned long steps_remaining[]); 73 | void do_step(int axis); 74 | void kill(byte debug); 75 | 76 | -------------------------------------------------------------------------------- /Sprinter/SdFatUtil.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2008 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | #ifndef SdFatUtil_h 21 | #define SdFatUtil_h 22 | /** 23 | * \file 24 | * Useful utility functions. 25 | */ 26 | #include 27 | #include 28 | /** Store and print a string in flash memory.*/ 29 | #define PgmPrint(x) SerialPrint_P(PSTR(x)) 30 | /** Store and print a string in flash memory followed by a CR/LF.*/ 31 | #define PgmPrintln(x) SerialPrintln_P(PSTR(x)) 32 | /** Defined so doxygen works for function definitions. */ 33 | #define NOINLINE __attribute__((noinline)) 34 | //------------------------------------------------------------------------------ 35 | /** Return the number of bytes currently free in RAM. */ 36 | static int FreeRam(void) { 37 | extern int __bss_end; 38 | extern int* __brkval; 39 | int free_memory; 40 | if (reinterpret_cast(__brkval) == 0) { 41 | // if no heap use from end of bss section 42 | free_memory = reinterpret_cast(&free_memory) 43 | - reinterpret_cast(&__bss_end); 44 | } else { 45 | // use from top of stack to heap 46 | free_memory = reinterpret_cast(&free_memory) 47 | - reinterpret_cast(__brkval); 48 | } 49 | return free_memory; 50 | } 51 | //------------------------------------------------------------------------------ 52 | /** 53 | * %Print a string in flash memory to the serial port. 54 | * 55 | * \param[in] str Pointer to string stored in flash memory. 56 | */ 57 | static NOINLINE void SerialPrint_P(PGM_P str) { 58 | for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.print(c); 59 | } 60 | //------------------------------------------------------------------------------ 61 | /** 62 | * %Print a string in flash memory followed by a CR/LF. 63 | * 64 | * \param[in] str Pointer to string stored in flash memory. 65 | */ 66 | static NOINLINE void SerialPrintln_P(PGM_P str) { 67 | SerialPrint_P(str); 68 | Serial.println(); 69 | } 70 | #endif // #define SdFatUtil_h 71 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The leading developers of Sprinter are currently Kliment and caru, though many others contribute with their patches. 2 | 3 | This 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. 4 | 5 | This work is licensed under the GNU GPL v3 or (at the user's discretion) any later version. 6 | 7 | It is based on Tonokips's firmware, which was licensed under GPL v2 or later. 8 | 9 | WARNING: This version (April 19th, 2011) fixes a bug that caused speeds to be lower than what 10 | set in GCODE. So before attempting any print, you will have to check all 11 | your axis max speed, including the extruder retract speed. Not following 12 | this guidelines can seriously damage your printer. 13 | 14 | The 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: 15 | #include "ThermistorTable.h" 16 | 17 | In 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: 18 | #define BNUMTEMPS NUMPTEMPS 19 | #define bedtemptable temptable 20 | Then add a line pointing to your second thermistor table, for example: 21 | #include "BedThermistorTable.h" 22 | Finally, 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. 23 | 24 | There are examples of all these configurations in the configuration.h file. Please look at them before you change anything. 25 | 26 | 27 | Complete beginners guide 28 | ======================= 29 | 30 | From a fresh Ubuntu install how to update the firmware of your Prusa Mendel ? 31 | (the specifics are for the Prusa Mendel built at the Bath RepRap masterclass. 32 | This version uses the http://reprap.org/wiki/Sanguinololu. 33 | Some details may not fit your hardware, be sure to check what you are doing) 34 | 35 | Software installation 36 | ---------------------- 37 | 38 | 1. Install the required packages (gcc-avr, avr-libc, etc.) 39 | sudo apt-get install arduino-core 40 | 41 | 2. Get the arduino software version 0018, uncompress it in a directory 42 | http://www.arduino.cc/en/Main/Software 43 | 44 | 3. Get the sanguino software, version 0018 45 | http://sanguino.cc/softwareforlinux 46 | 47 | follow the sanguino's readme so that your arduino hardware folder looks like 48 | arduino-0018/hardware/arduino 49 | arduino-0018/hardware/sanguino 50 | arduino-0018/hardware/tools 51 | 52 | 4. Clone the Sprinter git repository. 53 | git clone https://github.com/kliment/Sprinter.git 54 | Optionally, switch to the desired branch 55 | git branch -a 56 | git checkout THE_BRANCH_YOU_WANT 57 | 58 | Firmware compilation and upload 59 | ------------------------------- 60 | 61 | 5. Edit INSTALL_DIR inside Sprinter/Makefile (do not mind the default reference to arduino 0022) 62 | 63 | 6. Run make. If everything goes well Sprinter/applet/Sprinter.cpp should have been created. 64 | You can safely ignore the error message mentioning arduino-0018/hardware/arduino/cores/arduino/WString.o 65 | 66 | 7. Connect your Sanguinololu to your computer 67 | http://reprap.org/wiki/Sanguinololu 68 | 69 | 8. Launch arduino-0018/arduino, open Sprinter/Sprinter.pde 70 | 71 | 9. Go to Tools -> Serial Port, and select the relevant option 72 | 73 | 10. Go to Tools -> Board, select Sanguino 74 | 75 | 11. Go to the Configuration.h file and edit the following lines: 76 | #define MOTHERBOARD 62 77 | 62 indicates Sanguino 1.2 or superior 78 | 79 | float axis_steps_per_unit[] 80 | 81 | set values that match your hardware. For the special cast gears of the Bath Masterclass Prusa Mendel, these values are 82 | float axis_steps_per_unit[] = {91.42857, 91.42857, 3200/1.25,700}; 83 | 84 | also for the mentioned hardware setup 85 | const bool ENDSTOPS_INVERTING = false; //set to true to invert the logic of the endstops 86 | // false because the switch SIG signal is linked to the ground 87 | // "no touch == closed circuit == SIG connects to GND" 88 | // see http://reprap.org/wiki/Sanguinololu#Endstops 89 | 90 | 12. Click on the "play" button to compile. If everything goes well you should see a "Binary sketch size: " message. 91 | 92 | 13. Click on "the arrow going to the right" button to upload (you had done steps 7,8,9 before, right ?). 93 | If everything goes well you should see the message "Done uploading". 94 | 95 | Congratulations, you have just upgraded the firmware of your RepRap ! 96 | 97 | You can use pronterface.py to do some manual verifications by moving the printer's tip along 98 | the axes and verifying that the physical displacements match the ones indicated on the interface. 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /Sprinter/createTemperatureLookup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Creates a C code lookup table for doing ADC to temperature conversion 4 | # on a microcontroller 5 | # based on: http://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html 6 | """Thermistor Value Lookup Table Generator 7 | 8 | Generates lookup to temperature values for use in a microcontroller in C format based on: 9 | http://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html 10 | 11 | The main use is for Arduino programs that read data from the circuit board described here: 12 | http://make.rrrf.org/ts-1.0 13 | 14 | Usage: python createTemperatureLookup.py [options] 15 | 16 | Options: 17 | -h, --help show this help 18 | --r0=... thermistor rating where # is the ohm rating of the thermistor at t0 (eg: 10K = 10000) 19 | --t0=... thermistor temp rating where # is the temperature in Celsuis to get r0 (from your datasheet) 20 | --beta=... thermistor beta rating. see http://reprap.org/bin/view/Main/MeasuringThermistorBeta 21 | --r1=... R1 rating where # is the ohm rating of R1 (eg: 10K = 10000) 22 | --r2=... R2 rating where # is the ohm rating of R2 (eg: 10K = 10000) 23 | --num-temps=... the number of temperature points to calculate (default: 20) 24 | --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 25 | """ 26 | 27 | from math import * 28 | import sys 29 | import getopt 30 | 31 | class Thermistor: 32 | "Class to do the thermistor maths" 33 | def __init__(self, r0, t0, beta, r1, r2): 34 | self.r0 = r0 # stated resistance, e.g. 10K 35 | self.t0 = t0 + 273.15 # temperature at stated resistance, e.g. 25C 36 | self.beta = beta # stated beta, e.g. 3500 37 | self.vadc = 5.0 # ADC reference 38 | self.vcc = 5.0 # supply voltage to potential divider 39 | self.k = r0 * exp(-beta / self.t0) # constant part of calculation 40 | 41 | if r1 > 0: 42 | self.vs = r1 * self.vcc / (r1 + r2) # effective bias voltage 43 | self.rs = r1 * r2 / (r1 + r2) # effective bias impedance 44 | else: 45 | self.vs = self.vcc # effective bias voltage 46 | self.rs = r2 # effective bias impedance 47 | 48 | def temp(self,adc): 49 | "Convert ADC reading into a temperature in Celcius" 50 | v = adc * self.vadc / 1024 # convert the 10 bit ADC value to a voltage 51 | r = self.rs * v / (self.vs - v) # resistance of thermistor 52 | return (self.beta / log(r / self.k)) - 273.15 # temperature 53 | 54 | def setting(self, t): 55 | "Convert a temperature into a ADC value" 56 | r = self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0)) # resistance of the thermistor 57 | v = self.vs * r / (self.rs + r) # the voltage at the potential divider 58 | return round(v / self.vadc * 1024) # the ADC reading 59 | 60 | def main(argv): 61 | 62 | r0 = 10000; 63 | t0 = 25; 64 | beta = 3947; 65 | r1 = 680; 66 | r2 = 1600; 67 | num_temps = int(20); 68 | 69 | try: 70 | opts, args = getopt.getopt(argv, "h", ["help", "r0=", "t0=", "beta=", "r1=", "r2="]) 71 | except getopt.GetoptError: 72 | usage() 73 | sys.exit(2) 74 | 75 | for opt, arg in opts: 76 | if opt in ("-h", "--help"): 77 | usage() 78 | sys.exit() 79 | elif opt == "--r0": 80 | r0 = int(arg) 81 | elif opt == "--t0": 82 | t0 = int(arg) 83 | elif opt == "--beta": 84 | beta = int(arg) 85 | elif opt == "--r1": 86 | r1 = int(arg) 87 | elif opt == "--r2": 88 | r2 = int(arg) 89 | 90 | if r1: 91 | max_adc = int(1023 * r1 / (r1 + r2)); 92 | else: 93 | max_adc = 1023 94 | increment = int(max_adc/(num_temps-1)); 95 | 96 | t = Thermistor(r0, t0, beta, r1, r2) 97 | 98 | adcs = range(1, max_adc, increment); 99 | # adcs = [1, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100, 110, 130, 150, 190, 220, 250, 300] 100 | first = 1 101 | 102 | print "// Thermistor lookup table for RepRap Temperature Sensor Boards (http://make.rrrf.org/ts)" 103 | print "// Made with createTemperatureLookup.py (http://svn.reprap.org/trunk/reprap/firmware/Arduino/utilities/createTemperatureLookup.py)" 104 | print "// ./createTemperatureLookup.py --r0=%s --t0=%s --r1=%s --r2=%s --beta=%s --max-adc=%s" % (r0, t0, r1, r2, beta, max_adc) 105 | print "// r0: %s" % (r0) 106 | print "// t0: %s" % (t0) 107 | print "// r1: %s" % (r1) 108 | print "// r2: %s" % (r2) 109 | print "// beta: %s" % (beta) 110 | print "// max adc: %s" % (max_adc) 111 | print "#define NUMTEMPS %s" % (len(adcs)) 112 | print "short temptable[NUMTEMPS][2] = {" 113 | 114 | counter = 0 115 | for adc in adcs: 116 | counter = counter +1 117 | if counter == len(adcs): 118 | print " {%s, %s}" % (adc, int(t.temp(adc))) 119 | else: 120 | print " {%s, %s}," % (adc, int(t.temp(adc))) 121 | print "};" 122 | 123 | def usage(): 124 | print __doc__ 125 | 126 | if __name__ == "__main__": 127 | main(sys.argv[1:]) 128 | -------------------------------------------------------------------------------- /Sprinter/thermistortables.h: -------------------------------------------------------------------------------- 1 | #ifndef THERMISTORTABLES_H_ 2 | #define THERMISTORTABLES_H_ 3 | 4 | #if (THERMISTORHEATER == 1) || (THERMISTORBED == 1) //100k bed thermistor 5 | 6 | 7 | #define NUMTEMPS_1 61 8 | const short temptable_1[NUMTEMPS_1][2] = { 9 | { 23 , 300 }, 10 | { 25 , 295 }, 11 | { 27 , 290 }, 12 | { 28 , 285 }, 13 | { 31 , 280 }, 14 | { 33 , 275 }, 15 | { 35 , 270 }, 16 | { 38 , 265 }, 17 | { 41 , 260 }, 18 | { 44 , 255 }, 19 | { 48 , 250 }, 20 | { 52 , 245 }, 21 | { 56 , 240 }, 22 | { 61 , 235 }, 23 | { 66 , 230 }, 24 | { 71 , 225 }, 25 | { 78 , 220 }, 26 | { 84 , 215 }, 27 | { 92 , 210 }, 28 | { 100 , 205 }, 29 | { 109 , 200 }, 30 | { 120 , 195 }, 31 | { 131 , 190 }, 32 | { 143 , 185 }, 33 | { 156 , 180 }, 34 | { 171 , 175 }, 35 | { 187 , 170 }, 36 | { 205 , 165 }, 37 | { 224 , 160 }, 38 | { 245 , 155 }, 39 | { 268 , 150 }, 40 | { 293 , 145 }, 41 | { 320 , 140 }, 42 | { 348 , 135 }, 43 | { 379 , 130 }, 44 | { 411 , 125 }, 45 | { 445 , 120 }, 46 | { 480 , 115 }, 47 | { 516 , 110 }, 48 | { 553 , 105 }, 49 | { 591 , 100 }, 50 | { 628 , 95 }, 51 | { 665 , 90 }, 52 | { 702 , 85 }, 53 | { 737 , 80 }, 54 | { 770 , 75 }, 55 | { 801 , 70 }, 56 | { 830 , 65 }, 57 | { 857 , 60 }, 58 | { 881 , 55 }, 59 | { 903 , 50 }, 60 | { 922 , 45 }, 61 | { 939 , 40 }, 62 | { 954 , 35 }, 63 | { 966 , 30 }, 64 | { 977 , 25 }, 65 | { 985 , 20 }, 66 | { 993 , 15 }, 67 | { 999 , 10 }, 68 | { 1004 , 5 }, 69 | { 1008 , 0 } //safety 70 | }; 71 | #endif 72 | #if (THERMISTORHEATER == 2) || (THERMISTORBED == 2) //200k bed thermistor 73 | #define NUMTEMPS_2 21 74 | const short temptable_2[NUMTEMPS_2][2] = { 75 | {1, 848}, 76 | {54, 275}, 77 | {107, 228}, 78 | {160, 202}, 79 | {213, 185}, 80 | {266, 171}, 81 | {319, 160}, 82 | {372, 150}, 83 | {425, 141}, 84 | {478, 133}, 85 | {531, 125}, 86 | {584, 118}, 87 | {637, 110}, 88 | {690, 103}, 89 | {743, 95}, 90 | {796, 86}, 91 | {849, 77}, 92 | {902, 65}, 93 | {955, 49}, 94 | {1008, 17}, 95 | {1020, 0} //safety 96 | }; 97 | 98 | #endif 99 | #if (THERMISTORHEATER == 3) || (THERMISTORBED == 3) //mendel-parts 100 | #define NUMTEMPS_3 28 101 | const short temptable_3[NUMTEMPS_3][2] = { 102 | {1,864}, 103 | {21,300}, 104 | {25,290}, 105 | {29,280}, 106 | {33,270}, 107 | {39,260}, 108 | {46,250}, 109 | {54,240}, 110 | {64,230}, 111 | {75,220}, 112 | {90,210}, 113 | {107,200}, 114 | {128,190}, 115 | {154,180}, 116 | {184,170}, 117 | {221,160}, 118 | {265,150}, 119 | {316,140}, 120 | {375,130}, 121 | {441,120}, 122 | {513,110}, 123 | {588,100}, 124 | {734,80}, 125 | {856,60}, 126 | {938,40}, 127 | {986,20}, 128 | {1008,0}, 129 | {1018,-20} 130 | }; 131 | 132 | #endif 133 | #if (THERMISTORHEATER == 4) || (THERMISTORBED == 4) //10k thermistor 134 | 135 | #define NUMTEMPS_4 20 136 | short temptable_4[NUMTEMPS_4][2] = { 137 | {1, 430}, 138 | {54, 137}, 139 | {107, 107}, 140 | {160, 91}, 141 | {213, 80}, 142 | {266, 71}, 143 | {319, 64}, 144 | {372, 57}, 145 | {425, 51}, 146 | {478, 46}, 147 | {531, 41}, 148 | {584, 35}, 149 | {637, 30}, 150 | {690, 25}, 151 | {743, 20}, 152 | {796, 14}, 153 | {849, 7}, 154 | {902, 0}, 155 | {955, -11}, 156 | {1008, -35} 157 | }; 158 | #endif 159 | 160 | #if (THERMISTORHEATER == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) 161 | 162 | #define NUMTEMPS_5 61 163 | const short temptable_5[NUMTEMPS_5][2] = { 164 | {1, 713}, 165 | {18, 316}, 166 | {35, 266}, 167 | {52, 239}, 168 | {69, 221}, 169 | {86, 208}, 170 | {103, 197}, 171 | {120, 188}, 172 | {137, 181}, 173 | {154, 174}, 174 | {171, 169}, 175 | {188, 163}, 176 | {205, 159}, 177 | {222, 154}, 178 | {239, 150}, 179 | {256, 147}, 180 | {273, 143}, 181 | {290, 140}, 182 | {307, 136}, 183 | {324, 133}, 184 | {341, 130}, 185 | {358, 128}, 186 | {375, 125}, 187 | {392, 122}, 188 | {409, 120}, 189 | {426, 117}, 190 | {443, 115}, 191 | {460, 112}, 192 | {477, 110}, 193 | {494, 108}, 194 | {511, 106}, 195 | {528, 103}, 196 | {545, 101}, 197 | {562, 99}, 198 | {579, 97}, 199 | {596, 95}, 200 | {613, 92}, 201 | {630, 90}, 202 | {647, 88}, 203 | {664, 86}, 204 | {681, 84}, 205 | {698, 81}, 206 | {715, 79}, 207 | {732, 77}, 208 | {749, 75}, 209 | {766, 72}, 210 | {783, 70}, 211 | {800, 67}, 212 | {817, 64}, 213 | {834, 61}, 214 | {851, 58}, 215 | {868, 55}, 216 | {885, 52}, 217 | {902, 48}, 218 | {919, 44}, 219 | {936, 40}, 220 | {953, 34}, 221 | {970, 28}, 222 | {987, 20}, 223 | {1004, 8}, 224 | {1021, 0} 225 | }; 226 | #endif 227 | 228 | #if (THERMISTORHEATER == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor 229 | #define NUMTEMPS_6 36 230 | const short temptable_6[NUMTEMPS_6][2] = { 231 | {28, 250}, 232 | {31, 245}, 233 | {35, 240}, 234 | {39, 235}, 235 | {42, 230}, 236 | {44, 225}, 237 | {49, 220}, 238 | {53, 215}, 239 | {62, 210}, 240 | {73, 205}, 241 | {72, 200}, 242 | {94, 190}, 243 | {102, 185}, 244 | {116, 170}, 245 | {143, 160}, 246 | {183, 150}, 247 | {223, 140}, 248 | {270, 130}, 249 | {318, 120}, 250 | {383, 110}, 251 | {413, 105}, 252 | {439, 100}, 253 | {484, 95}, 254 | {513, 90}, 255 | {607, 80}, 256 | {664, 70}, 257 | {781, 60}, 258 | {810, 55}, 259 | {849, 50}, 260 | {914, 45}, 261 | {914, 40}, 262 | {935, 35}, 263 | {954, 30}, 264 | {970, 25}, 265 | {978, 22}, 266 | {1008, 3} 267 | }; 268 | #endif 269 | 270 | #if THERMISTORHEATER == 1 271 | #define NUMTEMPS NUMTEMPS_1 272 | #define temptable temptable_1 273 | #elif THERMISTORHEATER == 2 274 | #define NUMTEMPS NUMTEMPS_2 275 | #define temptable temptable_2 276 | #elif THERMISTORHEATER == 3 277 | #define NUMTEMPS NUMTEMPS_3 278 | #define temptable temptable_3 279 | #elif THERMISTORHEATER == 4 280 | #define NUMTEMPS NUMTEMPS_4 281 | #define temptable temptable_4 282 | #elif THERMISTORHEATER == 5 283 | #define NUMTEMPS NUMTEMPS_5 284 | #define temptable temptable_5 285 | #elif THERMISTORHEATER == 6 286 | #define NUMTEMPS NUMTEMPS_6 287 | #define temptable temptable_6 288 | #elif defined HEATER_USES_THERMISTOR 289 | #error No heater thermistor table specified 290 | #endif 291 | #if THERMISTORBED == 1 292 | #define BNUMTEMPS NUMTEMPS_1 293 | #define bedtemptable temptable_1 294 | #elif THERMISTORBED == 2 295 | #define BNUMTEMPS NUMTEMPS_2 296 | #define bedtemptable temptable_2 297 | #elif THERMISTORBED == 3 298 | #define BNUMTEMPS NUMTEMPS_3 299 | #define bedtemptable temptable_3 300 | #elif THERMISTORBED == 4 301 | #define BNUMTEMPS NUMTEMPS_4 302 | #define bedtemptable temptable_4 303 | #elif THERMISTORBED == 5 304 | #define BNUMTEMPS NUMTEMPS_5 305 | #define bedtemptable temptable_5 306 | #elif THERMISTORBED == 6 307 | #define BNUMTEMPS NUMTEMPS_6 308 | #define bedtemptable temptable_6 309 | #elif defined BED_USES_THERMISTOR 310 | #error No bed thermistor table specified 311 | #endif 312 | 313 | #endif //THERMISTORTABLES_H_ 314 | -------------------------------------------------------------------------------- /Sprinter/SdInfo.h: -------------------------------------------------------------------------------- 1 | /* Arduino Sd2Card Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino Sd2Card Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino Sd2Card Library. If not, see 18 | * . 19 | */ 20 | #ifndef SdInfo_h 21 | #define SdInfo_h 22 | #include 23 | // Based on the document: 24 | // 25 | // SD Specifications 26 | // Part 1 27 | // Physical Layer 28 | // Simplified Specification 29 | // Version 2.00 30 | // September 25, 2006 31 | // 32 | // www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf 33 | //------------------------------------------------------------------------------ 34 | // SD card commands 35 | /** GO_IDLE_STATE - init card in spi mode if CS low */ 36 | uint8_t const CMD0 = 0X00; 37 | /** SEND_IF_COND - verify SD Memory Card interface operating condition.*/ 38 | uint8_t const CMD8 = 0X08; 39 | /** SEND_CSD - read the Card Specific Data (CSD register) */ 40 | uint8_t const CMD9 = 0X09; 41 | /** SEND_CID - read the card identification information (CID register) */ 42 | uint8_t const CMD10 = 0X0A; 43 | /** SEND_STATUS - read the card status register */ 44 | uint8_t const CMD13 = 0X0D; 45 | /** READ_BLOCK - read a single data block from the card */ 46 | uint8_t const CMD17 = 0X11; 47 | /** WRITE_BLOCK - write a single data block to the card */ 48 | uint8_t const CMD24 = 0X18; 49 | /** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ 50 | uint8_t const CMD25 = 0X19; 51 | /** ERASE_WR_BLK_START - sets the address of the first block to be erased */ 52 | uint8_t const CMD32 = 0X20; 53 | /** ERASE_WR_BLK_END - sets the address of the last block of the continuous 54 | range to be erased*/ 55 | uint8_t const CMD33 = 0X21; 56 | /** ERASE - erase all previously selected blocks */ 57 | uint8_t const CMD38 = 0X26; 58 | /** APP_CMD - escape for application specific command */ 59 | uint8_t const CMD55 = 0X37; 60 | /** READ_OCR - read the OCR register of a card */ 61 | uint8_t const CMD58 = 0X3A; 62 | /** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be 63 | pre-erased before writing */ 64 | uint8_t const ACMD23 = 0X17; 65 | /** SD_SEND_OP_COMD - Sends host capacity support information and 66 | activates the card's initialization process */ 67 | uint8_t const ACMD41 = 0X29; 68 | //------------------------------------------------------------------------------ 69 | /** status for card in the ready state */ 70 | uint8_t const R1_READY_STATE = 0X00; 71 | /** status for card in the idle state */ 72 | uint8_t const R1_IDLE_STATE = 0X01; 73 | /** status bit for illegal command */ 74 | uint8_t const R1_ILLEGAL_COMMAND = 0X04; 75 | /** start data token for read or write single block*/ 76 | uint8_t const DATA_START_BLOCK = 0XFE; 77 | /** stop token for write multiple blocks*/ 78 | uint8_t const STOP_TRAN_TOKEN = 0XFD; 79 | /** start data token for write multiple blocks*/ 80 | uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC; 81 | /** mask for data response tokens after a write block operation */ 82 | uint8_t const DATA_RES_MASK = 0X1F; 83 | /** write data accepted token */ 84 | uint8_t const DATA_RES_ACCEPTED = 0X05; 85 | //------------------------------------------------------------------------------ 86 | typedef struct CID { 87 | // byte 0 88 | uint8_t mid; // Manufacturer ID 89 | // byte 1-2 90 | char oid[2]; // OEM/Application ID 91 | // byte 3-7 92 | char pnm[5]; // Product name 93 | // byte 8 94 | unsigned prv_m : 4; // Product revision n.m 95 | unsigned prv_n : 4; 96 | // byte 9-12 97 | uint32_t psn; // Product serial number 98 | // byte 13 99 | unsigned mdt_year_high : 4; // Manufacturing date 100 | unsigned reserved : 4; 101 | // byte 14 102 | unsigned mdt_month : 4; 103 | unsigned mdt_year_low :4; 104 | // byte 15 105 | unsigned always1 : 1; 106 | unsigned crc : 7; 107 | }cid_t; 108 | //------------------------------------------------------------------------------ 109 | // CSD for version 1.00 cards 110 | typedef struct CSDV1 { 111 | // byte 0 112 | unsigned reserved1 : 6; 113 | unsigned csd_ver : 2; 114 | // byte 1 115 | uint8_t taac; 116 | // byte 2 117 | uint8_t nsac; 118 | // byte 3 119 | uint8_t tran_speed; 120 | // byte 4 121 | uint8_t ccc_high; 122 | // byte 5 123 | unsigned read_bl_len : 4; 124 | unsigned ccc_low : 4; 125 | // byte 6 126 | unsigned c_size_high : 2; 127 | unsigned reserved2 : 2; 128 | unsigned dsr_imp : 1; 129 | unsigned read_blk_misalign :1; 130 | unsigned write_blk_misalign : 1; 131 | unsigned read_bl_partial : 1; 132 | // byte 7 133 | uint8_t c_size_mid; 134 | // byte 8 135 | unsigned vdd_r_curr_max : 3; 136 | unsigned vdd_r_curr_min : 3; 137 | unsigned c_size_low :2; 138 | // byte 9 139 | unsigned c_size_mult_high : 2; 140 | unsigned vdd_w_cur_max : 3; 141 | unsigned vdd_w_curr_min : 3; 142 | // byte 10 143 | unsigned sector_size_high : 6; 144 | unsigned erase_blk_en : 1; 145 | unsigned c_size_mult_low : 1; 146 | // byte 11 147 | unsigned wp_grp_size : 7; 148 | unsigned sector_size_low : 1; 149 | // byte 12 150 | unsigned write_bl_len_high : 2; 151 | unsigned r2w_factor : 3; 152 | unsigned reserved3 : 2; 153 | unsigned wp_grp_enable : 1; 154 | // byte 13 155 | unsigned reserved4 : 5; 156 | unsigned write_partial : 1; 157 | unsigned write_bl_len_low : 2; 158 | // byte 14 159 | unsigned reserved5: 2; 160 | unsigned file_format : 2; 161 | unsigned tmp_write_protect : 1; 162 | unsigned perm_write_protect : 1; 163 | unsigned copy : 1; 164 | unsigned file_format_grp : 1; 165 | // byte 15 166 | unsigned always1 : 1; 167 | unsigned crc : 7; 168 | }csd1_t; 169 | //------------------------------------------------------------------------------ 170 | // CSD for version 2.00 cards 171 | typedef struct CSDV2 { 172 | // byte 0 173 | unsigned reserved1 : 6; 174 | unsigned csd_ver : 2; 175 | // byte 1 176 | uint8_t taac; 177 | // byte 2 178 | uint8_t nsac; 179 | // byte 3 180 | uint8_t tran_speed; 181 | // byte 4 182 | uint8_t ccc_high; 183 | // byte 5 184 | unsigned read_bl_len : 4; 185 | unsigned ccc_low : 4; 186 | // byte 6 187 | unsigned reserved2 : 4; 188 | unsigned dsr_imp : 1; 189 | unsigned read_blk_misalign :1; 190 | unsigned write_blk_misalign : 1; 191 | unsigned read_bl_partial : 1; 192 | // byte 7 193 | unsigned reserved3 : 2; 194 | unsigned c_size_high : 6; 195 | // byte 8 196 | uint8_t c_size_mid; 197 | // byte 9 198 | uint8_t c_size_low; 199 | // byte 10 200 | unsigned sector_size_high : 6; 201 | unsigned erase_blk_en : 1; 202 | unsigned reserved4 : 1; 203 | // byte 11 204 | unsigned wp_grp_size : 7; 205 | unsigned sector_size_low : 1; 206 | // byte 12 207 | unsigned write_bl_len_high : 2; 208 | unsigned r2w_factor : 3; 209 | unsigned reserved5 : 2; 210 | unsigned wp_grp_enable : 1; 211 | // byte 13 212 | unsigned reserved6 : 5; 213 | unsigned write_partial : 1; 214 | unsigned write_bl_len_low : 2; 215 | // byte 14 216 | unsigned reserved7: 2; 217 | unsigned file_format : 2; 218 | unsigned tmp_write_protect : 1; 219 | unsigned perm_write_protect : 1; 220 | unsigned copy : 1; 221 | unsigned file_format_grp : 1; 222 | // byte 15 223 | unsigned always1 : 1; 224 | unsigned crc : 7; 225 | }csd2_t; 226 | //------------------------------------------------------------------------------ 227 | // union of old and new style CSD register 228 | union csd_t { 229 | csd1_t v1; 230 | csd2_t v2; 231 | }; 232 | #endif // SdInfo_h 233 | -------------------------------------------------------------------------------- /Sprinter/Configuration.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIGURATION_H 2 | #define CONFIGURATION_H 3 | 4 | // BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration 5 | 6 | //// The following define selects which electronics board you have. Please choose the one that matches your setup 7 | // MEGA/RAMPS up to 1.2 = 3, 8 | // RAMPS 1.3 = 33 9 | // Gen6 = 5, 10 | // Sanguinololu up to 1.1 = 6 11 | // Sanguinololu 1.2 and above = 62 12 | // Gen 3 Plus = 21 13 | // gen 3 Monolithic Electronics = 22 14 | #define MOTHERBOARD 3 15 | 16 | //// Thermistor settings: 17 | // 1 is 100k thermistor 18 | // 2 is 200k thermistor 19 | // 3 is mendel-parts thermistor 20 | // 4 is 10k thermistor 21 | // 5 is ParCan supplied 104GT-2 100K 22 | // 6 is EPCOS 100k 23 | #define THERMISTORHEATER 1 24 | #define THERMISTORBED 1 25 | 26 | //// Calibration variables 27 | // X, Y, Z, E steps per unit - Metric Prusa Mendel with Wade extruder: 28 | float axis_steps_per_unit[] = {80, 80, 3200/1.25,700}; 29 | // Metric Prusa Mendel with Makergear geared stepper extruder: 30 | //float axis_steps_per_unit[] = {80,80,3200/1.25,1380}; 31 | // MakerGear Hybrid Prusa Mendel: 32 | // Z axis value is for .9 stepper(if you have 1.8 steppers for Z, you need to use 2272.7272) 33 | //float axis_steps_per_unit[] = {104.987, 104.987, 4545.4544, 1487}; 34 | 35 | //// Endstop Settings 36 | #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors 37 | // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. 38 | const bool ENDSTOPS_INVERTING = false; //set to true to invert the logic of the endstops 39 | //If your axes are only moving in one direction, make sure the endstops are connected properly. 40 | //If your axes move in one direction ONLY when the endstops are triggered, set ENDSTOPS_INVERTING to true here 41 | 42 | // This determines the communication speed of the printer 43 | #define BAUDRATE 115200 44 | 45 | // Comment out (using // at the start of the line) to disable SD support: 46 | #define SDSUPPORT 47 | 48 | 49 | //// ADVANCED SETTINGS - to tweak parameters 50 | 51 | #include "thermistortables.h" 52 | 53 | // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 54 | #define X_ENABLE_ON 0 55 | #define Y_ENABLE_ON 0 56 | #define Z_ENABLE_ON 0 57 | #define E_ENABLE_ON 0 58 | 59 | // Disables axis when it's not being used. 60 | const bool DISABLE_X = false; 61 | const bool DISABLE_Y = false; 62 | const bool DISABLE_Z = true; 63 | const bool DISABLE_E = false; 64 | 65 | // Inverting axis direction 66 | const bool INVERT_X_DIR = false; 67 | const bool INVERT_Y_DIR = false; 68 | const bool INVERT_Z_DIR = true; 69 | const bool INVERT_E_DIR = false; 70 | 71 | //// ENDSTOP SETTINGS: 72 | // Sets direction of endstops when homing; 1=MAX, -1=MIN 73 | #define X_HOME_DIR -1 74 | #define Y_HOME_DIR -1 75 | #define Z_HOME_DIR -1 76 | 77 | const bool min_software_endstops = false; //If true, axis won't move to coordinates less than zero. 78 | const bool max_software_endstops = true; //If true, axis won't move to coordinates greater than the defined lengths below. 79 | const int X_MAX_LENGTH = 200; 80 | const int Y_MAX_LENGTH = 200; 81 | const int Z_MAX_LENGTH = 100; 82 | 83 | //// MOVEMENT SETTINGS 84 | const int NUM_AXIS = 4; // The axis order in all axis related arrays is X, Y, Z, E 85 | float max_feedrate[] = {200000, 200000, 240, 500000}; 86 | float homing_feedrate[] = {1500,1500,120}; 87 | bool axis_relative_modes[] = {false, false, false, false}; 88 | 89 | // Min step delay in microseconds. If you are experiencing missing steps, try to raise the delay microseconds, but be aware this 90 | // If you enable this, make sure STEP_DELAY_RATIO is disabled. 91 | //#define STEP_DELAY_MICROS 1 92 | 93 | // Step delay over interval ratio. If you are still experiencing missing steps, try to uncomment the following line, but be aware this 94 | // If you enable this, make sure STEP_DELAY_MICROS is disabled. (except for Gen6: both need to be enabled.) 95 | //#define STEP_DELAY_RATIO 0.25 96 | 97 | // Comment this to disable ramp acceleration 98 | #define RAMP_ACCELERATION 99 | 100 | //// Acceleration settings 101 | #ifdef RAMP_ACCELERATION 102 | // 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. 103 | float max_start_speed_units_per_second[] = {25.0,25.0,0.2,10.0}; 104 | long max_acceleration_units_per_sq_second[] = {1000,1000,50,10000}; // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts 105 | long max_travel_acceleration_units_per_sq_second[] = {500,500,50,500}; // X, Y, Z max acceleration in mm/s^2 for travel moves 106 | #endif 107 | 108 | // Machine UUID 109 | // This may be useful if you have multiple machines and wish to identify them by using the M115 command. 110 | // By default we set it to zeros. 111 | char uuid[] = "00000000-0000-0000-0000-000000000000"; 112 | 113 | 114 | //// AD595 THERMOCOUPLE SUPPORT UNTESTED... USE WITH CAUTION!!!! 115 | 116 | //// PID settings: 117 | // Uncomment the following line to enable PID support. This is untested and could be disastrous. Be careful. 118 | //#define PIDTEMP 119 | #ifdef PIDTEMP 120 | #define PID_MAX 255 // limits current to nozzle 121 | #define PID_INTEGRAL_DRIVE_MAX 220 122 | #define PID_PGAIN 180 //100 is 1.0 123 | #define PID_IGAIN 2 //100 is 1.0 124 | #define PID_DGAIN 100 //100 is 1.0 125 | #endif 126 | 127 | // How often should the heater check for new temp readings, in milliseconds 128 | #define HEATER_CHECK_INTERVAL 500 129 | #define BED_CHECK_INTERVAL 5000 130 | // Comment the following line to enable heat management during acceleration 131 | #define DISABLE_CHECK_DURING_ACC 132 | #ifndef DISABLE_CHECK_DURING_ACC 133 | // Uncomment the following line to disable heat management during moves 134 | //#define DISABLE_CHECK_DURING_MOVE 135 | #endif 136 | // 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. 137 | // Probably this should remain commented if are using PID. 138 | // It also defines the max milliseconds interval after which a travel move is not considered so for the sake of this feature. 139 | #define DISABLE_CHECK_DURING_TRAVEL 1000 140 | 141 | //// Temperature smoothing - only uncomment this if your temp readings are noisy (Gen6 without EvdZ's 5V hack) 142 | //#define SMOOTHING 143 | //#define SMOOTHFACTOR 16 //best to use a power of two here - determines how many values are averaged together by the smoothing algorithm 144 | 145 | //// Experimental watchdog and minimal temp 146 | // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature 147 | // 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 148 | //#define WATCHPERIOD 5000 //5 seconds 149 | 150 | //// The minimal temperature defines the temperature below which the heater will not be enabled 151 | #define MINTEMP 5 152 | 153 | //// Experimental max temp 154 | // When temperature exceeds max temp, your heater will be switched off. 155 | // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! 156 | // You should use MINTEMP for thermistor short/failure protection. 157 | #define MAXTEMP 275 158 | 159 | // Select one of these only to define how the nozzle temp is read. 160 | #define HEATER_USES_THERMISTOR 161 | //#define HEATER_USES_AD595 162 | //#define HEATER_USES_MAX6675 163 | 164 | // Select one of these only to define how the bed temp is read. 165 | #define BED_USES_THERMISTOR 166 | //#define BED_USES_AD595 167 | 168 | // Uncomment the following line to enable debugging. You can better control debugging below the following line 169 | //#define DEBUG 170 | #ifdef DEBUG 171 | //#define DEBUG_PREPARE_MOVE //Enable this to debug prepare_move() function 172 | //#define DEBUG_BRESENHAM //Enable this to debug the Bresenham algorithm 173 | //#define DEBUG_RAMP_ACCELERATION //Enable this to debug all constant acceleration info 174 | //#define DEBUG_MOVE_TIME //Enable this to time each move and print the result 175 | //#define DEBUG_HEAT_MGMT //Enable this to debug heat management. WARNING, this will cause axes to jitter! 176 | //#define DEBUG_DISABLE_CHECK_DURING_TRAVEL //Debug the namesake feature, see above in this file 177 | #endif 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /Sprinter/Makefile: -------------------------------------------------------------------------------- 1 | # Sprinter Arduino Project Makefile 2 | # 3 | # Makefile Based on: 4 | # Arduino 0011 Makefile 5 | # Arduino adaptation by mellis, eighthave, oli.keller 6 | # 7 | # This has been tested with Arduino 0022. 8 | # 9 | # This makefile allows you to build sketches from the command line 10 | # without the Arduino environment (or Java). 11 | # 12 | # Detailed instructions for using the makefile: 13 | # 14 | # 1. Modify the line containg "INSTALL_DIR" to point to the directory that 15 | # contains the Arduino installation (for example, under Mac OS X, this 16 | # might be /Applications/arduino-0012). 17 | # 18 | # 2. Modify the line containing "PORT" to refer to the filename 19 | # representing the USB or serial connection to your Arduino board 20 | # (e.g. PORT = /dev/tty.USB0). If the exact name of this file 21 | # changes, you can use * as a wildcard (e.g. PORT = /dev/tty.usb*). 22 | # 23 | # 3. Set the line containing "MCU" to match your board's processor. 24 | # Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth 25 | # or Diecimila have the atmega168. If you're using a LilyPad Arduino, 26 | # change F_CPU to 8000000. 27 | # 28 | # 4. Type "make" and press enter to compile/verify your program. 29 | # 30 | # 5. Type "make upload", reset your Arduino board, and press enter to 31 | # upload your program to the Arduino board. 32 | # 33 | # $Id$ 34 | 35 | TARGET = $(notdir $(CURDIR)) 36 | INSTALL_DIR = ../../arduino22/arduino-0022/ 37 | UPLOAD_RATE = 38400 38 | AVRDUDE_PROGRAMMER = stk500v1 39 | PORT = /dev/ttyUSB0 40 | MCU = atmega2560 41 | #For "old" Arduino Mega 42 | #MCU = atmega1280 43 | #For Sanguinololu 44 | #MCU = atmega644p 45 | F_CPU = 16000000 46 | 47 | 48 | ############################################################################ 49 | # Below here nothing should be changed... 50 | 51 | ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino 52 | AVR_TOOLS_PATH = /usr/bin 53 | SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ 54 | $(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ 55 | $(ARDUINO)/wiring_pulse.c \ 56 | $(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c 57 | CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp $(ARDUINO)/WString.cpp\ 58 | $(ARDUINO)/Print.cpp ./SdFile.cpp ./SdVolume.cpp ./Sd2Card.cpp 59 | FORMAT = ihex 60 | 61 | 62 | # Name of this Makefile (used for "make depend"). 63 | MAKEFILE = Makefile 64 | 65 | # Debugging format. 66 | # Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. 67 | # AVR (extended) COFF requires stabs, plus an avr-objcopy run. 68 | DEBUG = stabs 69 | 70 | OPT = s 71 | 72 | # Place -D or -U options here 73 | CDEFS = -DF_CPU=$(F_CPU) 74 | CXXDEFS = -DF_CPU=$(F_CPU) 75 | 76 | # Place -I options here 77 | CINCS = -I$(ARDUINO) 78 | CXXINCS = -I$(ARDUINO) 79 | 80 | # Compiler flag to set the C Standard level. 81 | # c89 - "ANSI" C 82 | # gnu89 - c89 plus GCC extensions 83 | # c99 - ISO C99 standard (not yet fully implemented) 84 | # gnu99 - c99 plus GCC extensions 85 | #CSTANDARD = -std=gnu99 86 | CDEBUG = -g$(DEBUG) 87 | CWARN = -Wall -Wstrict-prototypes 88 | CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -w -ffunction-sections -fdata-sections -DARDUINO=22 89 | #CEXTRA = -Wa,-adhlns=$(<:.c=.lst) 90 | 91 | CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) 92 | CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) 93 | #ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs 94 | LDFLAGS = -lm 95 | 96 | 97 | # Programming support using avrdude. Settings and variables. 98 | AVRDUDE_PORT = $(PORT) 99 | AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex:i 100 | AVRDUDE_FLAGS = -D -C $(INSTALL_DIR)/hardware/tools/avrdude.conf \ 101 | -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \ 102 | -b $(UPLOAD_RATE) 103 | 104 | # Program settings 105 | CC = $(AVR_TOOLS_PATH)/avr-gcc 106 | CXX = $(AVR_TOOLS_PATH)/avr-g++ 107 | OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy 108 | OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump 109 | AR = $(AVR_TOOLS_PATH)/avr-ar 110 | SIZE = $(AVR_TOOLS_PATH)/avr-size 111 | NM = $(AVR_TOOLS_PATH)/avr-nm 112 | AVRDUDE = $(INSTALL_DIR)/hardware/tools/avrdude 113 | REMOVE = rm -f 114 | MV = mv -f 115 | 116 | # Define all object files. 117 | OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) 118 | 119 | # Define all listing files. 120 | LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst) 121 | 122 | # Combine all necessary flags and optional flags. 123 | # Add target processor to flags. 124 | ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) 125 | ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS) 126 | ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) 127 | 128 | 129 | # Default target. 130 | all: applet_files build sizeafter 131 | 132 | build: elf hex 133 | 134 | applet_files: $(TARGET).pde 135 | # Here is the "preprocessing". 136 | # It creates a .cpp file based with the same name as the .pde file. 137 | # On top of the new .cpp file comes the WProgram.h header. 138 | # At the end there is a generic main() function attached. 139 | # Then the .cpp file will be compiled. Errors during compile will 140 | # refer to this new, automatically generated, file. 141 | # Not the original .pde file you actually edit... 142 | test -d applet || mkdir applet 143 | echo '#include "WProgram.h"' > applet/$(TARGET).cpp 144 | cat $(TARGET).pde >> applet/$(TARGET).cpp 145 | cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp 146 | 147 | elf: applet/$(TARGET).elf 148 | hex: applet/$(TARGET).hex 149 | eep: applet/$(TARGET).eep 150 | lss: applet/$(TARGET).lss 151 | sym: applet/$(TARGET).sym 152 | 153 | # Program the device. 154 | upload: applet/$(TARGET).hex 155 | $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) 156 | 157 | 158 | # Display size of file. 159 | HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex 160 | ELFSIZE = $(SIZE) applet/$(TARGET).elf 161 | sizebefore: 162 | @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi 163 | 164 | sizeafter: 165 | @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi 166 | 167 | 168 | # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. 169 | COFFCONVERT=$(OBJCOPY) --debugging \ 170 | --change-section-address .data-0x800000 \ 171 | --change-section-address .bss-0x800000 \ 172 | --change-section-address .noinit-0x800000 \ 173 | --change-section-address .eeprom-0x810000 174 | 175 | 176 | coff: applet/$(TARGET).elf 177 | $(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof 178 | 179 | 180 | extcoff: $(TARGET).elf 181 | $(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof 182 | 183 | 184 | .SUFFIXES: .elf .hex .eep .lss .sym 185 | 186 | .elf.hex: 187 | $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ 188 | 189 | .elf.eep: 190 | -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ 191 | --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ 192 | 193 | # Create extended listing file from ELF output file. 194 | .elf.lss: 195 | $(OBJDUMP) -h -S $< > $@ 196 | 197 | # Create a symbol table from ELF output file. 198 | .elf.sym: 199 | $(NM) -n $< > $@ 200 | 201 | # Link: create ELF output file from library. 202 | applet/$(TARGET).elf: $(TARGET).pde applet/core.a 203 | $(CC) $(ALL_CFLAGS) -Wl,--gc-sections -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) 204 | 205 | applet/core.a: $(OBJ) 206 | @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done 207 | 208 | 209 | 210 | # Compile: create object files from C++ source files. 211 | .cpp.o: 212 | $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ 213 | 214 | # Compile: create object files from C source files. 215 | .c.o: 216 | $(CC) -c $(ALL_CFLAGS) $< -o $@ 217 | 218 | 219 | # Compile: create assembler files from C source files. 220 | .c.s: 221 | $(CC) -S $(ALL_CFLAGS) $< -o $@ 222 | 223 | 224 | # Assemble: create object files from assembler source files. 225 | .S.o: 226 | $(CC) -c $(ALL_ASFLAGS) $< -o $@ 227 | 228 | 229 | 230 | # Target: clean project. 231 | clean: 232 | $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ 233 | applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ 234 | $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) 235 | 236 | depend: 237 | if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \ 238 | then \ 239 | sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \ 240 | $(MAKEFILE).$$$$ && \ 241 | $(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \ 242 | fi 243 | echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \ 244 | >> $(MAKEFILE); \ 245 | $(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE) 246 | 247 | .PHONY: all build elf hex eep lss sym program coff extcoff clean depend applet_files sizebefore sizeafter 248 | -------------------------------------------------------------------------------- /Sprinter/SdFatmainpage.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | 21 | /** 22 | \mainpage Arduino SdFat Library 23 |
Copyright © 2009 by William Greiman 24 |
25 | 26 | \section Intro Introduction 27 | The Arduino SdFat Library is a minimal implementation of FAT16 and FAT32 28 | file systems on SD flash memory cards. Standard SD and high capacity 29 | SDHC cards are supported. 30 | 31 | The SdFat only supports short 8.3 names. 32 | 33 | The main classes in SdFat are Sd2Card, SdVolume, and SdFile. 34 | 35 | The Sd2Card class supports access to standard SD cards and SDHC cards. Most 36 | applications will only need to call the Sd2Card::init() member function. 37 | 38 | The SdVolume class supports FAT16 and FAT32 partitions. Most applications 39 | will only need to call the SdVolume::init() member function. 40 | 41 | The SdFile class provides file access functions such as open(), read(), 42 | remove(), write(), close() and sync(). This class supports access to the root 43 | directory and subdirectories. 44 | 45 | A number of example are provided in the SdFat/examples folder. These were 46 | developed to test SdFat and illustrate its use. 47 | 48 | SdFat was developed for high speed data recording. SdFat was used to implement 49 | an audio record/play class, WaveRP, for the Adafruit Wave Shield. This 50 | application uses special Sd2Card calls to write to contiguous files in raw mode. 51 | These functions reduce write latency so that audio can be recorded with the 52 | small amount of RAM in the Arduino. 53 | 54 | \section SDcard SD\SDHC Cards 55 | 56 | Arduinos access SD cards using the cards SPI protocol. PCs, Macs, and 57 | most consumer devices use the 4-bit parallel SD protocol. A card that 58 | functions well on A PC or Mac may not work well on the Arduino. 59 | 60 | Most cards have good SPI read performance but cards vary widely in SPI 61 | write performance. Write performance is limited by how efficiently the 62 | card manages internal erase/remapping operations. The Arduino cannot 63 | optimize writes to reduce erase operations because of its limit RAM. 64 | 65 | SanDisk cards generally have good write performance. They seem to have 66 | more internal RAM buffering than other cards and therefore can limit 67 | the number of flash erase operations that the Arduino forces due to its 68 | limited RAM. 69 | 70 | \section Hardware Hardware Configuration 71 | 72 | SdFat was developed using an 73 | Adafruit Industries 74 | Wave Shield. 75 | 76 | The hardware interface to the SD card should not use a resistor based level 77 | shifter. SdFat sets the SPI bus frequency to 8 MHz which results in signal 78 | rise times that are too slow for the edge detectors in many newer SD card 79 | controllers when resistor voltage dividers are used. 80 | 81 | The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the 82 | 74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield 83 | uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the 84 | 74LCX245. 85 | 86 | If you are using a resistor based level shifter and are having problems try 87 | setting the SPI bus frequency to 4 MHz. This can be done by using 88 | card.init(SPI_HALF_SPEED) to initialize the SD card. 89 | 90 | \section comment Bugs and Comments 91 | 92 | If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net. 93 | 94 | \section SdFatClass SdFat Usage 95 | 96 | SdFat uses a slightly restricted form of short names. 97 | Only printable ASCII characters are supported. No characters with code point 98 | values greater than 127 are allowed. Space is not allowed even though space 99 | was allowed in the API of early versions of DOS. 100 | 101 | Short names are limited to 8 characters followed by an optional period (.) 102 | and extension of up to 3 characters. The characters may be any combination 103 | of letters and digits. The following special characters are also allowed: 104 | 105 | $ % ' - _ @ ~ ` ! ( ) { } ^ # & 106 | 107 | Short names are always converted to upper case and their original case 108 | value is lost. 109 | 110 | \note 111 | The Arduino Print class uses character 112 | at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink 113 | function to control when data is written to the SD card. 114 | 115 | \par 116 | An application which writes to a file using \link Print::print() print()\endlink, 117 | \link Print::println() println() \endlink 118 | or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink 119 | at the appropriate time to force data and directory information to be written 120 | to the SD Card. Data and directory information are also written to the SD card 121 | when \link SdFile::close() close() \endlink is called. 122 | 123 | \par 124 | Applications must use care calling \link SdFile::sync() sync() \endlink 125 | since 2048 bytes of I/O is required to update file and 126 | directory information. This includes writing the current data block, reading 127 | the block that contains the directory entry for update, writing the directory 128 | block back and reading back the current data block. 129 | 130 | It is possible to open a file with two or more instances of SdFile. A file may 131 | be corrupted if data is written to the file by more than one instance of SdFile. 132 | 133 | \section HowTo How to format SD Cards as FAT Volumes 134 | 135 | You should use a freshly formatted SD card for best performance. FAT 136 | file systems become slower if many files have been created and deleted. 137 | This is because the directory entry for a deleted file is marked as deleted, 138 | but is not deleted. When a new file is created, these entries must be scanned 139 | before creating the file, a flaw in the FAT design. Also files can become 140 | fragmented which causes reads and writes to be slower. 141 | 142 | Microsoft operating systems support removable media formatted with a 143 | Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector 144 | in block zero. 145 | 146 | Microsoft operating systems expect MBR formatted removable media 147 | to have only one partition. The first partition should be used. 148 | 149 | Microsoft operating systems do not support partitioning SD flash cards. 150 | If you erase an SD card with a program like KillDisk, Most versions of 151 | Windows will format the card as a super floppy. 152 | 153 | The best way to restore an SD card's format is to use SDFormatter 154 | which can be downloaded from: 155 | 156 | http://www.sdcard.org/consumers/formatter/ 157 | 158 | SDFormatter aligns flash erase boundaries with file 159 | system structures which reduces write latency and file system overhead. 160 | 161 | SDFormatter does not have an option for FAT type so it may format 162 | small cards as FAT12. 163 | 164 | After the MBR is restored by SDFormatter you may need to reformat small 165 | cards that have been formatted FAT12 to force the volume type to be FAT16. 166 | 167 | If you reformat the SD card with an OS utility, choose a cluster size that 168 | will result in: 169 | 170 | 4084 < CountOfClusters && CountOfClusters < 65525 171 | 172 | The volume will then be FAT16. 173 | 174 | If you are formatting an SD card on OS X or Linux, be sure to use the first 175 | partition. Format this partition with a cluster count in above range. 176 | 177 | \section References References 178 | 179 | Adafruit Industries: 180 | 181 | http://www.adafruit.com/ 182 | 183 | http://www.ladyada.net/make/waveshield/ 184 | 185 | The Arduino site: 186 | 187 | http://www.arduino.cc/ 188 | 189 | For more information about FAT file systems see: 190 | 191 | http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx 192 | 193 | For information about using SD cards as SPI devices see: 194 | 195 | http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf 196 | 197 | The ATmega328 datasheet: 198 | 199 | http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf 200 | 201 | 202 | */ 203 | -------------------------------------------------------------------------------- /Sprinter/Sd2Card.h: -------------------------------------------------------------------------------- 1 | /* Arduino Sd2Card Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino Sd2Card Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino Sd2Card Library. If not, see 18 | * . 19 | */ 20 | #ifndef Sd2Card_h 21 | #define Sd2Card_h 22 | /** 23 | * \file 24 | * Sd2Card class 25 | */ 26 | #include "Sd2PinMap.h" 27 | #include "SdInfo.h" 28 | /** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */ 29 | uint8_t const SPI_FULL_SPEED = 0; 30 | /** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */ 31 | uint8_t const SPI_HALF_SPEED = 1; 32 | /** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */ 33 | uint8_t const SPI_QUARTER_SPEED = 2; 34 | /** 35 | * Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos. 36 | * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. 37 | * 38 | * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used 39 | * on Mega Arduinos. Software SPI works well with GPS Shield V1.1 40 | * but many SD cards will fail with GPS Shield V1.0. 41 | */ 42 | #define MEGA_SOFT_SPI 0 43 | //------------------------------------------------------------------------------ 44 | #if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) 45 | #define SOFTWARE_SPI 46 | #endif // MEGA_SOFT_SPI 47 | //------------------------------------------------------------------------------ 48 | // SPI pin definitions 49 | // 50 | #ifndef SOFTWARE_SPI 51 | // hardware pin defs 52 | /** 53 | * SD Chip Select pin 54 | * 55 | * Warning if this pin is redefined the hardware SS will pin will be enabled 56 | * as an output by init(). An avr processor will not function as an SPI 57 | * master unless SS is set to output mode. 58 | */ 59 | /** The default chip select pin for the SD card is SS. */ 60 | uint8_t const SD_CHIP_SELECT_PIN = SS_PIN; 61 | // The following three pins must not be redefined for hardware SPI. 62 | /** SPI Master Out Slave In pin */ 63 | uint8_t const SPI_MOSI_PIN = MOSI_PIN; 64 | /** SPI Master In Slave Out pin */ 65 | uint8_t const SPI_MISO_PIN = MISO_PIN; 66 | /** SPI Clock pin */ 67 | uint8_t const SPI_SCK_PIN = SCK_PIN; 68 | /** optimize loops for hardware SPI */ 69 | #define OPTIMIZE_HARDWARE_SPI 70 | 71 | #else // SOFTWARE_SPI 72 | // define software SPI pins so Mega can use unmodified GPS Shield 73 | /** SPI chip select pin */ 74 | uint8_t const SD_CHIP_SELECT_PIN = 10; 75 | /** SPI Master Out Slave In pin */ 76 | uint8_t const SPI_MOSI_PIN = 11; 77 | /** SPI Master In Slave Out pin */ 78 | uint8_t const SPI_MISO_PIN = 12; 79 | /** SPI Clock pin */ 80 | uint8_t const SPI_SCK_PIN = 13; 81 | #endif // SOFTWARE_SPI 82 | //------------------------------------------------------------------------------ 83 | /** Protect block zero from write if nonzero */ 84 | #define SD_PROTECT_BLOCK_ZERO 1 85 | /** init timeout ms */ 86 | uint16_t const SD_INIT_TIMEOUT = 2000; 87 | /** erase timeout ms */ 88 | uint16_t const SD_ERASE_TIMEOUT = 10000; 89 | /** read timeout ms */ 90 | uint16_t const SD_READ_TIMEOUT = 300; 91 | /** write time out ms */ 92 | uint16_t const SD_WRITE_TIMEOUT = 600; 93 | //------------------------------------------------------------------------------ 94 | // SD card errors 95 | /** timeout error for command CMD0 */ 96 | uint8_t const SD_CARD_ERROR_CMD0 = 0X1; 97 | /** CMD8 was not accepted - not a valid SD card*/ 98 | uint8_t const SD_CARD_ERROR_CMD8 = 0X2; 99 | /** card returned an error response for CMD17 (read block) */ 100 | uint8_t const SD_CARD_ERROR_CMD17 = 0X3; 101 | /** card returned an error response for CMD24 (write block) */ 102 | uint8_t const SD_CARD_ERROR_CMD24 = 0X4; 103 | /** WRITE_MULTIPLE_BLOCKS command failed */ 104 | uint8_t const SD_CARD_ERROR_CMD25 = 0X05; 105 | /** card returned an error response for CMD58 (read OCR) */ 106 | uint8_t const SD_CARD_ERROR_CMD58 = 0X06; 107 | /** SET_WR_BLK_ERASE_COUNT failed */ 108 | uint8_t const SD_CARD_ERROR_ACMD23 = 0X07; 109 | /** card's ACMD41 initialization process timeout */ 110 | uint8_t const SD_CARD_ERROR_ACMD41 = 0X08; 111 | /** card returned a bad CSR version field */ 112 | uint8_t const SD_CARD_ERROR_BAD_CSD = 0X09; 113 | /** erase block group command failed */ 114 | uint8_t const SD_CARD_ERROR_ERASE = 0X0A; 115 | /** card not capable of single block erase */ 116 | uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B; 117 | /** Erase sequence timed out */ 118 | uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C; 119 | /** card returned an error token instead of read data */ 120 | uint8_t const SD_CARD_ERROR_READ = 0X0D; 121 | /** read CID or CSD failed */ 122 | uint8_t const SD_CARD_ERROR_READ_REG = 0X0E; 123 | /** timeout while waiting for start of read data */ 124 | uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F; 125 | /** card did not accept STOP_TRAN_TOKEN */ 126 | uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10; 127 | /** card returned an error token as a response to a write operation */ 128 | uint8_t const SD_CARD_ERROR_WRITE = 0X11; 129 | /** attempt to write protected block zero */ 130 | uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12; 131 | /** card did not go ready for a multiple block write */ 132 | uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13; 133 | /** card returned an error to a CMD13 status check after a write */ 134 | uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14; 135 | /** timeout occurred during write programming */ 136 | uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15; 137 | /** incorrect rate selected */ 138 | uint8_t const SD_CARD_ERROR_SCK_RATE = 0X16; 139 | //------------------------------------------------------------------------------ 140 | // card types 141 | /** Standard capacity V1 SD card */ 142 | uint8_t const SD_CARD_TYPE_SD1 = 1; 143 | /** Standard capacity V2 SD card */ 144 | uint8_t const SD_CARD_TYPE_SD2 = 2; 145 | /** High Capacity SD card */ 146 | uint8_t const SD_CARD_TYPE_SDHC = 3; 147 | //------------------------------------------------------------------------------ 148 | /** 149 | * \class Sd2Card 150 | * \brief Raw access to SD and SDHC flash memory cards. 151 | */ 152 | class Sd2Card { 153 | public: 154 | /** Construct an instance of Sd2Card. */ 155 | Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} 156 | uint32_t cardSize(void); 157 | uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); 158 | uint8_t eraseSingleBlockEnable(void); 159 | /** 160 | * \return error code for last error. See Sd2Card.h for a list of error codes. 161 | */ 162 | uint8_t errorCode(void) const {return errorCode_;} 163 | /** \return error data for last error. */ 164 | uint8_t errorData(void) const {return status_;} 165 | /** 166 | * Initialize an SD flash memory card with default clock rate and chip 167 | * select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). 168 | */ 169 | uint8_t init(void) { 170 | return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); 171 | } 172 | /** 173 | * Initialize an SD flash memory card with the selected SPI clock rate 174 | * and the default SD chip select pin. 175 | * See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). 176 | */ 177 | uint8_t init(uint8_t sckRateID) { 178 | return init(sckRateID, SD_CHIP_SELECT_PIN); 179 | } 180 | uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); 181 | void partialBlockRead(uint8_t value); 182 | /** Returns the current value, true or false, for partial block read. */ 183 | uint8_t partialBlockRead(void) const {return partialBlockRead_;} 184 | uint8_t readBlock(uint32_t block, uint8_t* dst); 185 | uint8_t readData(uint32_t block, 186 | uint16_t offset, uint16_t count, uint8_t* dst); 187 | /** 188 | * Read a cards CID register. The CID contains card identification 189 | * information such as Manufacturer ID, Product name, Product serial 190 | * number and Manufacturing date. */ 191 | uint8_t readCID(cid_t* cid) { 192 | return readRegister(CMD10, cid); 193 | } 194 | /** 195 | * Read a cards CSD register. The CSD contains Card-Specific Data that 196 | * provides information regarding access to the card's contents. */ 197 | uint8_t readCSD(csd_t* csd) { 198 | return readRegister(CMD9, csd); 199 | } 200 | void readEnd(void); 201 | uint8_t setSckRate(uint8_t sckRateID); 202 | /** Return the card type: SD V1, SD V2 or SDHC */ 203 | uint8_t type(void) const {return type_;} 204 | uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src); 205 | uint8_t writeData(const uint8_t* src); 206 | uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); 207 | uint8_t writeStop(void); 208 | private: 209 | uint32_t block_; 210 | uint8_t chipSelectPin_; 211 | uint8_t errorCode_; 212 | uint8_t inBlock_; 213 | uint16_t offset_; 214 | uint8_t partialBlockRead_; 215 | uint8_t status_; 216 | uint8_t type_; 217 | // private functions 218 | uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { 219 | cardCommand(CMD55, 0); 220 | return cardCommand(cmd, arg); 221 | } 222 | uint8_t cardCommand(uint8_t cmd, uint32_t arg); 223 | void error(uint8_t code) {errorCode_ = code;} 224 | uint8_t readRegister(uint8_t cmd, void* buf); 225 | uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); 226 | void chipSelectHigh(void); 227 | void chipSelectLow(void); 228 | void type(uint8_t value) {type_ = value;} 229 | uint8_t waitNotBusy(uint16_t timeoutMillis); 230 | uint8_t writeData(uint8_t token, const uint8_t* src); 231 | uint8_t waitStartBlock(void); 232 | }; 233 | #endif // Sd2Card_h 234 | -------------------------------------------------------------------------------- /Sprinter/SdVolume.cpp: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | #include "SdFat.h" 21 | //------------------------------------------------------------------------------ 22 | // raw block cache 23 | // init cacheBlockNumber_to invalid SD block number 24 | uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; 25 | cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card 26 | Sd2Card* SdVolume::sdCard_; // pointer to SD card object 27 | uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true 28 | uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT 29 | //------------------------------------------------------------------------------ 30 | // find a contiguous group of clusters 31 | uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { 32 | // start of group 33 | uint32_t bgnCluster; 34 | 35 | // flag to save place to start next search 36 | uint8_t setStart; 37 | 38 | // set search start cluster 39 | if (*curCluster) { 40 | // try to make file contiguous 41 | bgnCluster = *curCluster + 1; 42 | 43 | // don't save new start location 44 | setStart = false; 45 | } else { 46 | // start at likely place for free cluster 47 | bgnCluster = allocSearchStart_; 48 | 49 | // save next search start if one cluster 50 | setStart = 1 == count; 51 | } 52 | // end of group 53 | uint32_t endCluster = bgnCluster; 54 | 55 | // last cluster of FAT 56 | uint32_t fatEnd = clusterCount_ + 1; 57 | 58 | // search the FAT for free clusters 59 | for (uint32_t n = 0;; n++, endCluster++) { 60 | // can't find space checked all clusters 61 | if (n >= clusterCount_) return false; 62 | 63 | // past end - start from beginning of FAT 64 | if (endCluster > fatEnd) { 65 | bgnCluster = endCluster = 2; 66 | } 67 | uint32_t f; 68 | if (!fatGet(endCluster, &f)) return false; 69 | 70 | if (f != 0) { 71 | // cluster in use try next cluster as bgnCluster 72 | bgnCluster = endCluster + 1; 73 | } else if ((endCluster - bgnCluster + 1) == count) { 74 | // done - found space 75 | break; 76 | } 77 | } 78 | // mark end of chain 79 | if (!fatPutEOC(endCluster)) return false; 80 | 81 | // link clusters 82 | while (endCluster > bgnCluster) { 83 | if (!fatPut(endCluster - 1, endCluster)) return false; 84 | endCluster--; 85 | } 86 | if (*curCluster != 0) { 87 | // connect chains 88 | if (!fatPut(*curCluster, bgnCluster)) return false; 89 | } 90 | // return first cluster number to caller 91 | *curCluster = bgnCluster; 92 | 93 | // remember possible next free cluster 94 | if (setStart) allocSearchStart_ = bgnCluster + 1; 95 | 96 | return true; 97 | } 98 | //------------------------------------------------------------------------------ 99 | uint8_t SdVolume::cacheFlush(void) { 100 | if (cacheDirty_) { 101 | if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) { 102 | return false; 103 | } 104 | // mirror FAT tables 105 | if (cacheMirrorBlock_) { 106 | if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) { 107 | return false; 108 | } 109 | cacheMirrorBlock_ = 0; 110 | } 111 | cacheDirty_ = 0; 112 | } 113 | return true; 114 | } 115 | //------------------------------------------------------------------------------ 116 | uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) { 117 | if (cacheBlockNumber_ != blockNumber) { 118 | if (!cacheFlush()) return false; 119 | if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false; 120 | cacheBlockNumber_ = blockNumber; 121 | } 122 | cacheDirty_ |= action; 123 | return true; 124 | } 125 | //------------------------------------------------------------------------------ 126 | // cache a zero block for blockNumber 127 | uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) { 128 | if (!cacheFlush()) return false; 129 | 130 | // loop take less flash than memset(cacheBuffer_.data, 0, 512); 131 | for (uint16_t i = 0; i < 512; i++) { 132 | cacheBuffer_.data[i] = 0; 133 | } 134 | cacheBlockNumber_ = blockNumber; 135 | cacheSetDirty(); 136 | return true; 137 | } 138 | //------------------------------------------------------------------------------ 139 | // return the size in bytes of a cluster chain 140 | uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { 141 | uint32_t s = 0; 142 | do { 143 | if (!fatGet(cluster, &cluster)) return false; 144 | s += 512UL << clusterSizeShift_; 145 | } while (!isEOC(cluster)); 146 | *size = s; 147 | return true; 148 | } 149 | //------------------------------------------------------------------------------ 150 | // Fetch a FAT entry 151 | uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { 152 | if (cluster > (clusterCount_ + 1)) return false; 153 | uint32_t lba = fatStartBlock_; 154 | lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; 155 | if (lba != cacheBlockNumber_) { 156 | if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; 157 | } 158 | if (fatType_ == 16) { 159 | *value = cacheBuffer_.fat16[cluster & 0XFF]; 160 | } else { 161 | *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; 162 | } 163 | return true; 164 | } 165 | //------------------------------------------------------------------------------ 166 | // Store a FAT entry 167 | uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) { 168 | // error if reserved cluster 169 | if (cluster < 2) return false; 170 | 171 | // error if not in FAT 172 | if (cluster > (clusterCount_ + 1)) return false; 173 | 174 | // calculate block address for entry 175 | uint32_t lba = fatStartBlock_; 176 | lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; 177 | 178 | if (lba != cacheBlockNumber_) { 179 | if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; 180 | } 181 | // store entry 182 | if (fatType_ == 16) { 183 | cacheBuffer_.fat16[cluster & 0XFF] = value; 184 | } else { 185 | cacheBuffer_.fat32[cluster & 0X7F] = value; 186 | } 187 | cacheSetDirty(); 188 | 189 | // mirror second FAT 190 | if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_; 191 | return true; 192 | } 193 | //------------------------------------------------------------------------------ 194 | // free a cluster chain 195 | uint8_t SdVolume::freeChain(uint32_t cluster) { 196 | // clear free cluster location 197 | allocSearchStart_ = 2; 198 | 199 | do { 200 | uint32_t next; 201 | if (!fatGet(cluster, &next)) return false; 202 | 203 | // free cluster 204 | if (!fatPut(cluster, 0)) return false; 205 | 206 | cluster = next; 207 | } while (!isEOC(cluster)); 208 | 209 | return true; 210 | } 211 | //------------------------------------------------------------------------------ 212 | /** 213 | * Initialize a FAT volume. 214 | * 215 | * \param[in] dev The SD card where the volume is located. 216 | * 217 | * \param[in] part The partition to be used. Legal values for \a part are 218 | * 1-4 to use the corresponding partition on a device formatted with 219 | * a MBR, Master Boot Record, or zero if the device is formatted as 220 | * a super floppy with the FAT boot sector in block zero. 221 | * 222 | * \return The value one, true, is returned for success and 223 | * the value zero, false, is returned for failure. Reasons for 224 | * failure include not finding a valid partition, not finding a valid 225 | * FAT file system in the specified partition or an I/O error. 226 | */ 227 | uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { 228 | uint32_t volumeStartBlock = 0; 229 | sdCard_ = dev; 230 | // if part == 0 assume super floppy with FAT boot sector in block zero 231 | // if part > 0 assume mbr volume with partition table 232 | if (part) { 233 | if (part > 4)return false; 234 | if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; 235 | part_t* p = &cacheBuffer_.mbr.part[part-1]; 236 | if ((p->boot & 0X7F) !=0 || 237 | p->totalSectors < 100 || 238 | p->firstSector == 0) { 239 | // not a valid partition 240 | return false; 241 | } 242 | volumeStartBlock = p->firstSector; 243 | } 244 | if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; 245 | bpb_t* bpb = &cacheBuffer_.fbs.bpb; 246 | if (bpb->bytesPerSector != 512 || 247 | bpb->fatCount == 0 || 248 | bpb->reservedSectorCount == 0 || 249 | bpb->sectorsPerCluster == 0) { 250 | // not valid FAT volume 251 | return false; 252 | } 253 | fatCount_ = bpb->fatCount; 254 | blocksPerCluster_ = bpb->sectorsPerCluster; 255 | 256 | // determine shift that is same as multiply by blocksPerCluster_ 257 | clusterSizeShift_ = 0; 258 | while (blocksPerCluster_ != (1 << clusterSizeShift_)) { 259 | // error if not power of 2 260 | if (clusterSizeShift_++ > 7) return false; 261 | } 262 | blocksPerFat_ = bpb->sectorsPerFat16 ? 263 | bpb->sectorsPerFat16 : bpb->sectorsPerFat32; 264 | 265 | fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount; 266 | 267 | // count for FAT16 zero for FAT32 268 | rootDirEntryCount_ = bpb->rootDirEntryCount; 269 | 270 | // directory start for FAT16 dataStart for FAT32 271 | rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_; 272 | 273 | // data start for FAT16 and FAT32 274 | dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512); 275 | 276 | // total blocks for FAT16 or FAT32 277 | uint32_t totalBlocks = bpb->totalSectors16 ? 278 | bpb->totalSectors16 : bpb->totalSectors32; 279 | // total data blocks 280 | clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); 281 | 282 | // divide by cluster size to get cluster count 283 | clusterCount_ >>= clusterSizeShift_; 284 | 285 | // FAT type is determined by cluster count 286 | if (clusterCount_ < 4085) { 287 | fatType_ = 12; 288 | } else if (clusterCount_ < 65525) { 289 | fatType_ = 16; 290 | } else { 291 | rootDirStart_ = bpb->fat32RootCluster; 292 | fatType_ = 32; 293 | } 294 | return true; 295 | } 296 | -------------------------------------------------------------------------------- /Sprinter/Sd2PinMap.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2010 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | // Warning this file was generated by a program. 21 | #ifndef Sd2PinMap_h 22 | #define Sd2PinMap_h 23 | #include 24 | 25 | //------------------------------------------------------------------------------ 26 | /** struct for mapping digital pins */ 27 | struct pin_map_t { 28 | volatile uint8_t* ddr; 29 | volatile uint8_t* pin; 30 | volatile uint8_t* port; 31 | uint8_t bit; 32 | }; 33 | //------------------------------------------------------------------------------ 34 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 35 | // Mega 36 | 37 | // Two Wire (aka I2C) ports 38 | uint8_t const SDA_PIN = 20; 39 | uint8_t const SCL_PIN = 21; 40 | 41 | // SPI port 42 | uint8_t const SS_PIN = 53; 43 | uint8_t const MOSI_PIN = 51; 44 | uint8_t const MISO_PIN = 50; 45 | uint8_t const SCK_PIN = 52; 46 | 47 | static const pin_map_t digitalPinMap[] = { 48 | {&DDRE, &PINE, &PORTE, 0}, // E0 0 49 | {&DDRE, &PINE, &PORTE, 1}, // E1 1 50 | {&DDRE, &PINE, &PORTE, 4}, // E4 2 51 | {&DDRE, &PINE, &PORTE, 5}, // E5 3 52 | {&DDRG, &PING, &PORTG, 5}, // G5 4 53 | {&DDRE, &PINE, &PORTE, 3}, // E3 5 54 | {&DDRH, &PINH, &PORTH, 3}, // H3 6 55 | {&DDRH, &PINH, &PORTH, 4}, // H4 7 56 | {&DDRH, &PINH, &PORTH, 5}, // H5 8 57 | {&DDRH, &PINH, &PORTH, 6}, // H6 9 58 | {&DDRB, &PINB, &PORTB, 4}, // B4 10 59 | {&DDRB, &PINB, &PORTB, 5}, // B5 11 60 | {&DDRB, &PINB, &PORTB, 6}, // B6 12 61 | {&DDRB, &PINB, &PORTB, 7}, // B7 13 62 | {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 63 | {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 64 | {&DDRH, &PINH, &PORTH, 1}, // H1 16 65 | {&DDRH, &PINH, &PORTH, 0}, // H0 17 66 | {&DDRD, &PIND, &PORTD, 3}, // D3 18 67 | {&DDRD, &PIND, &PORTD, 2}, // D2 19 68 | {&DDRD, &PIND, &PORTD, 1}, // D1 20 69 | {&DDRD, &PIND, &PORTD, 0}, // D0 21 70 | {&DDRA, &PINA, &PORTA, 0}, // A0 22 71 | {&DDRA, &PINA, &PORTA, 1}, // A1 23 72 | {&DDRA, &PINA, &PORTA, 2}, // A2 24 73 | {&DDRA, &PINA, &PORTA, 3}, // A3 25 74 | {&DDRA, &PINA, &PORTA, 4}, // A4 26 75 | {&DDRA, &PINA, &PORTA, 5}, // A5 27 76 | {&DDRA, &PINA, &PORTA, 6}, // A6 28 77 | {&DDRA, &PINA, &PORTA, 7}, // A7 29 78 | {&DDRC, &PINC, &PORTC, 7}, // C7 30 79 | {&DDRC, &PINC, &PORTC, 6}, // C6 31 80 | {&DDRC, &PINC, &PORTC, 5}, // C5 32 81 | {&DDRC, &PINC, &PORTC, 4}, // C4 33 82 | {&DDRC, &PINC, &PORTC, 3}, // C3 34 83 | {&DDRC, &PINC, &PORTC, 2}, // C2 35 84 | {&DDRC, &PINC, &PORTC, 1}, // C1 36 85 | {&DDRC, &PINC, &PORTC, 0}, // C0 37 86 | {&DDRD, &PIND, &PORTD, 7}, // D7 38 87 | {&DDRG, &PING, &PORTG, 2}, // G2 39 88 | {&DDRG, &PING, &PORTG, 1}, // G1 40 89 | {&DDRG, &PING, &PORTG, 0}, // G0 41 90 | {&DDRL, &PINL, &PORTL, 7}, // L7 42 91 | {&DDRL, &PINL, &PORTL, 6}, // L6 43 92 | {&DDRL, &PINL, &PORTL, 5}, // L5 44 93 | {&DDRL, &PINL, &PORTL, 4}, // L4 45 94 | {&DDRL, &PINL, &PORTL, 3}, // L3 46 95 | {&DDRL, &PINL, &PORTL, 2}, // L2 47 96 | {&DDRL, &PINL, &PORTL, 1}, // L1 48 97 | {&DDRL, &PINL, &PORTL, 0}, // L0 49 98 | {&DDRB, &PINB, &PORTB, 3}, // B3 50 99 | {&DDRB, &PINB, &PORTB, 2}, // B2 51 100 | {&DDRB, &PINB, &PORTB, 1}, // B1 52 101 | {&DDRB, &PINB, &PORTB, 0}, // B0 53 102 | {&DDRF, &PINF, &PORTF, 0}, // F0 54 103 | {&DDRF, &PINF, &PORTF, 1}, // F1 55 104 | {&DDRF, &PINF, &PORTF, 2}, // F2 56 105 | {&DDRF, &PINF, &PORTF, 3}, // F3 57 106 | {&DDRF, &PINF, &PORTF, 4}, // F4 58 107 | {&DDRF, &PINF, &PORTF, 5}, // F5 59 108 | {&DDRF, &PINF, &PORTF, 6}, // F6 60 109 | {&DDRF, &PINF, &PORTF, 7}, // F7 61 110 | {&DDRK, &PINK, &PORTK, 0}, // K0 62 111 | {&DDRK, &PINK, &PORTK, 1}, // K1 63 112 | {&DDRK, &PINK, &PORTK, 2}, // K2 64 113 | {&DDRK, &PINK, &PORTK, 3}, // K3 65 114 | {&DDRK, &PINK, &PORTK, 4}, // K4 66 115 | {&DDRK, &PINK, &PORTK, 5}, // K5 67 116 | {&DDRK, &PINK, &PORTK, 6}, // K6 68 117 | {&DDRK, &PINK, &PORTK, 7} // K7 69 118 | }; 119 | //------------------------------------------------------------------------------ 120 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__) 121 | // Sanguino 122 | 123 | // Two Wire (aka I2C) ports 124 | uint8_t const SDA_PIN = 17; 125 | uint8_t const SCL_PIN = 18; 126 | 127 | // SPI port 128 | uint8_t const SS_PIN = 4; 129 | uint8_t const MOSI_PIN = 5; 130 | uint8_t const MISO_PIN = 6; 131 | uint8_t const SCK_PIN = 7; 132 | 133 | static const pin_map_t digitalPinMap[] = { 134 | {&DDRB, &PINB, &PORTB, 0}, // B0 0 135 | {&DDRB, &PINB, &PORTB, 1}, // B1 1 136 | {&DDRB, &PINB, &PORTB, 2}, // B2 2 137 | {&DDRB, &PINB, &PORTB, 3}, // B3 3 138 | {&DDRB, &PINB, &PORTB, 4}, // B4 4 139 | {&DDRB, &PINB, &PORTB, 5}, // B5 5 140 | {&DDRB, &PINB, &PORTB, 6}, // B6 6 141 | {&DDRB, &PINB, &PORTB, 7}, // B7 7 142 | {&DDRD, &PIND, &PORTD, 0}, // D0 8 143 | {&DDRD, &PIND, &PORTD, 1}, // D1 9 144 | {&DDRD, &PIND, &PORTD, 2}, // D2 10 145 | {&DDRD, &PIND, &PORTD, 3}, // D3 11 146 | {&DDRD, &PIND, &PORTD, 4}, // D4 12 147 | {&DDRD, &PIND, &PORTD, 5}, // D5 13 148 | {&DDRD, &PIND, &PORTD, 6}, // D6 14 149 | {&DDRD, &PIND, &PORTD, 7}, // D7 15 150 | {&DDRC, &PINC, &PORTC, 0}, // C0 16 151 | {&DDRC, &PINC, &PORTC, 1}, // C1 17 152 | {&DDRC, &PINC, &PORTC, 2}, // C2 18 153 | {&DDRC, &PINC, &PORTC, 3}, // C3 19 154 | {&DDRC, &PINC, &PORTC, 4}, // C4 20 155 | {&DDRC, &PINC, &PORTC, 5}, // C5 21 156 | {&DDRC, &PINC, &PORTC, 6}, // C6 22 157 | {&DDRC, &PINC, &PORTC, 7}, // C7 23 158 | {&DDRA, &PINA, &PORTA, 7}, // A7 24 159 | {&DDRA, &PINA, &PORTA, 6}, // A6 25 160 | {&DDRA, &PINA, &PORTA, 5}, // A5 26 161 | {&DDRA, &PINA, &PORTA, 4}, // A4 27 162 | {&DDRA, &PINA, &PORTA, 3}, // A3 28 163 | {&DDRA, &PINA, &PORTA, 2}, // A2 29 164 | {&DDRA, &PINA, &PORTA, 1}, // A1 30 165 | {&DDRA, &PINA, &PORTA, 0} // A0 31 166 | }; 167 | //------------------------------------------------------------------------------ 168 | #elif defined(__AVR_ATmega32U4__) 169 | // Teensy 2.0 170 | 171 | // Two Wire (aka I2C) ports 172 | uint8_t const SDA_PIN = 6; 173 | uint8_t const SCL_PIN = 5; 174 | 175 | // SPI port 176 | uint8_t const SS_PIN = 0; 177 | uint8_t const MOSI_PIN = 2; 178 | uint8_t const MISO_PIN = 3; 179 | uint8_t const SCK_PIN = 1; 180 | 181 | static const pin_map_t digitalPinMap[] = { 182 | {&DDRB, &PINB, &PORTB, 0}, // B0 0 183 | {&DDRB, &PINB, &PORTB, 1}, // B1 1 184 | {&DDRB, &PINB, &PORTB, 2}, // B2 2 185 | {&DDRB, &PINB, &PORTB, 3}, // B3 3 186 | {&DDRB, &PINB, &PORTB, 7}, // B7 4 187 | {&DDRD, &PIND, &PORTD, 0}, // D0 5 188 | {&DDRD, &PIND, &PORTD, 1}, // D1 6 189 | {&DDRD, &PIND, &PORTD, 2}, // D2 7 190 | {&DDRD, &PIND, &PORTD, 3}, // D3 8 191 | {&DDRC, &PINC, &PORTC, 6}, // C6 9 192 | {&DDRC, &PINC, &PORTC, 7}, // C7 10 193 | {&DDRD, &PIND, &PORTD, 6}, // D6 11 194 | {&DDRD, &PIND, &PORTD, 7}, // D7 12 195 | {&DDRB, &PINB, &PORTB, 4}, // B4 13 196 | {&DDRB, &PINB, &PORTB, 5}, // B5 14 197 | {&DDRB, &PINB, &PORTB, 6}, // B6 15 198 | {&DDRF, &PINF, &PORTF, 7}, // F7 16 199 | {&DDRF, &PINF, &PORTF, 6}, // F6 17 200 | {&DDRF, &PINF, &PORTF, 5}, // F5 18 201 | {&DDRF, &PINF, &PORTF, 4}, // F4 19 202 | {&DDRF, &PINF, &PORTF, 1}, // F1 20 203 | {&DDRF, &PINF, &PORTF, 0}, // F0 21 204 | {&DDRD, &PIND, &PORTD, 4}, // D4 22 205 | {&DDRD, &PIND, &PORTD, 5}, // D5 23 206 | {&DDRE, &PINE, &PORTE, 6} // E6 24 207 | }; 208 | //------------------------------------------------------------------------------ 209 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 210 | // Teensy++ 1.0 & 2.0 211 | 212 | // Two Wire (aka I2C) ports 213 | uint8_t const SDA_PIN = 1; 214 | uint8_t const SCL_PIN = 0; 215 | 216 | // SPI port 217 | uint8_t const SS_PIN = 20; 218 | uint8_t const MOSI_PIN = 22; 219 | uint8_t const MISO_PIN = 23; 220 | uint8_t const SCK_PIN = 21; 221 | 222 | static const pin_map_t digitalPinMap[] = { 223 | {&DDRD, &PIND, &PORTD, 0}, // D0 0 224 | {&DDRD, &PIND, &PORTD, 1}, // D1 1 225 | {&DDRD, &PIND, &PORTD, 2}, // D2 2 226 | {&DDRD, &PIND, &PORTD, 3}, // D3 3 227 | {&DDRD, &PIND, &PORTD, 4}, // D4 4 228 | {&DDRD, &PIND, &PORTD, 5}, // D5 5 229 | {&DDRD, &PIND, &PORTD, 6}, // D6 6 230 | {&DDRD, &PIND, &PORTD, 7}, // D7 7 231 | {&DDRE, &PINE, &PORTE, 0}, // E0 8 232 | {&DDRE, &PINE, &PORTE, 1}, // E1 9 233 | {&DDRC, &PINC, &PORTC, 0}, // C0 10 234 | {&DDRC, &PINC, &PORTC, 1}, // C1 11 235 | {&DDRC, &PINC, &PORTC, 2}, // C2 12 236 | {&DDRC, &PINC, &PORTC, 3}, // C3 13 237 | {&DDRC, &PINC, &PORTC, 4}, // C4 14 238 | {&DDRC, &PINC, &PORTC, 5}, // C5 15 239 | {&DDRC, &PINC, &PORTC, 6}, // C6 16 240 | {&DDRC, &PINC, &PORTC, 7}, // C7 17 241 | {&DDRE, &PINE, &PORTE, 6}, // E6 18 242 | {&DDRE, &PINE, &PORTE, 7}, // E7 19 243 | {&DDRB, &PINB, &PORTB, 0}, // B0 20 244 | {&DDRB, &PINB, &PORTB, 1}, // B1 21 245 | {&DDRB, &PINB, &PORTB, 2}, // B2 22 246 | {&DDRB, &PINB, &PORTB, 3}, // B3 23 247 | {&DDRB, &PINB, &PORTB, 4}, // B4 24 248 | {&DDRB, &PINB, &PORTB, 5}, // B5 25 249 | {&DDRB, &PINB, &PORTB, 6}, // B6 26 250 | {&DDRB, &PINB, &PORTB, 7}, // B7 27 251 | {&DDRA, &PINA, &PORTA, 0}, // A0 28 252 | {&DDRA, &PINA, &PORTA, 1}, // A1 29 253 | {&DDRA, &PINA, &PORTA, 2}, // A2 30 254 | {&DDRA, &PINA, &PORTA, 3}, // A3 31 255 | {&DDRA, &PINA, &PORTA, 4}, // A4 32 256 | {&DDRA, &PINA, &PORTA, 5}, // A5 33 257 | {&DDRA, &PINA, &PORTA, 6}, // A6 34 258 | {&DDRA, &PINA, &PORTA, 7}, // A7 35 259 | {&DDRE, &PINE, &PORTE, 4}, // E4 36 260 | {&DDRE, &PINE, &PORTE, 5}, // E5 37 261 | {&DDRF, &PINF, &PORTF, 0}, // F0 38 262 | {&DDRF, &PINF, &PORTF, 1}, // F1 39 263 | {&DDRF, &PINF, &PORTF, 2}, // F2 40 264 | {&DDRF, &PINF, &PORTF, 3}, // F3 41 265 | {&DDRF, &PINF, &PORTF, 4}, // F4 42 266 | {&DDRF, &PINF, &PORTF, 5}, // F5 43 267 | {&DDRF, &PINF, &PORTF, 6}, // F6 44 268 | {&DDRF, &PINF, &PORTF, 7} // F7 45 269 | }; 270 | //------------------------------------------------------------------------------ 271 | #else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 272 | // 168 and 328 Arduinos 273 | 274 | // Two Wire (aka I2C) ports 275 | uint8_t const SDA_PIN = 18; 276 | uint8_t const SCL_PIN = 19; 277 | 278 | // SPI port 279 | uint8_t const SS_PIN = 10; 280 | uint8_t const MOSI_PIN = 11; 281 | uint8_t const MISO_PIN = 12; 282 | uint8_t const SCK_PIN = 13; 283 | 284 | static const pin_map_t digitalPinMap[] = { 285 | {&DDRD, &PIND, &PORTD, 0}, // D0 0 286 | {&DDRD, &PIND, &PORTD, 1}, // D1 1 287 | {&DDRD, &PIND, &PORTD, 2}, // D2 2 288 | {&DDRD, &PIND, &PORTD, 3}, // D3 3 289 | {&DDRD, &PIND, &PORTD, 4}, // D4 4 290 | {&DDRD, &PIND, &PORTD, 5}, // D5 5 291 | {&DDRD, &PIND, &PORTD, 6}, // D6 6 292 | {&DDRD, &PIND, &PORTD, 7}, // D7 7 293 | {&DDRB, &PINB, &PORTB, 0}, // B0 8 294 | {&DDRB, &PINB, &PORTB, 1}, // B1 9 295 | {&DDRB, &PINB, &PORTB, 2}, // B2 10 296 | {&DDRB, &PINB, &PORTB, 3}, // B3 11 297 | {&DDRB, &PINB, &PORTB, 4}, // B4 12 298 | {&DDRB, &PINB, &PORTB, 5}, // B5 13 299 | {&DDRC, &PINC, &PORTC, 0}, // C0 14 300 | {&DDRC, &PINC, &PORTC, 1}, // C1 15 301 | {&DDRC, &PINC, &PORTC, 2}, // C2 16 302 | {&DDRC, &PINC, &PORTC, 3}, // C3 17 303 | {&DDRC, &PINC, &PORTC, 4}, // C4 18 304 | {&DDRC, &PINC, &PORTC, 5} // C5 19 305 | }; 306 | #endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 307 | //------------------------------------------------------------------------------ 308 | static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t); 309 | 310 | uint8_t badPinNumber(void) 311 | __attribute__((error("Pin number is too large or not a constant"))); 312 | 313 | static inline __attribute__((always_inline)) 314 | uint8_t getPinMode(uint8_t pin) { 315 | if (__builtin_constant_p(pin) && pin < digitalPinCount) { 316 | return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1; 317 | } else { 318 | return badPinNumber(); 319 | } 320 | } 321 | static inline __attribute__((always_inline)) 322 | void setPinMode(uint8_t pin, uint8_t mode) { 323 | if (__builtin_constant_p(pin) && pin < digitalPinCount) { 324 | if (mode) { 325 | *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit; 326 | } else { 327 | *digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit); 328 | } 329 | } else { 330 | badPinNumber(); 331 | } 332 | } 333 | static inline __attribute__((always_inline)) 334 | uint8_t fastDigitalRead(uint8_t pin) { 335 | if (__builtin_constant_p(pin) && pin < digitalPinCount) { 336 | return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1; 337 | } else { 338 | return badPinNumber(); 339 | } 340 | } 341 | static inline __attribute__((always_inline)) 342 | void fastDigitalWrite(uint8_t pin, uint8_t value) { 343 | if (__builtin_constant_p(pin) && pin < digitalPinCount) { 344 | if (value) { 345 | *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit; 346 | } else { 347 | *digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit); 348 | } 349 | } else { 350 | badPinNumber(); 351 | } 352 | } 353 | #endif // Sd2PinMap_h 354 | -------------------------------------------------------------------------------- /Sprinter/FatStructs.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | #ifndef FatStructs_h 21 | #define FatStructs_h 22 | /** 23 | * \file 24 | * FAT file structures 25 | */ 26 | /* 27 | * mostly from Microsoft document fatgen103.doc 28 | * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx 29 | */ 30 | //------------------------------------------------------------------------------ 31 | /** Value for byte 510 of boot block or MBR */ 32 | uint8_t const BOOTSIG0 = 0X55; 33 | /** Value for byte 511 of boot block or MBR */ 34 | uint8_t const BOOTSIG1 = 0XAA; 35 | //------------------------------------------------------------------------------ 36 | /** 37 | * \struct partitionTable 38 | * \brief MBR partition table entry 39 | * 40 | * A partition table entry for a MBR formatted storage device. 41 | * The MBR partition table has four entries. 42 | */ 43 | struct partitionTable { 44 | /** 45 | * Boot Indicator . Indicates whether the volume is the active 46 | * partition. Legal values include: 0X00. Do not use for booting. 47 | * 0X80 Active partition. 48 | */ 49 | uint8_t boot; 50 | /** 51 | * Head part of Cylinder-head-sector address of the first block in 52 | * the partition. Legal values are 0-255. Only used in old PC BIOS. 53 | */ 54 | uint8_t beginHead; 55 | /** 56 | * Sector part of Cylinder-head-sector address of the first block in 57 | * the partition. Legal values are 1-63. Only used in old PC BIOS. 58 | */ 59 | unsigned beginSector : 6; 60 | /** High bits cylinder for first block in partition. */ 61 | unsigned beginCylinderHigh : 2; 62 | /** 63 | * Combine beginCylinderLow with beginCylinderHigh. Legal values 64 | * are 0-1023. Only used in old PC BIOS. 65 | */ 66 | uint8_t beginCylinderLow; 67 | /** 68 | * Partition type. See defines that begin with PART_TYPE_ for 69 | * some Microsoft partition types. 70 | */ 71 | uint8_t type; 72 | /** 73 | * head part of cylinder-head-sector address of the last sector in the 74 | * partition. Legal values are 0-255. Only used in old PC BIOS. 75 | */ 76 | uint8_t endHead; 77 | /** 78 | * Sector part of cylinder-head-sector address of the last sector in 79 | * the partition. Legal values are 1-63. Only used in old PC BIOS. 80 | */ 81 | unsigned endSector : 6; 82 | /** High bits of end cylinder */ 83 | unsigned endCylinderHigh : 2; 84 | /** 85 | * Combine endCylinderLow with endCylinderHigh. Legal values 86 | * are 0-1023. Only used in old PC BIOS. 87 | */ 88 | uint8_t endCylinderLow; 89 | /** Logical block address of the first block in the partition. */ 90 | uint32_t firstSector; 91 | /** Length of the partition, in blocks. */ 92 | uint32_t totalSectors; 93 | }; 94 | /** Type name for partitionTable */ 95 | typedef struct partitionTable part_t; 96 | //------------------------------------------------------------------------------ 97 | /** 98 | * \struct masterBootRecord 99 | * 100 | * \brief Master Boot Record 101 | * 102 | * The first block of a storage device that is formatted with a MBR. 103 | */ 104 | struct masterBootRecord { 105 | /** Code Area for master boot program. */ 106 | uint8_t codeArea[440]; 107 | /** Optional WindowsNT disk signature. May contain more boot code. */ 108 | uint32_t diskSignature; 109 | /** Usually zero but may be more boot code. */ 110 | uint16_t usuallyZero; 111 | /** Partition tables. */ 112 | part_t part[4]; 113 | /** First MBR signature byte. Must be 0X55 */ 114 | uint8_t mbrSig0; 115 | /** Second MBR signature byte. Must be 0XAA */ 116 | uint8_t mbrSig1; 117 | }; 118 | /** Type name for masterBootRecord */ 119 | typedef struct masterBootRecord mbr_t; 120 | //------------------------------------------------------------------------------ 121 | /** 122 | * \struct biosParmBlock 123 | * 124 | * \brief BIOS parameter block 125 | * 126 | * The BIOS parameter block describes the physical layout of a FAT volume. 127 | */ 128 | struct biosParmBlock { 129 | /** 130 | * Count of bytes per sector. This value may take on only the 131 | * following values: 512, 1024, 2048 or 4096 132 | */ 133 | uint16_t bytesPerSector; 134 | /** 135 | * Number of sectors per allocation unit. This value must be a 136 | * power of 2 that is greater than 0. The legal values are 137 | * 1, 2, 4, 8, 16, 32, 64, and 128. 138 | */ 139 | uint8_t sectorsPerCluster; 140 | /** 141 | * Number of sectors before the first FAT. 142 | * This value must not be zero. 143 | */ 144 | uint16_t reservedSectorCount; 145 | /** The count of FAT data structures on the volume. This field should 146 | * always contain the value 2 for any FAT volume of any type. 147 | */ 148 | uint8_t fatCount; 149 | /** 150 | * For FAT12 and FAT16 volumes, this field contains the count of 151 | * 32-byte directory entries in the root directory. For FAT32 volumes, 152 | * this field must be set to 0. For FAT12 and FAT16 volumes, this 153 | * value should always specify a count that when multiplied by 32 154 | * results in a multiple of bytesPerSector. FAT16 volumes should 155 | * use the value 512. 156 | */ 157 | uint16_t rootDirEntryCount; 158 | /** 159 | * This field is the old 16-bit total count of sectors on the volume. 160 | * This count includes the count of all sectors in all four regions 161 | * of the volume. This field can be 0; if it is 0, then totalSectors32 162 | * must be non-zero. For FAT32 volumes, this field must be 0. For 163 | * FAT12 and FAT16 volumes, this field contains the sector count, and 164 | * totalSectors32 is 0 if the total sector count fits 165 | * (is less than 0x10000). 166 | */ 167 | uint16_t totalSectors16; 168 | /** 169 | * This dates back to the old MS-DOS 1.x media determination and is 170 | * no longer usually used for anything. 0xF8 is the standard value 171 | * for fixed (non-removable) media. For removable media, 0xF0 is 172 | * frequently used. Legal values are 0xF0 or 0xF8-0xFF. 173 | */ 174 | uint8_t mediaType; 175 | /** 176 | * Count of sectors occupied by one FAT on FAT12/FAT16 volumes. 177 | * On FAT32 volumes this field must be 0, and sectorsPerFat32 178 | * contains the FAT size count. 179 | */ 180 | uint16_t sectorsPerFat16; 181 | /** Sectors per track for interrupt 0x13. Not used otherwise. */ 182 | uint16_t sectorsPerTrtack; 183 | /** Number of heads for interrupt 0x13. Not used otherwise. */ 184 | uint16_t headCount; 185 | /** 186 | * Count of hidden sectors preceding the partition that contains this 187 | * FAT volume. This field is generally only relevant for media 188 | * visible on interrupt 0x13. 189 | */ 190 | uint32_t hidddenSectors; 191 | /** 192 | * This field is the new 32-bit total count of sectors on the volume. 193 | * This count includes the count of all sectors in all four regions 194 | * of the volume. This field can be 0; if it is 0, then 195 | * totalSectors16 must be non-zero. 196 | */ 197 | uint32_t totalSectors32; 198 | /** 199 | * Count of sectors occupied by one FAT on FAT32 volumes. 200 | */ 201 | uint32_t sectorsPerFat32; 202 | /** 203 | * This field is only defined for FAT32 media and does not exist on 204 | * FAT12 and FAT16 media. 205 | * Bits 0-3 -- Zero-based number of active FAT. 206 | * Only valid if mirroring is disabled. 207 | * Bits 4-6 -- Reserved. 208 | * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. 209 | * -- 1 means only one FAT is active; it is the one referenced in bits 0-3. 210 | * Bits 8-15 -- Reserved. 211 | */ 212 | uint16_t fat32Flags; 213 | /** 214 | * FAT32 version. High byte is major revision number. 215 | * Low byte is minor revision number. Only 0.0 define. 216 | */ 217 | uint16_t fat32Version; 218 | /** 219 | * Cluster number of the first cluster of the root directory for FAT32. 220 | * This usually 2 but not required to be 2. 221 | */ 222 | uint32_t fat32RootCluster; 223 | /** 224 | * Sector number of FSINFO structure in the reserved area of the 225 | * FAT32 volume. Usually 1. 226 | */ 227 | uint16_t fat32FSInfo; 228 | /** 229 | * If non-zero, indicates the sector number in the reserved area 230 | * of the volume of a copy of the boot record. Usually 6. 231 | * No value other than 6 is recommended. 232 | */ 233 | uint16_t fat32BackBootBlock; 234 | /** 235 | * Reserved for future expansion. Code that formats FAT32 volumes 236 | * should always set all of the bytes of this field to 0. 237 | */ 238 | uint8_t fat32Reserved[12]; 239 | }; 240 | /** Type name for biosParmBlock */ 241 | typedef struct biosParmBlock bpb_t; 242 | //------------------------------------------------------------------------------ 243 | /** 244 | * \struct fat32BootSector 245 | * 246 | * \brief Boot sector for a FAT16 or FAT32 volume. 247 | * 248 | */ 249 | struct fat32BootSector { 250 | /** X86 jmp to boot program */ 251 | uint8_t jmpToBootCode[3]; 252 | /** informational only - don't depend on it */ 253 | char oemName[8]; 254 | /** BIOS Parameter Block */ 255 | bpb_t bpb; 256 | /** for int0x13 use value 0X80 for hard drive */ 257 | uint8_t driveNumber; 258 | /** used by Windows NT - should be zero for FAT */ 259 | uint8_t reserved1; 260 | /** 0X29 if next three fields are valid */ 261 | uint8_t bootSignature; 262 | /** usually generated by combining date and time */ 263 | uint32_t volumeSerialNumber; 264 | /** should match volume label in root dir */ 265 | char volumeLabel[11]; 266 | /** informational only - don't depend on it */ 267 | char fileSystemType[8]; 268 | /** X86 boot code */ 269 | uint8_t bootCode[420]; 270 | /** must be 0X55 */ 271 | uint8_t bootSectorSig0; 272 | /** must be 0XAA */ 273 | uint8_t bootSectorSig1; 274 | }; 275 | //------------------------------------------------------------------------------ 276 | // End Of Chain values for FAT entries 277 | /** FAT16 end of chain value used by Microsoft. */ 278 | uint16_t const FAT16EOC = 0XFFFF; 279 | /** Minimum value for FAT16 EOC. Use to test for EOC. */ 280 | uint16_t const FAT16EOC_MIN = 0XFFF8; 281 | /** FAT32 end of chain value used by Microsoft. */ 282 | uint32_t const FAT32EOC = 0X0FFFFFFF; 283 | /** Minimum value for FAT32 EOC. Use to test for EOC. */ 284 | uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; 285 | /** Mask a for FAT32 entry. Entries are 28 bits. */ 286 | uint32_t const FAT32MASK = 0X0FFFFFFF; 287 | 288 | /** Type name for fat32BootSector */ 289 | typedef struct fat32BootSector fbs_t; 290 | //------------------------------------------------------------------------------ 291 | /** 292 | * \struct directoryEntry 293 | * \brief FAT short directory entry 294 | * 295 | * Short means short 8.3 name, not the entry size. 296 | * 297 | * Date Format. A FAT directory entry date stamp is a 16-bit field that is 298 | * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the 299 | * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the 300 | * 16-bit word): 301 | * 302 | * Bits 9-15: Count of years from 1980, valid value range 0-127 303 | * inclusive (1980-2107). 304 | * 305 | * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. 306 | * 307 | * Bits 0-4: Day of month, valid value range 1-31 inclusive. 308 | * 309 | * Time Format. A FAT directory entry time stamp is a 16-bit field that has 310 | * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the 311 | * 16-bit word, bit 15 is the MSB of the 16-bit word). 312 | * 313 | * Bits 11-15: Hours, valid value range 0-23 inclusive. 314 | * 315 | * Bits 5-10: Minutes, valid value range 0-59 inclusive. 316 | * 317 | * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). 318 | * 319 | * The valid time range is from Midnight 00:00:00 to 23:59:58. 320 | */ 321 | struct directoryEntry { 322 | /** 323 | * Short 8.3 name. 324 | * The first eight bytes contain the file name with blank fill. 325 | * The last three bytes contain the file extension with blank fill. 326 | */ 327 | uint8_t name[11]; 328 | /** Entry attributes. 329 | * 330 | * The upper two bits of the attribute byte are reserved and should 331 | * always be set to 0 when a file is created and never modified or 332 | * looked at after that. See defines that begin with DIR_ATT_. 333 | */ 334 | uint8_t attributes; 335 | /** 336 | * Reserved for use by Windows NT. Set value to 0 when a file is 337 | * created and never modify or look at it after that. 338 | */ 339 | uint8_t reservedNT; 340 | /** 341 | * The granularity of the seconds part of creationTime is 2 seconds 342 | * so this field is a count of tenths of a second and its valid 343 | * value range is 0-199 inclusive. (WHG note - seems to be hundredths) 344 | */ 345 | uint8_t creationTimeTenths; 346 | /** Time file was created. */ 347 | uint16_t creationTime; 348 | /** Date file was created. */ 349 | uint16_t creationDate; 350 | /** 351 | * Last access date. Note that there is no last access time, only 352 | * a date. This is the date of last read or write. In the case of 353 | * a write, this should be set to the same date as lastWriteDate. 354 | */ 355 | uint16_t lastAccessDate; 356 | /** 357 | * High word of this entry's first cluster number (always 0 for a 358 | * FAT12 or FAT16 volume). 359 | */ 360 | uint16_t firstClusterHigh; 361 | /** Time of last write. File creation is considered a write. */ 362 | uint16_t lastWriteTime; 363 | /** Date of last write. File creation is considered a write. */ 364 | uint16_t lastWriteDate; 365 | /** Low word of this entry's first cluster number. */ 366 | uint16_t firstClusterLow; 367 | /** 32-bit unsigned holding this file's size in bytes. */ 368 | uint32_t fileSize; 369 | }; 370 | //------------------------------------------------------------------------------ 371 | // Definitions for directory entries 372 | // 373 | /** Type name for directoryEntry */ 374 | typedef struct directoryEntry dir_t; 375 | /** escape for name[0] = 0XE5 */ 376 | uint8_t const DIR_NAME_0XE5 = 0X05; 377 | /** name[0] value for entry that is free after being "deleted" */ 378 | uint8_t const DIR_NAME_DELETED = 0XE5; 379 | /** name[0] value for entry that is free and no allocated entries follow */ 380 | uint8_t const DIR_NAME_FREE = 0X00; 381 | /** file is read-only */ 382 | uint8_t const DIR_ATT_READ_ONLY = 0X01; 383 | /** File should hidden in directory listings */ 384 | uint8_t const DIR_ATT_HIDDEN = 0X02; 385 | /** Entry is for a system file */ 386 | uint8_t const DIR_ATT_SYSTEM = 0X04; 387 | /** Directory entry contains the volume label */ 388 | uint8_t const DIR_ATT_VOLUME_ID = 0X08; 389 | /** Entry is for a directory */ 390 | uint8_t const DIR_ATT_DIRECTORY = 0X10; 391 | /** Old DOS archive bit for backup support */ 392 | uint8_t const DIR_ATT_ARCHIVE = 0X20; 393 | /** Test value for long name entry. Test is 394 | (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ 395 | uint8_t const DIR_ATT_LONG_NAME = 0X0F; 396 | /** Test mask for long name entry */ 397 | uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; 398 | /** defined attribute bits */ 399 | uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; 400 | /** Directory entry is part of a long name */ 401 | static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { 402 | return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; 403 | } 404 | /** Mask for file/subdirectory tests */ 405 | uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); 406 | /** Directory entry is for a file */ 407 | static inline uint8_t DIR_IS_FILE(const dir_t* dir) { 408 | return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; 409 | } 410 | /** Directory entry is for a subdirectory */ 411 | static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { 412 | return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; 413 | } 414 | /** Directory entry is for a file or subdirectory */ 415 | static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { 416 | return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; 417 | } 418 | #endif // FatStructs_h 419 | -------------------------------------------------------------------------------- /Sprinter/pins.h: -------------------------------------------------------------------------------- 1 | #ifndef PINS_H 2 | #define PINS_H 3 | 4 | /**************************************************************************************** 5 | * Arduino pin assignment 6 | * 7 | * ATMega168 8 | * +-\/-+ 9 | * PC6 1| |28 PC5 (AI 5 / D19) 10 | * (D 0) PD0 2| |27 PC4 (AI 4 / D18) 11 | * (D 1) PD1 3| |26 PC3 (AI 3 / D17) 12 | * (D 2) PD2 4| |25 PC2 (AI 2 / D16) 13 | * PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) 14 | * (D 4) PD4 6| |23 PC0 (AI 0 / D14) 15 | * VCC 7| |22 GND 16 | * GND 8| |21 AREF 17 | * PB6 9| |20 AVCC 18 | * PB7 10| |19 PB5 (D 13) 19 | * PWM+ (D 5) PD5 11| |18 PB4 (D 12) 20 | * PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM 21 | * (D 7) PD7 13| |16 PB2 (D 10) PWM 22 | * (D 8) PB0 14| |15 PB1 (D 9) PWM 23 | * +----+ 24 | ****************************************************************************************/ 25 | #if MOTHERBOARD == 0 26 | #define KNOWN_BOARD 1 27 | 28 | #ifndef __AVR_ATmega168__ 29 | #error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. 30 | #endif 31 | 32 | #define X_STEP_PIN 2 33 | #define X_DIR_PIN 3 34 | #define X_ENABLE_PIN -1 35 | #define X_MIN_PIN 4 36 | #define X_MAX_PIN 9 37 | 38 | #define Y_STEP_PIN 10 39 | #define Y_DIR_PIN 7 40 | #define Y_ENABLE_PIN -1 41 | #define Y_MIN_PIN 8 42 | #define Y_MAX_PIN 13 43 | 44 | #define Z_STEP_PIN 19 45 | #define Z_DIR_PIN 18 46 | #define Z_ENABLE_PIN 5 47 | #define Z_MIN_PIN 17 48 | #define Z_MAX_PIN 16 49 | 50 | #define E_STEP_PIN 11 51 | #define E_DIR_PIN 12 52 | #define E_ENABLE_PIN -1 53 | 54 | #define SDPOWER -1 55 | #define SDSS -1 56 | #define LED_PIN -1 57 | #define FAN_PIN -1 58 | #define PS_ON_PIN 15 59 | #define KILL_PIN -1 60 | 61 | #define HEATER_0_PIN 6 62 | #define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! 63 | 64 | 65 | #endif 66 | 67 | 68 | 69 | /**************************************************************************************** 70 | * Sanguino/RepRap Motherboard with direct-drive extruders 71 | * 72 | * ATMega644P 73 | * 74 | * +---\/---+ 75 | * (D 0) PB0 1| |40 PA0 (AI 0 / D31) 76 | * (D 1) PB1 2| |39 PA1 (AI 1 / D30) 77 | * INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) 78 | * PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) 79 | * PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) 80 | * MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) 81 | * MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) 82 | * SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) 83 | * RST 9| |32 AREF 84 | * VCC 10| |31 GND 85 | * GND 11| |30 AVCC 86 | * XTAL2 12| |29 PC7 (D 23) 87 | * XTAL1 13| |28 PC6 (D 22) 88 | * RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI 89 | * TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO 90 | * INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS 91 | * INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK 92 | * PWM (D 12) PD4 18| |23 PC1 (D 17) SDA 93 | * PWM (D 13) PD5 19| |22 PC0 (D 16) SCL 94 | * PWM (D 14) PD6 20| |21 PD7 (D 15) PWM 95 | * +--------+ 96 | * 97 | ****************************************************************************************/ 98 | #if MOTHERBOARD == 1 99 | #define KNOWN_BOARD 1 100 | 101 | #if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) 102 | #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. 103 | #endif 104 | 105 | #define X_STEP_PIN 15 106 | #define X_DIR_PIN 18 107 | #define X_ENABLE_PIN 19 108 | #define X_MIN_PIN 20 109 | #define X_MAX_PIN 21 110 | 111 | #define Y_STEP_PIN 23 112 | #define Y_DIR_PIN 22 113 | #define Y_ENABLE_PIN 19 114 | #define Y_MIN_PIN 25 115 | #define Y_MAX_PIN 26 116 | 117 | #define Z_STEP_PIN 29 118 | #define Z_DIR_PIN 30 119 | #define Z_ENABLE_PIN 31 120 | #define Z_MIN_PIN 2 121 | #define Z_MAX_PIN 1 122 | 123 | #define E_STEP_PIN 12 124 | #define E_DIR_PIN 16 125 | #define E_ENABLE_PIN 3 126 | 127 | #define SDPOWER -1 128 | #define SDSS -1 129 | #define LED_PIN 0 130 | #define FAN_PIN -1 131 | #define PS_ON_PIN -1 132 | #define KILL_PIN -1 133 | 134 | #define HEATER_0_PIN 14 135 | #define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! 136 | 137 | /* 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) */ 138 | 139 | 140 | 141 | #endif 142 | 143 | 144 | /**************************************************************************************** 145 | * RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* 146 | * 147 | ****************************************************************************************/ 148 | #if MOTHERBOARD == 2 149 | #define KNOWN_BOARD 1 150 | 151 | #if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) 152 | #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. 153 | #endif 154 | 155 | #define X_STEP_PIN 15 156 | #define X_DIR_PIN 18 157 | #define X_ENABLE_PIN 19 158 | #define X_MIN_PIN 20 159 | #define X_MAX_PIN 21 160 | 161 | #define Y_STEP_PIN 23 162 | #define Y_DIR_PIN 22 163 | #define Y_ENABLE_PIN 24 164 | #define Y_MIN_PIN 25 165 | #define Y_MAX_PIN 26 166 | 167 | #define Z_STEP_PINN 27 168 | #define Z_DIR_PINN 28 169 | #define Z_ENABLE_PIN 29 170 | #define Z_MIN_PIN 30 171 | #define Z_MAX_PIN 31 172 | 173 | #define E_STEP_PIN 17 174 | #define E_DIR_PIN 16 175 | #define E_ENABLE_PIN -1 176 | 177 | #define SDPOWER -1 178 | #define SDSS 4 179 | #define LED_PIN 0 180 | 181 | #define SD_CARD_WRITE 2 182 | #define SD_CARD_DETECT 3 183 | #define SD_CARD_SELECT 4 184 | 185 | //our RS485 pins 186 | #define TX_ENABLE_PIN 12 187 | #define RX_ENABLE_PIN 13 188 | 189 | //pin for controlling the PSU. 190 | #define PS_ON_PIN 14 191 | 192 | #define FAN_PIN -1 193 | #define KILL_PIN -1 194 | 195 | #define HEATER_0_PIN -1 196 | #define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! 197 | 198 | 199 | 200 | 201 | #endif 202 | 203 | /**************************************************************************************** 204 | * Gen3 PLUS 205 | * 206 | ****************************************************************************************/ 207 | #if MOTHERBOARD == 21 208 | #define KNOWN_BOARD 1 209 | 210 | #ifndef __AVR_ATmega644P__ 211 | #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. 212 | #endif 213 | 214 | 215 | //x axis pins 216 | #define X_STEP_PIN 15 217 | #define X_DIR_PIN 18 218 | #define X_ENABLE_PIN 19 219 | #define X_MIN_PIN 20 220 | #define X_MAX_PIN -1 221 | 222 | //y axis pins 223 | #define Y_STEP_PIN 23 224 | #define Y_DIR_PIN 22 225 | #define Y_ENABLE_PIN 24 226 | #define Y_MIN_PIN 25 227 | #define Y_MAX_PIN -1 228 | 229 | //z axis pins 230 | #define Z_STEP_PIN 27 231 | #define Z_DIR_PIN 28 232 | #define Z_ENABLE_PIN 29 233 | #define Z_MIN_PIN 30 234 | #define Z_MAX_PIN -1 235 | 236 | #define E_DIR_PIN 21 237 | #define E_STEP_PIN 17 238 | #define E_ENABLE_PIN 13 239 | 240 | //heaters 241 | 242 | //pin for hot end heater 243 | #define HEATER_0_PIN 12 244 | 245 | //Pin for heated bed heater 246 | #define HEATER_1_PIN 5 247 | 248 | 249 | //pin for debugging. 250 | #define DEBUG_PIN -1 251 | 252 | //SD card pin 253 | 254 | #define SDSS 4 255 | 256 | #define SDPOWER -1 257 | #define FAN_PIN -1 258 | #define TEMP_0_PIN 0 259 | #define TEMP_1_PIN 5 260 | #define LED_PIN -1 261 | 262 | //pin for controlling the PSU. 263 | #define PS_ON_PIN 14 264 | 265 | #endif 266 | 267 | /**************************************************************************************** 268 | * Gen3 Monolithic Electronics 269 | * 270 | ****************************************************************************************/ 271 | #if MOTHERBOARD == 22 272 | #define KNOWN_BOARD 1 273 | 274 | #ifndef __AVR_ATmega644P__ 275 | #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. 276 | #endif 277 | 278 | #define DEBUG_PIN 0 279 | 280 | 281 | // x axis 282 | #define X_STEP_PIN 15 283 | #define X_DIR_PIN 18 284 | #define X_MIN_PIN 20 285 | #define X_ENABLE_PIN 24 //actually uses Y_enable_pin 286 | #define X_MAX_PIN -1 287 | 288 | // y axes 289 | #define Y_STEP_PIN 23 290 | #define Y_DIR_PIN 22 291 | #define Y_MIN_PIN 25 292 | #define Y_ENABLE_PIN 24 //shared with X_enable_pin 293 | #define Y_MAX_PIN -1 294 | 295 | // z axes 296 | #define Z_STEP_PIN 27 297 | #define Z_DIR_PIN 28 298 | #define Z_MIN_PIN 30 299 | #define Z_ENABLE_PIN 29 300 | #define Z_MAX_PIN -1 301 | 302 | //extruder pins 303 | #define E_STEP_PIN 12 304 | #define E_DIR_PIN 17 305 | #define E_ENABLE_PIN 3 306 | #define HEATER_0_PIN 16 307 | #define TEMP_0_PIN 0 308 | 309 | #define FAN_PIN -1 310 | 311 | //bed pins 312 | #define HEATER_1_PIN -1 313 | #define TEMP_1_PIN -1 314 | 315 | 316 | #define SDSS -1 317 | #define SDPOWER -1 318 | #define LED_PIN -1 319 | 320 | //pin for controlling the PSU. 321 | #define PS_ON_PIN 14 322 | 323 | #endif 324 | 325 | 326 | /**************************************************************************************** 327 | * Arduino Mega pin assignment 328 | * 329 | ****************************************************************************************/ 330 | #if MOTHERBOARD == 33 331 | #define MOTHERBOARD 3 332 | #define RAMPS_V_1_3 333 | #endif 334 | #if MOTHERBOARD == 3 335 | #define KNOWN_BOARD 1 336 | 337 | //////////////////FIX THIS////////////// 338 | #ifndef __AVR_ATmega1280__ 339 | #ifndef __AVR_ATmega2560__ 340 | #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. 341 | #endif 342 | #endif 343 | 344 | // uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 345 | // #define RAMPS_V_1_3 346 | // #define RAMPS_V_1_0 347 | 348 | #ifdef RAMPS_V_1_3 349 | 350 | #define X_STEP_PIN 54 351 | #define X_DIR_PIN 55 352 | #define X_ENABLE_PIN 38 353 | #define X_MIN_PIN 3 354 | #define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. 355 | 356 | #define Y_STEP_PIN 60 357 | #define Y_DIR_PIN 61 358 | #define Y_ENABLE_PIN 56 359 | #define Y_MIN_PIN 14 360 | #define Y_MAX_PIN -1 //15 361 | 362 | #define Z_STEP_PIN 46 363 | #define Z_DIR_PIN 48 364 | #define Z_ENABLE_PIN 62 365 | #define Z_MIN_PIN 18 366 | #define Z_MAX_PIN -1 //19 367 | 368 | #define E_STEP_PIN 26 369 | #define E_DIR_PIN 28 370 | #define E_ENABLE_PIN 24 371 | 372 | #define E_1_STEP_PIN 36 373 | #define E_1_DIR_PIN 34 374 | #define E_1_ENABLE_PIN 30 375 | 376 | #define SDPOWER -1 377 | #define SDSS 53 378 | #define LED_PIN 13 379 | #define FAN_PIN 9 380 | #define PS_ON_PIN 12 381 | #define KILL_PIN -1 382 | 383 | #define HEATER_0_PIN 10 384 | #define HEATER_1_PIN 8 385 | #define TEMP_0_PIN 13 // ANALOG NUMBERING 386 | #define TEMP_1_PIN 14 // ANALOG NUMBERING 387 | 388 | 389 | #else // RAMPS_V_1_1 or RAMPS_V_1_2 as default 390 | 391 | #define X_STEP_PIN 26 392 | #define X_DIR_PIN 28 393 | #define X_ENABLE_PIN 24 394 | #define X_MIN_PIN 3 395 | #define X_MAX_PIN -1 //2 396 | 397 | #define Y_STEP_PIN 38 398 | #define Y_DIR_PIN 40 399 | #define Y_ENABLE_PIN 36 400 | #define Y_MIN_PIN 16 401 | #define Y_MAX_PIN -1 //17 402 | 403 | #define Z_STEP_PIN 44 404 | #define Z_DIR_PIN 46 405 | #define Z_ENABLE_PIN 42 406 | #define Z_MIN_PIN 18 407 | #define Z_MAX_PIN -1 //19 408 | 409 | #define E_STEP_PIN 32 410 | #define E_DIR_PIN 34 411 | #define E_ENABLE_PIN 30 412 | 413 | #define SDPOWER 48 414 | #define SDSS 53 415 | #define LED_PIN 13 416 | #define PS_ON_PIN -1 417 | #define KILL_PIN -1 418 | 419 | 420 | 421 | #ifdef RAMPS_V_1_0 // RAMPS_V_1_0 422 | #define HEATER_0_PIN 12 // RAMPS 1.0 423 | #define HEATER_1_PIN -1 // RAMPS 1.0 424 | #define FAN_PIN 11 // RAMPS 1.0 425 | 426 | #else // RAMPS_V_1_1 or RAMPS_V_1_2 427 | #define HEATER_0_PIN 10 // RAMPS 1.1 428 | #define HEATER_1_PIN 8 // RAMPS 1.1 429 | #define FAN_PIN 9 // RAMPS 1.1 430 | #endif 431 | 432 | #define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! 433 | #define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! 434 | #endif 435 | 436 | // SPI for Max6675 Thermocouple 437 | 438 | #ifndef SDSUPPORT 439 | // these pins are defined in the SD library if building with SD support #define SCK_PIN 52 440 | #define MISO_PIN 50 441 | #define MOSI_PIN 51 442 | #define MAX6675_SS 53 443 | #else 444 | #define MAX6675_SS 49 445 | #endif 446 | 447 | 448 | #endif 449 | /**************************************************************************************** 450 | * Duemilanove w/ ATMega328P pin assignment 451 | * 452 | ****************************************************************************************/ 453 | #if MOTHERBOARD == 4 454 | #define KNOWN_BOARD 1 455 | 456 | #ifndef __AVR_ATmega328P__ 457 | #error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. 458 | #endif 459 | 460 | #define X_STEP_PIN 19 461 | #define X_DIR_PIN 18 462 | #define X_ENABLE_PIN -1 463 | #define X_MIN_PIN 17 464 | #define X_MAX_PIN -1 465 | 466 | #define Y_STEP_PIN 10 467 | #define Y_DIR_PIN 7 468 | #define Y_ENABLE_PIN -1 469 | #define Y_MIN_PIN 8 470 | #define Y_MAX_PIN -1 471 | 472 | #define Z_STEP_PIN 13 473 | #define Z_DIR_PIN 3 474 | #define Z_ENABLE_PIN 2 475 | #define Z_MIN_PIN 4 476 | #define Z_MAX_PIN -1 477 | 478 | #define E_STEP_PIN 11 479 | #define E_DIR_PIN 12 480 | #define E_ENABLE_PIN -1 481 | 482 | #define SDPOWER -1 483 | #define SDSS -1 484 | #define LED_PIN -1 485 | #define FAN_PIN 5 486 | #define PS_ON_PIN -1 487 | #define KILL_PIN -1 488 | 489 | #define HEATER_0_PIN 6 490 | #define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! 491 | 492 | 493 | #endif 494 | 495 | /**************************************************************************************** 496 | * Gen6 pin assignment 497 | * 498 | ****************************************************************************************/ 499 | #if MOTHERBOARD == 5 500 | #define KNOWN_BOARD 1 501 | 502 | #if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) 503 | #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. 504 | #endif 505 | 506 | //x axis pins 507 | #define X_STEP_PIN 15 508 | #define X_DIR_PIN 18 509 | #define X_ENABLE_PIN 19 510 | #define X_MIN_PIN 20 511 | #define X_MAX_PIN -1 512 | 513 | //y axis pins 514 | #define Y_STEP_PIN 23 515 | #define Y_DIR_PIN 22 516 | #define Y_ENABLE_PIN 24 517 | #define Y_MIN_PIN 25 518 | #define Y_MAX_PIN -1 519 | 520 | //z axis pins 521 | #define Z_STEP_PIN 27 522 | #define Z_DIR_PIN 28 523 | #define Z_ENABLE_PIN 29 524 | #define Z_MIN_PIN 30 525 | #define Z_MAX_PIN -1 526 | 527 | //extruder pins 528 | #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 529 | #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 530 | #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 531 | #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 532 | #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 533 | #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 534 | 535 | 536 | #define SDPOWER -1 537 | #define SDSS 17 538 | #define LED_PIN -1 //changed @ rkoeppl 20110410 539 | #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 540 | #define FAN_PIN -1 //changed @ rkoeppl 20110410 541 | #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 542 | //our pin for debugging. 543 | 544 | #define DEBUG_PIN 0 545 | 546 | //our RS485 pins 547 | #define TX_ENABLE_PIN 12 548 | #define RX_ENABLE_PIN 13 549 | 550 | #endif 551 | /**************************************************************************************** 552 | * Sanguinololu pin assignment 553 | * 554 | ****************************************************************************************/ 555 | #if MOTHERBOARD == 62 556 | #define MOTHERBOARD 6 557 | #define SANGUINOLOLU_V_1_2 558 | #endif 559 | #if MOTHERBOARD == 6 560 | #define KNOWN_BOARD 1 561 | #if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) 562 | #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. 563 | #endif 564 | 565 | #define X_STEP_PIN 15 566 | #define X_DIR_PIN 21 567 | #define X_MIN_PIN 18 568 | #define X_MAX_PIN -2 569 | 570 | #define Y_STEP_PIN 22 571 | #define Y_DIR_PIN 23 572 | #define Y_MIN_PIN 19 573 | #define Y_MAX_PIN -1 574 | 575 | #define Z_STEP_PIN 3 576 | #define Z_DIR_PIN 2 577 | #define Z_MIN_PIN 20 578 | #define Z_MAX_PIN -1 579 | 580 | #define E_STEP_PIN 1 581 | #define E_DIR_PIN 0 582 | 583 | #define LED_PIN -1 584 | 585 | #define FAN_PIN -1 586 | 587 | #define PS_ON_PIN -1 588 | #define KILL_PIN -1 589 | 590 | #define HEATER_0_PIN 13 // (extruder) 591 | 592 | #ifdef SANGUINOLOLU_V_1_2 593 | 594 | #define HEATER_1_PIN 12 // (bed) 595 | #define X_ENABLE_PIN 14 596 | #define Y_ENABLE_PIN 14 597 | #define Z_ENABLE_PIN 26 598 | #define E_ENABLE_PIN 14 599 | 600 | #else 601 | 602 | #define HEATER_1_PIN 14 // (bed) 603 | #define X_ENABLE_PIN -1 604 | #define Y_ENABLE_PIN -1 605 | #define Z_ENABLE_PIN -1 606 | #define E_ENABLE_PIN -1 607 | 608 | #endif 609 | 610 | #define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) 611 | #define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) 612 | #define SDPOWER -1 613 | #define SDSS 31 614 | 615 | #ifndef KNOWN_BOARD 616 | #error Unknown MOTHERBOARD value in configuration.h 617 | #endif 618 | 619 | #endif 620 | 621 | #endif 622 | -------------------------------------------------------------------------------- /Sprinter/Sd2Card.cpp: -------------------------------------------------------------------------------- 1 | /* Arduino Sd2Card Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino Sd2Card Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino Sd2Card Library. If not, see 18 | * . 19 | */ 20 | #include 21 | #include "Sd2Card.h" 22 | //------------------------------------------------------------------------------ 23 | #ifndef SOFTWARE_SPI 24 | // functions for hardware SPI 25 | /** Send a byte to the card */ 26 | static void spiSend(uint8_t b) { 27 | SPDR = b; 28 | while (!(SPSR & (1 << SPIF))); 29 | } 30 | /** Receive a byte from the card */ 31 | static uint8_t spiRec(void) { 32 | spiSend(0XFF); 33 | return SPDR; 34 | } 35 | #else // SOFTWARE_SPI 36 | //------------------------------------------------------------------------------ 37 | /** nop to tune soft SPI timing */ 38 | #define nop asm volatile ("nop\n\t") 39 | //------------------------------------------------------------------------------ 40 | /** Soft SPI receive */ 41 | uint8_t spiRec(void) { 42 | uint8_t data = 0; 43 | // no interrupts during byte receive - about 8 us 44 | cli(); 45 | // output pin high - like sending 0XFF 46 | fastDigitalWrite(SPI_MOSI_PIN, HIGH); 47 | 48 | for (uint8_t i = 0; i < 8; i++) { 49 | fastDigitalWrite(SPI_SCK_PIN, HIGH); 50 | 51 | // adjust so SCK is nice 52 | nop; 53 | nop; 54 | 55 | data <<= 1; 56 | 57 | if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; 58 | 59 | fastDigitalWrite(SPI_SCK_PIN, LOW); 60 | } 61 | // enable interrupts 62 | sei(); 63 | return data; 64 | } 65 | //------------------------------------------------------------------------------ 66 | /** Soft SPI send */ 67 | void spiSend(uint8_t data) { 68 | // no interrupts during byte send - about 8 us 69 | cli(); 70 | for (uint8_t i = 0; i < 8; i++) { 71 | fastDigitalWrite(SPI_SCK_PIN, LOW); 72 | 73 | fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); 74 | 75 | data <<= 1; 76 | 77 | fastDigitalWrite(SPI_SCK_PIN, HIGH); 78 | } 79 | // hold SCK high for a few ns 80 | nop; 81 | nop; 82 | nop; 83 | nop; 84 | 85 | fastDigitalWrite(SPI_SCK_PIN, LOW); 86 | // enable interrupts 87 | sei(); 88 | } 89 | #endif // SOFTWARE_SPI 90 | //------------------------------------------------------------------------------ 91 | // send command and return error code. Return zero for OK 92 | uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { 93 | // end read if in partialBlockRead mode 94 | readEnd(); 95 | 96 | // select card 97 | chipSelectLow(); 98 | 99 | // wait up to 300 ms if busy 100 | waitNotBusy(300); 101 | 102 | // send command 103 | spiSend(cmd | 0x40); 104 | 105 | // send argument 106 | for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); 107 | 108 | // send CRC 109 | uint8_t crc = 0XFF; 110 | if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 111 | if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA 112 | spiSend(crc); 113 | 114 | // wait for response 115 | for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); 116 | return status_; 117 | } 118 | //------------------------------------------------------------------------------ 119 | /** 120 | * Determine the size of an SD flash memory card. 121 | * 122 | * \return The number of 512 byte data blocks in the card 123 | * or zero if an error occurs. 124 | */ 125 | uint32_t Sd2Card::cardSize(void) { 126 | csd_t csd; 127 | if (!readCSD(&csd)) return 0; 128 | if (csd.v1.csd_ver == 0) { 129 | uint8_t read_bl_len = csd.v1.read_bl_len; 130 | uint16_t c_size = (csd.v1.c_size_high << 10) 131 | | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; 132 | uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) 133 | | csd.v1.c_size_mult_low; 134 | return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); 135 | } else if (csd.v2.csd_ver == 1) { 136 | uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) 137 | | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; 138 | return (c_size + 1) << 10; 139 | } else { 140 | error(SD_CARD_ERROR_BAD_CSD); 141 | return 0; 142 | } 143 | } 144 | //------------------------------------------------------------------------------ 145 | void Sd2Card::chipSelectHigh(void) { 146 | digitalWrite(chipSelectPin_, HIGH); 147 | } 148 | //------------------------------------------------------------------------------ 149 | void Sd2Card::chipSelectLow(void) { 150 | digitalWrite(chipSelectPin_, LOW); 151 | } 152 | //------------------------------------------------------------------------------ 153 | /** Erase a range of blocks. 154 | * 155 | * \param[in] firstBlock The address of the first block in the range. 156 | * \param[in] lastBlock The address of the last block in the range. 157 | * 158 | * \note This function requests the SD card to do a flash erase for a 159 | * range of blocks. The data on the card after an erase operation is 160 | * either 0 or 1, depends on the card vendor. The card must support 161 | * single block erase. 162 | * 163 | * \return The value one, true, is returned for success and 164 | * the value zero, false, is returned for failure. 165 | */ 166 | uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { 167 | if (!eraseSingleBlockEnable()) { 168 | error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); 169 | goto fail; 170 | } 171 | if (type_ != SD_CARD_TYPE_SDHC) { 172 | firstBlock <<= 9; 173 | lastBlock <<= 9; 174 | } 175 | if (cardCommand(CMD32, firstBlock) 176 | || cardCommand(CMD33, lastBlock) 177 | || cardCommand(CMD38, 0)) { 178 | error(SD_CARD_ERROR_ERASE); 179 | goto fail; 180 | } 181 | if (!waitNotBusy(SD_ERASE_TIMEOUT)) { 182 | error(SD_CARD_ERROR_ERASE_TIMEOUT); 183 | goto fail; 184 | } 185 | chipSelectHigh(); 186 | return true; 187 | 188 | fail: 189 | chipSelectHigh(); 190 | return false; 191 | } 192 | //------------------------------------------------------------------------------ 193 | /** Determine if card supports single block erase. 194 | * 195 | * \return The value one, true, is returned if single block erase is supported. 196 | * The value zero, false, is returned if single block erase is not supported. 197 | */ 198 | uint8_t Sd2Card::eraseSingleBlockEnable(void) { 199 | csd_t csd; 200 | return readCSD(&csd) ? csd.v1.erase_blk_en : 0; 201 | } 202 | //------------------------------------------------------------------------------ 203 | /** 204 | * Initialize an SD flash memory card. 205 | * 206 | * \param[in] sckRateID SPI clock rate selector. See setSckRate(). 207 | * \param[in] chipSelectPin SD chip select pin number. 208 | * 209 | * \return The value one, true, is returned for success and 210 | * the value zero, false, is returned for failure. The reason for failure 211 | * can be determined by calling errorCode() and errorData(). 212 | */ 213 | uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { 214 | errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0; 215 | chipSelectPin_ = chipSelectPin; 216 | // 16-bit init start time allows over a minute 217 | uint16_t t0 = (uint16_t)millis(); 218 | uint32_t arg; 219 | 220 | // set pin modes 221 | pinMode(chipSelectPin_, OUTPUT); 222 | chipSelectHigh(); 223 | pinMode(SPI_MISO_PIN, INPUT); 224 | pinMode(SPI_MOSI_PIN, OUTPUT); 225 | pinMode(SPI_SCK_PIN, OUTPUT); 226 | 227 | #ifndef SOFTWARE_SPI 228 | // SS must be in output mode even it is not chip select 229 | pinMode(SS_PIN, OUTPUT); 230 | // Enable SPI, Master, clock rate f_osc/128 231 | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); 232 | // clear double speed 233 | SPSR &= ~(1 << SPI2X); 234 | #endif // SOFTWARE_SPI 235 | 236 | // must supply min of 74 clock cycles with CS high. 237 | for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); 238 | 239 | chipSelectLow(); 240 | 241 | // command to go idle in SPI mode 242 | while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { 243 | if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { 244 | error(SD_CARD_ERROR_CMD0); 245 | goto fail; 246 | } 247 | } 248 | // check SD version 249 | if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { 250 | type(SD_CARD_TYPE_SD1); 251 | } else { 252 | // only need last byte of r7 response 253 | for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); 254 | if (status_ != 0XAA) { 255 | error(SD_CARD_ERROR_CMD8); 256 | goto fail; 257 | } 258 | type(SD_CARD_TYPE_SD2); 259 | } 260 | // initialize card and send host supports SDHC if SD2 261 | arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; 262 | 263 | while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { 264 | // check for timeout 265 | if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { 266 | error(SD_CARD_ERROR_ACMD41); 267 | goto fail; 268 | } 269 | } 270 | // if SD2 read OCR register to check for SDHC card 271 | if (type() == SD_CARD_TYPE_SD2) { 272 | if (cardCommand(CMD58, 0)) { 273 | error(SD_CARD_ERROR_CMD58); 274 | goto fail; 275 | } 276 | if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); 277 | // discard rest of ocr - contains allowed voltage range 278 | for (uint8_t i = 0; i < 3; i++) spiRec(); 279 | } 280 | chipSelectHigh(); 281 | 282 | #ifndef SOFTWARE_SPI 283 | return setSckRate(sckRateID); 284 | #else // SOFTWARE_SPI 285 | return true; 286 | #endif // SOFTWARE_SPI 287 | 288 | fail: 289 | chipSelectHigh(); 290 | return false; 291 | } 292 | //------------------------------------------------------------------------------ 293 | /** 294 | * Enable or disable partial block reads. 295 | * 296 | * Enabling partial block reads improves performance by allowing a block 297 | * to be read over the SPI bus as several sub-blocks. Errors may occur 298 | * if the time between reads is too long since the SD card may timeout. 299 | * The SPI SS line will be held low until the entire block is read or 300 | * readEnd() is called. 301 | * 302 | * Use this for applications like the Adafruit Wave Shield. 303 | * 304 | * \param[in] value The value TRUE (non-zero) or FALSE (zero).) 305 | */ 306 | void Sd2Card::partialBlockRead(uint8_t value) { 307 | readEnd(); 308 | partialBlockRead_ = value; 309 | } 310 | //------------------------------------------------------------------------------ 311 | /** 312 | * Read a 512 byte block from an SD card device. 313 | * 314 | * \param[in] block Logical block to be read. 315 | * \param[out] dst Pointer to the location that will receive the data. 316 | 317 | * \return The value one, true, is returned for success and 318 | * the value zero, false, is returned for failure. 319 | */ 320 | uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { 321 | return readData(block, 0, 512, dst); 322 | } 323 | //------------------------------------------------------------------------------ 324 | /** 325 | * Read part of a 512 byte block from an SD card. 326 | * 327 | * \param[in] block Logical block to be read. 328 | * \param[in] offset Number of bytes to skip at start of block 329 | * \param[out] dst Pointer to the location that will receive the data. 330 | * \param[in] count Number of bytes to read 331 | * \return The value one, true, is returned for success and 332 | * the value zero, false, is returned for failure. 333 | */ 334 | uint8_t Sd2Card::readData(uint32_t block, 335 | uint16_t offset, uint16_t count, uint8_t* dst) { 336 | uint16_t n; 337 | if (count == 0) return true; 338 | if ((count + offset) > 512) { 339 | goto fail; 340 | } 341 | if (!inBlock_ || block != block_ || offset < offset_) { 342 | block_ = block; 343 | // use address if not SDHC card 344 | if (type()!= SD_CARD_TYPE_SDHC) block <<= 9; 345 | if (cardCommand(CMD17, block)) { 346 | error(SD_CARD_ERROR_CMD17); 347 | goto fail; 348 | } 349 | if (!waitStartBlock()) { 350 | goto fail; 351 | } 352 | offset_ = 0; 353 | inBlock_ = 1; 354 | } 355 | 356 | #ifdef OPTIMIZE_HARDWARE_SPI 357 | // start first spi transfer 358 | SPDR = 0XFF; 359 | 360 | // skip data before offset 361 | for (;offset_ < offset; offset_++) { 362 | while (!(SPSR & (1 << SPIF))); 363 | SPDR = 0XFF; 364 | } 365 | // transfer data 366 | n = count - 1; 367 | for (uint16_t i = 0; i < n; i++) { 368 | while (!(SPSR & (1 << SPIF))); 369 | dst[i] = SPDR; 370 | SPDR = 0XFF; 371 | } 372 | // wait for last byte 373 | while (!(SPSR & (1 << SPIF))); 374 | dst[n] = SPDR; 375 | 376 | #else // OPTIMIZE_HARDWARE_SPI 377 | 378 | // skip data before offset 379 | for (;offset_ < offset; offset_++) { 380 | spiRec(); 381 | } 382 | // transfer data 383 | for (uint16_t i = 0; i < count; i++) { 384 | dst[i] = spiRec(); 385 | } 386 | #endif // OPTIMIZE_HARDWARE_SPI 387 | 388 | offset_ += count; 389 | if (!partialBlockRead_ || offset_ >= 512) { 390 | // read rest of data, checksum and set chip select high 391 | readEnd(); 392 | } 393 | return true; 394 | 395 | fail: 396 | chipSelectHigh(); 397 | return false; 398 | } 399 | //------------------------------------------------------------------------------ 400 | /** Skip remaining data in a block when in partial block read mode. */ 401 | void Sd2Card::readEnd(void) { 402 | if (inBlock_) { 403 | // skip data and crc 404 | #ifdef OPTIMIZE_HARDWARE_SPI 405 | // optimize skip for hardware 406 | SPDR = 0XFF; 407 | while (offset_++ < 513) { 408 | while (!(SPSR & (1 << SPIF))); 409 | SPDR = 0XFF; 410 | } 411 | // wait for last crc byte 412 | while (!(SPSR & (1 << SPIF))); 413 | #else // OPTIMIZE_HARDWARE_SPI 414 | while (offset_++ < 514) spiRec(); 415 | #endif // OPTIMIZE_HARDWARE_SPI 416 | chipSelectHigh(); 417 | inBlock_ = 0; 418 | } 419 | } 420 | //------------------------------------------------------------------------------ 421 | /** read CID or CSR register */ 422 | uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { 423 | uint8_t* dst = reinterpret_cast(buf); 424 | if (cardCommand(cmd, 0)) { 425 | error(SD_CARD_ERROR_READ_REG); 426 | goto fail; 427 | } 428 | if (!waitStartBlock()) goto fail; 429 | // transfer data 430 | for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec(); 431 | spiRec(); // get first crc byte 432 | spiRec(); // get second crc byte 433 | chipSelectHigh(); 434 | return true; 435 | 436 | fail: 437 | chipSelectHigh(); 438 | return false; 439 | } 440 | //------------------------------------------------------------------------------ 441 | /** 442 | * Set the SPI clock rate. 443 | * 444 | * \param[in] sckRateID A value in the range [0, 6]. 445 | * 446 | * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum 447 | * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 448 | * for \a scsRateID = 6. 449 | * 450 | * \return The value one, true, is returned for success and the value zero, 451 | * false, is returned for an invalid value of \a sckRateID. 452 | */ 453 | uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { 454 | if (sckRateID > 6) { 455 | error(SD_CARD_ERROR_SCK_RATE); 456 | return false; 457 | } 458 | // see avr processor datasheet for SPI register bit definitions 459 | if ((sckRateID & 1) || sckRateID == 6) { 460 | SPSR &= ~(1 << SPI2X); 461 | } else { 462 | SPSR |= (1 << SPI2X); 463 | } 464 | SPCR &= ~((1 < SD_READ_TIMEOUT) { 485 | error(SD_CARD_ERROR_READ_TIMEOUT); 486 | goto fail; 487 | } 488 | } 489 | if (status_ != DATA_START_BLOCK) { 490 | error(SD_CARD_ERROR_READ); 491 | goto fail; 492 | } 493 | return true; 494 | 495 | fail: 496 | chipSelectHigh(); 497 | return false; 498 | } 499 | //------------------------------------------------------------------------------ 500 | /** 501 | * Writes a 512 byte block to an SD card. 502 | * 503 | * \param[in] blockNumber Logical block to be written. 504 | * \param[in] src Pointer to the location of the data to be written. 505 | * \return The value one, true, is returned for success and 506 | * the value zero, false, is returned for failure. 507 | */ 508 | uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { 509 | #if SD_PROTECT_BLOCK_ZERO 510 | // don't allow write to first block 511 | if (blockNumber == 0) { 512 | error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); 513 | goto fail; 514 | } 515 | #endif // SD_PROTECT_BLOCK_ZERO 516 | 517 | // use address if not SDHC card 518 | if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; 519 | if (cardCommand(CMD24, blockNumber)) { 520 | error(SD_CARD_ERROR_CMD24); 521 | goto fail; 522 | } 523 | if (!writeData(DATA_START_BLOCK, src)) goto fail; 524 | 525 | // wait for flash programming to complete 526 | if (!waitNotBusy(SD_WRITE_TIMEOUT)) { 527 | error(SD_CARD_ERROR_WRITE_TIMEOUT); 528 | goto fail; 529 | } 530 | // response is r2 so get and check two bytes for nonzero 531 | if (cardCommand(CMD13, 0) || spiRec()) { 532 | error(SD_CARD_ERROR_WRITE_PROGRAMMING); 533 | goto fail; 534 | } 535 | chipSelectHigh(); 536 | return true; 537 | 538 | fail: 539 | chipSelectHigh(); 540 | return false; 541 | } 542 | //------------------------------------------------------------------------------ 543 | /** Write one data block in a multiple block write sequence */ 544 | uint8_t Sd2Card::writeData(const uint8_t* src) { 545 | // wait for previous write to finish 546 | if (!waitNotBusy(SD_WRITE_TIMEOUT)) { 547 | error(SD_CARD_ERROR_WRITE_MULTIPLE); 548 | chipSelectHigh(); 549 | return false; 550 | } 551 | return writeData(WRITE_MULTIPLE_TOKEN, src); 552 | } 553 | //------------------------------------------------------------------------------ 554 | // send one block of data for write block or write multiple blocks 555 | uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { 556 | #ifdef OPTIMIZE_HARDWARE_SPI 557 | 558 | // send data - optimized loop 559 | SPDR = token; 560 | 561 | // send two byte per iteration 562 | for (uint16_t i = 0; i < 512; i += 2) { 563 | while (!(SPSR & (1 << SPIF))); 564 | SPDR = src[i]; 565 | while (!(SPSR & (1 << SPIF))); 566 | SPDR = src[i+1]; 567 | } 568 | 569 | // wait for last data byte 570 | while (!(SPSR & (1 << SPIF))); 571 | 572 | #else // OPTIMIZE_HARDWARE_SPI 573 | spiSend(token); 574 | for (uint16_t i = 0; i < 512; i++) { 575 | spiSend(src[i]); 576 | } 577 | #endif // OPTIMIZE_HARDWARE_SPI 578 | spiSend(0xff); // dummy crc 579 | spiSend(0xff); // dummy crc 580 | 581 | status_ = spiRec(); 582 | if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { 583 | error(SD_CARD_ERROR_WRITE); 584 | chipSelectHigh(); 585 | return false; 586 | } 587 | return true; 588 | } 589 | //------------------------------------------------------------------------------ 590 | /** Start a write multiple blocks sequence. 591 | * 592 | * \param[in] blockNumber Address of first block in sequence. 593 | * \param[in] eraseCount The number of blocks to be pre-erased. 594 | * 595 | * \note This function is used with writeData() and writeStop() 596 | * for optimized multiple block writes. 597 | * 598 | * \return The value one, true, is returned for success and 599 | * the value zero, false, is returned for failure. 600 | */ 601 | uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { 602 | #if SD_PROTECT_BLOCK_ZERO 603 | // don't allow write to first block 604 | if (blockNumber == 0) { 605 | error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); 606 | goto fail; 607 | } 608 | #endif // SD_PROTECT_BLOCK_ZERO 609 | // send pre-erase count 610 | if (cardAcmd(ACMD23, eraseCount)) { 611 | error(SD_CARD_ERROR_ACMD23); 612 | goto fail; 613 | } 614 | // use address if not SDHC card 615 | if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; 616 | if (cardCommand(CMD25, blockNumber)) { 617 | error(SD_CARD_ERROR_CMD25); 618 | goto fail; 619 | } 620 | return true; 621 | 622 | fail: 623 | chipSelectHigh(); 624 | return false; 625 | } 626 | //------------------------------------------------------------------------------ 627 | /** End a write multiple blocks sequence. 628 | * 629 | * \return The value one, true, is returned for success and 630 | * the value zero, false, is returned for failure. 631 | */ 632 | uint8_t Sd2Card::writeStop(void) { 633 | if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; 634 | spiSend(STOP_TRAN_TOKEN); 635 | if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; 636 | chipSelectHigh(); 637 | return true; 638 | 639 | fail: 640 | error(SD_CARD_ERROR_STOP_TRAN); 641 | chipSelectHigh(); 642 | return false; 643 | } 644 | -------------------------------------------------------------------------------- /Sprinter/SdFat.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | #ifndef SdFat_h 21 | #define SdFat_h 22 | /** 23 | * \file 24 | * SdFile and SdVolume classes 25 | */ 26 | #include 27 | #include "Sd2Card.h" 28 | #include "FatStructs.h" 29 | #include "Print.h" 30 | //------------------------------------------------------------------------------ 31 | /** 32 | * Allow use of deprecated functions if non-zero 33 | */ 34 | #define ALLOW_DEPRECATED_FUNCTIONS 1 35 | //------------------------------------------------------------------------------ 36 | // forward declaration since SdVolume is used in SdFile 37 | class SdVolume; 38 | //============================================================================== 39 | // SdFile class 40 | 41 | // flags for ls() 42 | /** ls() flag to print modify date */ 43 | uint8_t const LS_DATE = 1; 44 | /** ls() flag to print file size */ 45 | uint8_t const LS_SIZE = 2; 46 | /** ls() flag for recursive list of subdirectories */ 47 | uint8_t const LS_R = 4; 48 | 49 | // use the gnu style oflag in open() 50 | /** open() oflag for reading */ 51 | uint8_t const O_READ = 0X01; 52 | /** open() oflag - same as O_READ */ 53 | uint8_t const O_RDONLY = O_READ; 54 | /** open() oflag for write */ 55 | uint8_t const O_WRITE = 0X02; 56 | /** open() oflag - same as O_WRITE */ 57 | uint8_t const O_WRONLY = O_WRITE; 58 | /** open() oflag for reading and writing */ 59 | uint8_t const O_RDWR = (O_READ | O_WRITE); 60 | /** open() oflag mask for access modes */ 61 | uint8_t const O_ACCMODE = (O_READ | O_WRITE); 62 | /** The file offset shall be set to the end of the file prior to each write. */ 63 | uint8_t const O_APPEND = 0X04; 64 | /** synchronous writes - call sync() after each write */ 65 | uint8_t const O_SYNC = 0X08; 66 | /** create the file if nonexistent */ 67 | uint8_t const O_CREAT = 0X10; 68 | /** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ 69 | uint8_t const O_EXCL = 0X20; 70 | /** truncate the file to zero length */ 71 | uint8_t const O_TRUNC = 0X40; 72 | 73 | // flags for timestamp 74 | /** set the file's last access date */ 75 | uint8_t const T_ACCESS = 1; 76 | /** set the file's creation date and time */ 77 | uint8_t const T_CREATE = 2; 78 | /** Set the file's write date and time */ 79 | uint8_t const T_WRITE = 4; 80 | // values for type_ 81 | /** This SdFile has not been opened. */ 82 | uint8_t const FAT_FILE_TYPE_CLOSED = 0; 83 | /** SdFile for a file */ 84 | uint8_t const FAT_FILE_TYPE_NORMAL = 1; 85 | /** SdFile for a FAT16 root directory */ 86 | uint8_t const FAT_FILE_TYPE_ROOT16 = 2; 87 | /** SdFile for a FAT32 root directory */ 88 | uint8_t const FAT_FILE_TYPE_ROOT32 = 3; 89 | /** SdFile for a subdirectory */ 90 | uint8_t const FAT_FILE_TYPE_SUBDIR = 4; 91 | /** Test value for directory type */ 92 | uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; 93 | 94 | /** date field for FAT directory entry */ 95 | static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { 96 | return (year - 1980) << 9 | month << 5 | day; 97 | } 98 | /** year part of FAT directory date field */ 99 | static inline uint16_t FAT_YEAR(uint16_t fatDate) { 100 | return 1980 + (fatDate >> 9); 101 | } 102 | /** month part of FAT directory date field */ 103 | static inline uint8_t FAT_MONTH(uint16_t fatDate) { 104 | return (fatDate >> 5) & 0XF; 105 | } 106 | /** day part of FAT directory date field */ 107 | static inline uint8_t FAT_DAY(uint16_t fatDate) { 108 | return fatDate & 0X1F; 109 | } 110 | /** time field for FAT directory entry */ 111 | static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { 112 | return hour << 11 | minute << 5 | second >> 1; 113 | } 114 | /** hour part of FAT directory time field */ 115 | static inline uint8_t FAT_HOUR(uint16_t fatTime) { 116 | return fatTime >> 11; 117 | } 118 | /** minute part of FAT directory time field */ 119 | static inline uint8_t FAT_MINUTE(uint16_t fatTime) { 120 | return(fatTime >> 5) & 0X3F; 121 | } 122 | /** second part of FAT directory time field */ 123 | static inline uint8_t FAT_SECOND(uint16_t fatTime) { 124 | return 2*(fatTime & 0X1F); 125 | } 126 | /** Default date for file timestamps is 1 Jan 2000 */ 127 | uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; 128 | /** Default time for file timestamp is 1 am */ 129 | uint16_t const FAT_DEFAULT_TIME = (1 << 11); 130 | //------------------------------------------------------------------------------ 131 | /** 132 | * \class SdFile 133 | * \brief Access FAT16 and FAT32 files on SD and SDHC cards. 134 | */ 135 | class SdFile : public Print { 136 | public: 137 | /** Create an instance of SdFile. */ 138 | SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} 139 | /** 140 | * writeError is set to true if an error occurs during a write(). 141 | * Set writeError to false before calling print() and/or write() and check 142 | * for true after calls to print() and/or write(). 143 | */ 144 | bool writeError; 145 | /** 146 | * Cancel unbuffered reads for this file. 147 | * See setUnbufferedRead() 148 | */ 149 | void clearUnbufferedRead(void) { 150 | flags_ &= ~F_FILE_UNBUFFERED_READ; 151 | } 152 | uint8_t close(void); 153 | uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); 154 | uint8_t createContiguous(SdFile* dirFile, 155 | const char* fileName, uint32_t size); 156 | /** \return The current cluster number for a file or directory. */ 157 | uint32_t curCluster(void) const {return curCluster_;} 158 | /** \return The current position for a file or directory. */ 159 | uint32_t curPosition(void) const {return curPosition_;} 160 | /** 161 | * Set the date/time callback function 162 | * 163 | * \param[in] dateTime The user's call back function. The callback 164 | * function is of the form: 165 | * 166 | * \code 167 | * void dateTime(uint16_t* date, uint16_t* time) { 168 | * uint16_t year; 169 | * uint8_t month, day, hour, minute, second; 170 | * 171 | * // User gets date and time from GPS or real-time clock here 172 | * 173 | * // return date using FAT_DATE macro to format fields 174 | * *date = FAT_DATE(year, month, day); 175 | * 176 | * // return time using FAT_TIME macro to format fields 177 | * *time = FAT_TIME(hour, minute, second); 178 | * } 179 | * \endcode 180 | * 181 | * Sets the function that is called when a file is created or when 182 | * a file's directory entry is modified by sync(). All timestamps, 183 | * access, creation, and modify, are set when a file is created. 184 | * sync() maintains the last access date and last modify date/time. 185 | * 186 | * See the timestamp() function. 187 | */ 188 | static void dateTimeCallback( 189 | void (*dateTime)(uint16_t* date, uint16_t* time)) { 190 | dateTime_ = dateTime; 191 | } 192 | /** 193 | * Cancel the date/time callback function. 194 | */ 195 | static void dateTimeCallbackCancel(void) { 196 | // use explicit zero since NULL is not defined for Sanguino 197 | dateTime_ = 0; 198 | } 199 | /** \return Address of the block that contains this file's directory. */ 200 | uint32_t dirBlock(void) const {return dirBlock_;} 201 | uint8_t dirEntry(dir_t* dir); 202 | /** \return Index of this file's directory in the block dirBlock. */ 203 | uint8_t dirIndex(void) const {return dirIndex_;} 204 | static void dirName(const dir_t& dir, char* name); 205 | /** \return The total number of bytes in a file or directory. */ 206 | uint32_t fileSize(void) const {return fileSize_;} 207 | /** \return The first cluster number for a file or directory. */ 208 | uint32_t firstCluster(void) const {return firstCluster_;} 209 | /** \return True if this is a SdFile for a directory else false. */ 210 | uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;} 211 | /** \return True if this is a SdFile for a file else false. */ 212 | uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;} 213 | /** \return True if this is a SdFile for an open file/directory else false. */ 214 | uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;} 215 | /** \return True if this is a SdFile for a subdirectory else false. */ 216 | uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;} 217 | /** \return True if this is a SdFile for the root directory. */ 218 | uint8_t isRoot(void) const { 219 | return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; 220 | } 221 | void ls(uint8_t flags = 0, uint8_t indent = 0); 222 | uint8_t makeDir(SdFile* dir, const char* dirName); 223 | uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag); 224 | uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag); 225 | 226 | uint8_t openRoot(SdVolume* vol); 227 | static void printDirName(const dir_t& dir, uint8_t width); 228 | static void printFatDate(uint16_t fatDate); 229 | static void printFatTime(uint16_t fatTime); 230 | static void printTwoDigits(uint8_t v); 231 | /** 232 | * Read the next byte from a file. 233 | * 234 | * \return For success read returns the next byte in the file as an int. 235 | * If an error occurs or end of file is reached -1 is returned. 236 | */ 237 | int16_t read(void) { 238 | uint8_t b; 239 | return read(&b, 1) == 1 ? b : -1; 240 | } 241 | int16_t read(void* buf, uint16_t nbyte); 242 | int8_t readDir(dir_t* dir); 243 | static uint8_t remove(SdFile* dirFile, const char* fileName); 244 | uint8_t remove(void); 245 | /** Set the file's current position to zero. */ 246 | void rewind(void) { 247 | curPosition_ = curCluster_ = 0; 248 | } 249 | uint8_t rmDir(void); 250 | uint8_t rmRfStar(void); 251 | /** Set the files position to current position + \a pos. See seekSet(). */ 252 | uint8_t seekCur(uint32_t pos) { 253 | return seekSet(curPosition_ + pos); 254 | } 255 | /** 256 | * Set the files current position to end of file. Useful to position 257 | * a file for append. See seekSet(). 258 | */ 259 | uint8_t seekEnd(void) {return seekSet(fileSize_);} 260 | uint8_t seekSet(uint32_t pos); 261 | /** 262 | * Use unbuffered reads to access this file. Used with Wave 263 | * Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. 264 | * 265 | * Not recommended for normal applications. 266 | */ 267 | void setUnbufferedRead(void) { 268 | if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ; 269 | } 270 | uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, 271 | uint8_t hour, uint8_t minute, uint8_t second); 272 | uint8_t sync(void); 273 | /** Type of this SdFile. You should use isFile() or isDir() instead of type() 274 | * if possible. 275 | * 276 | * \return The file or directory type. 277 | */ 278 | uint8_t type(void) const {return type_;} 279 | uint8_t truncate(uint32_t size); 280 | /** \return Unbuffered read flag. */ 281 | uint8_t unbufferedRead(void) const { 282 | return flags_ & F_FILE_UNBUFFERED_READ; 283 | } 284 | /** \return SdVolume that contains this file. */ 285 | SdVolume* volume(void) const {return vol_;} 286 | void write(uint8_t b); 287 | int16_t write(const void* buf, uint16_t nbyte); 288 | void write(const char* str); 289 | void write_P(PGM_P str); 290 | void writeln_P(PGM_P str); 291 | //------------------------------------------------------------------------------ 292 | #if ALLOW_DEPRECATED_FUNCTIONS 293 | // Deprecated functions - suppress cpplint warnings with NOLINT comment 294 | /** \deprecated Use: 295 | * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); 296 | */ 297 | uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT 298 | return contiguousRange(&bgnBlock, &endBlock); 299 | } 300 | /** \deprecated Use: 301 | * uint8_t SdFile::createContiguous(SdFile* dirFile, 302 | * const char* fileName, uint32_t size) 303 | */ 304 | uint8_t createContiguous(SdFile& dirFile, // NOLINT 305 | const char* fileName, uint32_t size) { 306 | return createContiguous(&dirFile, fileName, size); 307 | } 308 | 309 | /** 310 | * \deprecated Use: 311 | * static void SdFile::dateTimeCallback( 312 | * void (*dateTime)(uint16_t* date, uint16_t* time)); 313 | */ 314 | static void dateTimeCallback( 315 | void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT 316 | oldDateTime_ = dateTime; 317 | dateTime_ = dateTime ? oldToNew : 0; 318 | } 319 | /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ 320 | uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT 321 | /** \deprecated Use: 322 | * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); 323 | */ 324 | uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT 325 | return makeDir(&dir, dirName); 326 | } 327 | /** \deprecated Use: 328 | * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); 329 | */ 330 | uint8_t open(SdFile& dirFile, // NOLINT 331 | const char* fileName, uint8_t oflag) { 332 | return open(&dirFile, fileName, oflag); 333 | } 334 | /** \deprecated Do not use in new apps */ 335 | uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT 336 | return open(dirFile, fileName, O_RDWR); 337 | } 338 | /** \deprecated Use: 339 | * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); 340 | */ 341 | uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT 342 | return open(&dirFile, index, oflag); 343 | } 344 | /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ 345 | uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT 346 | 347 | /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ 348 | int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT 349 | /** \deprecated Use: 350 | * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); 351 | */ 352 | static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT 353 | return remove(&dirFile, fileName); 354 | } 355 | //------------------------------------------------------------------------------ 356 | // rest are private 357 | private: 358 | static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT 359 | static void oldToNew(uint16_t* date, uint16_t* time) { 360 | uint16_t d; 361 | uint16_t t; 362 | oldDateTime_(d, t); 363 | *date = d; 364 | *time = t; 365 | } 366 | #endif // ALLOW_DEPRECATED_FUNCTIONS 367 | private: 368 | // bits defined in flags_ 369 | // should be 0XF 370 | static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); 371 | // available bits 372 | static uint8_t const F_UNUSED = 0X30; 373 | // use unbuffered SD read 374 | static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; 375 | // sync of directory entry required 376 | static uint8_t const F_FILE_DIR_DIRTY = 0X80; 377 | 378 | // make sure F_OFLAG is ok 379 | #if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG) 380 | #error flags_ bits conflict 381 | #endif // flags_ bits 382 | 383 | // private data 384 | uint8_t flags_; // See above for definition of flags_ bits 385 | uint8_t type_; // type of file see above for values 386 | uint32_t curCluster_; // cluster for current file position 387 | uint32_t curPosition_; // current file position in bytes from beginning 388 | uint32_t dirBlock_; // SD block that contains directory entry for file 389 | uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF 390 | uint32_t fileSize_; // file size in bytes 391 | uint32_t firstCluster_; // first cluster of file 392 | SdVolume* vol_; // volume where file is located 393 | 394 | // private functions 395 | uint8_t addCluster(void); 396 | uint8_t addDirCluster(void); 397 | dir_t* cacheDirEntry(uint8_t action); 398 | static void (*dateTime_)(uint16_t* date, uint16_t* time); 399 | static uint8_t make83Name(const char* str, uint8_t* name); 400 | uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); 401 | dir_t* readDirCache(void); 402 | }; 403 | //============================================================================== 404 | // SdVolume class 405 | /** 406 | * \brief Cache for an SD data block 407 | */ 408 | union cache_t { 409 | /** Used to access cached file data blocks. */ 410 | uint8_t data[512]; 411 | /** Used to access cached FAT16 entries. */ 412 | uint16_t fat16[256]; 413 | /** Used to access cached FAT32 entries. */ 414 | uint32_t fat32[128]; 415 | /** Used to access cached directory entries. */ 416 | dir_t dir[16]; 417 | /** Used to access a cached MasterBoot Record. */ 418 | mbr_t mbr; 419 | /** Used to access to a cached FAT boot sector. */ 420 | fbs_t fbs; 421 | }; 422 | //------------------------------------------------------------------------------ 423 | /** 424 | * \class SdVolume 425 | * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. 426 | */ 427 | class SdVolume { 428 | public: 429 | /** Create an instance of SdVolume */ 430 | SdVolume(void) :allocSearchStart_(2), fatType_(0) {} 431 | /** Clear the cache and returns a pointer to the cache. Used by the WaveRP 432 | * recorder to do raw write to the SD card. Not for normal apps. 433 | */ 434 | static uint8_t* cacheClear(void) { 435 | cacheFlush(); 436 | cacheBlockNumber_ = 0XFFFFFFFF; 437 | return cacheBuffer_.data; 438 | } 439 | /** 440 | * Initialize a FAT volume. Try partition one first then try super 441 | * floppy format. 442 | * 443 | * \param[in] dev The Sd2Card where the volume is located. 444 | * 445 | * \return The value one, true, is returned for success and 446 | * the value zero, false, is returned for failure. Reasons for 447 | * failure include not finding a valid partition, not finding a valid 448 | * FAT file system or an I/O error. 449 | */ 450 | uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);} 451 | uint8_t init(Sd2Card* dev, uint8_t part); 452 | 453 | // inline functions that return volume info 454 | /** \return The volume's cluster size in blocks. */ 455 | uint8_t blocksPerCluster(void) const {return blocksPerCluster_;} 456 | /** \return The number of blocks in one FAT. */ 457 | uint32_t blocksPerFat(void) const {return blocksPerFat_;} 458 | /** \return The total number of clusters in the volume. */ 459 | uint32_t clusterCount(void) const {return clusterCount_;} 460 | /** \return The shift count required to multiply by blocksPerCluster. */ 461 | uint8_t clusterSizeShift(void) const {return clusterSizeShift_;} 462 | /** \return The logical block number for the start of file data. */ 463 | uint32_t dataStartBlock(void) const {return dataStartBlock_;} 464 | /** \return The number of FAT structures on the volume. */ 465 | uint8_t fatCount(void) const {return fatCount_;} 466 | /** \return The logical block number for the start of the first FAT. */ 467 | uint32_t fatStartBlock(void) const {return fatStartBlock_;} 468 | /** \return The FAT type of the volume. Values are 12, 16 or 32. */ 469 | uint8_t fatType(void) const {return fatType_;} 470 | /** \return The number of entries in the root directory for FAT16 volumes. */ 471 | uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;} 472 | /** \return The logical block number for the start of the root directory 473 | on FAT16 volumes or the first cluster number on FAT32 volumes. */ 474 | uint32_t rootDirStart(void) const {return rootDirStart_;} 475 | /** return a pointer to the Sd2Card object for this volume */ 476 | static Sd2Card* sdCard(void) {return sdCard_;} 477 | //------------------------------------------------------------------------------ 478 | #if ALLOW_DEPRECATED_FUNCTIONS 479 | // Deprecated functions - suppress cpplint warnings with NOLINT comment 480 | /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ 481 | uint8_t init(Sd2Card& dev) {return init(&dev);} // NOLINT 482 | 483 | /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ 484 | uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT 485 | return init(&dev, part); 486 | } 487 | #endif // ALLOW_DEPRECATED_FUNCTIONS 488 | //------------------------------------------------------------------------------ 489 | private: 490 | // Allow SdFile access to SdVolume private data. 491 | friend class SdFile; 492 | 493 | // value for action argument in cacheRawBlock to indicate read from cache 494 | static uint8_t const CACHE_FOR_READ = 0; 495 | // value for action argument in cacheRawBlock to indicate cache dirty 496 | static uint8_t const CACHE_FOR_WRITE = 1; 497 | 498 | static cache_t cacheBuffer_; // 512 byte cache for device blocks 499 | static uint32_t cacheBlockNumber_; // Logical number of block in the cache 500 | static Sd2Card* sdCard_; // Sd2Card object for cache 501 | static uint8_t cacheDirty_; // cacheFlush() will write block if true 502 | static uint32_t cacheMirrorBlock_; // block number for mirror FAT 503 | // 504 | uint32_t allocSearchStart_; // start cluster for alloc search 505 | uint8_t blocksPerCluster_; // cluster size in blocks 506 | uint32_t blocksPerFat_; // FAT size in blocks 507 | uint32_t clusterCount_; // clusters in one FAT 508 | uint8_t clusterSizeShift_; // shift to convert cluster count to block count 509 | uint32_t dataStartBlock_; // first data block number 510 | uint8_t fatCount_; // number of FATs on volume 511 | uint32_t fatStartBlock_; // start block for first FAT 512 | uint8_t fatType_; // volume type (12, 16, OR 32) 513 | uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir 514 | uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 515 | //---------------------------------------------------------------------------- 516 | uint8_t allocContiguous(uint32_t count, uint32_t* curCluster); 517 | uint8_t blockOfCluster(uint32_t position) const { 518 | return (position >> 9) & (blocksPerCluster_ - 1);} 519 | uint32_t clusterStartBlock(uint32_t cluster) const { 520 | return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} 521 | uint32_t blockNumber(uint32_t cluster, uint32_t position) const { 522 | return clusterStartBlock(cluster) + blockOfCluster(position);} 523 | static uint8_t cacheFlush(void); 524 | static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); 525 | static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;} 526 | static uint8_t cacheZeroBlock(uint32_t blockNumber); 527 | uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const; 528 | uint8_t fatGet(uint32_t cluster, uint32_t* value) const; 529 | uint8_t fatPut(uint32_t cluster, uint32_t value); 530 | uint8_t fatPutEOC(uint32_t cluster) { 531 | return fatPut(cluster, 0x0FFFFFFF); 532 | } 533 | uint8_t freeChain(uint32_t cluster); 534 | uint8_t isEOC(uint32_t cluster) const { 535 | return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); 536 | } 537 | uint8_t readBlock(uint32_t block, uint8_t* dst) { 538 | return sdCard_->readBlock(block, dst);} 539 | uint8_t readData(uint32_t block, uint16_t offset, 540 | uint16_t count, uint8_t* dst) { 541 | return sdCard_->readData(block, offset, count, dst); 542 | } 543 | uint8_t writeBlock(uint32_t block, const uint8_t* dst) { 544 | return sdCard_->writeBlock(block, dst); 545 | } 546 | }; 547 | #endif // SdFat_h 548 | -------------------------------------------------------------------------------- /Sprinter/SdFile.cpp: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | #include "SdFat.h" 21 | #include 22 | #include 23 | //------------------------------------------------------------------------------ 24 | // callback function for date/time 25 | void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL; 26 | 27 | #if ALLOW_DEPRECATED_FUNCTIONS 28 | // suppress cpplint warnings with NOLINT comment 29 | void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL; // NOLINT 30 | #endif // ALLOW_DEPRECATED_FUNCTIONS 31 | //------------------------------------------------------------------------------ 32 | // add a cluster to a file 33 | uint8_t SdFile::addCluster() { 34 | if (!vol_->allocContiguous(1, &curCluster_)) return false; 35 | 36 | // if first cluster of file link to directory entry 37 | if (firstCluster_ == 0) { 38 | firstCluster_ = curCluster_; 39 | flags_ |= F_FILE_DIR_DIRTY; 40 | } 41 | return true; 42 | } 43 | //------------------------------------------------------------------------------ 44 | // Add a cluster to a directory file and zero the cluster. 45 | // return with first block of cluster in the cache 46 | uint8_t SdFile::addDirCluster(void) { 47 | if (!addCluster()) return false; 48 | 49 | // zero data in cluster insure first cluster is in cache 50 | uint32_t block = vol_->clusterStartBlock(curCluster_); 51 | for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) { 52 | if (!SdVolume::cacheZeroBlock(block + i - 1)) return false; 53 | } 54 | // Increase directory file size by cluster size 55 | fileSize_ += 512UL << vol_->clusterSizeShift_; 56 | return true; 57 | } 58 | //------------------------------------------------------------------------------ 59 | // cache a file's directory entry 60 | // return pointer to cached entry or null for failure 61 | dir_t* SdFile::cacheDirEntry(uint8_t action) { 62 | if (!SdVolume::cacheRawBlock(dirBlock_, action)) return NULL; 63 | return SdVolume::cacheBuffer_.dir + dirIndex_; 64 | } 65 | //------------------------------------------------------------------------------ 66 | /** 67 | * Close a file and force cached data and directory information 68 | * to be written to the storage device. 69 | * 70 | * \return The value one, true, is returned for success and 71 | * the value zero, false, is returned for failure. 72 | * Reasons for failure include no file is open or an I/O error. 73 | */ 74 | uint8_t SdFile::close(void) { 75 | if (!sync())return false; 76 | type_ = FAT_FILE_TYPE_CLOSED; 77 | return true; 78 | } 79 | //------------------------------------------------------------------------------ 80 | /** 81 | * Check for contiguous file and return its raw block range. 82 | * 83 | * \param[out] bgnBlock the first block address for the file. 84 | * \param[out] endBlock the last block address for the file. 85 | * 86 | * \return The value one, true, is returned for success and 87 | * the value zero, false, is returned for failure. 88 | * Reasons for failure include file is not contiguous, file has zero length 89 | * or an I/O error occurred. 90 | */ 91 | uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { 92 | // error if no blocks 93 | if (firstCluster_ == 0) return false; 94 | 95 | for (uint32_t c = firstCluster_; ; c++) { 96 | uint32_t next; 97 | if (!vol_->fatGet(c, &next)) return false; 98 | 99 | // check for contiguous 100 | if (next != (c + 1)) { 101 | // error if not end of chain 102 | if (!vol_->isEOC(next)) return false; 103 | *bgnBlock = vol_->clusterStartBlock(firstCluster_); 104 | *endBlock = vol_->clusterStartBlock(c) 105 | + vol_->blocksPerCluster_ - 1; 106 | return true; 107 | } 108 | } 109 | } 110 | //------------------------------------------------------------------------------ 111 | /** 112 | * Create and open a new contiguous file of a specified size. 113 | * 114 | * \note This function only supports short DOS 8.3 names. 115 | * See open() for more information. 116 | * 117 | * \param[in] dirFile The directory where the file will be created. 118 | * \param[in] fileName A valid DOS 8.3 file name. 119 | * \param[in] size The desired file size. 120 | * 121 | * \return The value one, true, is returned for success and 122 | * the value zero, false, is returned for failure. 123 | * Reasons for failure include \a fileName contains 124 | * an invalid DOS 8.3 file name, the FAT volume has not been initialized, 125 | * a file is already open, the file already exists, the root 126 | * directory is full or an I/O error. 127 | * 128 | */ 129 | uint8_t SdFile::createContiguous(SdFile* dirFile, 130 | const char* fileName, uint32_t size) { 131 | // don't allow zero length file 132 | if (size == 0) return false; 133 | if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) return false; 134 | 135 | // calculate number of clusters needed 136 | uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; 137 | 138 | // allocate clusters 139 | if (!vol_->allocContiguous(count, &firstCluster_)) { 140 | remove(); 141 | return false; 142 | } 143 | fileSize_ = size; 144 | 145 | // insure sync() will update dir entry 146 | flags_ |= F_FILE_DIR_DIRTY; 147 | return sync(); 148 | } 149 | //------------------------------------------------------------------------------ 150 | /** 151 | * Return a files directory entry 152 | * 153 | * \param[out] dir Location for return of the files directory entry. 154 | * 155 | * \return The value one, true, is returned for success and 156 | * the value zero, false, is returned for failure. 157 | */ 158 | uint8_t SdFile::dirEntry(dir_t* dir) { 159 | // make sure fields on SD are correct 160 | if (!sync()) return false; 161 | 162 | // read entry 163 | dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); 164 | if (!p) return false; 165 | 166 | // copy to caller's struct 167 | memcpy(dir, p, sizeof(dir_t)); 168 | return true; 169 | } 170 | //------------------------------------------------------------------------------ 171 | /** 172 | * Format the name field of \a dir into the 13 byte array 173 | * \a name in standard 8.3 short name format. 174 | * 175 | * \param[in] dir The directory structure containing the name. 176 | * \param[out] name A 13 byte char array for the formatted name. 177 | */ 178 | void SdFile::dirName(const dir_t& dir, char* name) { 179 | uint8_t j = 0; 180 | for (uint8_t i = 0; i < 11; i++) { 181 | if (dir.name[i] == ' ')continue; 182 | if (i == 8) name[j++] = '.'; 183 | name[j++] = dir.name[i]; 184 | } 185 | name[j] = 0; 186 | } 187 | //------------------------------------------------------------------------------ 188 | /** List directory contents to Serial. 189 | * 190 | * \param[in] flags The inclusive OR of 191 | * 192 | * LS_DATE - %Print file modification date 193 | * 194 | * LS_SIZE - %Print file size. 195 | * 196 | * LS_R - Recursive list of subdirectories. 197 | * 198 | * \param[in] indent Amount of space before file name. Used for recursive 199 | * list to indicate subdirectory level. 200 | */ 201 | void SdFile::ls(uint8_t flags, uint8_t indent) { 202 | dir_t* p; 203 | 204 | rewind(); 205 | while ((p = readDirCache())) { 206 | // done if past last used entry 207 | if (p->name[0] == DIR_NAME_FREE) break; 208 | 209 | // skip deleted entry and entries for . and .. 210 | if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; 211 | 212 | // only list subdirectories and files 213 | if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; 214 | 215 | // print any indent spaces 216 | for (int8_t i = 0; i < indent; i++) Serial.print(' '); 217 | 218 | // print file name with possible blank fill 219 | printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0); 220 | 221 | // print modify date/time if requested 222 | if (flags & LS_DATE) { 223 | printFatDate(p->lastWriteDate); 224 | Serial.print(' '); 225 | printFatTime(p->lastWriteTime); 226 | } 227 | // print size if requested 228 | if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) { 229 | Serial.print(' '); 230 | Serial.print(p->fileSize); 231 | } 232 | Serial.println(); 233 | 234 | // list subdirectory content if requested 235 | if ((flags & LS_R) && DIR_IS_SUBDIR(p)) { 236 | uint16_t index = curPosition()/32 - 1; 237 | SdFile s; 238 | if (s.open(this, index, O_READ)) s.ls(flags, indent + 2); 239 | seekSet(32 * (index + 1)); 240 | } 241 | } 242 | } 243 | //------------------------------------------------------------------------------ 244 | // format directory name field from a 8.3 name string 245 | uint8_t SdFile::make83Name(const char* str, uint8_t* name) { 246 | uint8_t c; 247 | uint8_t n = 7; // max index for part before dot 248 | uint8_t i = 0; 249 | // blank fill name and extension 250 | while (i < 11) name[i++] = ' '; 251 | i = 0; 252 | while ((c = *str++) != '\0') { 253 | if (c == '.') { 254 | if (n == 10) return false; // only one dot allowed 255 | n = 10; // max index for full 8.3 name 256 | i = 8; // place for extension 257 | } else { 258 | // illegal FAT characters 259 | PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); 260 | uint8_t b; 261 | while ((b = pgm_read_byte(p++))) if (b == c) return false; 262 | // check size and only allow ASCII printable characters 263 | if (i > n || c < 0X21 || c > 0X7E)return false; 264 | // only upper case allowed in 8.3 names - convert lower to upper 265 | name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); 266 | } 267 | } 268 | // must have a file name, extension is optional 269 | return name[0] != ' '; 270 | } 271 | //------------------------------------------------------------------------------ 272 | /** Make a new directory. 273 | * 274 | * \param[in] dir An open SdFat instance for the directory that will containing 275 | * the new directory. 276 | * 277 | * \param[in] dirName A valid 8.3 DOS name for the new directory. 278 | * 279 | * \return The value one, true, is returned for success and 280 | * the value zero, false, is returned for failure. 281 | * Reasons for failure include this SdFile is already open, \a dir is not a 282 | * directory, \a dirName is invalid or already exists in \a dir. 283 | */ 284 | uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { 285 | dir_t d; 286 | 287 | // create a normal file 288 | if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) return false; 289 | 290 | // convert SdFile to directory 291 | flags_ = O_READ; 292 | type_ = FAT_FILE_TYPE_SUBDIR; 293 | 294 | // allocate and zero first cluster 295 | if (!addDirCluster())return false; 296 | 297 | // force entry to SD 298 | if (!sync()) return false; 299 | 300 | // cache entry - should already be in cache due to sync() call 301 | dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); 302 | if (!p) return false; 303 | 304 | // change directory entry attribute 305 | p->attributes = DIR_ATT_DIRECTORY; 306 | 307 | // make entry for '.' 308 | memcpy(&d, p, sizeof(d)); 309 | for (uint8_t i = 1; i < 11; i++) d.name[i] = ' '; 310 | d.name[0] = '.'; 311 | 312 | // cache block for '.' and '..' 313 | uint32_t block = vol_->clusterStartBlock(firstCluster_); 314 | if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false; 315 | 316 | // copy '.' to block 317 | memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d)); 318 | 319 | // make entry for '..' 320 | d.name[1] = '.'; 321 | if (dir->isRoot()) { 322 | d.firstClusterLow = 0; 323 | d.firstClusterHigh = 0; 324 | } else { 325 | d.firstClusterLow = dir->firstCluster_ & 0XFFFF; 326 | d.firstClusterHigh = dir->firstCluster_ >> 16; 327 | } 328 | // copy '..' to block 329 | memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d)); 330 | 331 | // set position after '..' 332 | curPosition_ = 2 * sizeof(d); 333 | 334 | // write first block 335 | return SdVolume::cacheFlush(); 336 | } 337 | //------------------------------------------------------------------------------ 338 | /** 339 | * Open a file or directory by name. 340 | * 341 | * \param[in] dirFile An open SdFat instance for the directory containing the 342 | * file to be opened. 343 | * 344 | * \param[in] fileName A valid 8.3 DOS name for a file to be opened. 345 | * 346 | * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive 347 | * OR of flags from the following list 348 | * 349 | * O_READ - Open for reading. 350 | * 351 | * O_RDONLY - Same as O_READ. 352 | * 353 | * O_WRITE - Open for writing. 354 | * 355 | * O_WRONLY - Same as O_WRITE. 356 | * 357 | * O_RDWR - Open for reading and writing. 358 | * 359 | * O_APPEND - If set, the file offset shall be set to the end of the 360 | * file prior to each write. 361 | * 362 | * O_CREAT - If the file exists, this flag has no effect except as noted 363 | * under O_EXCL below. Otherwise, the file shall be created 364 | * 365 | * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. 366 | * 367 | * O_SYNC - Call sync() after each write. This flag should not be used with 368 | * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. 369 | * These functions do character at a time writes so sync() will be called 370 | * after each byte. 371 | * 372 | * O_TRUNC - If the file exists and is a regular file, and the file is 373 | * successfully opened and is not read only, its length shall be truncated to 0. 374 | * 375 | * \note Directory files must be opened read only. Write and truncation is 376 | * not allowed for directory files. 377 | * 378 | * \return The value one, true, is returned for success and 379 | * the value zero, false, is returned for failure. 380 | * Reasons for failure include this SdFile is already open, \a difFile is not 381 | * a directory, \a fileName is invalid, the file does not exist 382 | * or can't be opened in the access mode specified by oflag. 383 | */ 384 | uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { 385 | uint8_t dname[11]; 386 | dir_t* p; 387 | 388 | // error if already open 389 | if (isOpen())return false; 390 | 391 | if (!make83Name(fileName, dname)) return false; 392 | vol_ = dirFile->vol_; 393 | dirFile->rewind(); 394 | 395 | // bool for empty entry found 396 | uint8_t emptyFound = false; 397 | 398 | // search for file 399 | while (dirFile->curPosition_ < dirFile->fileSize_) { 400 | uint8_t index = 0XF & (dirFile->curPosition_ >> 5); 401 | p = dirFile->readDirCache(); 402 | if (p == NULL) return false; 403 | 404 | if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { 405 | // remember first empty slot 406 | if (!emptyFound) { 407 | emptyFound = true; 408 | dirIndex_ = index; 409 | dirBlock_ = SdVolume::cacheBlockNumber_; 410 | } 411 | // done if no entries follow 412 | if (p->name[0] == DIR_NAME_FREE) break; 413 | } else if (!memcmp(dname, p->name, 11)) { 414 | // don't open existing file if O_CREAT and O_EXCL 415 | if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; 416 | 417 | // open found file 418 | return openCachedEntry(0XF & index, oflag); 419 | } 420 | } 421 | // only create file if O_CREAT and O_WRITE 422 | if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false; 423 | 424 | // cache found slot or add cluster if end of file 425 | if (emptyFound) { 426 | p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); 427 | if (!p) return false; 428 | } else { 429 | if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false; 430 | 431 | // add and zero cluster for dirFile - first cluster is in cache for write 432 | if (!dirFile->addDirCluster()) return false; 433 | 434 | // use first entry in cluster 435 | dirIndex_ = 0; 436 | p = SdVolume::cacheBuffer_.dir; 437 | } 438 | // initialize as empty file 439 | memset(p, 0, sizeof(dir_t)); 440 | memcpy(p->name, dname, 11); 441 | 442 | // set timestamps 443 | if (dateTime_) { 444 | // call user function 445 | dateTime_(&p->creationDate, &p->creationTime); 446 | } else { 447 | // use default date/time 448 | p->creationDate = FAT_DEFAULT_DATE; 449 | p->creationTime = FAT_DEFAULT_TIME; 450 | } 451 | p->lastAccessDate = p->creationDate; 452 | p->lastWriteDate = p->creationDate; 453 | p->lastWriteTime = p->creationTime; 454 | 455 | // force write of entry to SD 456 | if (!SdVolume::cacheFlush()) return false; 457 | 458 | // open entry in cache 459 | return openCachedEntry(dirIndex_, oflag); 460 | } 461 | //------------------------------------------------------------------------------ 462 | /** 463 | * Open a file by index. 464 | * 465 | * \param[in] dirFile An open SdFat instance for the directory. 466 | * 467 | * \param[in] index The \a index of the directory entry for the file to be 468 | * opened. The value for \a index is (directory file position)/32. 469 | * 470 | * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive 471 | * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. 472 | * 473 | * See open() by fileName for definition of flags and return values. 474 | * 475 | */ 476 | uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { 477 | // error if already open 478 | if (isOpen())return false; 479 | 480 | // don't open existing file if O_CREAT and O_EXCL - user call error 481 | if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; 482 | 483 | vol_ = dirFile->vol_; 484 | 485 | // seek to location of entry 486 | if (!dirFile->seekSet(32 * index)) return false; 487 | 488 | // read entry into cache 489 | dir_t* p = dirFile->readDirCache(); 490 | if (p == NULL) return false; 491 | 492 | // error if empty slot or '.' or '..' 493 | if (p->name[0] == DIR_NAME_FREE || 494 | p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { 495 | return false; 496 | } 497 | // open cached entry 498 | return openCachedEntry(index & 0XF, oflag); 499 | } 500 | //------------------------------------------------------------------------------ 501 | // open a cached directory entry. Assumes vol_ is initializes 502 | uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { 503 | // location of entry in cache 504 | dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex; 505 | 506 | // write or truncate is an error for a directory or read-only file 507 | if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { 508 | if (oflag & (O_WRITE | O_TRUNC)) return false; 509 | } 510 | // remember location of directory entry on SD 511 | dirIndex_ = dirIndex; 512 | dirBlock_ = SdVolume::cacheBlockNumber_; 513 | 514 | // copy first cluster number for directory fields 515 | firstCluster_ = (uint32_t)p->firstClusterHigh << 16; 516 | firstCluster_ |= p->firstClusterLow; 517 | 518 | // make sure it is a normal file or subdirectory 519 | if (DIR_IS_FILE(p)) { 520 | fileSize_ = p->fileSize; 521 | type_ = FAT_FILE_TYPE_NORMAL; 522 | } else if (DIR_IS_SUBDIR(p)) { 523 | if (!vol_->chainSize(firstCluster_, &fileSize_)) return false; 524 | type_ = FAT_FILE_TYPE_SUBDIR; 525 | } else { 526 | return false; 527 | } 528 | // save open flags for read/write 529 | flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND); 530 | 531 | // set to start of file 532 | curCluster_ = 0; 533 | curPosition_ = 0; 534 | 535 | // truncate file to zero length if requested 536 | if (oflag & O_TRUNC) return truncate(0); 537 | return true; 538 | } 539 | //------------------------------------------------------------------------------ 540 | /** 541 | * Open a volume's root directory. 542 | * 543 | * \param[in] vol The FAT volume containing the root directory to be opened. 544 | * 545 | * \return The value one, true, is returned for success and 546 | * the value zero, false, is returned for failure. 547 | * Reasons for failure include the FAT volume has not been initialized 548 | * or it a FAT12 volume. 549 | */ 550 | uint8_t SdFile::openRoot(SdVolume* vol) { 551 | // error if file is already open 552 | if (isOpen()) return false; 553 | 554 | if (vol->fatType() == 16) { 555 | type_ = FAT_FILE_TYPE_ROOT16; 556 | firstCluster_ = 0; 557 | fileSize_ = 32 * vol->rootDirEntryCount(); 558 | } else if (vol->fatType() == 32) { 559 | type_ = FAT_FILE_TYPE_ROOT32; 560 | firstCluster_ = vol->rootDirStart(); 561 | if (!vol->chainSize(firstCluster_, &fileSize_)) return false; 562 | } else { 563 | // volume is not initialized or FAT12 564 | return false; 565 | } 566 | vol_ = vol; 567 | // read only 568 | flags_ = O_READ; 569 | 570 | // set to start of file 571 | curCluster_ = 0; 572 | curPosition_ = 0; 573 | 574 | // root has no directory entry 575 | dirBlock_ = 0; 576 | dirIndex_ = 0; 577 | return true; 578 | } 579 | //------------------------------------------------------------------------------ 580 | /** %Print the name field of a directory entry in 8.3 format to Serial. 581 | * 582 | * \param[in] dir The directory structure containing the name. 583 | * \param[in] width Blank fill name if length is less than \a width. 584 | */ 585 | void SdFile::printDirName(const dir_t& dir, uint8_t width) { 586 | uint8_t w = 0; 587 | for (uint8_t i = 0; i < 11; i++) { 588 | if (dir.name[i] == ' ')continue; 589 | if (i == 8) { 590 | Serial.print('.'); 591 | w++; 592 | } 593 | Serial.print(dir.name[i]); 594 | w++; 595 | } 596 | if (DIR_IS_SUBDIR(&dir)) { 597 | Serial.print('/'); 598 | w++; 599 | } 600 | while (w < width) { 601 | Serial.print(' '); 602 | w++; 603 | } 604 | } 605 | //------------------------------------------------------------------------------ 606 | /** %Print a directory date field to Serial. 607 | * 608 | * Format is yyyy-mm-dd. 609 | * 610 | * \param[in] fatDate The date field from a directory entry. 611 | */ 612 | void SdFile::printFatDate(uint16_t fatDate) { 613 | Serial.print(FAT_YEAR(fatDate)); 614 | Serial.print('-'); 615 | printTwoDigits(FAT_MONTH(fatDate)); 616 | Serial.print('-'); 617 | printTwoDigits(FAT_DAY(fatDate)); 618 | } 619 | //------------------------------------------------------------------------------ 620 | /** %Print a directory time field to Serial. 621 | * 622 | * Format is hh:mm:ss. 623 | * 624 | * \param[in] fatTime The time field from a directory entry. 625 | */ 626 | void SdFile::printFatTime(uint16_t fatTime) { 627 | printTwoDigits(FAT_HOUR(fatTime)); 628 | Serial.print(':'); 629 | printTwoDigits(FAT_MINUTE(fatTime)); 630 | Serial.print(':'); 631 | printTwoDigits(FAT_SECOND(fatTime)); 632 | } 633 | //------------------------------------------------------------------------------ 634 | /** %Print a value as two digits to Serial. 635 | * 636 | * \param[in] v Value to be printed, 0 <= \a v <= 99 637 | */ 638 | void SdFile::printTwoDigits(uint8_t v) { 639 | char str[3]; 640 | str[0] = '0' + v/10; 641 | str[1] = '0' + v % 10; 642 | str[2] = 0; 643 | Serial.print(str); 644 | } 645 | //------------------------------------------------------------------------------ 646 | /** 647 | * Read data from a file starting at the current position. 648 | * 649 | * \param[out] buf Pointer to the location that will receive the data. 650 | * 651 | * \param[in] nbyte Maximum number of bytes to read. 652 | * 653 | * \return For success read() returns the number of bytes read. 654 | * A value less than \a nbyte, including zero, will be returned 655 | * if end of file is reached. 656 | * If an error occurs, read() returns -1. Possible errors include 657 | * read() called before a file has been opened, corrupt file system 658 | * or an I/O error occurred. 659 | */ 660 | int16_t SdFile::read(void* buf, uint16_t nbyte) { 661 | uint8_t* dst = reinterpret_cast(buf); 662 | 663 | // error if not open or write only 664 | if (!isOpen() || !(flags_ & O_READ)) return -1; 665 | 666 | // max bytes left in file 667 | if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_; 668 | 669 | // amount left to read 670 | uint16_t toRead = nbyte; 671 | while (toRead > 0) { 672 | uint32_t block; // raw device block number 673 | uint16_t offset = curPosition_ & 0X1FF; // offset in block 674 | if (type_ == FAT_FILE_TYPE_ROOT16) { 675 | block = vol_->rootDirStart() + (curPosition_ >> 9); 676 | } else { 677 | uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); 678 | if (offset == 0 && blockOfCluster == 0) { 679 | // start of new cluster 680 | if (curPosition_ == 0) { 681 | // use first cluster in file 682 | curCluster_ = firstCluster_; 683 | } else { 684 | // get next cluster from FAT 685 | if (!vol_->fatGet(curCluster_, &curCluster_)) return -1; 686 | } 687 | } 688 | block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; 689 | } 690 | uint16_t n = toRead; 691 | 692 | // amount to be read from current block 693 | if (n > (512 - offset)) n = 512 - offset; 694 | 695 | // no buffering needed if n == 512 or user requests no buffering 696 | if ((unbufferedRead() || n == 512) && 697 | block != SdVolume::cacheBlockNumber_) { 698 | if (!vol_->readData(block, offset, n, dst)) return -1; 699 | dst += n; 700 | } else { 701 | // read block to cache and copy data to caller 702 | if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1; 703 | uint8_t* src = SdVolume::cacheBuffer_.data + offset; 704 | uint8_t* end = src + n; 705 | while (src != end) *dst++ = *src++; 706 | } 707 | curPosition_ += n; 708 | toRead -= n; 709 | } 710 | return nbyte; 711 | } 712 | //------------------------------------------------------------------------------ 713 | /** 714 | * Read the next directory entry from a directory file. 715 | * 716 | * \param[out] dir The dir_t struct that will receive the data. 717 | * 718 | * \return For success readDir() returns the number of bytes read. 719 | * A value of zero will be returned if end of file is reached. 720 | * If an error occurs, readDir() returns -1. Possible errors include 721 | * readDir() called before a directory has been opened, this is not 722 | * a directory file or an I/O error occurred. 723 | */ 724 | int8_t SdFile::readDir(dir_t* dir) { 725 | int8_t n; 726 | // if not a directory file or miss-positioned return an error 727 | if (!isDir() || (0X1F & curPosition_)) return -1; 728 | 729 | while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) { 730 | // last entry if DIR_NAME_FREE 731 | if (dir->name[0] == DIR_NAME_FREE) break; 732 | // skip empty entries and entry for . and .. 733 | if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; 734 | // return if normal file or subdirectory 735 | if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; 736 | } 737 | // error, end of file, or past last entry 738 | return n < 0 ? -1 : 0; 739 | } 740 | //------------------------------------------------------------------------------ 741 | // Read next directory entry into the cache 742 | // Assumes file is correctly positioned 743 | dir_t* SdFile::readDirCache(void) { 744 | // error if not directory 745 | if (!isDir()) return NULL; 746 | 747 | // index of entry in cache 748 | uint8_t i = (curPosition_ >> 5) & 0XF; 749 | 750 | // use read to locate and cache block 751 | if (read() < 0) return NULL; 752 | 753 | // advance to next entry 754 | curPosition_ += 31; 755 | 756 | // return pointer to entry 757 | return (SdVolume::cacheBuffer_.dir + i); 758 | } 759 | //------------------------------------------------------------------------------ 760 | /** 761 | * Remove a file. 762 | * 763 | * The directory entry and all data for the file are deleted. 764 | * 765 | * \note This function should not be used to delete the 8.3 version of a 766 | * file that has a long name. For example if a file has the long name 767 | * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". 768 | * 769 | * \return The value one, true, is returned for success and 770 | * the value zero, false, is returned for failure. 771 | * Reasons for failure include the file read-only, is a directory, 772 | * or an I/O error occurred. 773 | */ 774 | uint8_t SdFile::remove(void) { 775 | // free any clusters - will fail if read-only or directory 776 | if (!truncate(0)) return false; 777 | 778 | // cache directory entry 779 | dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); 780 | if (!d) return false; 781 | 782 | // mark entry deleted 783 | d->name[0] = DIR_NAME_DELETED; 784 | 785 | // set this SdFile closed 786 | type_ = FAT_FILE_TYPE_CLOSED; 787 | 788 | // write entry to SD 789 | return SdVolume::cacheFlush(); 790 | } 791 | //------------------------------------------------------------------------------ 792 | /** 793 | * Remove a file. 794 | * 795 | * The directory entry and all data for the file are deleted. 796 | * 797 | * \param[in] dirFile The directory that contains the file. 798 | * \param[in] fileName The name of the file to be removed. 799 | * 800 | * \note This function should not be used to delete the 8.3 version of a 801 | * file that has a long name. For example if a file has the long name 802 | * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". 803 | * 804 | * \return The value one, true, is returned for success and 805 | * the value zero, false, is returned for failure. 806 | * Reasons for failure include the file is a directory, is read only, 807 | * \a dirFile is not a directory, \a fileName is not found 808 | * or an I/O error occurred. 809 | */ 810 | uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) { 811 | SdFile file; 812 | if (!file.open(dirFile, fileName, O_WRITE)) return false; 813 | return file.remove(); 814 | } 815 | //------------------------------------------------------------------------------ 816 | /** Remove a directory file. 817 | * 818 | * The directory file will be removed only if it is empty and is not the 819 | * root directory. rmDir() follows DOS and Windows and ignores the 820 | * read-only attribute for the directory. 821 | * 822 | * \note This function should not be used to delete the 8.3 version of a 823 | * directory that has a long name. For example if a directory has the 824 | * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". 825 | * 826 | * \return The value one, true, is returned for success and 827 | * the value zero, false, is returned for failure. 828 | * Reasons for failure include the file is not a directory, is the root 829 | * directory, is not empty, or an I/O error occurred. 830 | */ 831 | uint8_t SdFile::rmDir(void) { 832 | // must be open subdirectory 833 | if (!isSubDir()) return false; 834 | 835 | rewind(); 836 | 837 | // make sure directory is empty 838 | while (curPosition_ < fileSize_) { 839 | dir_t* p = readDirCache(); 840 | if (p == NULL) return false; 841 | // done if past last used entry 842 | if (p->name[0] == DIR_NAME_FREE) break; 843 | // skip empty slot or '.' or '..' 844 | if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; 845 | // error not empty 846 | if (DIR_IS_FILE_OR_SUBDIR(p)) return false; 847 | } 848 | // convert empty directory to normal file for remove 849 | type_ = FAT_FILE_TYPE_NORMAL; 850 | flags_ |= O_WRITE; 851 | return remove(); 852 | } 853 | //------------------------------------------------------------------------------ 854 | /** Recursively delete a directory and all contained files. 855 | * 856 | * This is like the Unix/Linux 'rm -rf *' if called with the root directory 857 | * hence the name. 858 | * 859 | * Warning - This will remove all contents of the directory including 860 | * subdirectories. The directory will then be removed if it is not root. 861 | * The read-only attribute for files will be ignored. 862 | * 863 | * \note This function should not be used to delete the 8.3 version of 864 | * a directory that has a long name. See remove() and rmDir(). 865 | * 866 | * \return The value one, true, is returned for success and 867 | * the value zero, false, is returned for failure. 868 | */ 869 | uint8_t SdFile::rmRfStar(void) { 870 | rewind(); 871 | while (curPosition_ < fileSize_) { 872 | SdFile f; 873 | 874 | // remember position 875 | uint16_t index = curPosition_/32; 876 | 877 | dir_t* p = readDirCache(); 878 | if (!p) return false; 879 | 880 | // done if past last entry 881 | if (p->name[0] == DIR_NAME_FREE) break; 882 | 883 | // skip empty slot or '.' or '..' 884 | if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; 885 | 886 | // skip if part of long file name or volume label in root 887 | if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; 888 | 889 | if (!f.open(this, index, O_READ)) return false; 890 | if (f.isSubDir()) { 891 | // recursively delete 892 | if (!f.rmRfStar()) return false; 893 | } else { 894 | // ignore read-only 895 | f.flags_ |= O_WRITE; 896 | if (!f.remove()) return false; 897 | } 898 | // position to next entry if required 899 | if (curPosition_ != (32*(index + 1))) { 900 | if (!seekSet(32*(index + 1))) return false; 901 | } 902 | } 903 | // don't try to delete root 904 | if (isRoot()) return true; 905 | return rmDir(); 906 | } 907 | //------------------------------------------------------------------------------ 908 | /** 909 | * Sets a file's position. 910 | * 911 | * \param[in] pos The new position in bytes from the beginning of the file. 912 | * 913 | * \return The value one, true, is returned for success and 914 | * the value zero, false, is returned for failure. 915 | */ 916 | uint8_t SdFile::seekSet(uint32_t pos) { 917 | // error if file not open or seek past end of file 918 | if (!isOpen() || pos > fileSize_) return false; 919 | 920 | if (type_ == FAT_FILE_TYPE_ROOT16) { 921 | curPosition_ = pos; 922 | return true; 923 | } 924 | if (pos == 0) { 925 | // set position to start of file 926 | curCluster_ = 0; 927 | curPosition_ = 0; 928 | return true; 929 | } 930 | // calculate cluster index for cur and new position 931 | uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); 932 | uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); 933 | 934 | if (nNew < nCur || curPosition_ == 0) { 935 | // must follow chain from first cluster 936 | curCluster_ = firstCluster_; 937 | } else { 938 | // advance from curPosition 939 | nNew -= nCur; 940 | } 941 | while (nNew--) { 942 | if (!vol_->fatGet(curCluster_, &curCluster_)) return false; 943 | } 944 | curPosition_ = pos; 945 | return true; 946 | } 947 | //------------------------------------------------------------------------------ 948 | /** 949 | * The sync() call causes all modified data and directory fields 950 | * to be written to the storage device. 951 | * 952 | * \return The value one, true, is returned for success and 953 | * the value zero, false, is returned for failure. 954 | * Reasons for failure include a call to sync() before a file has been 955 | * opened or an I/O error. 956 | */ 957 | uint8_t SdFile::sync(void) { 958 | // only allow open files and directories 959 | if (!isOpen()) return false; 960 | 961 | if (flags_ & F_FILE_DIR_DIRTY) { 962 | dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); 963 | if (!d) return false; 964 | 965 | // do not set filesize for dir files 966 | if (!isDir()) d->fileSize = fileSize_; 967 | 968 | // update first cluster fields 969 | d->firstClusterLow = firstCluster_ & 0XFFFF; 970 | d->firstClusterHigh = firstCluster_ >> 16; 971 | 972 | // set modify time if user supplied a callback date/time function 973 | if (dateTime_) { 974 | dateTime_(&d->lastWriteDate, &d->lastWriteTime); 975 | d->lastAccessDate = d->lastWriteDate; 976 | } 977 | // clear directory dirty 978 | flags_ &= ~F_FILE_DIR_DIRTY; 979 | } 980 | return SdVolume::cacheFlush(); 981 | } 982 | //------------------------------------------------------------------------------ 983 | /** 984 | * Set a file's timestamps in its directory entry. 985 | * 986 | * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive 987 | * OR of flags from the following list 988 | * 989 | * T_ACCESS - Set the file's last access date. 990 | * 991 | * T_CREATE - Set the file's creation date and time. 992 | * 993 | * T_WRITE - Set the file's last write/modification date and time. 994 | * 995 | * \param[in] year Valid range 1980 - 2107 inclusive. 996 | * 997 | * \param[in] month Valid range 1 - 12 inclusive. 998 | * 999 | * \param[in] day Valid range 1 - 31 inclusive. 1000 | * 1001 | * \param[in] hour Valid range 0 - 23 inclusive. 1002 | * 1003 | * \param[in] minute Valid range 0 - 59 inclusive. 1004 | * 1005 | * \param[in] second Valid range 0 - 59 inclusive 1006 | * 1007 | * \note It is possible to set an invalid date since there is no check for 1008 | * the number of days in a month. 1009 | * 1010 | * \note 1011 | * Modify and access timestamps may be overwritten if a date time callback 1012 | * function has been set by dateTimeCallback(). 1013 | * 1014 | * \return The value one, true, is returned for success and 1015 | * the value zero, false, is returned for failure. 1016 | */ 1017 | uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, 1018 | uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { 1019 | if (!isOpen() 1020 | || year < 1980 1021 | || year > 2107 1022 | || month < 1 1023 | || month > 12 1024 | || day < 1 1025 | || day > 31 1026 | || hour > 23 1027 | || minute > 59 1028 | || second > 59) { 1029 | return false; 1030 | } 1031 | dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); 1032 | if (!d) return false; 1033 | 1034 | uint16_t dirDate = FAT_DATE(year, month, day); 1035 | uint16_t dirTime = FAT_TIME(hour, minute, second); 1036 | if (flags & T_ACCESS) { 1037 | d->lastAccessDate = dirDate; 1038 | } 1039 | if (flags & T_CREATE) { 1040 | d->creationDate = dirDate; 1041 | d->creationTime = dirTime; 1042 | // seems to be units of 1/100 second not 1/10 as Microsoft states 1043 | d->creationTimeTenths = second & 1 ? 100 : 0; 1044 | } 1045 | if (flags & T_WRITE) { 1046 | d->lastWriteDate = dirDate; 1047 | d->lastWriteTime = dirTime; 1048 | } 1049 | SdVolume::cacheSetDirty(); 1050 | return sync(); 1051 | } 1052 | //------------------------------------------------------------------------------ 1053 | /** 1054 | * Truncate a file to a specified length. The current file position 1055 | * will be maintained if it is less than or equal to \a length otherwise 1056 | * it will be set to end of file. 1057 | * 1058 | * \param[in] length The desired length for the file. 1059 | * 1060 | * \return The value one, true, is returned for success and 1061 | * the value zero, false, is returned for failure. 1062 | * Reasons for failure include file is read only, file is a directory, 1063 | * \a length is greater than the current file size or an I/O error occurs. 1064 | */ 1065 | uint8_t SdFile::truncate(uint32_t length) { 1066 | // error if not a normal file or read-only 1067 | if (!isFile() || !(flags_ & O_WRITE)) return false; 1068 | 1069 | // error if length is greater than current size 1070 | if (length > fileSize_) return false; 1071 | 1072 | // fileSize and length are zero - nothing to do 1073 | if (fileSize_ == 0) return true; 1074 | 1075 | // remember position for seek after truncation 1076 | uint32_t newPos = curPosition_ > length ? length : curPosition_; 1077 | 1078 | // position to last cluster in truncated file 1079 | if (!seekSet(length)) return false; 1080 | 1081 | if (length == 0) { 1082 | // free all clusters 1083 | if (!vol_->freeChain(firstCluster_)) return false; 1084 | firstCluster_ = 0; 1085 | } else { 1086 | uint32_t toFree; 1087 | if (!vol_->fatGet(curCluster_, &toFree)) return false; 1088 | 1089 | if (!vol_->isEOC(toFree)) { 1090 | // free extra clusters 1091 | if (!vol_->freeChain(toFree)) return false; 1092 | 1093 | // current cluster is end of chain 1094 | if (!vol_->fatPutEOC(curCluster_)) return false; 1095 | } 1096 | } 1097 | fileSize_ = length; 1098 | 1099 | // need to update directory entry 1100 | flags_ |= F_FILE_DIR_DIRTY; 1101 | 1102 | if (!sync()) return false; 1103 | 1104 | // set file to correct position 1105 | return seekSet(newPos); 1106 | } 1107 | //------------------------------------------------------------------------------ 1108 | /** 1109 | * Write data to an open file. 1110 | * 1111 | * \note Data is moved to the cache but may not be written to the 1112 | * storage device until sync() is called. 1113 | * 1114 | * \param[in] buf Pointer to the location of the data to be written. 1115 | * 1116 | * \param[in] nbyte Number of bytes to write. 1117 | * 1118 | * \return For success write() returns the number of bytes written, always 1119 | * \a nbyte. If an error occurs, write() returns -1. Possible errors 1120 | * include write() is called before a file has been opened, write is called 1121 | * for a read-only file, device is full, a corrupt file system or an I/O error. 1122 | * 1123 | */ 1124 | int16_t SdFile::write(const void* buf, uint16_t nbyte) { 1125 | // convert void* to uint8_t* - must be before goto statements 1126 | const uint8_t* src = reinterpret_cast(buf); 1127 | 1128 | // number of bytes left to write - must be before goto statements 1129 | uint16_t nToWrite = nbyte; 1130 | 1131 | // error if not a normal file or is read-only 1132 | if (!isFile() || !(flags_ & O_WRITE)) goto writeErrorReturn; 1133 | 1134 | // seek to end of file if append flag 1135 | if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { 1136 | if (!seekEnd()) goto writeErrorReturn; 1137 | } 1138 | 1139 | while (nToWrite > 0) { 1140 | uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); 1141 | uint16_t blockOffset = curPosition_ & 0X1FF; 1142 | if (blockOfCluster == 0 && blockOffset == 0) { 1143 | // start of new cluster 1144 | if (curCluster_ == 0) { 1145 | if (firstCluster_ == 0) { 1146 | // allocate first cluster of file 1147 | if (!addCluster()) goto writeErrorReturn; 1148 | } else { 1149 | curCluster_ = firstCluster_; 1150 | } 1151 | } else { 1152 | uint32_t next; 1153 | if (!vol_->fatGet(curCluster_, &next)) return false; 1154 | if (vol_->isEOC(next)) { 1155 | // add cluster if at end of chain 1156 | if (!addCluster()) goto writeErrorReturn; 1157 | } else { 1158 | curCluster_ = next; 1159 | } 1160 | } 1161 | } 1162 | // max space in block 1163 | uint16_t n = 512 - blockOffset; 1164 | 1165 | // lesser of space and amount to write 1166 | if (n > nToWrite) n = nToWrite; 1167 | 1168 | // block for data write 1169 | uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; 1170 | if (n == 512) { 1171 | // full block - don't need to use cache 1172 | // invalidate cache if block is in cache 1173 | if (SdVolume::cacheBlockNumber_ == block) { 1174 | SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; 1175 | } 1176 | if (!vol_->writeBlock(block, src)) goto writeErrorReturn; 1177 | src += 512; 1178 | } else { 1179 | if (blockOffset == 0 && curPosition_ >= fileSize_) { 1180 | // start of new block don't need to read into cache 1181 | if (!SdVolume::cacheFlush()) goto writeErrorReturn; 1182 | SdVolume::cacheBlockNumber_ = block; 1183 | SdVolume::cacheSetDirty(); 1184 | } else { 1185 | // rewrite part of block 1186 | if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { 1187 | goto writeErrorReturn; 1188 | } 1189 | } 1190 | uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset; 1191 | uint8_t* end = dst + n; 1192 | while (dst != end) *dst++ = *src++; 1193 | } 1194 | nToWrite -= n; 1195 | curPosition_ += n; 1196 | } 1197 | if (curPosition_ > fileSize_) { 1198 | // update fileSize and insure sync will update dir entry 1199 | fileSize_ = curPosition_; 1200 | flags_ |= F_FILE_DIR_DIRTY; 1201 | } else if (dateTime_ && nbyte) { 1202 | // insure sync will update modified date and time 1203 | flags_ |= F_FILE_DIR_DIRTY; 1204 | } 1205 | 1206 | if (flags_ & O_SYNC) { 1207 | if (!sync()) goto writeErrorReturn; 1208 | } 1209 | return nbyte; 1210 | 1211 | writeErrorReturn: 1212 | // return for write error 1213 | writeError = true; 1214 | return -1; 1215 | } 1216 | //------------------------------------------------------------------------------ 1217 | /** 1218 | * Write a byte to a file. Required by the Arduino Print class. 1219 | * 1220 | * Use SdFile::writeError to check for errors. 1221 | */ 1222 | void SdFile::write(uint8_t b) { 1223 | write(&b, 1); 1224 | } 1225 | //------------------------------------------------------------------------------ 1226 | /** 1227 | * Write a string to a file. Used by the Arduino Print class. 1228 | * 1229 | * Use SdFile::writeError to check for errors. 1230 | */ 1231 | void SdFile::write(const char* str) { 1232 | write(str, strlen(str)); 1233 | } 1234 | //------------------------------------------------------------------------------ 1235 | /** 1236 | * Write a PROGMEM string to a file. 1237 | * 1238 | * Use SdFile::writeError to check for errors. 1239 | */ 1240 | void SdFile::write_P(PGM_P str) { 1241 | for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c); 1242 | } 1243 | //------------------------------------------------------------------------------ 1244 | /** 1245 | * Write a PROGMEM string followed by CR/LF to a file. 1246 | * 1247 | * Use SdFile::writeError to check for errors. 1248 | */ 1249 | void SdFile::writeln_P(PGM_P str) { 1250 | write_P(str); 1251 | println(); 1252 | } 1253 | --------------------------------------------------------------------------------