diff --git a/.gitignore b/.gitignore index fe36653..a26923b 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ Configuration_*.h Repetier.depend Repetier.layout activate*.bat +~$Translate.xlsx diff --git a/.travis.yml b/.travis.yml index 636d9f5..8ce027a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,46 +5,40 @@ language: bash os: - linux -before_install: - - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16" - +env: + matrix: + - DAVINCI=0 MODEL=0 + - DAVINCI=1 MODEL=0 + - DAVINCI=2 MODEL=0 + - DAVINCI=3 MODEL=0 + - DAVINCI=1 MODEL=1 + - DAVINCI=2 MODEL=1 + - DAVINCI=4 MODEL=1 + before_script: - - "export DISPLAY=:99.0" - - sleep 3 # give xvfb some time to start - - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz - - tar xf arduino-1.6.5-linux64.tar.xz - - mv arduino-1.6.5 $HOME/arduino_ide - - mkdir -p $HOME/.arduino15/packages/arduino/hardware/sam - - cd $HOME/.arduino15/packages/arduino/hardware/sam - - wget http://downloads.arduino.cc/cores/sam-1.6.4.tar.bz2 - - tar xf sam-1.6.4.tar.bz2 - - mkdir -p $HOME/.arduino15/packages/arduino/tools/arm-none-eabi-gcc - - cd $HOME/.arduino15/packages/arduino/tools/arm-none-eabi-gcc - - wget http://downloads.arduino.cc/gcc-arm-none-eabi-4.8.3-2014q1-linux64.tar.gz - - tar xf gcc-arm-none-eabi-4.8.3-2014q1-linux64.tar.gz - - mv gcc-arm-none-eabi-4.8.3-2014q1 4.8.3-2014q1 - - cp -f "$TRAVIS_BUILD_DIR/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.5 -Due 1.6.4/Arduino15/packages/hardware/sam/1.6.4/variants/arduino_due_x/variant.cpp" $HOME/.arduino15/packages/arduino/hardware/sam/1.6.4/variants/arduino_due_x/variant.cpp + - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" + - sleep 3 + - export DISPLAY=:1.0 + - wget http://downloads.arduino.cc/arduino-1.6.9-linux64.tar.xz + - tar xf arduino-1.6.9-linux64.tar.xz + - mv arduino-1.6.9 $HOME/arduino_ide + - export PATH="$HOME/arduino_ide:$PATH" + - arduino --install-boards arduino:sam:1.6.8 + - arduino --board arduino:sam:arduino_due_x --save-prefs + - arduino --pref "compiler.warning_level=all" --save-prefs + - cp -f "$TRAVIS_BUILD_DIR/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.9 -Due 1.6.8/Arduino15/packages/arduino/hardware/sam/1.6.8/variants/arduino_due_x/variant.cpp" $HOME/.arduino15/packages/arduino/hardware/sam/1.6.8/variants/arduino_due_x/variant.cpp script: - cd $TRAVIS_BUILD_DIR - source command.sh - - export PATH="$HOME/arduino_ide:$PATH" - - arduino --board arduino:sam:arduino_due_x --save-prefs - - arduino --get-pref sketchbook.path - - build_sketch ./src/ArduinoDUE/Repetier/Repetier.ino - - sed -i 's/#define DAVINCI 1 /#define DAVINCI 2 /g' ./src/ArduinoDUE/Repetier/Configuration.h - - build_sketch ./src/ArduinoDUE/Repetier/Repetier.ino - - sed -i 's/#define DAVINCI 2 /#define DAVINCI 3 /g' ./src/ArduinoDUE/Repetier/Configuration.h - - build_sketch ./src/ArduinoDUE/Repetier/Repetier.ino - - sed -i 's/#define DAVINCI 3 /#define DAVINCI 0 /g' ./src/ArduinoDUE/Repetier/Configuration.h - - build_sketch ./src/ArduinoDUE/Repetier/Repetier.ino - - sed -i 's/#define DAVINCI 0 /#define DAVINCI 1 /g' ./src/ArduinoDUE/Repetier/Configuration.h - - sed -i 's/#define MODEL 0/#define MODEL 1/g' ./src/ArduinoDUE/Repetier/Configuration.h - - build_sketch ./src/ArduinoDUE/Repetier/Repetier.ino - - sed -i 's/#define DAVINCI 1 /#define DAVINCI 3 /g' ./src/ArduinoDUE/Repetier/Configuration.h - - build_sketch ./src/ArduinoDUE/Repetier/Repetier.ino - - sed -i 's/#define DAVINCI 3 /#define DAVINCI 4 /g' ./src/ArduinoDUE/Repetier/Configuration.h + - sed -i "s/#define DAVINCI 0 /#define DAVINCI $DAVINCI /g" ./src/ArduinoDUE/Repetier/Configuration.h + - sed -i "s/#define DAVINCI 1 /#define DAVINCI $DAVINCI /g" ./src/ArduinoDUE/Repetier/Configuration.h + - sed -i "s/#define DAVINCI 2 /#define DAVINCI $DAVINCI /g" ./src/ArduinoDUE/Repetier/Configuration.h + - sed -i "s/#define DAVINCI 3 /#define DAVINCI $DAVINCI /g" ./src/ArduinoDUE/Repetier/Configuration.h + - sed -i "s/#define DAVINCI 4 /#define DAVINCI $DAVINCI /g" ./src/ArduinoDUE/Repetier/Configuration.h + - sed -i "s/#define MODEL 1/#define MODEL $MODEL/g" ./src/ArduinoDUE/Repetier/Configuration.h + - sed -i "s/#define MODEL 0/#define MODEL $MODEL/g" ./src/ArduinoDUE/Repetier/Configuration.h - build_sketch ./src/ArduinoDUE/Repetier/Repetier.ino notifications: diff --git a/README.md b/README.md index 51327e3..d94f19d 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,24 @@ -##Da Vinci Firmware based on Repetier (0.92.3) +##Da Vinci Firmware based on Repetier (0.92.10) Alpha ============================ -[![Join the chat at https://gitter.im/luc-github/Repetier-Firmware-0.92](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/luc-github/Repetier-Firmware-0.92?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Ide 1.6.5 and module Due 1.6.4 : [![Build Status](https://travis-ci.org/luc-github/Repetier-Firmware-0.92.svg?branch=master)](https://travis-ci.org/luc-github/Repetier-Firmware-0.92) +[![Join the chat at https://gitter.im/luc-github/Repetier-Firmware-0.92](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/luc-github/Repetier-Firmware-0.92?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Build Status: [![Build Status](https://travis-ci.org/luc-github/Repetier-Firmware-0.92.svg?branch=master)](https://travis-ci.org/luc-github/Repetier-Firmware-0.92) + This firmware is based on the popular repetier firmware and modified to work with first generation Da Vinci 1.0, 2.0 single fan, 2.0 dual fans and also AiO (NB:scanner function is not supported so AiO will work like an 1.0A) If you change the board, currently DUE based are supported with RADDS, as well as Graphical screen and LCD with encoder, there are some sample configuration files provided for RADDS/DUE/GLCD using 1/128 step drivers. YOU MIGHT DAMAGE YOUR PRINTER OR VOID YOUR WARRANTY, DO IT ON YOUR OWN RISK. When it is possible on 1.0/2.0, currently on 1.0A/2.0A and AiO there is no way to revert to stock fw so be sure of what you are doing. *** -###Support for 1.0A/2.0A/AiO(no scanner) is implemented and need feedback. - -###:boom:New alpha version based on 0.92.10 is ready for test [here](https://github.com/luc-github/Repetier-Firmware-0.92/tree/devt) -* Multilangue :globe_with_meridians: -* AiO support for scanner :camera: -* Better auto leveling :tractor: +AiO scanner support is present in FW but scanner software support is currently basic, [horus](https://github.com/bqlabs/horus) is a good candidat, feel free to help [here](https://github.com/luc-github/Repetier-Firmware-0.92/issues/156) The board can be easily exposed by removing the back panel of the printer secured by two torx screws. Supported boards have a jumper labeled JP1, second generation boards have a jumper labeled J37. More info can be found on the [Voltivo forum](http://voltivo.com/forum/davinci-peersupport/340-new-kind-of-mainboard-no-j1-erase-jumper). *** -Here are just a few of the benifits of using this firmware: +Here are just a few of the benefits of using this firmware: * It works with host software such as [repetier host](http://repetier.com) and [OctoPrint](http://octoprint.org/) giving you full control of your hardware. * It works stand alone if you use a WIFI SD Card. @@ -35,16 +32,16 @@ The previous version (based on repetier v0.91) can be found [here](https://githu *** ##Current Status -####Beta - so far so good +####Alpha - so far so good *** ##Installation 1. With the machine off remove the back panel and short the jumper JP1 or J37 depending on model. Some Boards do not have jumper pins exposed but can still be shorted with a conductive wire. -2. Turn the machine on and wait a few seconds then turn it off again. The machine will have been flashed removing the current stock firmware and allowing it to be detected as a normal arduino DUE. NOTE: Windows users may need to install drivers to detect the board. Consult the Voltivo forums. -Note : points 1 and 2 are only needed to wipe the stock fw or a corrupted fw, for update they are not necessary. -3. Use an arduino IDE supporting arduino DUE, [version 1.5.8+ or 1.6.5](http://arduino.cc/en/Main/OldSoftwareReleases), 1.6.0+ bring several issues, but 1.6.5 seems working well with Due 1.6.4 module for board manager. -4. Update arduino files (variants.cpp and USBCore.cpp) with the one(s) present in src\ArduinoDUE\AdditionalArduinoFiles\1.5.8. or in src\ArduinoDUE\AdditionalArduinoFiles\1.6.5 according your IDE version -NOTE: You do not need to compile arduino from source these files are in the arduino directory structure. On Mac you will need to right click on the Arduino.app to Show Package Contents. +2. Turn the machine on and wait a few seconds then turn it off again. The machine will have been flashed removing the current stock firmware and allowing it to be detected as a normal arduino DUE. NOTE: Windows users may need to install drivers to detect the board. Consult the Voltivo forums. +Note : points 1 and 2 are only needed to wipe the stock fw or a corrupted fw, for update they are not necessary. +3. Use an arduino IDE supporting arduino DUE, [1.6.9](http://arduino.cc/en/Main/OldSoftwareReleases) with Due 1.6.8 module from board manager. +4. Update variants.cpp arduino file with the one present in src\ArduinoDUE\AdditionalArduinoFile according your IDE version +NOTE: You do not need to compile arduino from source these files are in the arduino directory structure (click on preferences.txt in Files/Preferences dialog box). 5. Open the project file named repetier.ino located in src\ArduinoDUE\Repetier directory in the arduino IDE. 6. Modify the DAVINCI define in Configuration.h file to match your targeted Da Vinci. See below. 7. Under the tools menu select the board type as Arduino DUE (Native USB Port) and the proper port you have connected to the printer. NOTE: You can usually find this out by looking at the tools -> port menu both before and after plugging in the printer to your computer's USB. @@ -58,14 +55,14 @@ If done correctly you will see the arduino sketch compile successfully and outpu For information on upgrading from or reverting to stock FW and other procedures please check [Da Vinci Voltivo forum](http://voltivo.com/forum/davinci).

:warning:There is no known way to revert to stock FW on 1.0A/2.0A/AiO until today.

-Do not forget to modify the Configuration.h to match your targeted Da Vinci: 1.0, 2.0 SF or 2.0. +Do not forget to modify the configuration.h to match your targeted Da Vinci: 1.0, 2.0 SF or 2.0. for basic installation just change : '#define DAVINCI 1 // "1" For DAVINCI 1.0, "2" For DAVINCI 2.0 with 1 FAN, "3" For DAVINCI 2.0 with 2 FANS, 4 For AiO (no scanner)' 0 for not Davinci board (like DUE/RADDS) 1 for DaVinci 1.0 (1Fan, 1 Extruder) 2 for DaVinci 2.0 SF (1Fan, 2 Extruders) 3 for DaVinci 2.0 (2Fans, 2 Extruders) - 4 for DaVinci AiO (no scanner) + 4 for DaVinci AiO Support for 1.0A and 2.0A: need to change #define MODEL 0 to #define MODEL 1 @@ -78,13 +75,18 @@ Or a great video done by Daniel Gonos: https://www.youtube.com/watch?v=rjuCvlnpB *** ##TODO or Questions ? -[Check issue list](https://github.com/luc-github/Repetier-Firmware-0.92/issues) -[FAQ](https://github.com/luc-github/Repetier-Firmware-0.92/issues?utf8=%E2%9C%93&q=is%3Aclosed+label%3AFAQ+) +* [Check issue list](https://github.com/luc-github/Repetier-Firmware-0.92/issues) +Do not ask help on repetier github they do not support this FW / printer - please use this [github for issues](https://github.com/luc-github/Repetier-Firmware-0.92/issues) + +* [FAQ](https://github.com/luc-github/Repetier-Firmware-0.92/issues?utf8=%E2%9C%93&q=is%3Aclosed+label%3AFAQ+) + +* [Documentation](https://github.com/luc-github/Repetier-Firmware-0.92/wiki) TBD - feel free to help *** ##Implemented -* Standard GCODE commands -* Single/Dual extruders support (DaVinci 1.0(a)/2.0(a) and AiO without scanner) +* 0.92.10 [Repetier](https://github.com/repetier/Repetier-Firmware) based +* Standard GCODE commands +* Single/Dual extruders support (DaVinci 1.0/2.0 all generations but AiO) * Single Fan / Dual fans support according printer configuration * Repurpose of second fan usage to be controlled by M106/M107 commands on Da Vinci 2.0 * Sound and Lights management, including powersaving function (light can be managed remotely by GCODE) @@ -104,7 +106,8 @@ Or a great video done by Daniel Gonos: https://www.youtube.com/watch?v=rjuCvlnpB * Several fixes from original FW * Watchdog * Basic Wifi support for module ESP8266 (https://github.com/luc-github/ESP8266/blob/master/README.md#result-of-esp12e-on-davinci) -* Customized thermistor tables for bed and extruder(s) as Davinci board do not follow design of others 3D printer boards so standard tables do not work properly [check here](http://voltivo.com/forum/davinci-firmware/438-repetier-91-e3d-v6-extruder#3631) +* Customized thermistor tables for bed and extruder(s) as Davinci boards do not follow design of others 3D printer boards so standard tables do not work properly [check here](http://voltivo.com/forum/davinci-firmware/438-repetier-91-e3d-v6-extruder#3631) +* Multilanguage at runtime (EN/FR/GE/NL/SW) more to come if get help : check [here](https://github.com/luc-github/Repetier-Firmware-0.92/issues/123) * More to come .... *** @@ -119,7 +122,4 @@ If not, you should have "Watchdog feature was not compiled into this version!" i ##Current menu (not up to date): Easy: Advanced : -*** -##Donation: -Every support is welcome: [PayPal – The safer, easier way to pay online.](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VT5LV38N4U3VQ) -Especially if need to buy new printer to add FW support. + diff --git a/Translate.xlsx b/Translate.xlsx new file mode 100644 index 0000000..bf2d58f Binary files /dev/null and b/Translate.xlsx differ diff --git a/pinout.xlsx b/pinout.xlsx index 858573e..aa5b7d3 100644 Binary files a/pinout.xlsx and b/pinout.xlsx differ diff --git a/src/ArduinoDUE/AdditionalArduinoFiles/1.5.8/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp b/src/ArduinoDUE/AdditionalArduinoFiles/1.5.8/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp deleted file mode 100644 index d51ec5e..0000000 --- a/src/ArduinoDUE/AdditionalArduinoFiles/1.5.8/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp +++ /dev/null @@ -1,891 +0,0 @@ -// Copyright (c) 2010, Peter Barrett -/* -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. -*/ - -#include "Arduino.h" -#include "USBAPI.h" -#include "Reset.h" -#include - -//#define TRACE_CORE(x) x -#define TRACE_CORE(x) - -static const uint32_t EndPoints[] = -{ - EP_TYPE_CONTROL, - -#ifdef CDC_ENABLED - EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM - EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT - EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN -#endif - -#ifdef HID_ENABLED - EP_TYPE_INTERRUPT_IN_HID // HID_ENDPOINT_INT -#endif -}; - -/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ -#define TX_RX_LED_PULSE_MS 100 -volatile uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ -volatile uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ -static char isRemoteWakeUpEnabled = 0; -static char isEndpointHalt = 0; -//================================================================== -//================================================================== - -extern const uint16_t STRING_LANGUAGE[]; -extern const uint8_t STRING_PRODUCT[]; -extern const uint8_t STRING_MANUFACTURER[]; -extern const DeviceDescriptor USB_DeviceDescriptor; -extern const DeviceDescriptor USB_DeviceDescriptorA; - -const uint16_t STRING_LANGUAGE[2] = { - (3<<8) | (2+2), - 0x0409 // English -}; - -#ifndef USB_PRODUCT -// Use a hardcoded product name if none is provided -#if USB_PID == USB_PID_DUE -#define USB_PRODUCT "Arduino Due" -#else -#define USB_PRODUCT "USB IO Board" -#endif -#endif - -const uint8_t STRING_PRODUCT[] = USB_PRODUCT; - -#if USB_VID == 0x2341 -# if defined(USB_MANUFACTURER) -# undef USB_MANUFACTURER -# endif -# define USB_MANUFACTURER "Arduino LLC" -#elif !defined(USB_MANUFACTURER) -// Fall through to unknown if no manufacturer name was provided in a macro -# define USB_MANUFACTURER "Unknown" -#endif - -const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER; - -#ifdef CDC_ENABLED -#define DEVICE_CLASS 0x02 -#else -#define DEVICE_CLASS 0x00 -#endif - -// DEVICE DESCRIPTOR -const DeviceDescriptor USB_DeviceDescriptor = - D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); - -const DeviceDescriptor USB_DeviceDescriptorA = - D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); - -const DeviceDescriptor USB_DeviceQualifier = - D_QUALIFIER(0x00,0x00,0x00,64,1); - -//! 7.1.20 Test Mode Support -static const unsigned char test_packet_buffer[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9 - 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8 - 0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8 - 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8 - 0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8 - 0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK -}; - -//================================================================== -//================================================================== - -volatile uint32_t _usbConfiguration = 0; -volatile uint32_t _usbInitialized = 0; -uint32_t _usbSetInterface = 0; -uint32_t _cdcComposite = 0; - -//================================================================== -//================================================================== - -#define USB_RECV_TIMEOUT -class LockEP -{ - irqflags_t flags; -public: - LockEP(uint32_t ep) : flags(cpu_irq_save()) - { - } - ~LockEP() - { - cpu_irq_restore(flags); - } -}; - -// Number of bytes, assumes a rx endpoint -uint32_t USBD_Available(uint32_t ep) -{ - LockEP lock(ep); - return UDD_FifoByteCount(ep & 0xF); -} - -// Non Blocking receive -// Return number of bytes read -uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len) -{ - if (!_usbConfiguration) - return -1; - - LockEP lock(ep); - uint32_t n = UDD_FifoByteCount(ep & 0xF); - len = min(n,len); - n = len; - uint8_t* dst = (uint8_t*)d; - while (n--) - *dst++ = UDD_Recv8(ep & 0xF); - if (len && !UDD_FifoByteCount(ep & 0xF)) // release empty buffer - UDD_ReleaseRX(ep & 0xF); - - return len; -} - -// Recv 1 byte if ready -uint32_t USBD_Recv(uint32_t ep) -{ - uint8_t c; - if (USBD_Recv(ep & 0xF, &c, 1) != 1) - return -1; - else - return c; -} - -// Space in send EP -//uint32_t USBD_SendSpace(uint32_t ep) -//{ - //LockEP lock(ep); -//// if (!UDD_ReadWriteAllowed(ep & 0xF)) - ////{ - ////printf("pb "); // UOTGHS->UOTGHS_DEVEPTISR[%d]=0x%X\n\r", ep, UOTGHS->UOTGHS_DEVEPTISR[ep]); - ////return 0; - ////} - - //if(ep==0) return 64 - UDD_FifoByteCount(ep & 0xF); // EP0_SIZE jcb - //else return 512 - UDD_FifoByteCount(ep & 0xF); // EPX_SIZE jcb -//} - -// Blocking Send of data to an endpoint -uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len) -{ - uint32_t n; - int r = len; - const uint8_t* data = (const uint8_t*)d; - - if (!_usbConfiguration) - { - TRACE_CORE(printf("pb conf\n\r");) - return -1; - } - - while (len) - { - if(ep==0) n = EP0_SIZE; - else n = EPX_SIZE; - if (n > len) - n = len; - len -= n; - int count=0; - while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[ep & 0xF] & UOTGHS_DEVEPTISR_TXINI )) - { - count++; - if (count>10000) return len; - } - UDD_Send(ep & 0xF, data, n); - data += n; - } - //TXLED1; // light the TX LED - //TxLEDPulse = TX_RX_LED_PULSE_MS; - return r; -} - -int _cmark; -int _cend; - -void USBD_InitControl(int end) -{ - _cmark = 0; - _cend = end; -} - -// Clipped by _cmark/_cend -int USBD_SendControl(uint8_t flags, const void* d, uint32_t len) -{ - const uint8_t* data = (const uint8_t*)d; - uint32_t length = len; - uint32_t sent = 0; - uint32_t pos = 0; - - TRACE_CORE(printf("=> USBD_SendControl TOTAL len=%lu\r\n", len);) - - if (_cmark < _cend) - { - while (len > 0) - { - sent = UDD_Send(EP0, data + pos, len); - TRACE_CORE(printf("=> USBD_SendControl sent=%lu\r\n", sent);) - pos += sent; - len -= sent; - } - } - - _cmark += length; - - return length; -} - -// Send a USB descriptor string. The string is stored as a -// plain ASCII string but is sent out as UTF-16 with the -// correct 2-byte prefix -static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) { - uint16_t buff[64]; - int l = 1; - wLength-=2; - while (*string && wLength>0) { - buff[l++] = (uint8_t)(*string++); - wLength-=2; - } - buff[0] = (3<<8) | (l*2); - return USBD_SendControl(0, (uint8_t*)buff, l*2); -} - -// Does not timeout or cross fifo boundaries -// Will only work for transfers <= 64 bytes -// TODO -int USBD_RecvControl(void* d, uint32_t len) -{ - UDD_WaitOUT(); - UDD_Recv(EP0, (uint8_t*)d, len); - UDD_ClearOUT(); - - return len; -} - -// Handle CLASS_INTERFACE requests -bool USBD_ClassInterfaceRequest(Setup& setup) -{ - uint8_t i = setup.wIndex; - - TRACE_CORE(printf("=> USBD_ClassInterfaceRequest\r\n");) - -#ifdef CDC_ENABLED - if (CDC_ACM_INTERFACE == i) - { - return CDC_Setup(setup); - } -#endif - -#ifdef HID_ENABLED - if (HID_INTERFACE == i) - { - return HID_Setup(setup); - } -#endif - - return false; -} - -int USBD_SendInterfaces(void) -{ - int total = 0; - uint8_t interfaces = 0; - -#ifdef CDC_ENABLED - total = CDC_GetInterface(&interfaces); -#endif - -#ifdef HID_ENABLED - total += HID_GetInterface(&interfaces); -#endif - - total = total; // Get rid of compiler warning - TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);) - return interfaces; -} - -int USBD_SendOtherInterfaces(void) -{ - int total = 0; - uint8_t interfaces = 0; - -#ifdef CDC_ENABLED - total = CDC_GetOtherInterface(&interfaces); -#endif - -#ifdef HID_ENABLED - total += HID_GetInterface(&interfaces); -#endif - - total = total; // Get rid of compiler warning - TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);) - return interfaces; -} - -// Construct a dynamic configuration descriptor -// This really needs dynamic endpoint allocation etc -// TODO -static bool USBD_SendConfiguration(int maxlen) -{ - // Count and measure interfaces - USBD_InitControl(0); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);) - int interfaces = USBD_SendInterfaces(); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);) - //TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));) - -_Pragma("pack(1)") - ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); -_Pragma("pack()") - //TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);) - - //TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);) - - // Now send them - USBD_InitControl(maxlen); - USBD_SendControl(0,&config,sizeof(ConfigDescriptor)); - USBD_SendInterfaces(); - return true; -} - -static bool USBD_SendOtherConfiguration(int maxlen) -{ - // Count and measure interfaces - USBD_InitControl(0); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);) - int interfaces = USBD_SendOtherInterfaces(); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);) - //TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));) - -_Pragma("pack(1)") - ConfigDescriptor config = D_OTHERCONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); -_Pragma("pack()") - //TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);) - - //TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);) - - // Now send them - USBD_InitControl(maxlen); - USBD_SendControl(0,&config,sizeof(ConfigDescriptor)); - USBD_SendOtherInterfaces(); - return true; -} - -static bool USBD_SendDescriptor(Setup& setup) -{ - uint8_t t = setup.wValueH; - uint8_t desc_length = 0; - const uint8_t* desc_addr = 0; - - if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(printf("=> USBD_SendDescriptor : USB_CONFIGURATION_DESCRIPTOR_TYPE length=%d\r\n", setup.wLength);) - return USBD_SendConfiguration(setup.wLength); - } - - USBD_InitControl(setup.wLength); -#ifdef HID_ENABLED - if (HID_REPORT_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(puts("=> USBD_SendDescriptor : HID_REPORT_DESCRIPTOR_TYPE\r\n");) - return HID_GetDescriptor(t); - } -#endif - - if (USB_DEVICE_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(puts("=> USBD_SendDescriptor : USB_DEVICE_DESCRIPTOR_TYPE\r\n");) - if (setup.wLength == 8) - { - _cdcComposite = 1; - } - desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptorA : (const uint8_t*)&USB_DeviceDescriptor; - if( *desc_addr > setup.wLength ) { - desc_length = setup.wLength; - } - } - else if (USB_STRING_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(puts("=> USBD_SendDescriptor : USB_STRING_DESCRIPTOR_TYPE\r\n");) - if (setup.wValueL == 0) { - desc_addr = (const uint8_t*)&STRING_LANGUAGE; - } - else if (setup.wValueL == IPRODUCT) { - return USB_SendStringDescriptor(STRING_PRODUCT, setup.wLength); - } - else if (setup.wValueL == IMANUFACTURER) { - return USB_SendStringDescriptor(STRING_MANUFACTURER, setup.wLength); - } - else { - return false; - } - if( *desc_addr > setup.wLength ) { - desc_length = setup.wLength; - } - } - else if (USB_DEVICE_QUALIFIER == t) - { - // Device qualifier descriptor requested - desc_addr = (const uint8_t*)&USB_DeviceQualifier; - if( *desc_addr > setup.wLength ) { - desc_length = setup.wLength; - } - } - else if (USB_OTHER_SPEED_CONFIGURATION == t) - { - // Other configuration descriptor requested - return USBD_SendOtherConfiguration(setup.wLength); - } - else - { - //printf("Device ERROR"); - } - - if (desc_addr == 0) - { - return false; - } - - if (desc_length == 0) - { - desc_length = *desc_addr; - } - - TRACE_CORE(printf("=> USBD_SendDescriptor : desc_addr=%p desc_length=%d\r\n", desc_addr, desc_length);) - USBD_SendControl(0, desc_addr, desc_length); - - return true; -} - - -static void USB_SendZlp( void ) -{ - while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[0] & UOTGHS_DEVEPTISR_TXINI ) ) - { - if((UOTGHS->UOTGHS_DEVISR & UOTGHS_DEVISR_SUSP) == UOTGHS_DEVISR_SUSP) - { - return; - } - } - UOTGHS->UOTGHS_DEVEPTICR[0] = UOTGHS_DEVEPTICR_TXINIC; -} - - -static void Test_Mode_Support( uint8_t wIndex ) -{ - uint8_t i; - uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(2); - - switch( wIndex ) - { - case 4: - //Test mode Test_Packet: - //Upon command, a port must repetitively transmit the following test packet until - //the exit action is taken. This enables the testing of rise and fall times, eye - //patterns, jitter, and any other dynamic waveform specifications. - //The test packet is made up by concatenating the following strings. - //(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one - //transmitted. "S" indicates that a bit stuff occurs, which inserts an "extra" NRZI data bit. - //"* N" is used to indicate N occurrences of a string of bits or symbols.) - //A port in Test_Packet mode must send this packet repetitively. The inter-packet timing - //must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and - //no greater than 125 us. - - // Send ZLP - USB_SendZlp(); - - UOTGHS->UOTGHS_DEVDMA[0].UOTGHS_DEVDMACONTROL = 0; // raz - UOTGHS->UOTGHS_DEVDMA[1].UOTGHS_DEVDMACONTROL = 0; // raz - - // Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank - UOTGHS->UOTGHS_DEVEPTCFG[2] = UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE - | UOTGHS_DEVEPTCFG_EPDIR_IN - | UOTGHS_DEVEPTCFG_EPTYPE_BLK - | UOTGHS_DEVEPTCFG_EPBK_1_BANK; - // Check if the configuration is ok - UOTGHS->UOTGHS_DEVEPTCFG[2] |= UOTGHS_DEVEPTCFG_ALLOC; - while((UOTGHS->UOTGHS_DEVEPTISR[2]&UOTGHS_DEVEPTISR_CFGOK)==0) {} - UOTGHS->UOTGHS_DEVEPT |= UOTGHS_DEVEPT_EPEN2; - // Write FIFO - for( i=0; iUOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTPCKT; - // Send packet - UOTGHS->UOTGHS_DEVEPTICR[2] = UOTGHS_DEVEPTICR_TXINIC; - UOTGHS->UOTGHS_DEVEPTIDR[2] = UOTGHS_DEVEPTIDR_FIFOCONC; - for(;;); -// break; - - case 1: - //Test mode Test_J: - //Upon command, a port's transceiver must enter the high-speed J state and remain in that - //state until the exit action is taken. This enables the testing of the high output drive - //level on the D+ line. - // Send a ZLP - USB_SendZlp(); - UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTJ; - for(;;); -// break; - - case 2: - //Test mode Test_K: - //Upon command, a port's transceiver must enter the high-speed K state and remain in - //that state until the exit action is taken. This enables the testing of the high output drive - //level on the D- line. - // Send a ZLP - USB_SendZlp(); - UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTK; - for(;;); -// break; - - case 3: - //Test mode Test_SE0_NAK: - //Upon command, a port's transceiver must enter the high-speed receive mode - //and remain in that mode until the exit action is taken. This enables the testing - //of output impedance, low level output voltage, and loading characteristics. - //In addition, while in this mode, upstream facing ports (and only upstream facing ports) - //must respond to any IN token packet with a NAK handshake (only if the packet CRC is - //determined to be correct) within the normal allowed device response time. This enables testing of - //the device squelch level circuitry and, additionally, provides a general purpose stimulus/response - //test for basic functional testing. - - // Send a ZLP - USB_SendZlp(); - UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_SUSPEC - | UOTGHS_DEVIDR_MSOFEC - | UOTGHS_DEVIDR_SOFEC - | UOTGHS_DEVIDR_EORSTEC - | UOTGHS_DEVIDR_WAKEUPEC - | UOTGHS_DEVIDR_EORSMEC - | UOTGHS_DEVIDR_UPRSMEC - | UOTGHS_DEVIDR_PEP_0 - | UOTGHS_DEVIDR_PEP_1 - | UOTGHS_DEVIDR_PEP_2 - | UOTGHS_DEVIDR_PEP_3 - | UOTGHS_DEVIDR_PEP_4 - | UOTGHS_DEVIDR_PEP_5 - | UOTGHS_DEVIDR_PEP_6 - | UOTGHS_DEVIDR_DMA_1 - | UOTGHS_DEVIDR_DMA_2 - | UOTGHS_DEVIDR_DMA_3 - | UOTGHS_DEVIDR_DMA_4 - | UOTGHS_DEVIDR_DMA_5 - | UOTGHS_DEVIDR_DMA_6; - for(;;); -// break; - } -} - - -//unsigned int iii=0; -// Endpoint 0 interrupt -static void USB_ISR(void) -{ -// printf("ISR=0x%X\n\r", UOTGHS->UOTGHS_DEVISR); // jcb -// if( iii++ > 1500 ) while(1); // jcb - // End of bus reset - if (Is_udd_reset()) - { - TRACE_CORE(printf(">>> End of Reset\r\n");) - - // Reset USB address to 0 - udd_configure_address(0); - udd_enable_address(); - - // Configure EP 0 - UDD_InitEP(0, EP_TYPE_CONTROL); - udd_enable_setup_received_interrupt(0); - udd_enable_endpoint_interrupt(0); - - _usbConfiguration = 0; - udd_ack_reset(); - } - -#ifdef CDC_ENABLED - if (Is_udd_endpoint_interrupt(CDC_RX)) - { - udd_ack_out_received(CDC_RX); - - // Handle received bytes - if (USBD_Available(CDC_RX)) - SerialUSB.accept(); - } - - if (Is_udd_sof()) - { - udd_ack_sof(); - // USBD_Flush(CDC_TX); // jcb - } -#endif - - // EP 0 Interrupt - if (Is_udd_endpoint_interrupt(0) ) - { - if (!UDD_ReceivedSetupInt()) - { - return; - } - - Setup setup; - UDD_Recv(EP0, (uint8_t*)&setup, 8); - UDD_ClearSetupInt(); - - uint8_t requestType = setup.bmRequestType; - if (requestType & REQUEST_DEVICETOHOST) - { - TRACE_CORE(puts(">>> EP0 Int: IN Request\r\n");) - UDD_WaitIN(); - } - else - { - TRACE_CORE(puts(">>> EP0 Int: OUT Request\r\n");) - UDD_ClearIN(); - } - - bool ok = true; - if (REQUEST_STANDARD == (requestType & REQUEST_TYPE)) - { - // Standard Requests - uint8_t r = setup.bRequest; - if (GET_STATUS == r) - { - if( setup.bmRequestType == 0 ) // device - { - // Send the device status - TRACE_CORE(puts(">>> EP0 Int: GET_STATUS\r\n");) - // Check current configuration for power mode (if device is configured) - // TODO - // Check if remote wake-up is enabled - // TODO - UDD_Send8(EP0, 0); // TODO - UDD_Send8(EP0, 0); - } - // if( setup.bmRequestType == 2 ) // Endpoint: - else - { - // Send the endpoint status - // Check if the endpoint if currently halted - if( isEndpointHalt == 1 ) - UDD_Send8(EP0, 1); // TODO - else - UDD_Send8(EP0, 0); // TODO - UDD_Send8(EP0, 0); - } - } - else if (CLEAR_FEATURE == r) - { - // Check which is the selected feature - if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP - { - // Enable remote wake-up and send a ZLP - if( isRemoteWakeUpEnabled == 1 ) - UDD_Send8(EP0, 1); - else - UDD_Send8(EP0, 0); - UDD_Send8(EP0, 0); - } - else // if( setup.wValueL == 0) // ENDPOINTHALT - { - isEndpointHalt = 0; // TODO - UDD_Send8(EP0, 0); - UDD_Send8(EP0, 0); - } - - } - else if (SET_FEATURE == r) - { - // Check which is the selected feature - if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP - { - // Enable remote wake-up and send a ZLP - isRemoteWakeUpEnabled = 1; - UDD_Send8(EP0, 0); - } - if( setup.wValueL == 0) // ENDPOINTHALT - { - // Halt endpoint - isEndpointHalt = 1; - //USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest)); - UDD_Send8(EP0, 0); - } - if( setup.wValueL == 2) // TEST_MODE - { - // 7.1.20 Test Mode Support, 9.4.9 SetFeature - if( (setup.bmRequestType == 0 /*USBGenericRequest_DEVICE*/) && - ((setup.wIndex & 0x000F) == 0) ) - { - // the lower byte of wIndex must be zero - // the most significant byte of wIndex is used to specify the specific test mode - - UOTGHS->UOTGHS_DEVIDR &= ~UOTGHS_DEVIDR_SUSPEC; - UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED; // remove suspend ? - - Test_Mode_Support( (setup.wIndex & 0xFF00)>>8 ); - } - } - } - else if (SET_ADDRESS == r) - { - TRACE_CORE(puts(">>> EP0 Int: SET_ADDRESS\r\n");) - UDD_WaitIN(); - UDD_SetAddress(setup.wValueL); - } - else if (GET_DESCRIPTOR == r) - { - TRACE_CORE(puts(">>> EP0 Int: GET_DESCRIPTOR\r\n");) - ok = USBD_SendDescriptor(setup); - } - else if (SET_DESCRIPTOR == r) - { - TRACE_CORE(puts(">>> EP0 Int: SET_DESCRIPTOR\r\n");) - ok = false; - } - else if (GET_CONFIGURATION == r) - { - TRACE_CORE(puts(">>> EP0 Int: GET_CONFIGURATION\r\n");) - UDD_Send8(EP0, _usbConfiguration); - } - else if (SET_CONFIGURATION == r) - { - if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT)) - { - TRACE_CORE(printf(">>> EP0 Int: SET_CONFIGURATION REQUEST_DEVICE %d\r\n", setup.wValueL);) - - UDD_InitEndpoints(EndPoints, (sizeof(EndPoints) / sizeof(EndPoints[0]))); - _usbConfiguration = setup.wValueL; - -#ifdef CDC_ENABLED - // Enable interrupt for CDC reception from host (OUT packet) - udd_enable_out_received_interrupt(CDC_RX); - udd_enable_endpoint_interrupt(CDC_RX); -#endif - } - else - { - TRACE_CORE(puts(">>> EP0 Int: SET_CONFIGURATION failed!\r\n");) - ok = false; - } - } - else if (GET_INTERFACE == r) - { - TRACE_CORE(puts(">>> EP0 Int: GET_INTERFACE\r\n");) - UDD_Send8(EP0, _usbSetInterface); - } - else if (SET_INTERFACE == r) - { - _usbSetInterface = setup.wValueL; - TRACE_CORE(puts(">>> EP0 Int: SET_INTERFACE\r\n");) - } - } - else - { - TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");) - - UDD_WaitIN(); // Workaround: need tempo here, else CDC serial won't open correctly - - USBD_InitControl(setup.wLength); // Max length of transfer - ok = USBD_ClassInterfaceRequest(setup); - } - - if (ok) - { - TRACE_CORE(puts(">>> EP0 Int: Send packet\r\n");) - UDD_ClearIN(); - } - else - { - TRACE_CORE(puts(">>> EP0 Int: Stall\r\n");) - UDD_Stall(); - } - } -} - -void USBD_Flush(uint32_t ep) -{ - if (UDD_FifoByteCount(ep)) - UDD_ReleaseTX(ep); -} - -// VBUS or counting frames -// Any frame counting? -uint32_t USBD_Connected(void) -{ - uint8_t f = UDD_GetFrameNumber(); - - delay(3); - - return f != UDD_GetFrameNumber(); -} - - -//======================================================================= -//======================================================================= - -USBDevice_ USBDevice; - -USBDevice_::USBDevice_() -{ - UDD_SetStack(&USB_ISR); - - if (UDD_Init() == 0UL) - { - _usbInitialized=1UL; - } -} - -bool USBDevice_::attach(void) -{ - if (_usbInitialized != 0UL) - { - UDD_Attach(); - _usbConfiguration = 0; - return true; - } - else - { - return false; - } -} - -bool USBDevice_::detach(void) -{ - if (_usbInitialized != 0UL) - { - UDD_Detach(); - return true; - } - else - { - return false; - } -} - -// Check for interrupts -// TODO: VBUS detection -bool USBDevice_::configured() -{ - return _usbConfiguration; -} - -void USBDevice_::poll() -{ -} diff --git a/src/ArduinoDUE/AdditionalArduinoFiles/1.5.8/hardware/arduino/sam/variants/arduino_due_x/variant.cpp b/src/ArduinoDUE/AdditionalArduinoFiles/1.5.8/hardware/arduino/sam/variants/arduino_due_x/variant.cpp deleted file mode 100644 index d1350bb..0000000 --- a/src/ArduinoDUE/AdditionalArduinoFiles/1.5.8/hardware/arduino/sam/variants/arduino_due_x/variant.cpp +++ /dev/null @@ -1,492 +0,0 @@ -/* - Copyright (c) 2011 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "variant.h" - -/* - * DUE Board pin | PORT | Label - * ----------------+--------+------- - * 0 | PA8 | "RX0" - * 1 | PA9 | "TX0" - * 2 TIOA0 | PB25 | - * 3 TIOA7 | PC28 | - * 4 NPCS1 | PA29 | - * TIOB6 | PC26 | - * 5 TIOA6 | PC25 | - * 6 PWML7 | PC24 | - * 7 PWML6 | PC23 | - * 8 PWML5 | PC22 | - * 9 PWML4 | PC21 | - * 10 NPCS0 | PA28 | - * TIOB7 | PC29 | - * 11 TIOA8 | PD7 | - * 12 TIOB8 | PD8 | - * 13 TIOB0 | PB27 | LED AMBER "L" - * 14 TXD3 | PD4 | "TX3" - * 15 RXD3 | PD5 | "RX3" - * 16 TXD1 | PA13 | "TX2" - * 17 RXD1 | PA12 | "RX2" - * 18 TXD0 | PA11 | "TX1" - * 19 RXD0 | PA10 | "RX1" - * 20 | PB12 | "SDA" - * 21 | PB13 | "SCL" - * 22 | PB26 | - * 23 | PA14 | - * 24 | PA15 | - * 25 | PD0 | - * 26 | PD1 | - * 27 | PD2 | - * 28 | PD3 | - * 29 | PD6 | - * 30 | PD9 | - * 31 | PA7 | - * 32 | PD10 | - * 33 | PC1 | - * 34 | PC2 | - * 35 | PC3 | - * 36 | PC4 | - * 37 | PC5 | - * 38 | PC6 | - * 39 | PC7 | - * 40 | PC8 | - * 41 | PC9 | - * 42 | PA19 | - * 43 | PA20 | - * 44 | PC19 | - * 45 | PC18 | - * 46 | PC17 | - * 47 | PC16 | - * 48 | PC15 | - * 49 | PC14 | - * 50 | PC13 | - * 51 | PC12 | - * 52 NPCS2 | PB21 | - * 53 | PB14 | - * 54 | PA16 | "A0" - * 55 | PA24 | "A1" - * 56 | PA23 | "A2" - * 57 | PA22 | "A3" - * 58 TIOB2 | PA6 | "A4" - * 69 | PA4 | "A5" - * 60 TIOB1 | PA3 | "A6" - * 61 TIOA1 | PA2 | "A7" - * 62 | PB17 | "A8" - * 63 | PB18 | "A9" - * 64 | PB19 | "A10" - * 65 | PB20 | "A11" - * 66 | PB15 | "DAC0" - * 67 | PB16 | "DAC1" - * 68 | PA1 | "CANRX" - * 69 | PA0 | "CANTX" - * 70 | PA17 | "SDA1" - * 71 | PA18 | "SCL1" - * 72 | PC30 | LED AMBER "RX" - * 73 | PA21 | LED AMBER "TX" - * 74 MISO | PA25 | - * 75 MOSI | PA26 | - * 76 SCLK | PA27 | - * 77 NPCS0 | PA28 | - * 78 NPCS3 | PB23 | unconnected! - * - * USB pin | PORT - * ----------------+-------- - * ID | PB11 - * VBOF | PB10 - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Pins descriptions - */ -extern const PinDescription g_APinDescription[]= -{ - // 0 .. 53 - Digital pins - // ---------------------- - // 0/1 - UART (Serial) - { PIOA, PIO_PA8A_URXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // URXD - { PIOA, PIO_PA9A_UTXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // UTXD - - // 2 - { PIOB, PIO_PB25B_TIOA0, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC0_CHA0 }, // TIOA0 - { PIOC, PIO_PC28B_TIOA7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA7 }, // TIOA7 - { PIOC, PIO_PC26B_TIOB6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB6 }, // TIOB6 - - // 5 - { PIOC, PIO_PC25B_TIOA6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA6 }, // TIOA6 - { PIOC, PIO_PC24B_PWML7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH7, NOT_ON_TIMER }, // PWML7 - { PIOC, PIO_PC23B_PWML6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH6, NOT_ON_TIMER }, // PWML6 - { PIOC, PIO_PC22B_PWML5, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH5, NOT_ON_TIMER }, // PWML5 - { PIOC, PIO_PC21B_PWML4, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH4, NOT_ON_TIMER }, // PWML4 - // 10 - { PIOC, PIO_PC29B_TIOB7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB7 }, // TIOB7 - { PIOD, PIO_PD7B_TIOA8, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA8 }, // TIOA8 - { PIOD, PIO_PD8B_TIOB8, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB8 }, // TIOB8 - - // 13 - AMBER LED - { PIOB, PIO_PB27B_TIOB0, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC0_CHB0 }, // TIOB0 - - // 14/15 - USART3 (Serial3) - { PIOD, PIO_PD4B_TXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD3 - { PIOD, PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD3 - - // 16/17 - USART1 (Serial2) - { PIOA, PIO_PA13A_TXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD1 - { PIOA, PIO_PA12A_RXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD1 - - // 18/19 - USART0 (Serial1) - { PIOA, PIO_PA11A_TXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD0 - { PIOA, PIO_PA10A_RXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD0 - - // 20/21 - TWI1 - { PIOB, PIO_PB12A_TWD1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWD1 - SDA0 - { PIOB, PIO_PB13A_TWCK1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWCK1 - SCL0 - - // 22 - { PIOB, PIO_PB26, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 22 - { PIOA, PIO_PA14, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 23 - { PIOA, PIO_PA15, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 24 - { PIOD, PIO_PD0, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 25 - - // 26 - { PIOD, PIO_PD1, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 26 - { PIOD, PIO_PD2, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 27 - { PIOD, PIO_PD3, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 28 - { PIOD, PIO_PD6, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 29 - - // 30 - { PIOD, PIO_PD9, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 30 - { PIOA, PIO_PA7, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 31 - { PIOD, PIO_PD10, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 32 - { PIOC, PIO_PC1, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 33 - - // 34 - { PIOC, PIO_PC2, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 34 - { PIOC, PIO_PC3, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 35 - { PIOC, PIO_PC4, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 36 - { PIOC, PIO_PC5, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 37 - - // 38 - { PIOC, PIO_PC6, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 38 - { PIOC, PIO_PC7, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 39 - { PIOC, PIO_PC8, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 40 - { PIOC, PIO_PC9, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 41 - - // 42 - { PIOA, PIO_PA19, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 42 - { PIOA, PIO_PA20, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 43 - { PIOC, PIO_PC19, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 44 - { PIOC, PIO_PC18, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 45 - - // 46 - { PIOC, PIO_PC17, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 46 - { PIOC, PIO_PC16, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 47 - { PIOC, PIO_PC15, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 48 - { PIOC, PIO_PC14, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 49 - - // 50 - { PIOC, PIO_PC13, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 50 - { PIOC, PIO_PC12, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 51 - { PIOB, PIO_PB21, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 52 - { PIOB, PIO_PB14, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 53 - - - // 54 .. 65 - Analog pins - // ---------------------- - { PIOA, PIO_PA16X1_AD7, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC7, NOT_ON_PWM, NOT_ON_TIMER }, // AD0 - { PIOA, PIO_PA24X1_AD6, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC1, ADC6, NOT_ON_PWM, NOT_ON_TIMER }, // AD1 - { PIOA, PIO_PA23X1_AD5, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC2, ADC5, NOT_ON_PWM, NOT_ON_TIMER }, // AD2 - { PIOA, PIO_PA22X1_AD4, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC3, ADC4, NOT_ON_PWM, NOT_ON_TIMER }, // AD3 - // 58 - { PIOA, PIO_PA6X1_AD3, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC4, ADC3, NOT_ON_PWM, TC0_CHB2 }, // AD4 - { PIOA, PIO_PA4X1_AD2, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC5, ADC2, NOT_ON_PWM, NOT_ON_TIMER }, // AD5 - { PIOA, PIO_PA3X1_AD1, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC6, ADC1, NOT_ON_PWM, TC0_CHB1 }, // AD6 - { PIOA, PIO_PA2X1_AD0, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC7, ADC0, NOT_ON_PWM, TC0_CHA1 }, // AD7 - // 62 - { PIOB, PIO_PB17X1_AD10, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC8, ADC10, NOT_ON_PWM, NOT_ON_TIMER }, // AD8 - { PIOB, PIO_PB18X1_AD11, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC9, ADC11, NOT_ON_PWM, NOT_ON_TIMER }, // AD9 - { PIOB, PIO_PB19X1_AD12, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC10, ADC12, NOT_ON_PWM, NOT_ON_TIMER }, // AD10 - { PIOB, PIO_PB20X1_AD13, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC11, ADC13, NOT_ON_PWM, NOT_ON_TIMER }, // AD11 - - // 66/67 - DAC0/DAC1 - { PIOB, PIO_PB15X1_DAC0, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC12, DA0, NOT_ON_PWM, NOT_ON_TIMER }, // DAC0 - { PIOB, PIO_PB16X1_DAC1, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC13, DA1, NOT_ON_PWM, NOT_ON_TIMER }, // DAC1 - - // 68/69 - CANRX0/CANTX0 - { PIOA, PIO_PA1A_CANRX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, ADC14, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANRX - { PIOA, PIO_PA0A_CANTX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, ADC15, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANTX - - // 70/71 - TWI0 - { PIOA, PIO_PA17A_TWD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWD0 - SDA1 - { PIOA, PIO_PA18A_TWCK0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWCK0 - SCL1 - - // 72/73 - LEDs - { PIOC, PIO_PC30, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // LED AMBER RXL - { PIOA, PIO_PA21, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // LED AMBER TXL - - // 74/75/76 - SPI - { PIOA, PIO_PA25A_SPI0_MISO,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // MISO - { PIOA, PIO_PA26A_SPI0_MOSI,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI - { PIOA, PIO_PA27A_SPI0_SPCK,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // SPCK - - // 77 - SPI CS0 - { PIOA, PIO_PA28A_SPI0_NPCS0,ID_PIOA,PIO_PERIPH_A,PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS0 - - // 78 - SPI CS3 (unconnected) - { PIOB, PIO_PB23B_SPI0_NPCS3,ID_PIOB,PIO_PERIPH_B,PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS3 - - // 79 .. 84 - "All pins" masks - - // 79 - TWI0 all pins - { PIOA, PIO_PA17A_TWD0|PIO_PA18A_TWCK0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 80 - TWI1 all pins - { PIOB, PIO_PB12A_TWD1|PIO_PB13A_TWCK1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 81 - UART (Serial) all pins - { PIOA, PIO_PA8A_URXD|PIO_PA9A_UTXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 82 - USART0 (Serial1) all pins - { PIOA, PIO_PA11A_TXD0|PIO_PA10A_RXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 83 - USART1 (Serial2) all pins - { PIOA, PIO_PA13A_TXD1|PIO_PA12A_RXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 84 - USART3 (Serial3) all pins - { PIOD, PIO_PD4B_TXD3|PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - - // 85 - USB - { PIOB, PIO_PB11A_UOTGID, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID -// { PIOB, PIO_PB11A_UOTGID|PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF - // 86 - SPI CS2 - { PIOB, PIO_PB21B_SPI0_NPCS2, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS2 - - // 87 - SPI CS1 - { PIOA, PIO_PA29A_SPI0_NPCS1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS1 - - // 88/89 - CANRX1/CANTX1 (same physical pin for 66/53) - { PIOB, PIO_PB15A_CANRX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANRX1 - { PIOB, PIO_PB14A_CANTX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANTX1 - - // 90 .. 91 - "All CAN pins" masks - // 90 - CAN0 all pins - { PIOA, PIO_PA1A_CANRX0|PIO_PA0A_CANTX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 91 - CAN1 all pins - { PIOB, PIO_PB15A_CANRX1|PIO_PB14A_CANTX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - - // 92 .. 99 placeholders, future-proofing. - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 100 - 108 extra SAM3X8E pins, not wired on Due - { PIOA, PIO_PA5, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 100 - { PIOC, PIO_PC27, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 101 - { PIOA, PIO_PA0, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 102 - { PIOA, PIO_PA1, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 103 - { PIOC, PIO_PC11, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 104 - { PIOC, PIO_PC8B_PWML3, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH3, NOT_ON_TIMER }, // PWM 105 - { PIOC, PIO_PC2B_PWML0, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH0, NOT_ON_TIMER }, // PWM 106 - { PIOC, PIO_PC6B_PWML2, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH2, NOT_ON_TIMER }, //PWM 107 - { PIOC, PIO_PC20, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, //PWM 108 - // 109 .. 114 - { PIOA, PIO_PA20A_MCCDA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCCDA_GPIO 109 - { PIOA, PIO_PA19A_MCCK, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCCK_GPIO 110 - { PIOA, PIO_PA21A_MCDA0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA0_GPIO 111 - { PIOA, PIO_PA22A_MCDA1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA1_GPIO 112 - { PIOA, PIO_PA23A_MCDA2, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA2_GPIO 113 - { PIOA, PIO_PA24A_MCDA3, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA3_GPIO 114 - // 115 .. 124 - ETHERNET MAC - { PIOB, PIO_PB0A_ETXCK, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETXCK 115 - { PIOB, PIO_PB1A_ETXEN, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETXEN 116 - { PIOB, PIO_PB2A_ETX0, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETX0 117 - { PIOB, PIO_PB3A_ETX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETX1 118 - { PIOB, PIO_PB4A_ECRSDV, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ECRSDV 119 - { PIOB, PIO_PB5A_ERX0, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ERX0 120 - { PIOB, PIO_PB6A_ERX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ERX1 121 - { PIOB, PIO_PB7A_ERXER, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ERXER 122 - { PIOB, PIO_PB8A_EMDC, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // EMDC 123 - { PIOB, PIO_PB9A_EMDIO, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // EMDIO 124 - // 125 - { PIOB, PIO_PB24, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 125 - { PIOB, PIO_PB21X1_AD14, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC14, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 126 - PB21 with enabled ADC - { PIOB, PIO_PB13X1_AD9, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC9, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 127 - PB13 with enabled ACD AD9 - { PIOB, PIO_PB22, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 128 - PB22 E1 Enabled - { PIOB, PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF 129 - - // END - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER } -} ; - -#ifdef __cplusplus -} -#endif - -/* - * UART objects - */ -RingBuffer rx_buffer1; - -UARTClass Serial(UART, UART_IRQn, ID_UART, &rx_buffer1); -void serialEvent() __attribute__((weak)); -void serialEvent() { } - -// IT handlers -void UART_Handler(void) -{ - Serial.IrqHandler(); -} - -// ---------------------------------------------------------------------------- -/* - * USART objects - */ -RingBuffer rx_buffer2; -RingBuffer rx_buffer3; -RingBuffer rx_buffer4; - -USARTClass Serial1(USART0, USART0_IRQn, ID_USART0, &rx_buffer2); -void serialEvent1() __attribute__((weak)); -void serialEvent1() { } -USARTClass Serial2(USART1, USART1_IRQn, ID_USART1, &rx_buffer3); -void serialEvent2() __attribute__((weak)); -void serialEvent2() { } -USARTClass Serial3(USART3, USART3_IRQn, ID_USART3, &rx_buffer4); -void serialEvent3() __attribute__((weak)); -void serialEvent3() { } - -// IT handlers -void USART0_Handler(void) -{ - Serial1.IrqHandler(); -} - -void USART1_Handler(void) -{ - Serial2.IrqHandler(); -} - -void USART3_Handler(void) -{ - Serial3.IrqHandler(); -} - -// ---------------------------------------------------------------------------- - -void serialEventRun(void) -{ - if (Serial.available()) serialEvent(); - if (Serial1.available()) serialEvent1(); - if (Serial2.available()) serialEvent2(); - if (Serial3.available()) serialEvent3(); -} - -// ---------------------------------------------------------------------------- - -#ifdef __cplusplus -extern "C" { -#endif - -void __libc_init_array(void); - -void init( void ) -{ - SystemInit(); - - // Set Systick to 1ms interval, common to all SAM3 variants - if (SysTick_Config(SystemCoreClock / 1000)) - { - // Capture error - while (true); - } - - // Disable watchdog - //WDT_Disable(WDT); - // Initialize C library - __libc_init_array(); - - // Disable pull-up on every pin - for (int i = 0; i < PINS_COUNT; i++) - digitalWrite(i, LOW); - - // Enable parallel access on PIO output data registers - PIOA->PIO_OWER = 0xFFFFFFFF; - PIOB->PIO_OWER = 0xFFFFFFFF; - PIOC->PIO_OWER = 0xFFFFFFFF; - PIOD->PIO_OWER = 0xFFFFFFFF; - - // Initialize Serial port U(S)ART pins - PIO_Configure( - g_APinDescription[PINS_UART].pPort, - g_APinDescription[PINS_UART].ulPinType, - g_APinDescription[PINS_UART].ulPin, - g_APinDescription[PINS_UART].ulPinConfiguration); - digitalWrite(0, HIGH); // Enable pullup for RX0 - PIO_Configure( - g_APinDescription[PINS_USART0].pPort, - g_APinDescription[PINS_USART0].ulPinType, - g_APinDescription[PINS_USART0].ulPin, - g_APinDescription[PINS_USART0].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PINS_USART1].pPort, - g_APinDescription[PINS_USART1].ulPinType, - g_APinDescription[PINS_USART1].ulPin, - g_APinDescription[PINS_USART1].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PINS_USART3].pPort, - g_APinDescription[PINS_USART3].ulPinType, - g_APinDescription[PINS_USART3].ulPin, - g_APinDescription[PINS_USART3].ulPinConfiguration); - - // Initialize USB pins - PIO_Configure( - g_APinDescription[PINS_USB].pPort, - g_APinDescription[PINS_USB].ulPinType, - g_APinDescription[PINS_USB].ulPin, - g_APinDescription[PINS_USB].ulPinConfiguration); - - // Initialize CAN pins - PIO_Configure( - g_APinDescription[PINS_CAN0].pPort, - g_APinDescription[PINS_CAN0].ulPinType, - g_APinDescription[PINS_CAN0].ulPin, - g_APinDescription[PINS_CAN0].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PINS_CAN1].pPort, - g_APinDescription[PINS_CAN1].ulPinType, - g_APinDescription[PINS_CAN1].ulPin, - g_APinDescription[PINS_CAN1].ulPinConfiguration); - - // Initialize Analog Controller - pmc_enable_periph_clk(ID_ADC); - adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST); - adc_configure_timing(ADC, 0, ADC_SETTLING_TIME_3, 1); - adc_configure_trigger(ADC, ADC_TRIG_SW, 0); // Disable hardware trigger. - adc_disable_interrupt(ADC, 0xFFFFFFFF); // Disable all ADC interrupts. - adc_disable_all_channel(ADC); - - // Initialize analogOutput module - analogOutputInit(); -} - -#ifdef __cplusplus -} -#endif - diff --git a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.5 -Due 1.6.4/Arduino15/packages/hardware/sam/1.6.4/cores/arduino/USB/USBCore.cpp b/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.5 -Due 1.6.4/Arduino15/packages/hardware/sam/1.6.4/cores/arduino/USB/USBCore.cpp deleted file mode 100644 index d51ec5e..0000000 --- a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.5 -Due 1.6.4/Arduino15/packages/hardware/sam/1.6.4/cores/arduino/USB/USBCore.cpp +++ /dev/null @@ -1,891 +0,0 @@ -// Copyright (c) 2010, Peter Barrett -/* -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. -*/ - -#include "Arduino.h" -#include "USBAPI.h" -#include "Reset.h" -#include - -//#define TRACE_CORE(x) x -#define TRACE_CORE(x) - -static const uint32_t EndPoints[] = -{ - EP_TYPE_CONTROL, - -#ifdef CDC_ENABLED - EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM - EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT - EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN -#endif - -#ifdef HID_ENABLED - EP_TYPE_INTERRUPT_IN_HID // HID_ENDPOINT_INT -#endif -}; - -/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ -#define TX_RX_LED_PULSE_MS 100 -volatile uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ -volatile uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ -static char isRemoteWakeUpEnabled = 0; -static char isEndpointHalt = 0; -//================================================================== -//================================================================== - -extern const uint16_t STRING_LANGUAGE[]; -extern const uint8_t STRING_PRODUCT[]; -extern const uint8_t STRING_MANUFACTURER[]; -extern const DeviceDescriptor USB_DeviceDescriptor; -extern const DeviceDescriptor USB_DeviceDescriptorA; - -const uint16_t STRING_LANGUAGE[2] = { - (3<<8) | (2+2), - 0x0409 // English -}; - -#ifndef USB_PRODUCT -// Use a hardcoded product name if none is provided -#if USB_PID == USB_PID_DUE -#define USB_PRODUCT "Arduino Due" -#else -#define USB_PRODUCT "USB IO Board" -#endif -#endif - -const uint8_t STRING_PRODUCT[] = USB_PRODUCT; - -#if USB_VID == 0x2341 -# if defined(USB_MANUFACTURER) -# undef USB_MANUFACTURER -# endif -# define USB_MANUFACTURER "Arduino LLC" -#elif !defined(USB_MANUFACTURER) -// Fall through to unknown if no manufacturer name was provided in a macro -# define USB_MANUFACTURER "Unknown" -#endif - -const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER; - -#ifdef CDC_ENABLED -#define DEVICE_CLASS 0x02 -#else -#define DEVICE_CLASS 0x00 -#endif - -// DEVICE DESCRIPTOR -const DeviceDescriptor USB_DeviceDescriptor = - D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); - -const DeviceDescriptor USB_DeviceDescriptorA = - D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); - -const DeviceDescriptor USB_DeviceQualifier = - D_QUALIFIER(0x00,0x00,0x00,64,1); - -//! 7.1.20 Test Mode Support -static const unsigned char test_packet_buffer[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9 - 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8 - 0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8 - 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8 - 0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8 - 0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK -}; - -//================================================================== -//================================================================== - -volatile uint32_t _usbConfiguration = 0; -volatile uint32_t _usbInitialized = 0; -uint32_t _usbSetInterface = 0; -uint32_t _cdcComposite = 0; - -//================================================================== -//================================================================== - -#define USB_RECV_TIMEOUT -class LockEP -{ - irqflags_t flags; -public: - LockEP(uint32_t ep) : flags(cpu_irq_save()) - { - } - ~LockEP() - { - cpu_irq_restore(flags); - } -}; - -// Number of bytes, assumes a rx endpoint -uint32_t USBD_Available(uint32_t ep) -{ - LockEP lock(ep); - return UDD_FifoByteCount(ep & 0xF); -} - -// Non Blocking receive -// Return number of bytes read -uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len) -{ - if (!_usbConfiguration) - return -1; - - LockEP lock(ep); - uint32_t n = UDD_FifoByteCount(ep & 0xF); - len = min(n,len); - n = len; - uint8_t* dst = (uint8_t*)d; - while (n--) - *dst++ = UDD_Recv8(ep & 0xF); - if (len && !UDD_FifoByteCount(ep & 0xF)) // release empty buffer - UDD_ReleaseRX(ep & 0xF); - - return len; -} - -// Recv 1 byte if ready -uint32_t USBD_Recv(uint32_t ep) -{ - uint8_t c; - if (USBD_Recv(ep & 0xF, &c, 1) != 1) - return -1; - else - return c; -} - -// Space in send EP -//uint32_t USBD_SendSpace(uint32_t ep) -//{ - //LockEP lock(ep); -//// if (!UDD_ReadWriteAllowed(ep & 0xF)) - ////{ - ////printf("pb "); // UOTGHS->UOTGHS_DEVEPTISR[%d]=0x%X\n\r", ep, UOTGHS->UOTGHS_DEVEPTISR[ep]); - ////return 0; - ////} - - //if(ep==0) return 64 - UDD_FifoByteCount(ep & 0xF); // EP0_SIZE jcb - //else return 512 - UDD_FifoByteCount(ep & 0xF); // EPX_SIZE jcb -//} - -// Blocking Send of data to an endpoint -uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len) -{ - uint32_t n; - int r = len; - const uint8_t* data = (const uint8_t*)d; - - if (!_usbConfiguration) - { - TRACE_CORE(printf("pb conf\n\r");) - return -1; - } - - while (len) - { - if(ep==0) n = EP0_SIZE; - else n = EPX_SIZE; - if (n > len) - n = len; - len -= n; - int count=0; - while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[ep & 0xF] & UOTGHS_DEVEPTISR_TXINI )) - { - count++; - if (count>10000) return len; - } - UDD_Send(ep & 0xF, data, n); - data += n; - } - //TXLED1; // light the TX LED - //TxLEDPulse = TX_RX_LED_PULSE_MS; - return r; -} - -int _cmark; -int _cend; - -void USBD_InitControl(int end) -{ - _cmark = 0; - _cend = end; -} - -// Clipped by _cmark/_cend -int USBD_SendControl(uint8_t flags, const void* d, uint32_t len) -{ - const uint8_t* data = (const uint8_t*)d; - uint32_t length = len; - uint32_t sent = 0; - uint32_t pos = 0; - - TRACE_CORE(printf("=> USBD_SendControl TOTAL len=%lu\r\n", len);) - - if (_cmark < _cend) - { - while (len > 0) - { - sent = UDD_Send(EP0, data + pos, len); - TRACE_CORE(printf("=> USBD_SendControl sent=%lu\r\n", sent);) - pos += sent; - len -= sent; - } - } - - _cmark += length; - - return length; -} - -// Send a USB descriptor string. The string is stored as a -// plain ASCII string but is sent out as UTF-16 with the -// correct 2-byte prefix -static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) { - uint16_t buff[64]; - int l = 1; - wLength-=2; - while (*string && wLength>0) { - buff[l++] = (uint8_t)(*string++); - wLength-=2; - } - buff[0] = (3<<8) | (l*2); - return USBD_SendControl(0, (uint8_t*)buff, l*2); -} - -// Does not timeout or cross fifo boundaries -// Will only work for transfers <= 64 bytes -// TODO -int USBD_RecvControl(void* d, uint32_t len) -{ - UDD_WaitOUT(); - UDD_Recv(EP0, (uint8_t*)d, len); - UDD_ClearOUT(); - - return len; -} - -// Handle CLASS_INTERFACE requests -bool USBD_ClassInterfaceRequest(Setup& setup) -{ - uint8_t i = setup.wIndex; - - TRACE_CORE(printf("=> USBD_ClassInterfaceRequest\r\n");) - -#ifdef CDC_ENABLED - if (CDC_ACM_INTERFACE == i) - { - return CDC_Setup(setup); - } -#endif - -#ifdef HID_ENABLED - if (HID_INTERFACE == i) - { - return HID_Setup(setup); - } -#endif - - return false; -} - -int USBD_SendInterfaces(void) -{ - int total = 0; - uint8_t interfaces = 0; - -#ifdef CDC_ENABLED - total = CDC_GetInterface(&interfaces); -#endif - -#ifdef HID_ENABLED - total += HID_GetInterface(&interfaces); -#endif - - total = total; // Get rid of compiler warning - TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);) - return interfaces; -} - -int USBD_SendOtherInterfaces(void) -{ - int total = 0; - uint8_t interfaces = 0; - -#ifdef CDC_ENABLED - total = CDC_GetOtherInterface(&interfaces); -#endif - -#ifdef HID_ENABLED - total += HID_GetInterface(&interfaces); -#endif - - total = total; // Get rid of compiler warning - TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);) - return interfaces; -} - -// Construct a dynamic configuration descriptor -// This really needs dynamic endpoint allocation etc -// TODO -static bool USBD_SendConfiguration(int maxlen) -{ - // Count and measure interfaces - USBD_InitControl(0); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);) - int interfaces = USBD_SendInterfaces(); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);) - //TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));) - -_Pragma("pack(1)") - ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); -_Pragma("pack()") - //TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);) - - //TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);) - - // Now send them - USBD_InitControl(maxlen); - USBD_SendControl(0,&config,sizeof(ConfigDescriptor)); - USBD_SendInterfaces(); - return true; -} - -static bool USBD_SendOtherConfiguration(int maxlen) -{ - // Count and measure interfaces - USBD_InitControl(0); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);) - int interfaces = USBD_SendOtherInterfaces(); - //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);) - //TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));) - -_Pragma("pack(1)") - ConfigDescriptor config = D_OTHERCONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); -_Pragma("pack()") - //TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);) - - //TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);) - - // Now send them - USBD_InitControl(maxlen); - USBD_SendControl(0,&config,sizeof(ConfigDescriptor)); - USBD_SendOtherInterfaces(); - return true; -} - -static bool USBD_SendDescriptor(Setup& setup) -{ - uint8_t t = setup.wValueH; - uint8_t desc_length = 0; - const uint8_t* desc_addr = 0; - - if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(printf("=> USBD_SendDescriptor : USB_CONFIGURATION_DESCRIPTOR_TYPE length=%d\r\n", setup.wLength);) - return USBD_SendConfiguration(setup.wLength); - } - - USBD_InitControl(setup.wLength); -#ifdef HID_ENABLED - if (HID_REPORT_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(puts("=> USBD_SendDescriptor : HID_REPORT_DESCRIPTOR_TYPE\r\n");) - return HID_GetDescriptor(t); - } -#endif - - if (USB_DEVICE_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(puts("=> USBD_SendDescriptor : USB_DEVICE_DESCRIPTOR_TYPE\r\n");) - if (setup.wLength == 8) - { - _cdcComposite = 1; - } - desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptorA : (const uint8_t*)&USB_DeviceDescriptor; - if( *desc_addr > setup.wLength ) { - desc_length = setup.wLength; - } - } - else if (USB_STRING_DESCRIPTOR_TYPE == t) - { - TRACE_CORE(puts("=> USBD_SendDescriptor : USB_STRING_DESCRIPTOR_TYPE\r\n");) - if (setup.wValueL == 0) { - desc_addr = (const uint8_t*)&STRING_LANGUAGE; - } - else if (setup.wValueL == IPRODUCT) { - return USB_SendStringDescriptor(STRING_PRODUCT, setup.wLength); - } - else if (setup.wValueL == IMANUFACTURER) { - return USB_SendStringDescriptor(STRING_MANUFACTURER, setup.wLength); - } - else { - return false; - } - if( *desc_addr > setup.wLength ) { - desc_length = setup.wLength; - } - } - else if (USB_DEVICE_QUALIFIER == t) - { - // Device qualifier descriptor requested - desc_addr = (const uint8_t*)&USB_DeviceQualifier; - if( *desc_addr > setup.wLength ) { - desc_length = setup.wLength; - } - } - else if (USB_OTHER_SPEED_CONFIGURATION == t) - { - // Other configuration descriptor requested - return USBD_SendOtherConfiguration(setup.wLength); - } - else - { - //printf("Device ERROR"); - } - - if (desc_addr == 0) - { - return false; - } - - if (desc_length == 0) - { - desc_length = *desc_addr; - } - - TRACE_CORE(printf("=> USBD_SendDescriptor : desc_addr=%p desc_length=%d\r\n", desc_addr, desc_length);) - USBD_SendControl(0, desc_addr, desc_length); - - return true; -} - - -static void USB_SendZlp( void ) -{ - while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[0] & UOTGHS_DEVEPTISR_TXINI ) ) - { - if((UOTGHS->UOTGHS_DEVISR & UOTGHS_DEVISR_SUSP) == UOTGHS_DEVISR_SUSP) - { - return; - } - } - UOTGHS->UOTGHS_DEVEPTICR[0] = UOTGHS_DEVEPTICR_TXINIC; -} - - -static void Test_Mode_Support( uint8_t wIndex ) -{ - uint8_t i; - uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(2); - - switch( wIndex ) - { - case 4: - //Test mode Test_Packet: - //Upon command, a port must repetitively transmit the following test packet until - //the exit action is taken. This enables the testing of rise and fall times, eye - //patterns, jitter, and any other dynamic waveform specifications. - //The test packet is made up by concatenating the following strings. - //(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one - //transmitted. "S" indicates that a bit stuff occurs, which inserts an "extra" NRZI data bit. - //"* N" is used to indicate N occurrences of a string of bits or symbols.) - //A port in Test_Packet mode must send this packet repetitively. The inter-packet timing - //must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and - //no greater than 125 us. - - // Send ZLP - USB_SendZlp(); - - UOTGHS->UOTGHS_DEVDMA[0].UOTGHS_DEVDMACONTROL = 0; // raz - UOTGHS->UOTGHS_DEVDMA[1].UOTGHS_DEVDMACONTROL = 0; // raz - - // Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank - UOTGHS->UOTGHS_DEVEPTCFG[2] = UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE - | UOTGHS_DEVEPTCFG_EPDIR_IN - | UOTGHS_DEVEPTCFG_EPTYPE_BLK - | UOTGHS_DEVEPTCFG_EPBK_1_BANK; - // Check if the configuration is ok - UOTGHS->UOTGHS_DEVEPTCFG[2] |= UOTGHS_DEVEPTCFG_ALLOC; - while((UOTGHS->UOTGHS_DEVEPTISR[2]&UOTGHS_DEVEPTISR_CFGOK)==0) {} - UOTGHS->UOTGHS_DEVEPT |= UOTGHS_DEVEPT_EPEN2; - // Write FIFO - for( i=0; iUOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTPCKT; - // Send packet - UOTGHS->UOTGHS_DEVEPTICR[2] = UOTGHS_DEVEPTICR_TXINIC; - UOTGHS->UOTGHS_DEVEPTIDR[2] = UOTGHS_DEVEPTIDR_FIFOCONC; - for(;;); -// break; - - case 1: - //Test mode Test_J: - //Upon command, a port's transceiver must enter the high-speed J state and remain in that - //state until the exit action is taken. This enables the testing of the high output drive - //level on the D+ line. - // Send a ZLP - USB_SendZlp(); - UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTJ; - for(;;); -// break; - - case 2: - //Test mode Test_K: - //Upon command, a port's transceiver must enter the high-speed K state and remain in - //that state until the exit action is taken. This enables the testing of the high output drive - //level on the D- line. - // Send a ZLP - USB_SendZlp(); - UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTK; - for(;;); -// break; - - case 3: - //Test mode Test_SE0_NAK: - //Upon command, a port's transceiver must enter the high-speed receive mode - //and remain in that mode until the exit action is taken. This enables the testing - //of output impedance, low level output voltage, and loading characteristics. - //In addition, while in this mode, upstream facing ports (and only upstream facing ports) - //must respond to any IN token packet with a NAK handshake (only if the packet CRC is - //determined to be correct) within the normal allowed device response time. This enables testing of - //the device squelch level circuitry and, additionally, provides a general purpose stimulus/response - //test for basic functional testing. - - // Send a ZLP - USB_SendZlp(); - UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_SUSPEC - | UOTGHS_DEVIDR_MSOFEC - | UOTGHS_DEVIDR_SOFEC - | UOTGHS_DEVIDR_EORSTEC - | UOTGHS_DEVIDR_WAKEUPEC - | UOTGHS_DEVIDR_EORSMEC - | UOTGHS_DEVIDR_UPRSMEC - | UOTGHS_DEVIDR_PEP_0 - | UOTGHS_DEVIDR_PEP_1 - | UOTGHS_DEVIDR_PEP_2 - | UOTGHS_DEVIDR_PEP_3 - | UOTGHS_DEVIDR_PEP_4 - | UOTGHS_DEVIDR_PEP_5 - | UOTGHS_DEVIDR_PEP_6 - | UOTGHS_DEVIDR_DMA_1 - | UOTGHS_DEVIDR_DMA_2 - | UOTGHS_DEVIDR_DMA_3 - | UOTGHS_DEVIDR_DMA_4 - | UOTGHS_DEVIDR_DMA_5 - | UOTGHS_DEVIDR_DMA_6; - for(;;); -// break; - } -} - - -//unsigned int iii=0; -// Endpoint 0 interrupt -static void USB_ISR(void) -{ -// printf("ISR=0x%X\n\r", UOTGHS->UOTGHS_DEVISR); // jcb -// if( iii++ > 1500 ) while(1); // jcb - // End of bus reset - if (Is_udd_reset()) - { - TRACE_CORE(printf(">>> End of Reset\r\n");) - - // Reset USB address to 0 - udd_configure_address(0); - udd_enable_address(); - - // Configure EP 0 - UDD_InitEP(0, EP_TYPE_CONTROL); - udd_enable_setup_received_interrupt(0); - udd_enable_endpoint_interrupt(0); - - _usbConfiguration = 0; - udd_ack_reset(); - } - -#ifdef CDC_ENABLED - if (Is_udd_endpoint_interrupt(CDC_RX)) - { - udd_ack_out_received(CDC_RX); - - // Handle received bytes - if (USBD_Available(CDC_RX)) - SerialUSB.accept(); - } - - if (Is_udd_sof()) - { - udd_ack_sof(); - // USBD_Flush(CDC_TX); // jcb - } -#endif - - // EP 0 Interrupt - if (Is_udd_endpoint_interrupt(0) ) - { - if (!UDD_ReceivedSetupInt()) - { - return; - } - - Setup setup; - UDD_Recv(EP0, (uint8_t*)&setup, 8); - UDD_ClearSetupInt(); - - uint8_t requestType = setup.bmRequestType; - if (requestType & REQUEST_DEVICETOHOST) - { - TRACE_CORE(puts(">>> EP0 Int: IN Request\r\n");) - UDD_WaitIN(); - } - else - { - TRACE_CORE(puts(">>> EP0 Int: OUT Request\r\n");) - UDD_ClearIN(); - } - - bool ok = true; - if (REQUEST_STANDARD == (requestType & REQUEST_TYPE)) - { - // Standard Requests - uint8_t r = setup.bRequest; - if (GET_STATUS == r) - { - if( setup.bmRequestType == 0 ) // device - { - // Send the device status - TRACE_CORE(puts(">>> EP0 Int: GET_STATUS\r\n");) - // Check current configuration for power mode (if device is configured) - // TODO - // Check if remote wake-up is enabled - // TODO - UDD_Send8(EP0, 0); // TODO - UDD_Send8(EP0, 0); - } - // if( setup.bmRequestType == 2 ) // Endpoint: - else - { - // Send the endpoint status - // Check if the endpoint if currently halted - if( isEndpointHalt == 1 ) - UDD_Send8(EP0, 1); // TODO - else - UDD_Send8(EP0, 0); // TODO - UDD_Send8(EP0, 0); - } - } - else if (CLEAR_FEATURE == r) - { - // Check which is the selected feature - if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP - { - // Enable remote wake-up and send a ZLP - if( isRemoteWakeUpEnabled == 1 ) - UDD_Send8(EP0, 1); - else - UDD_Send8(EP0, 0); - UDD_Send8(EP0, 0); - } - else // if( setup.wValueL == 0) // ENDPOINTHALT - { - isEndpointHalt = 0; // TODO - UDD_Send8(EP0, 0); - UDD_Send8(EP0, 0); - } - - } - else if (SET_FEATURE == r) - { - // Check which is the selected feature - if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP - { - // Enable remote wake-up and send a ZLP - isRemoteWakeUpEnabled = 1; - UDD_Send8(EP0, 0); - } - if( setup.wValueL == 0) // ENDPOINTHALT - { - // Halt endpoint - isEndpointHalt = 1; - //USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest)); - UDD_Send8(EP0, 0); - } - if( setup.wValueL == 2) // TEST_MODE - { - // 7.1.20 Test Mode Support, 9.4.9 SetFeature - if( (setup.bmRequestType == 0 /*USBGenericRequest_DEVICE*/) && - ((setup.wIndex & 0x000F) == 0) ) - { - // the lower byte of wIndex must be zero - // the most significant byte of wIndex is used to specify the specific test mode - - UOTGHS->UOTGHS_DEVIDR &= ~UOTGHS_DEVIDR_SUSPEC; - UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED; // remove suspend ? - - Test_Mode_Support( (setup.wIndex & 0xFF00)>>8 ); - } - } - } - else if (SET_ADDRESS == r) - { - TRACE_CORE(puts(">>> EP0 Int: SET_ADDRESS\r\n");) - UDD_WaitIN(); - UDD_SetAddress(setup.wValueL); - } - else if (GET_DESCRIPTOR == r) - { - TRACE_CORE(puts(">>> EP0 Int: GET_DESCRIPTOR\r\n");) - ok = USBD_SendDescriptor(setup); - } - else if (SET_DESCRIPTOR == r) - { - TRACE_CORE(puts(">>> EP0 Int: SET_DESCRIPTOR\r\n");) - ok = false; - } - else if (GET_CONFIGURATION == r) - { - TRACE_CORE(puts(">>> EP0 Int: GET_CONFIGURATION\r\n");) - UDD_Send8(EP0, _usbConfiguration); - } - else if (SET_CONFIGURATION == r) - { - if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT)) - { - TRACE_CORE(printf(">>> EP0 Int: SET_CONFIGURATION REQUEST_DEVICE %d\r\n", setup.wValueL);) - - UDD_InitEndpoints(EndPoints, (sizeof(EndPoints) / sizeof(EndPoints[0]))); - _usbConfiguration = setup.wValueL; - -#ifdef CDC_ENABLED - // Enable interrupt for CDC reception from host (OUT packet) - udd_enable_out_received_interrupt(CDC_RX); - udd_enable_endpoint_interrupt(CDC_RX); -#endif - } - else - { - TRACE_CORE(puts(">>> EP0 Int: SET_CONFIGURATION failed!\r\n");) - ok = false; - } - } - else if (GET_INTERFACE == r) - { - TRACE_CORE(puts(">>> EP0 Int: GET_INTERFACE\r\n");) - UDD_Send8(EP0, _usbSetInterface); - } - else if (SET_INTERFACE == r) - { - _usbSetInterface = setup.wValueL; - TRACE_CORE(puts(">>> EP0 Int: SET_INTERFACE\r\n");) - } - } - else - { - TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");) - - UDD_WaitIN(); // Workaround: need tempo here, else CDC serial won't open correctly - - USBD_InitControl(setup.wLength); // Max length of transfer - ok = USBD_ClassInterfaceRequest(setup); - } - - if (ok) - { - TRACE_CORE(puts(">>> EP0 Int: Send packet\r\n");) - UDD_ClearIN(); - } - else - { - TRACE_CORE(puts(">>> EP0 Int: Stall\r\n");) - UDD_Stall(); - } - } -} - -void USBD_Flush(uint32_t ep) -{ - if (UDD_FifoByteCount(ep)) - UDD_ReleaseTX(ep); -} - -// VBUS or counting frames -// Any frame counting? -uint32_t USBD_Connected(void) -{ - uint8_t f = UDD_GetFrameNumber(); - - delay(3); - - return f != UDD_GetFrameNumber(); -} - - -//======================================================================= -//======================================================================= - -USBDevice_ USBDevice; - -USBDevice_::USBDevice_() -{ - UDD_SetStack(&USB_ISR); - - if (UDD_Init() == 0UL) - { - _usbInitialized=1UL; - } -} - -bool USBDevice_::attach(void) -{ - if (_usbInitialized != 0UL) - { - UDD_Attach(); - _usbConfiguration = 0; - return true; - } - else - { - return false; - } -} - -bool USBDevice_::detach(void) -{ - if (_usbInitialized != 0UL) - { - UDD_Detach(); - return true; - } - else - { - return false; - } -} - -// Check for interrupts -// TODO: VBUS detection -bool USBDevice_::configured() -{ - return _usbConfiguration; -} - -void USBDevice_::poll() -{ -} diff --git a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.5 -Due 1.6.4/Arduino15/packages/hardware/sam/1.6.4/variants/arduino_due_x/variant.cpp b/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.5 -Due 1.6.4/Arduino15/packages/hardware/sam/1.6.4/variants/arduino_due_x/variant.cpp deleted file mode 100644 index fa81e84..0000000 --- a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.5 -Due 1.6.4/Arduino15/packages/hardware/sam/1.6.4/variants/arduino_due_x/variant.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/* - Copyright (c) 2011 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "variant.h" - -/* - * DUE Board pin | PORT | Label - * ----------------+--------+------- - * 0 | PA8 | "RX0" - * 1 | PA9 | "TX0" - * 2 TIOA0 | PB25 | - * 3 TIOA7 | PC28 | - * 4 NPCS1 | PA29 | - * TIOB6 | PC26 | - * 5 TIOA6 | PC25 | - * 6 PWML7 | PC24 | - * 7 PWML6 | PC23 | - * 8 PWML5 | PC22 | - * 9 PWML4 | PC21 | - * 10 NPCS0 | PA28 | - * TIOB7 | PC29 | - * 11 TIOA8 | PD7 | - * 12 TIOB8 | PD8 | - * 13 TIOB0 | PB27 | LED AMBER "L" - * 14 TXD3 | PD4 | "TX3" - * 15 RXD3 | PD5 | "RX3" - * 16 TXD1 | PA13 | "TX2" - * 17 RXD1 | PA12 | "RX2" - * 18 TXD0 | PA11 | "TX1" - * 19 RXD0 | PA10 | "RX1" - * 20 | PB12 | "SDA" - * 21 | PB13 | "SCL" - * 22 | PB26 | - * 23 | PA14 | - * 24 | PA15 | - * 25 | PD0 | - * 26 | PD1 | - * 27 | PD2 | - * 28 | PD3 | - * 29 | PD6 | - * 30 | PD9 | - * 31 | PA7 | - * 32 | PD10 | - * 33 | PC1 | - * 34 | PC2 | - * 35 | PC3 | - * 36 | PC4 | - * 37 | PC5 | - * 38 | PC6 | - * 39 | PC7 | - * 40 | PC8 | - * 41 | PC9 | - * 42 | PA19 | - * 43 | PA20 | - * 44 | PC19 | - * 45 | PC18 | - * 46 | PC17 | - * 47 | PC16 | - * 48 | PC15 | - * 49 | PC14 | - * 50 | PC13 | - * 51 | PC12 | - * 52 NPCS2 | PB21 | - * 53 | PB14 | - * 54 | PA16 | "A0" - * 55 | PA24 | "A1" - * 56 | PA23 | "A2" - * 57 | PA22 | "A3" - * 58 TIOB2 | PA6 | "A4" - * 69 | PA4 | "A5" - * 60 TIOB1 | PA3 | "A6" - * 61 TIOA1 | PA2 | "A7" - * 62 | PB17 | "A8" - * 63 | PB18 | "A9" - * 64 | PB19 | "A10" - * 65 | PB20 | "A11" - * 66 | PB15 | "DAC0" - * 67 | PB16 | "DAC1" - * 68 | PA1 | "CANRX" - * 69 | PA0 | "CANTX" - * 70 | PA17 | "SDA1" - * 71 | PA18 | "SCL1" - * 72 | PC30 | LED AMBER "RX" - * 73 | PA21 | LED AMBER "TX" - * 74 MISO | PA25 | - * 75 MOSI | PA26 | - * 76 SCLK | PA27 | - * 77 NPCS0 | PA28 | - * 78 NPCS3 | PB23 | unconnected! - * - * USB pin | PORT - * ----------------+-------- - * ID | PB11 - * VBOF | PB10 - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Pins descriptions - */ -extern const PinDescription g_APinDescription[]= -{ - // 0 .. 53 - Digital pins - // ---------------------- - // 0/1 - UART (Serial) - { PIOA, PIO_PA8A_URXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // URXD - { PIOA, PIO_PA9A_UTXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // UTXD - - // 2 - { PIOB, PIO_PB25B_TIOA0, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC0_CHA0 }, // TIOA0 - { PIOC, PIO_PC28B_TIOA7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA7 }, // TIOA7 - { PIOC, PIO_PC26B_TIOB6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB6 }, // TIOB6 - - // 5 - { PIOC, PIO_PC25B_TIOA6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA6 }, // TIOA6 - { PIOC, PIO_PC24B_PWML7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH7, NOT_ON_TIMER }, // PWML7 - { PIOC, PIO_PC23B_PWML6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH6, NOT_ON_TIMER }, // PWML6 - { PIOC, PIO_PC22B_PWML5, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH5, NOT_ON_TIMER }, // PWML5 - { PIOC, PIO_PC21B_PWML4, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH4, NOT_ON_TIMER }, // PWML4 - // 10 - { PIOC, PIO_PC29B_TIOB7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB7 }, // TIOB7 - { PIOD, PIO_PD7B_TIOA8, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA8 }, // TIOA8 - { PIOD, PIO_PD8B_TIOB8, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB8 }, // TIOB8 - - // 13 - AMBER LED - { PIOB, PIO_PB27B_TIOB0, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC0_CHB0 }, // TIOB0 - - // 14/15 - USART3 (Serial3) - { PIOD, PIO_PD4B_TXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD3 - { PIOD, PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD3 - - // 16/17 - USART1 (Serial2) - { PIOA, PIO_PA13A_TXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD1 - { PIOA, PIO_PA12A_RXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD1 - - // 18/19 - USART0 (Serial1) - { PIOA, PIO_PA11A_TXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD0 - { PIOA, PIO_PA10A_RXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD0 - - // 20/21 - TWI1 - { PIOB, PIO_PB12A_TWD1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWD1 - SDA0 - { PIOB, PIO_PB13A_TWCK1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWCK1 - SCL0 - - // 22 - { PIOB, PIO_PB26, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 22 - { PIOA, PIO_PA14, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 23 - { PIOA, PIO_PA15, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 24 - { PIOD, PIO_PD0, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 25 - - // 26 - { PIOD, PIO_PD1, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 26 - { PIOD, PIO_PD2, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 27 - { PIOD, PIO_PD3, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 28 - { PIOD, PIO_PD6, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 29 - - // 30 - { PIOD, PIO_PD9, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 30 - { PIOA, PIO_PA7, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 31 - { PIOD, PIO_PD10, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 32 - { PIOC, PIO_PC1, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 33 - - // 34 - { PIOC, PIO_PC2, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 34 - { PIOC, PIO_PC3, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 35 - { PIOC, PIO_PC4, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 36 - { PIOC, PIO_PC5, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 37 - - // 38 - { PIOC, PIO_PC6, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 38 - { PIOC, PIO_PC7, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 39 - { PIOC, PIO_PC8, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 40 - { PIOC, PIO_PC9, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 41 - - // 42 - { PIOA, PIO_PA19, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 42 - { PIOA, PIO_PA20, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 43 - { PIOC, PIO_PC19, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 44 - { PIOC, PIO_PC18, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 45 - - // 46 - { PIOC, PIO_PC17, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 46 - { PIOC, PIO_PC16, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 47 - { PIOC, PIO_PC15, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 48 - { PIOC, PIO_PC14, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 49 - - // 50 - { PIOC, PIO_PC13, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 50 - { PIOC, PIO_PC12, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 51 - { PIOB, PIO_PB21, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 52 - { PIOB, PIO_PB14, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 53 - - - // 54 .. 65 - Analog pins - // ---------------------- - { PIOA, PIO_PA16X1_AD7, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC7, NOT_ON_PWM, NOT_ON_TIMER }, // AD0 - { PIOA, PIO_PA24X1_AD6, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC1, ADC6, NOT_ON_PWM, NOT_ON_TIMER }, // AD1 - { PIOA, PIO_PA23X1_AD5, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC2, ADC5, NOT_ON_PWM, NOT_ON_TIMER }, // AD2 - { PIOA, PIO_PA22X1_AD4, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC3, ADC4, NOT_ON_PWM, NOT_ON_TIMER }, // AD3 - // 58 - { PIOA, PIO_PA6X1_AD3, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC4, ADC3, NOT_ON_PWM, TC0_CHB2 }, // AD4 - { PIOA, PIO_PA4X1_AD2, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC5, ADC2, NOT_ON_PWM, NOT_ON_TIMER }, // AD5 - { PIOA, PIO_PA3X1_AD1, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC6, ADC1, NOT_ON_PWM, TC0_CHB1 }, // AD6 - { PIOA, PIO_PA2X1_AD0, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC7, ADC0, NOT_ON_PWM, TC0_CHA1 }, // AD7 - // 62 - { PIOB, PIO_PB17X1_AD10, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC8, ADC10, NOT_ON_PWM, NOT_ON_TIMER }, // AD8 - { PIOB, PIO_PB18X1_AD11, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC9, ADC11, NOT_ON_PWM, NOT_ON_TIMER }, // AD9 - { PIOB, PIO_PB19X1_AD12, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC10, ADC12, NOT_ON_PWM, NOT_ON_TIMER }, // AD10 - { PIOB, PIO_PB20X1_AD13, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC11, ADC13, NOT_ON_PWM, NOT_ON_TIMER }, // AD11 - - // 66/67 - DAC0/DAC1 - { PIOB, PIO_PB15X1_DAC0, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC12, DA0, NOT_ON_PWM, NOT_ON_TIMER }, // DAC0 - { PIOB, PIO_PB16X1_DAC1, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC13, DA1, NOT_ON_PWM, NOT_ON_TIMER }, // DAC1 - - // 68/69 - CANRX0/CANTX0 - { PIOA, PIO_PA1A_CANRX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, ADC14, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANRX - { PIOA, PIO_PA0A_CANTX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, ADC15, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANTX - - // 70/71 - TWI0 - { PIOA, PIO_PA17A_TWD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWD0 - SDA1 - { PIOA, PIO_PA18A_TWCK0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWCK0 - SCL1 - - // 72/73 - LEDs - { PIOC, PIO_PC30, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // LED AMBER RXL - { PIOA, PIO_PA21, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // LED AMBER TXL - - // 74/75/76 - SPI - { PIOA, PIO_PA25A_SPI0_MISO,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // MISO - { PIOA, PIO_PA26A_SPI0_MOSI,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI - { PIOA, PIO_PA27A_SPI0_SPCK,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // SPCK - - // 77 - SPI CS0 - { PIOA, PIO_PA28A_SPI0_NPCS0,ID_PIOA,PIO_PERIPH_A,PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS0 - - // 78 - SPI CS3 (unconnected) - { PIOB, PIO_PB23B_SPI0_NPCS3,ID_PIOB,PIO_PERIPH_B,PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS3 - - // 79 .. 84 - "All pins" masks - - // 79 - TWI0 all pins - { PIOA, PIO_PA17A_TWD0|PIO_PA18A_TWCK0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 80 - TWI1 all pins - { PIOB, PIO_PB12A_TWD1|PIO_PB13A_TWCK1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 81 - UART (Serial) all pins - { PIOA, PIO_PA8A_URXD|PIO_PA9A_UTXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 82 - USART0 (Serial1) all pins - { PIOA, PIO_PA11A_TXD0|PIO_PA10A_RXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 83 - USART1 (Serial2) all pins - { PIOA, PIO_PA13A_TXD1|PIO_PA12A_RXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 84 - USART3 (Serial3) all pins - { PIOD, PIO_PD4B_TXD3|PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - - // 85 - USB - { PIOB, PIO_PB11A_UOTGID, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID -// { PIOB, PIO_PB11A_UOTGID|PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF - // 86 - SPI CS2 - { PIOB, PIO_PB21B_SPI0_NPCS2, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS2 - - // 87 - SPI CS1 - { PIOA, PIO_PA29A_SPI0_NPCS1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS1 - - // 88/89 - CANRX1/CANTX1 (same physical pin for 66/53) - { PIOB, PIO_PB15A_CANRX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANRX1 - { PIOB, PIO_PB14A_CANTX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANTX1 - - // 90 .. 91 - "All CAN pins" masks - // 90 - CAN0 all pins - { PIOA, PIO_PA1A_CANRX0|PIO_PA0A_CANTX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 91 - CAN1 all pins - { PIOB, PIO_PB15A_CANRX1|PIO_PB14A_CANTX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - - // 92 .. 99 placeholders, future-proofing. - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 100 - 108 extra SAM3X8E pins, not wired on Due - { PIOA, PIO_PA5, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 100 - { PIOC, PIO_PC27, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 101 - { PIOA, PIO_PA0, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 102 - { PIOA, PIO_PA1, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 103 - { PIOC, PIO_PC11, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 104 - { PIOC, PIO_PC8B_PWML3, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH3, NOT_ON_TIMER }, // PWM 105 - { PIOC, PIO_PC2B_PWML0, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH0, NOT_ON_TIMER }, // PWM 106 - { PIOC, PIO_PC6B_PWML2, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH2, NOT_ON_TIMER }, //PWM 107 - { PIOC, PIO_PC20, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, //PWM 108 - // 109 .. 114 - { PIOA, PIO_PA20A_MCCDA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCCDA_GPIO 109 - { PIOA, PIO_PA19A_MCCK, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCCK_GPIO 110 - { PIOA, PIO_PA21A_MCDA0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA0_GPIO 111 - { PIOA, PIO_PA22A_MCDA1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA1_GPIO 112 - { PIOA, PIO_PA23A_MCDA2, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA2_GPIO 113 - { PIOA, PIO_PA24A_MCDA3, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN_HSMCI_MCDA3_GPIO 114 - // 115 .. 124 - ETHERNET MAC - { PIOB, PIO_PB0A_ETXCK, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETXCK 115 - { PIOB, PIO_PB1A_ETXEN, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETXEN 116 - { PIOB, PIO_PB2A_ETX0, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETX0 117 - { PIOB, PIO_PB3A_ETX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ETX1 118 - { PIOB, PIO_PB4A_ECRSDV, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ECRSDV 119 - { PIOB, PIO_PB5A_ERX0, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ERX0 120 - { PIOB, PIO_PB6A_ERX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ERX1 121 - { PIOB, PIO_PB7A_ERXER, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ERXER 122 - { PIOB, PIO_PB8A_EMDC, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // EMDC 123 - { PIOB, PIO_PB9A_EMDIO, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // EMDIO 124 - // 125 - { PIOB, PIO_PB24, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 125 - { PIOB, PIO_PB21X1_AD14, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC14, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 126 - PB21 with enabled ADC - { PIOB, PIO_PB13X1_AD9, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC9, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 127 - PB13 with enabled ACD AD9 - { PIOB, PIO_PB22, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 128 - PB22 E1 Enabled - { PIOB, PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF 129 - - // END - { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER } -} ; - -#ifdef __cplusplus -} -#endif - -/* - * UART objects - */ -RingBuffer rx_buffer1; -RingBuffer tx_buffer1; - -UARTClass Serial(UART, UART_IRQn, ID_UART, &rx_buffer1, &tx_buffer1); -void serialEvent() __attribute__((weak)); -void serialEvent() { } - -// IT handlers -void UART_Handler(void) -{ - Serial.IrqHandler(); -} - -// ---------------------------------------------------------------------------- -/* - * USART objects - */ -RingBuffer rx_buffer2; -RingBuffer rx_buffer3; -RingBuffer rx_buffer4; -RingBuffer tx_buffer2; -RingBuffer tx_buffer3; -RingBuffer tx_buffer4; - -USARTClass Serial1(USART0, USART0_IRQn, ID_USART0, &rx_buffer2, &tx_buffer2); -void serialEvent1() __attribute__((weak)); -void serialEvent1() { } -USARTClass Serial2(USART1, USART1_IRQn, ID_USART1, &rx_buffer3, &tx_buffer3); -void serialEvent2() __attribute__((weak)); -void serialEvent2() { } -USARTClass Serial3(USART3, USART3_IRQn, ID_USART3, &rx_buffer4, &tx_buffer4); -void serialEvent3() __attribute__((weak)); -void serialEvent3() { } - -// IT handlers -void USART0_Handler(void) -{ - Serial1.IrqHandler(); -} - -void USART1_Handler(void) -{ - Serial2.IrqHandler(); -} - -void USART3_Handler(void) -{ - Serial3.IrqHandler(); -} - -// ---------------------------------------------------------------------------- - -void serialEventRun(void) -{ - if (Serial.available()) serialEvent(); - if (Serial1.available()) serialEvent1(); - if (Serial2.available()) serialEvent2(); - if (Serial3.available()) serialEvent3(); -} - -// ---------------------------------------------------------------------------- - -#ifdef __cplusplus -extern "C" { -#endif - -void __libc_init_array(void); - -void init( void ) -{ - SystemInit(); - - // Set Systick to 1ms interval, common to all SAM3 variants - if (SysTick_Config(SystemCoreClock / 1000)) - { - // Capture error - while (true); - } - - // Disable watchdog - //WDT_Disable(WDT); - // Initialize C library - __libc_init_array(); - - // Disable pull-up on every pin - for (unsigned i = 0; i < PINS_COUNT; i++) - digitalWrite(i, LOW); - - // Enable parallel access on PIO output data registers - PIOA->PIO_OWER = 0xFFFFFFFF; - PIOB->PIO_OWER = 0xFFFFFFFF; - PIOC->PIO_OWER = 0xFFFFFFFF; - PIOD->PIO_OWER = 0xFFFFFFFF; - - // Initialize Serial port U(S)ART pins - PIO_Configure( - g_APinDescription[PINS_UART].pPort, - g_APinDescription[PINS_UART].ulPinType, - g_APinDescription[PINS_UART].ulPin, - g_APinDescription[PINS_UART].ulPinConfiguration); - digitalWrite(0, HIGH); // Enable pullup for RX0 - PIO_Configure( - g_APinDescription[PINS_USART0].pPort, - g_APinDescription[PINS_USART0].ulPinType, - g_APinDescription[PINS_USART0].ulPin, - g_APinDescription[PINS_USART0].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PINS_USART1].pPort, - g_APinDescription[PINS_USART1].ulPinType, - g_APinDescription[PINS_USART1].ulPin, - g_APinDescription[PINS_USART1].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PINS_USART3].pPort, - g_APinDescription[PINS_USART3].ulPinType, - g_APinDescription[PINS_USART3].ulPin, - g_APinDescription[PINS_USART3].ulPinConfiguration); - - // Initialize USB pins - PIO_Configure( - g_APinDescription[PINS_USB].pPort, - g_APinDescription[PINS_USB].ulPinType, - g_APinDescription[PINS_USB].ulPin, - g_APinDescription[PINS_USB].ulPinConfiguration); - - // Initialize CAN pins - PIO_Configure( - g_APinDescription[PINS_CAN0].pPort, - g_APinDescription[PINS_CAN0].ulPinType, - g_APinDescription[PINS_CAN0].ulPin, - g_APinDescription[PINS_CAN0].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PINS_CAN1].pPort, - g_APinDescription[PINS_CAN1].ulPinType, - g_APinDescription[PINS_CAN1].ulPin, - g_APinDescription[PINS_CAN1].ulPinConfiguration); - - // Initialize Analog Controller - pmc_enable_periph_clk(ID_ADC); - adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST); - adc_configure_timing(ADC, 0, ADC_SETTLING_TIME_3, 1); - adc_configure_trigger(ADC, ADC_TRIG_SW, 0); // Disable hardware trigger. - adc_disable_interrupt(ADC, 0xFFFFFFFF); // Disable all ADC interrupts. - adc_disable_all_channel(ADC); - - // Initialize analogOutput module - analogOutputInit(); -} - -#ifdef __cplusplus -} -#endif - diff --git a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.8 -Due 1.6.7/Arduino15/packages/hardware/sam/1.6.7/cores/arduino/USB/USBCore.cpp b/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.9 -Due 1.6.8/Arduino15/packages/arduino/hardware/sam/1.6.8/cores/arduino/USB/USBCore.cpp similarity index 98% rename from src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.8 -Due 1.6.7/Arduino15/packages/hardware/sam/1.6.7/cores/arduino/USB/USBCore.cpp rename to src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.9 -Due 1.6.8/Arduino15/packages/arduino/hardware/sam/1.6.8/cores/arduino/USB/USBCore.cpp index fa83806..615bd64 100644 --- a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.8 -Due 1.6.7/Arduino15/packages/hardware/sam/1.6.7/cores/arduino/USB/USBCore.cpp +++ b/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.9 -Due 1.6.8/Arduino15/packages/arduino/hardware/sam/1.6.8/cores/arduino/USB/USBCore.cpp @@ -66,27 +66,16 @@ const uint16_t STRING_LANGUAGE[2] = { }; #ifndef USB_PRODUCT -// Use a hardcoded product name if none is provided -#if USB_PID == USB_PID_DUE #define USB_PRODUCT "Arduino Due" -#else -#define USB_PRODUCT "USB IO Board" -#endif #endif const uint8_t STRING_PRODUCT[] = USB_PRODUCT; -#if USB_VID == 0x2341 -# if defined(USB_MANUFACTURER) -# undef USB_MANUFACTURER -# endif -# define USB_MANUFACTURER "Arduino LLC" -#elif !defined(USB_MANUFACTURER) -// Fall through to unknown if no manufacturer name was provided in a macro -# define USB_MANUFACTURER "Unknown" +#ifndef USB_MANUFACTURER +#define USB_MANUFACTURER "Arduino LLC" #endif -const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER; +const uint8_t STRING_MANUFACTURER[] = USB_MANUFACTURER; #ifdef CDC_ENABLED #define DEVICE_CLASS 0x02 diff --git a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.8 -Due 1.6.7/Arduino15/packages/hardware/sam/1.6.7/variants/arduino_due_x/variant.cpp b/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.9 -Due 1.6.8/Arduino15/packages/arduino/hardware/sam/1.6.8/variants/arduino_due_x/variant.cpp similarity index 98% rename from src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.8 -Due 1.6.7/Arduino15/packages/hardware/sam/1.6.7/variants/arduino_due_x/variant.cpp rename to src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.9 -Due 1.6.8/Arduino15/packages/arduino/hardware/sam/1.6.8/variants/arduino_due_x/variant.cpp index 4d0d4d3..792b7d4 100644 --- a/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.8 -Due 1.6.7/Arduino15/packages/hardware/sam/1.6.7/variants/arduino_due_x/variant.cpp +++ b/src/ArduinoDUE/AdditionalArduinoFiles/Arduino - 1.6.9 -Due 1.6.8/Arduino15/packages/arduino/hardware/sam/1.6.8/variants/arduino_due_x/variant.cpp @@ -268,10 +268,8 @@ extern const PinDescription g_APinDescription[]= // 84 - USART3 (Serial3) all pins { PIOD, PIO_PD4B_TXD3|PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, - // 85 - USB -//For Davinci only - { PIOB, PIO_PB11A_UOTGID, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID -// { PIOB, PIO_PB11A_UOTGID|PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF + // 85 - USB + { PIOB, PIO_PB11A_UOTGID|PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF // 86 - SPI CS2 { PIOB, PIO_PB21B_SPI0_NPCS2, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS2 @@ -330,7 +328,7 @@ extern const PinDescription g_APinDescription[]= { PIOB, PIO_PB21X1_AD14, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC14, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 126 - PB21 with enabled ADC { PIOB, PIO_PB13X1_AD9, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC9, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 127 - PB13 with enabled ACD AD9 { PIOB, PIO_PB22, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 128 - PB22 E1 Enabled - { PIOB, PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF 129 + { PIOB, PIO_PB10B_A18, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID 129 // END { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER } diff --git a/src/ArduinoDUE/AdditionalArduinoFiles/Horus-0.2rc1/src/horus/engine/driver/board.py b/src/ArduinoDUE/AdditionalArduinoFiles/Horus-0.2rc1/src/horus/engine/driver/board.py new file mode 100644 index 0000000..7f50a26 --- /dev/null +++ b/src/ArduinoDUE/AdditionalArduinoFiles/Horus-0.2rc1/src/horus/engine/driver/board.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +# This file is part of the Horus Project + +__author__ = 'Jesús Arroyo Torrens ' +__copyright__ = 'Copyright (C) 2014-2016 Mundo Reader S.L.' +__license__ = 'GNU General Public License v2 http://www.gnu.org/licenses/gpl2.html' + +import time +import glob +import serial +import threading +import platform + +import logging +logger = logging.getLogger(__name__) + +system = platform.system() + + +class WrongFirmware(Exception): + + def __init__(self): + Exception.__init__(self, "Wrong Firmware") + + +class BoardNotConnected(Exception): + + def __init__(self): + Exception.__init__(self, "Board Not Connected") + + +class OldFirmware(Exception): + + def __init__(self): + Exception.__init__(self, "Old Firmware") + + +class Board(object): + + """Board class. For accessing to the scanner board + Mofified for Davinci AiO support + Gcode commands: + + G201 Fnnn : feed rate + G201 Xnnn : move motor in mm + G201 Ennn : move motor in deg + G50 : reset origin position + M17 : motor_disable + M18 : motor_enable + M70 Tn : switch off laser n, 0 index based + M71 Tn : switch on laser n, 0 index based + + M60 Tn : read ldr sensor + + """ + + def __init__(self, parent=None, serial_name='/dev/ttyUSB0', baud_rate=115200): + self.parent = parent + self.serial_name = serial_name + self.baud_rate = baud_rate + self.unplug_callback = None + + self._serial_port = None + self._is_connected = False + self._motor_enabled = False + self._motor_position = 0 + self._motor_speed = 0 + self._motor_acceleration = 0 + self._motor_direction = 1 + self._laser_number = 2 + self._laser_enabled = self._laser_number * [False] + self._tries = 0 # Check if command fails + + def connect(self): + """Open serial port and perform handshake""" + logger.info("Connecting board {0} {1}".format(self.serial_name, self.baud_rate)) + self._is_connected = False + try: + self._serial_port = serial.Serial(self.serial_name, self.baud_rate, timeout=2) + if self._serial_port.isOpen(): + #self._reset() # Force Reset and flush + # version = self._serial_port.readline() + # if "Horus 0.1 ['$' for help]" in version: + # raise OldFirmware() + # elif "Horus 0.2 ['$' for help]" in version: + self.motor_speed(1) + self._serial_port.timeout = 0.05 + self._is_connected = True + # Set current position as origin + self.motor_reset_origin() + logger.info(" Done") + #else: + # raise WrongFirmware() + else: + raise BoardNotConnected() + except Exception as exception: + logger.error("Error opening the port {0}\n".format(self.serial_name)) + self._serial_port = None + raise exception + + def disconnect(self): + """Close serial port""" + if self._is_connected: + logger.info("Disconnecting board {0}".format(self.serial_name)) + try: + if self._serial_port is not None: + self.lasers_off() + self.motor_disable() + self._is_connected = False + self._serial_port.close() + del self._serial_port + except serial.SerialException: + logger.error("Error closing the port {0}\n".format(self.serial_name)) + logger.info(" Done") + + def set_unplug_callback(self, value): + self.unplug_callback = value + + def motor_invert(self, value): + if value: + self._motor_direction = -1 + else: + self._motor_direction = +1 + + def motor_speed(self, value): + if self._is_connected: + if self._motor_speed != value: + self._motor_speed = value + #Davici Specific + self._send_command("G201 F{0}".format(value)) + + def motor_acceleration(self, value): + if self._is_connected: + if self._motor_acceleration != value: + self._motor_acceleration = value + #Davinci Specific + #self._send_command("$120={0}".format(value)) + + def motor_enable(self): + if self._is_connected: + if not self._motor_enabled: + self._motor_enabled = True + # Save current speed value + speed = self._motor_speed + self.motor_speed(1) + # Enable stepper motor + self._send_command("M17") + time.sleep(1) + # Restore speed value + self.motor_speed(speed) + + def motor_disable(self): + if self._is_connected: + if self._motor_enabled: + self._motor_enabled = False + self._send_command("M18") + + def motor_reset_origin(self): + if self._is_connected: + self._send_command("G50") + self._motor_position = 0 + + def motor_move(self, step=0, nonblocking=False, callback=None): + if self._is_connected: + self._motor_position += step * self._motor_direction + #Davici Specific + self.send_command("G201 E{0}".format(self._motor_position), nonblocking, callback) + + def laser_on(self, index): + if self._is_connected: + if not self._laser_enabled[index]: + self._laser_enabled[index] = True + #Davici Specific + if index == 0: + strindex="1" + else : + strindex="0" + self._send_command("M71 T" + strindex) + + def laser_off(self, index): + if self._is_connected: + if self._laser_enabled[index]: + self._laser_enabled[index] = False + #Davici Specific + if index == 0: + strindex="1" + else : + strindex="0" + self._send_command("M70 T" + strindex) + + def lasers_on(self): + for i in xrange(self._laser_number): + self.laser_on(i) + + def lasers_off(self): + for i in xrange(self._laser_number): + self.laser_off(i) + + def ldr_sensor(self, pin): + value = self._send_command("M60 T" + pin, read_lines=True).split("\n")[0] + try: + return int(value) + except ValueError: + return 0 + + def send_command(self, req, nonblocking=False, callback=None, read_lines=False): + if nonblocking: + threading.Thread(target=self._send_command, + args=(req, callback, read_lines)).start() + else: + self._send_command(req, callback, read_lines) + + def _send_command(self, req, callback=None, read_lines=False): + """Sends the request and returns the response""" + ret = '' + logger.debug(req) + if self._is_connected and req != '': + if self._serial_port is not None and self._serial_port.isOpen(): + try: + self._serial_port.flushInput() + self._serial_port.flushOutput() + self._serial_port.write(req + "\r\n") + while req != '~' and req != '!' and ret == '': + ret = self.read(read_lines) + time.sleep(0.01) + self._success() + except: + if hasattr(self, '_serial_port'): + if callback is not None: + callback(ret) + self._fail() + if callback is not None: + callback(ret) + return ret + + def read(self, read_lines=False): + if read_lines: + return ''.join(self._serial_port.readlines()) + else: + return ''.join(self._serial_port.readline()) + + def _success(self): + self._tries = 0 + + def _fail(self): + if self._is_connected: + logger.debug("Board fail") + self._tries += 1 + if self._tries >= 3: + self._tries = 0 + if self.unplug_callback is not None and \ + self.parent is not None and \ + not self.parent.unplugged: + self.parent.unplugged = True + self.unplug_callback() + + def _reset(self): + self._serial_port.flushInput() + self._serial_port.flushOutput() + self._serial_port.write("\x18\r\n") # Ctrl-x + self._serial_port.readline() + + def get_serial_list(self): + """Obtain list of serial devices""" + baselist = [] + if system == 'Windows': + import _winreg + try: + key = _winreg.OpenKey( + _winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM") + i = 0 + while True: + try: + values = _winreg.EnumValue(key, i) + except: + return baselist + if 'USBSER' in values[0] or \ + 'VCP' in values[0] or \ + '\Device\Serial' in values[0]: + baselist.append(values[1]) + i += 1 + except: + return baselist + else: + for device in ['/dev/ttyACM*', '/dev/ttyUSB*', '/dev/tty.usb*', '/dev/tty.wchusb*', + '/dev/cu.*', '/dev/rfcomm*']: + baselist = baselist + glob.glob(device) + return baselist diff --git a/src/ArduinoDUE/Repetier/BedLeveling.cpp b/src/ArduinoDUE/Repetier/BedLeveling.cpp new file mode 100644 index 0000000..257362e --- /dev/null +++ b/src/ArduinoDUE/Repetier/BedLeveling.cpp @@ -0,0 +1,773 @@ + +/* +More and more printers now have automatic bed leveling using an ever increasing variety of methods. +This makes the leveling routine one of the most complex parts of the firmware and there is not one +way to level but hundreds of combinations. + +First you should decide on the correction method. Once we know how our bed is tilted we want to +remove that. This correction is defined by BED_CORRECTION_METHOD and allows the following values: +BED_CORRECTION_METHOD 0 +Use a rotation matrix. This will make z axis go up/down while moving in x/y direction to compensate +the tilt. For multiple extruders make sure the height match the tilt of the bed or one will scratch. + +BED_CORRECTION_METHOD 1 +Motorized correction. This method needs a bed that is fixed on 3 points from which 2 have a motor +to change the height. The positions are defined by +BED_MOTOR_1_X, BED_MOTOR_1_Y, BED_MOTOR_2_X, BED_MOTOR_2_Y, BED_MOTOR_3_X, BED_MOTOR_3_Y +Motor 2 and 3 are the one driven by motor driver 0 and 1. These can be extra motors like Felix Pro 1 +uses them or a system with 3 z axis where motors can be controlled individually like the Sparkcube +does. + +Next we have to distinguish several methods of z probing sensors. Each have their own advantages and +disadvantages. First the z probe has a position when activated and that position is defined by +#define Z_PROBE_X_OFFSET 0 +#define Z_PROBE_Y_OFFSET 0 +This is needed since we need to know where we measure the height when the z probe triggers. When +probing is activated you will see a move to make probe go over current extruder position. The +position can be changed in eeprom later on. + +Some probes need to be activated/deactivated so we can use them. This is defined in the scripts +#define Z_PROBE_START_SCRIPT "" +#define Z_PROBE_FINISHED_SCRIPT "" + +Now when we probe we want to know the distance of the extruder to the bed. This is defined by +#define Z_PROBE_HEIGHT 4 +The 4 means that when we trigger the distance of the nozzle tip is 4mm. If your switch tends +to return different points you might repeat a measured point and use the average height: +#define Z_PROBE_SWITCHING_DISTANCE 1 +#define Z_PROBE_REPETITIONS 5 +Switching distance is the z raise needed to turn back a signal reliably to off. Inductive sensors +need only a bit while mechanical switches may require a bit more. + +Next thing to consider is the force for switching. Some beds use a cantilever design and pushing on +the outside easily bends the bed. If your sensor needs some force to trigger you add the error of +bending. For this reason you might add a bending correction. Currently you define +#define BENDING_CORRECTION_A 0 +#define BENDING_CORRECTION_B 0 +#define BENDING_CORRECTION_C 0 +which are the deflections at the 3 z probe points. For all other possible measurements these values +get interpolated. You can modify the values later on in eeprom. For force less sensors set them to 0. + +Next thing is endstop handling. Without bed leveling you normally home to minimum position for x,y and z. +With bed leveling this is not that easy any more. Since we do bed leveling we already assume the bed is +not leveled for x/y moves. So without correction we would hit the bed for different x/y positions at +different heights. As a result we have no real minimum position. That makes a z min endstop quite useless. +There is an exception to this. If your nozzle triggers z min or if a inductive sensor would trigger at a given +position we could use that signal. With nozzle triggers you need to be careful as a drop of filament +would change the height. The other problem is that while homing the auto leveling is not used. So +the only position would be if the z min sensor is directly over the 0,0 coordinate which is the rotation point +if we have matrix based correction. For motor based correction this will work everywhere correctly. + +So the only useful position for a z endstop is z max position. Apart from not having the bed tilt problem it +also allows homing with a full bed so you can continue an aborted print with some gcode tweaking. With z max +homing we adjust the error by simply changing the max. z height. One thing you need to remember is setting +#define ENDSTOP_Z_BACK_ON_HOME 4 +so we release the z max endstop. This is very important if we move xy at z max. Auto leveling might want to +increase z and the endstop might prevent it causing wrong position and a head crash if we later go down. +The value should be larger then the maximum expected tilt. + +Now it is time to define how we measure the bed rotation. Here again we have several methods to choose. +All methods need at least 3 points to define the bed rotation correctly. The quality we get comes +from the selection of the right points and method. + +BED_LEVELING_METHOD 0 +This method measures at the 3 probe points and creates a plane through these points. If you have +a really planar bed this gives the optimum result. The 3 points must not be in one line and have +a long distance to increase numerical stability. + +BED_LEVELING_METHOD 1 +This measures a grid. Probe point 1 is the origin and points 2 and 3 span a grid. We measure +BED_LEVELING_GRID_SIZE points in each direction and compute a regression plane through all +points. This gives a good overall plane if you have small bumps measuring inaccuracies. + +BED_LEVELING_METHOD 2 +Bending correcting 4 point measurement. This is for cantilevered beds that have the rotation axis +not at the side but inside the bed. Here we can assume no bending on the axis and a symmetric +bending to both sides of the axis. So probe points 2 and 3 build the symmetric axis and +point 1 is mirrored to 1m across the axis. Using the symmetry we then remove the bending +from 1 and use that as plane. + +By now the leveling process is finished. All errors that remain are measuring errors and bumps on +the bed it self. For deltas you can enable distortion correction to follow the bumps. + +There are 2 ways to consider a changing bed coating, which are defined by Z_PROBE_Z_OFFSET_MODE. +Z_PROBE_Z_OFFSET_MODE = 0 means we measure the surface of the bed below any coating. This is e.g. +the case with inductive sensors where we put BuildTak on top. In that case we can set Z_PROBE_Z_OFFSET +to the thickness of BuildTak to compensate. If we later change the coating, we only change Z_PROBE_Z_OFFSET +to new coating thickness. + +Z_PROBE_Z_OFFSET_MODE = 1 means we measure the surface of the coating, e.g. because we have a mechanical switch. +In that case we add Z_PROBE_Z_OFFSET for the measured height to compensate for correct distance to bed surface. + +In homing to max we reduce z length by Z_PROBE_Z_OFFSET to get a correct height. +In homing to z min we assume z endstop is bed level so we move up Z_PROBE_Z_OFFSET after endstop is hit. This +requires the extruder to bend the coating thickness without harm! +*/ + +#include "Repetier.h" + +#ifndef BED_LEVELING_METHOD +#define BED_LEVELING_METHOD 0 +#endif + +#ifndef BED_CORRECTION_METHOD +#define BED_CORRECTION_METHOD 0 +#endif + +#ifndef BED_LEVELING_GRID_SIZE +#define BED_LEVELING_GRID_SIZE 5 +#endif + +#ifndef BED_LEVELING_REPETITIONS +#define BED_LEVELING_REPETITIONS 1 +#endif + + +class PlaneBuilder { + float sum_xx,sum_xy,sum_yy,sum_x,sum_y,sum_xz,sum_yz,sum_z,n; + public: + PlaneBuilder() { + reset(); + } + void reset() { + sum_xx = sum_xy = sum_yy = sum_x = sum_y = sum_xz = sum_yz = sum_z = n = 0; + } + void addPoint(float x,float y,float z) { + n++; + sum_xx += x * x; + sum_xy += x * y; + sum_yy += y * y; + sum_x += x; + sum_y += y; + sum_xz += x * z; + sum_yz += y * z; + sum_z += z; + } + void createPlane(Plane &plane,bool silent=false) { + float det = (sum_x * (sum_xy * sum_y - sum_x * sum_yy) + sum_xx * (n * sum_yy - sum_y * sum_y) + sum_xy * (sum_x * sum_y - n * sum_xy)); + plane.a = ((sum_xy * sum_y - sum_x * sum_yy) * sum_z + (sum_x * sum_y - n * sum_xy) * sum_yz + sum_xz * (n * sum_yy - sum_y * sum_y)) / det; + plane.b = ((sum_x * sum_xy - sum_xx * sum_y) * sum_z + (n * sum_xx - sum_x * sum_x) * sum_yz + sum_xz * (sum_x * sum_y - n * sum_xy)) / det; + plane.c = ((sum_xx * sum_yy - sum_xy * sum_xy) * sum_z + (sum_x * sum_xy - sum_xx * sum_y) * sum_yz + sum_xz * (sum_xy * sum_y - sum_x * sum_yy)) / det; + if(!silent) { + Com::printF(PSTR("plane: a = "),plane.a,4); + Com::printF(PSTR(" b = "),plane.b,4); + Com::printFLN(PSTR(" c = "),plane.c,4); + } + } +}; + +#if FEATURE_AUTOLEVEL && FEATURE_Z_PROBE + +bool measureAutolevelPlane(Plane &plane) { + PlaneBuilder builder; + builder.reset(); +#if BED_LEVELING_METHOD == 0 // 3 point + float h; + Printer::moveTo(EEPROM::zProbeX1(),EEPROM::zProbeY1(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + h = Printer::runZProbe(false,false); + if(h == ILLEGAL_Z_PROBE) + { + //Davinci Specific + Printer::Z_probe[0]=-2000; + Printer::zprobe_ok = false; + return false; + } + else + { + Printer::Z_probe[0]=h; + } + uid.refreshPage(); + builder.addPoint(EEPROM::zProbeX1(),EEPROM::zProbeY1(),h); + Printer::moveTo(EEPROM::zProbeX2(),EEPROM::zProbeY2(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + h = Printer::runZProbe(false,false); + if(h == ILLEGAL_Z_PROBE) + { + //Davinci Specific + Printer::Z_probe[1]=-2000; + Printer::zprobe_ok = false; + return false; + } + else + { + Printer::Z_probe[1]=h; + } + uid.refreshPage(); + builder.addPoint(EEPROM::zProbeX2(),EEPROM::zProbeY2(),h); + Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + h = Printer::runZProbe(false,false); + if(h == ILLEGAL_Z_PROBE) + { + //Davinci Specific + Printer::Z_probe[2]=-2000; + Printer::zprobe_ok = false; + return false; + } + else + { + Printer::Z_probe[2]=h; + } + uid.refreshPage(); + builder.addPoint(EEPROM::zProbeX3(),EEPROM::zProbeY3(),h); +#elif BED_LEVELING_METHOD == 1 // linear regression + float delta = 1.0 / (BED_LEVELING_GRID_SIZE - 1); + float ox = EEPROM::zProbeX1(); + float oy = EEPROM::zProbeY1(); + float ax = delta * (EEPROM::zProbeX2() - EEPROM::zProbeX1()); + float ay = delta * (EEPROM::zProbeY2() - EEPROM::zProbeY1()); + float bx = delta * (EEPROM::zProbeX3() - EEPROM::zProbeX1()); + float by = delta * (EEPROM::zProbeY3() - EEPROM::zProbeY1()); + for(int ix = 0; ix < BED_LEVELING_GRID_SIZE; ix++) { + for(int iy = 0; iy < BED_LEVELING_GRID_SIZE; iy++) { + float px = ox + static_cast(ix) * ax + static_cast(iy) * bx; + float py = oy + static_cast(ix) * ay + static_cast(iy) * by; + Printer::moveTo(px,py,IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + float h = Printer::runZProbe(false,false); + if(h == ILLEGAL_Z_PROBE) + return false; + builder.addPoint(px,py,h); + } + } + +#elif BED_LEVELING_METHOD == 2 // 4 point symmetric + float h1,h2,h3,h4; + float apx = EEPROM::zProbeX1() - EEPROM::zProbeX2(); + float apy = EEPROM::zProbeY1() - EEPROM::zProbeY2(); + float abx = EEPROM::zProbeX3() - EEPROM::zProbeX2(); + float aby = EEPROM::zProbeY3() - EEPROM::zProbeY2(); + float ab2 = abx * abx + aby * aby; + float abap = apx * abx + apy * aby; + float t = abap / ab2; + float xx = EEPROM::zProbeX2() + t * abx; + float xy = EEPROM::zProbeY2() + t * aby; + float x1Mirror = EEPROM::zProbeX1() + 2.0 * (xx - EEPROM::zProbeX1()); + float y1Mirror = EEPROM::zProbeY1() + 2.0 * (xy - EEPROM::zProbeY1()); + Printer::moveTo(EEPROM::zProbeX1(),EEPROM::zProbeY1(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + h1 = Printer::runZProbe(false,false); + if(h1 == ILLEGAL_Z_PROBE) + return false; + Printer::moveTo(EEPROM::zProbeX2(),EEPROM::zProbeY2(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + h2 = Printer::runZProbe(false,false); + if(h2 == ILLEGAL_Z_PROBE) + return false; + Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + h3 = Printer::runZProbe(false,false); + if(h3 == ILLEGAL_Z_PROBE) + return false; + Printer::moveTo(x1Mirror,y1Mirror,IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); + h4 = Printer::runZProbe(false,false); + if(h4 == ILLEGAL_Z_PROBE) + return false; + t = h2 + (h3 - h2) * t; // theoretical height for crossing point for symmetric axis + h1 = t - (h4 - h1) * 0.5; // remove bending part + builder.addPoint(EEPROM::zProbeX1(), EEPROM::zProbeY1(), h1); + builder.addPoint(EEPROM::zProbeX2(), EEPROM::zProbeY2(), h2); + builder.addPoint(EEPROM::zProbeX3(), EEPROM::zProbeY3(), h3); +#else +#error Unknown bed leveling method +#endif + builder.createPlane(plane,false); + return true; +} + +void correctAutolevel(GCode *code,Plane &plane) { +#if BED_CORRECTION_METHOD == 0 // rotation matrix + //Printer::buildTransformationMatrix(plane.z(EEPROM::zProbeX1(),EEPROM::zProbeY1()),plane.z(EEPROM::zProbeX2(),EEPROM::zProbeY2()),plane.z(EEPROM::zProbeX3(),EEPROM::zProbeY3())); + Printer::buildTransformationMatrix(plane); +#elif BED_CORRECTION_METHOD == 1 // motorized correction +#if !defined(NUM_MOTOR_DRIVERS) || NUM_MOTOR_DRIVERS < 2 +#error You need to define 2 motors for motorized bed correction +#endif + Commands::waitUntilEndOfAllMoves(); // move steppers might be leveling steppers as well ! + float h1 = plane.z(BED_MOTOR_1_X,BED_MOTOR_1_Y); + float h2 = plane.z(BED_MOTOR_2_X,BED_MOTOR_2_Y); + float h3 = plane.z(BED_MOTOR_3_X,BED_MOTOR_3_Y); + // h1 is reference heights, h2 => motor 0, h3 => motor 1 + h2 -= h1; + h3 -= h1; +#if defined(LIMIT_MOTORIZED_CORRECTION) + if(h2 < -LIMIT_MOTORIZED_CORRECTION) h2 = -LIMIT_MOTORIZED_CORRECTION; + if(h2 > LIMIT_MOTORIZED_CORRECTION) h2 = LIMIT_MOTORIZED_CORRECTION; + if(h3 < -LIMIT_MOTORIZED_CORRECTION) h3 = -LIMIT_MOTORIZED_CORRECTION; + if(h3 > LIMIT_MOTORIZED_CORRECTION) h3 = LIMIT_MOTORIZED_CORRECTION; +#endif + MotorDriverInterface *motor2 = getMotorDriver(0); + MotorDriverInterface *motor3 = getMotorDriver(1); + motor2->setCurrentAs(0); + motor3->setCurrentAs(0); + motor2->gotoPosition(h2); + motor3->gotoPosition(h3); + motor2->disable(); + motor3->disable(); // now bed is even + Printer::currentPositionSteps[Z_AXIS] = h1 * Printer::axisStepsPerMM[Z_AXIS]; +#else +#error Unknown bed correction method set +#endif +} + +/* +Implementation of the G32 command +G32 S<0..2> - Autolevel print bed. S = 1 measure zLength, S = 2 Measure and store new zLength +S = 0 : Do not update length - use this if you have not homed before or you mess up zlength! +S = 1 : Measure zLength so homing works +S = 2 : Like s = 1 plus store results in EEPROM for next connection. +*/ +bool runBedLeveling(GCode *com) { + float h1,h2,h3,hc,oldFeedrate = Printer::feedrate; + int s = com->hasS() ? com->S : -1; +#if DISTORTION_CORRECTION + bool distEnabled = Printer::distortion.isEnabled(); + Printer::distortion.disable(false); // if level has changed, distortion is also invalid +#endif + Printer::setAutolevelActive(false); // iterate + Printer::resetTransformationMatrix(true); // in case we switch from matrix to motorized! +#if DRIVE_SYSTEM == DELTA + // It is not possible to go to the edges at the top, also users try + // it often and wonder why the coordinate system is then wrong. + // For that reason we ensure a correct behavior by code. + Printer::homeAxis(true, true, true); + Printer::moveTo(IGNORE_COORDINATE, IGNORE_COORDINATE, EEPROM::zProbeBedDistance() + EEPROM::zProbeHeight(), IGNORE_COORDINATE, Printer::homingFeedrate[Z_AXIS]); +#endif + Printer::startProbing(true); + //GCode::executeFString(Com::tZProbeStartScript); + Printer::coordinateOffset[X_AXIS] = Printer::coordinateOffset[Y_AXIS] = Printer::coordinateOffset[Z_AXIS] = 0; + Plane plane; +#if BED_CORRECTION_METHOD == 1 + for(int r = 0; r < BED_LEVELING_REPETITIONS; r++) { +#if DRIVE_SYSTEM == DELTA + if(r > 0) { + Printer::finishProbing(); + Printer::homeAxis(true, true, true); + Printer::moveTo(IGNORE_COORDINATE, IGNORE_COORDINATE, EEPROM::zProbeBedDistance() + EEPROM::zProbeHeight(), IGNORE_COORDINATE, Printer::homingFeedrate[Z_AXIS]); + Printer::startProbing(true); + } +#endif // DELTA +#endif // BED_CORRECTION_METHOD == 1 + if(!measureAutolevelPlane(plane)) { + Com::printErrorFLN(PSTR("Probing had returned errors - autoleveling canceled.")); + return false; + } + correctAutolevel(com,plane); + + // Leveling is finished now update own positions and store leveling data if needed + //float currentZ = plane.z((float)Printer::currentPositionSteps[X_AXIS] * Printer::invAxisStepsPerMM[X_AXIS],(float)Printer::currentPositionSteps[Y_AXIS] * Printer::invAxisStepsPerMM[Y_AXIS]); + float currentZ = plane.z(0.0,0.0); // we rotated around this point, so that is now z height + Com::printF(PSTR("CurrentZ:"),currentZ); + Com::printFLN(PSTR(" atZ:"),Printer::currentPosition[Z_AXIS]); + // With max z endstop we adjust zlength so after next homing we have also a calibrated printer + Printer::zMin = 0; +#if MAX_HARDWARE_ENDSTOP_Z + //float xRot,yRot,zRot; + //Printer::transformFromPrinter(Printer::currentPosition[X_AXIS],Printer::currentPosition[Y_AXIS],Printer::currentPosition[Z_AXIS],xRot,yRot,zRot); + //Com::printFLN(PSTR("Z after rotation:"),zRot); + // With max z endstop we adjust zlength so after next homing we have also a calibrated printer + if(s != 0) { + // at origin rotations have no influence so use values there to update + Printer::zLength += currentZ - Printer::currentPosition[Z_AXIS]; + //Printer::zLength += /*currentZ*/ plane.z((float)Printer::currentPositionSteps[X_AXIS] * Printer::invAxisStepsPerMM[X_AXIS],(float)Printer::currentPositionSteps[Y_AXIS] * Printer::invAxisStepsPerMM[Y_AXIS]) - zRot; + Com::printFLN(Com::tZProbePrinterHeight, Printer::zLength); + } +#endif + Printer::currentPositionSteps[Z_AXIS] = currentZ * Printer::axisStepsPerMM[Z_AXIS]; + Printer::updateCurrentPosition(true); // set position based on steps position +#if BED_CORRECTION_METHOD == 1 + if(fabs(plane.a) < 0.00025 && fabsf(plane.b) < 0.00025 ) + break; // we reached achievable precision so we can stop + } +#endif // BED_CORRECTION_METHOD == 1 + Printer::updateDerivedParameter(); + Printer::finishProbing(); +#if BED_CORRECTION_METHOD != 1 + Printer::setAutolevelActive(true); // only for software correction or we can spare the comp. time +#endif + if(s >= 2) { + EEPROM::storeDataIntoEEPROM(); + } + Printer::updateCurrentPosition(true); + Commands::printCurrentPosition(PSTR("G32 ")); +#if DISTORTION_CORRECTION + if(distEnabled) + Printer::distortion.enable(false); // if level has changed, distortion is also invalid +#endif +#if DRIVE_SYSTEM == DELTA + Printer::homeAxis(true, true, true); // shifting z makes positioning invalid, need to recalibrate +#endif + Printer::feedrate = oldFeedrate; + return true; +} + +#endif + +void Printer::setAutolevelActive(bool on) { +#if FEATURE_AUTOLEVEL + if(on == isAutolevelActive()) return; + flag0 = (on ? flag0 | PRINTER_FLAG0_AUTOLEVEL_ACTIVE : flag0 & ~PRINTER_FLAG0_AUTOLEVEL_ACTIVE); + if(on) + Com::printInfoFLN(Com::tAutolevelEnabled); + else + Com::printInfoFLN(Com::tAutolevelDisabled); + updateCurrentPosition(false); +#endif // FEATURE_AUTOLEVEL +} +#if MAX_HARDWARE_ENDSTOP_Z +float Printer::runZMaxProbe() { +#if NONLINEAR_SYSTEM + long startZ = realDeltaPositionSteps[Z_AXIS] = currentNonlinearPositionSteps[Z_AXIS]; // update real +#endif + Commands::waitUntilEndOfAllMoves(); + long probeDepth = 2*(Printer::zMaxSteps-Printer::zMinSteps); + stepsRemainingAtZHit = -1; + setZProbingActive(true); + PrintLine::moveRelativeDistanceInSteps(0,0,probeDepth,0,EEPROM::zProbeSpeed(),true,true); + if(stepsRemainingAtZHit < 0) { + Com::printErrorFLN(PSTR("z-max homing failed")); + return ILLEGAL_Z_PROBE; + } + setZProbingActive(false); + currentPositionSteps[Z_AXIS] -= stepsRemainingAtZHit; +#if NONLINEAR_SYSTEM + probeDepth -= (realDeltaPositionSteps[Z_AXIS] - startZ); +#else + probeDepth -= stepsRemainingAtZHit; +#endif + float distance = (float)probeDepth * invAxisStepsPerMM[Z_AXIS]; + Com::printF(Com::tZProbeMax,distance); + Com::printF(Com::tSpaceXColon,realXPosition()); + Com::printFLN(Com::tSpaceYColon,realYPosition()); + PrintLine::moveRelativeDistanceInSteps(0,0,-probeDepth,0,EEPROM::zProbeSpeed(),true,true); + return distance; +} +#endif + +#if FEATURE_Z_PROBE +void Printer::startProbing(bool runScript) { + float oldOffX = Printer::offsetX; + float oldOffY = Printer::offsetY; + float oldOffZ = Printer::offsetZ; + if(runScript) + GCode::executeFString(Com::tZProbeStartScript); + float maxStartHeight = EEPROM::zProbeBedDistance() + (EEPROM::zProbeHeight() > 0 ? EEPROM::zProbeHeight() : 0) + 0.1; + if(currentPosition[Z_AXIS] > maxStartHeight) { + moveTo(IGNORE_COORDINATE, IGNORE_COORDINATE, maxStartHeight, IGNORE_COORDINATE, homingFeedrate[Z_AXIS]); + } + // Fix position to be inside print area when probe is enabled + float ZPOffsetX = EEPROM::zProbeXOffset(); + float ZPOffsetY = EEPROM::zProbeYOffset(); + float xExtra = 0,yExtra = 0; + if(ZPOffsetX > 0 && Printer::currentPosition[X_AXIS] - ZPOffsetX < Printer::xMin) + xExtra = Printer::xMin + ZPOffsetX - Printer::currentPosition[X_AXIS]; + if(ZPOffsetY > 0 && Printer::currentPosition[Y_AXIS] - ZPOffsetY < Printer::yMin) + yExtra = Printer::yMin + ZPOffsetY - Printer::currentPosition[Y_AXIS]; + if(ZPOffsetX < 0 && Printer::currentPosition[X_AXIS] - ZPOffsetX > Printer::xMin + Printer::xLength) + xExtra = Printer::xMin + Printer::xLength + ZPOffsetX - Printer::currentPosition[X_AXIS]; + if(ZPOffsetY < 0 && Printer::currentPosition[Y_AXIS] - ZPOffsetY > Printer::yMin + Printer::yLength) + yExtra = Printer::yMin + Printer::yLength + ZPOffsetY - Printer::currentPosition[Y_AXIS]; + // Update position + Printer::offsetX = -ZPOffsetX; + Printer::offsetY = -ZPOffsetY; + Printer::offsetZ = 0; // we correct this with probe height + PrintLine::moveRelativeDistanceInSteps((Printer::offsetX - oldOffX + xExtra) * Printer::axisStepsPerMM[X_AXIS], + (Printer::offsetY - oldOffY + yExtra) * Printer::axisStepsPerMM[Y_AXIS], + 0, 0, EEPROM::zProbeXYSpeed(), true, ALWAYS_CHECK_ENDSTOPS); + updateCurrentPosition(false); +} + +void Printer::finishProbing() { + float xExtra = 0,yExtra = 0; + float oldOffX = Printer::offsetX; + float oldOffY = Printer::offsetY; + float oldOffZ = Printer::offsetZ; + GCode::executeFString(Com::tZProbeEndScript); + if(Extruder::current) { + Printer::offsetX = -Extruder::current->xOffset * Printer::invAxisStepsPerMM[X_AXIS]; + Printer::offsetY = -Extruder::current->yOffset * Printer::invAxisStepsPerMM[Y_AXIS]; + Printer::offsetZ = -Extruder::current->zOffset * Printer::invAxisStepsPerMM[Z_AXIS]; + } + float ZPOffsetX = oldOffX - Printer::offsetX; + float ZPOffsetY = oldOffY - Printer::offsetY; + if(ZPOffsetX > 0 && Printer::currentPosition[X_AXIS] - ZPOffsetX < Printer::xMin) + xExtra = Printer::xMin + ZPOffsetX - Printer::currentPosition[X_AXIS]; + if(ZPOffsetY > 0 && Printer::currentPosition[Y_AXIS] - ZPOffsetY < Printer::yMin) + yExtra = Printer::yMin + ZPOffsetY - Printer::currentPosition[Y_AXIS]; + if(ZPOffsetX < 0 && Printer::currentPosition[X_AXIS] - ZPOffsetX > Printer::xMin + Printer::xLength) + xExtra = Printer::xMin + Printer::xLength + ZPOffsetX - Printer::currentPosition[X_AXIS]; + if(ZPOffsetY < 0 && Printer::currentPosition[Y_AXIS] - ZPOffsetY > Printer::yMin + Printer::yLength) + yExtra = Printer::yMin + Printer::yLength + ZPOffsetY - Printer::currentPosition[Y_AXIS]; + PrintLine::moveRelativeDistanceInSteps((xExtra - ZPOffsetX) * Printer::axisStepsPerMM[X_AXIS], + (yExtra - ZPOffsetY) * Printer::axisStepsPerMM[Y_AXIS], + (Printer::offsetZ - oldOffZ) * Printer::axisStepsPerMM[Z_AXIS], 0, EEPROM::zProbeXYSpeed(), true, ALWAYS_CHECK_ENDSTOPS); + updateCurrentPosition(false); +} + +/* +This is the most important function for bed leveling. It does +1. Run probe start script if first = true and runStartScript = true +2. Position zProbe at current position if first = true. If we are more then maxStartHeight away from bed we also go down to that distance. +3. Measure the the steps until probe hits the bed. +4. Undo positioning to z probe and run finish script if last = true. + +Now we compute the nozzle height as follows: +a) Compute average height from repeated measurements +b) Add zProbeHeight to correct difference between triggering point and nozzle height above bed +c) If Z_PROBE_Z_OFFSET_MODE == 1 we add zProbeZOffset() that is coating thickness if we measure below coating with indictive sensor. +d) Add distortion correction. +e) Add bending correction + +Then we return the measured and corrected z distance. +*/ +float Printer::runZProbe(bool first,bool last,uint8_t repeat,bool runStartScript) { + float oldOffX = Printer::offsetX; + float oldOffY = Printer::offsetY; + float oldOffZ = Printer::offsetZ; + if(first) + startProbing(runStartScript); + Commands::waitUntilEndOfAllMoves(); + int32_t sum = 0, probeDepth; + int32_t shortMove = static_cast((float)Z_PROBE_SWITCHING_DISTANCE * axisStepsPerMM[Z_AXIS]); // distance to go up for repeated moves + int32_t lastCorrection = currentPositionSteps[Z_AXIS]; // starting position +#if NONLINEAR_SYSTEM + realDeltaPositionSteps[Z_AXIS] = currentNonlinearPositionSteps[Z_AXIS]; // update real +#endif + //int32_t updateZ = 0; + waitForZProbeStart(); + Endstops::update(); + Endstops::update(); + if(Endstops::zProbe()) { + Com::printErrorFLN(PSTR("z-probe triggered before starting probing.")); + return ILLEGAL_Z_PROBE; + } + for(int8_t r = 0; r < repeat; r++) { + probeDepth = 2 * (Printer::zMaxSteps - Printer::zMinSteps); // probe should always hit within this distance + stepsRemainingAtZHit = -1; // Marker that we did not hit z probe + //int32_t offx = axisStepsPerMM[X_AXIS] * EEPROM::zProbeXOffset(); + //int32_t offy = axisStepsPerMM[Y_AXIS] * EEPROM::zProbeYOffset(); + //PrintLine::moveRelativeDistanceInSteps(-offx,-offy,0,0,EEPROM::zProbeXYSpeed(),true,true); + setZProbingActive(true); + PrintLine::moveRelativeDistanceInSteps(0, 0, -probeDepth, 0, EEPROM::zProbeSpeed(), true, true); + if(stepsRemainingAtZHit < 0) { + Com::printErrorFLN(Com::tZProbeFailed); + return ILLEGAL_Z_PROBE; + } + setZProbingActive(false); +#if NONLINEAR_SYSTEM + stepsRemainingAtZHit = realDeltaPositionSteps[C_TOWER] - currentNonlinearPositionSteps[C_TOWER]; // nonlinear moves may split z so stepsRemainingAtZHit is only what is left from last segment not total move. This corrects the problem. +#endif +#if DRIVE_SYSTEM == DELTA + currentNonlinearPositionSteps[A_TOWER] += stepsRemainingAtZHit; // Update difference + currentNonlinearPositionSteps[B_TOWER] += stepsRemainingAtZHit; + currentNonlinearPositionSteps[C_TOWER] += stepsRemainingAtZHit; +#endif + currentPositionSteps[Z_AXIS] += stepsRemainingAtZHit; // now current position is correct + sum += lastCorrection - currentPositionSteps[Z_AXIS]; + if(r + 1 < repeat) { + // go only shortest possible move up for repetitions + PrintLine::moveRelativeDistanceInSteps(0, 0, shortMove, 0, EEPROM::zProbeSpeed(), true, true); + if(Endstops::zProbe()) { + Com::printErrorFLN(PSTR("z-probe did not untrigger on repetitive measurement - maybe you need to increase distance!")); + return ILLEGAL_Z_PROBE; + } + } + } + float distance = static_cast(sum) * invAxisStepsPerMM[Z_AXIS] / static_cast(repeat) + EEPROM::zProbeHeight(); + //Com::printFLN(PSTR("OrigDistance:"),distance); +#if Z_PROBE_Z_OFFSET_MODE == 1 + distance += EEPROM::zProbeZOffset(); // We measured including coating, so we need to add coating thickness! +#endif +#if DISTORTION_CORRECTION + float zCorr = 0; + if(Printer::distortion.isEnabled()) { + zCorr = distortion.correct(currentPositionSteps[X_AXIS] + EEPROM::zProbeXOffset() * axisStepsPerMM[X_AXIS],currentPositionSteps[Y_AXIS] + + EEPROM::zProbeYOffset() * axisStepsPerMM[Y_AXIS],0) * invAxisStepsPerMM[Z_AXIS]; + distance += zCorr; + } +#endif + distance += bendingCorrectionAt(currentPosition[X_AXIS], currentPosition[Y_AXIS]); + Com::printF(Com::tZProbe, distance); + Com::printF(Com::tSpaceXColon, realXPosition()); +#if DISTORTION_CORRECTION + if(Printer::distortion.isEnabled()) { + Com::printF(Com::tSpaceYColon, realYPosition()); + Com::printFLN(PSTR(" zCorr:"), zCorr); + } else { + Com::printFLN(Com::tSpaceYColon, realYPosition()); + } +#else + Com::printFLN(Com::tSpaceYColon, realYPosition()); +#endif + // Go back to start position + PrintLine::moveRelativeDistanceInSteps(0, 0, lastCorrection - currentPositionSteps[Z_AXIS], 0, EEPROM::zProbeSpeed(), true, true); + if(Endstops::zProbe()) { + Com::printErrorFLN(PSTR("z-probe did not untrigger after going back to start position.")); + return ILLEGAL_Z_PROBE; + } + //PrintLine::moveRelativeDistanceInSteps(offx,offy,0,0,EEPROM::zProbeXYSpeed(),true,true); + if(last) + finishProbing(); + return distance; +} + +float Printer::bendingCorrectionAt(float x, float y) { + PlaneBuilder builder; + builder.addPoint(EEPROM::zProbeX1(),EEPROM::zProbeY1(),EEPROM::bendingCorrectionA()); + builder.addPoint(EEPROM::zProbeX2(),EEPROM::zProbeY2(),EEPROM::bendingCorrectionB()); + builder.addPoint(EEPROM::zProbeX3(),EEPROM::zProbeY3(),EEPROM::bendingCorrectionC()); + Plane plane; + builder.createPlane(plane,true); + return plane.z(x,y); +} + +void Printer::waitForZProbeStart() { +#if Z_PROBE_WAIT_BEFORE_TEST + Endstops::update(); + Endstops::update(); // double test to get right signal. Needed for crosstalk protection. + if(Endstops::zProbe()) return; +#if UI_DISPLAY_TYPE != NO_DISPLAY + uid.setStatusP(Com::tHitZProbe); + uid.refreshPage(); +#endif +#ifdef DEBUG_PRINT + debugWaitLoop = 3; +#endif + while(!Endstops::zProbe()) { + defaultLoopActions(); + Endstops::update(); + Endstops::update(); // double test to get right signal. Needed for crosstalk protection. + } +#ifdef DEBUG_PRINT + debugWaitLoop = 4; +#endif + HAL::delayMilliseconds(30); + while(Endstops::zProbe()) { + defaultLoopActions(); + Endstops::update(); + Endstops::update(); // double test to get right signal. Needed for crosstalk protection. + } + HAL::delayMilliseconds(30); + UI_CLEAR_STATUS; +#endif +} +#endif + +/* + Transforms theoretical correct coordinates to corrected coordinates resulting from bed rotation + and shear transformations. +*/ +void Printer::transformToPrinter(float x,float y,float z,float &transX,float &transY,float &transZ) { +#if FEATURE_AXISCOMP + // Axis compensation: + x = x + y * EEPROM::axisCompTanXY() + z * EEPROM::axisCompTanXZ(); + y = y + z * EEPROM::axisCompTanYZ(); +#endif +#if BED_CORRECTION_METHOD != 1 && FEATURE_AUTOLEVEL + if(isAutolevelActive()) { + transX = x * autolevelTransformation[0] + y * autolevelTransformation[3] + z * autolevelTransformation[6]; + transY = x * autolevelTransformation[1] + y * autolevelTransformation[4] + z * autolevelTransformation[7]; + transZ = x * autolevelTransformation[2] + y * autolevelTransformation[5] + z * autolevelTransformation[8]; + } else { + transX = x; + transY = y; + transZ = z; + } +#else + transX = x; + transY = y; + transZ = z; +#endif +} + +/* Transform back to real printer coordinates. */ +void Printer::transformFromPrinter(float x,float y,float z,float &transX,float &transY,float &transZ) { +#if BED_CORRECTION_METHOD != 1 && FEATURE_AUTOLEVEL + if(isAutolevelActive()) { + transX = x * autolevelTransformation[0] + y * autolevelTransformation[1] + z * autolevelTransformation[2]; + transY = x * autolevelTransformation[3] + y * autolevelTransformation[4] + z * autolevelTransformation[5]; + transZ = x * autolevelTransformation[6] + y * autolevelTransformation[7] + z * autolevelTransformation[8]; + } else { + transX = x; + transY = y; + transZ = z; + } +#else + transX = x; + transY = y; + transZ = z; +#endif +#if FEATURE_AXISCOMP + // Axis compensation: + transY = transY - transZ * EEPROM::axisCompTanYZ(); + transX = transX - transY * EEPROM::axisCompTanXY() - transZ * EEPROM::axisCompTanXZ(); +#endif +} +#if FEATURE_AUTOLEVEL +void Printer::resetTransformationMatrix(bool silent) { + autolevelTransformation[0] = autolevelTransformation[4] = autolevelTransformation[8] = 1; + autolevelTransformation[1] = autolevelTransformation[2] = autolevelTransformation[3] = + autolevelTransformation[5] = autolevelTransformation[6] = autolevelTransformation[7] = 0; + if(!silent) + Com::printInfoFLN(Com::tAutolevelReset); +} + +void Printer::buildTransformationMatrix(Plane &plane) { + float z0 = plane.z(0,0); + float az = z0-plane.z(1,0); // ax = 1, ay = 0 + float bz = z0-plane.z(0,1); // bx = 0, by = 1 + // First z direction + autolevelTransformation[6] = -az; + autolevelTransformation[7] = -bz; + autolevelTransformation[8] = 1; + float len = sqrt(az * az + bz * bz + 1); + autolevelTransformation[6] /= len; + autolevelTransformation[7] /= len; + autolevelTransformation[8] /= len; + autolevelTransformation[0] = 1; + autolevelTransformation[1] = 0; + autolevelTransformation[2] = -autolevelTransformation[6]/autolevelTransformation[8]; + len = sqrt(autolevelTransformation[0] * autolevelTransformation[0] + autolevelTransformation[1] * autolevelTransformation[1] + autolevelTransformation[2] * autolevelTransformation[2]); + autolevelTransformation[0] /= len; + autolevelTransformation[1] /= len; + autolevelTransformation[2] /= len; + // cross(z,x) y,z) + autolevelTransformation[3] = autolevelTransformation[7] * autolevelTransformation[2] - autolevelTransformation[8] * autolevelTransformation[1]; + autolevelTransformation[4] = autolevelTransformation[8] * autolevelTransformation[0] - autolevelTransformation[6] * autolevelTransformation[2]; + autolevelTransformation[5] = autolevelTransformation[6] * autolevelTransformation[1] - autolevelTransformation[7] * autolevelTransformation[0]; + len = sqrt(autolevelTransformation[3] * autolevelTransformation[3] + autolevelTransformation[4] * autolevelTransformation[4] + autolevelTransformation[5] * autolevelTransformation[5]); + autolevelTransformation[3] /= len; + autolevelTransformation[4] /= len; + autolevelTransformation[5] /= len; + + Com::printArrayFLN(Com::tTransformationMatrix,autolevelTransformation, 9, 6); +} +/* +void Printer::buildTransformationMatrix(float h1,float h2,float h3) { + float ax = EEPROM::zProbeX2() - EEPROM::zProbeX1(); + float ay = EEPROM::zProbeY2() - EEPROM::zProbeY1(); + float az = h1 - h2; + float bx = EEPROM::zProbeX3() - EEPROM::zProbeX1(); + float by = EEPROM::zProbeY3() - EEPROM::zProbeY1(); + float bz = h1 - h3; + // First z direction + autolevelTransformation[6] = ay * bz - az * by; + autolevelTransformation[7] = az * bx - ax * bz; + autolevelTransformation[8] = ax * by - ay * bx; + float len = sqrt(autolevelTransformation[6] * autolevelTransformation[6] + autolevelTransformation[7] * autolevelTransformation[7] + autolevelTransformation[8] * autolevelTransformation[8]); + if(autolevelTransformation[8] < 0) len = -len; + autolevelTransformation[6] /= len; + autolevelTransformation[7] /= len; + autolevelTransformation[8] /= len; + autolevelTransformation[3] = 0; + autolevelTransformation[4] = autolevelTransformation[8]; + autolevelTransformation[5] = -autolevelTransformation[7]; + // cross(y,z) + autolevelTransformation[0] = autolevelTransformation[4] * autolevelTransformation[8] - autolevelTransformation[5] * autolevelTransformation[7]; + autolevelTransformation[1] = autolevelTransformation[5] * autolevelTransformation[6];// - autolevelTransformation[3] * autolevelTransformation[8]; + autolevelTransformation[2] = autolevelTransformation[3] * autolevelTransformation[7] - autolevelTransformation[4] * autolevelTransformation[6]; + len = sqrt(autolevelTransformation[0] * autolevelTransformation[0] + autolevelTransformation[1] * autolevelTransformation[1] + autolevelTransformation[2] * autolevelTransformation[2]); + autolevelTransformation[0] /= len; + autolevelTransformation[1] /= len; + autolevelTransformation[2] /= len; + len = sqrt(autolevelTransformation[4] * autolevelTransformation[4] + autolevelTransformation[5] * autolevelTransformation[5]); + autolevelTransformation[4] /= len; + autolevelTransformation[5] /= len; + Com::printArrayFLN(Com::tTransformationMatrix,autolevelTransformation, 9, 6); +} +*/ +#endif diff --git a/src/ArduinoDUE/Repetier/Commands.cpp b/src/ArduinoDUE/Repetier/Commands.cpp index ea28110..026db1e 100644 --- a/src/ArduinoDUE/Repetier/Commands.cpp +++ b/src/ArduinoDUE/Repetier/Commands.cpp @@ -1,52 +1,94 @@ /* - This file is part of Repetier-Firmware. +This file is part of Repetier-Firmware. - Repetier-Firmware is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. +Repetier-Firmware is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. - Repetier-Firmware is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +Repetier-Firmware is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Repetier-Firmware. If not, see . +You should have received a copy of the GNU General Public License +along with Repetier-Firmware. If not, see . - This firmware is a nearly complete rewrite of the sprinter firmware - by kliment (https://github.com/kliment/Sprinter) - which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. +This firmware is a nearly complete rewrite of the sprinter firmware +by kliment (https://github.com/kliment/Sprinter) +which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. */ #include "Repetier.h" -const int sensitive_pins[] PROGMEM = SENSITIVE_PINS; // Sensitive pin list for M42 +const int8_t sensitive_pins[] PROGMEM = SENSITIVE_PINS; // Sensitive pin list for M42 int Commands::lowestRAMValue = MAX_RAM; int Commands::lowestRAMValueSend = MAX_RAM; -//Davinci Specific, specifi flag and counter +//Davinci Specific +extern bool benable_autoreturn; + +#if DAVINCI == 4 +//to avoid conflict between AiO home turn table sensor and Z-probe sensor +void Check_turntable(){ + + if (digitalRead(TABLE_HOME_PIN) == 0) { + getMotorDriver(0)->disable(); + getMotorDriver(0)->setCurrentAs(0); + int32_t tmpspeed = getMotorDriver(0)->getdelayUS(); + int32_t homespeed = 500000 / (TURNTABLE_HOME_SPEED * getMotorDriver(0)->getstepsPerMM()); + getMotorDriver(0)->setdelayUS(homespeed); + getMotorDriver(0)->gotoPosition(10); + getMotorDriver(0)->setdelayUS(tmpspeed); + } + getMotorDriver(0)->enable(); +} +//generic function to home a motor using max speed / max length and sensor pin +bool Home_motor(int id, float speed, int sensorpin, float maxlength) { + //check if need to move + bool result = false; + getMotorDriver(id)->enable(); + if (digitalRead(sensorpin) == 0) return true; + //save current speed + int32_t tmpspeed = getMotorDriver(id)->getdelayUS(); + int32_t homespeed = 500000 / (speed * getMotorDriver(id)->getstepsPerMM()); + getMotorDriver(id)->disable(); + getMotorDriver(id)->setCurrentAs(0); + getMotorDriver(id)->setdelayUS(homespeed); + //precision is 0.5 mm should be ok + for (float pos = 0.5; pos < maxlength;pos=pos+0.5) + { + getMotorDriver(id)->gotoPosition(pos); + if (digitalRead(sensorpin) == 0) { //here we go so exit + result = true; + break; + } + } + //lock motor and reverse speed to original and send status + getMotorDriver(id)->enable(); + getMotorDriver(id)->setdelayUS(tmpspeed); + getMotorDriver(id)->setCurrentAs(0); + return result; +} +#endif + +//Davinci Specific, specific flag and counter uint8_t Commands::delay_flag_change=0; uint8_t Commands::delay_flag_change2=0; uint8_t Commands::countersensor=0; -void Commands::commandLoop() -{ - while(true) - { +void Commands::commandLoop() { + while(true) { #ifdef DEBUG_PRINT debugWaitLoop = 1; #endif - if(!Printer::isBlockingReceive()) - { + if(!Printer::isBlockingReceive()) { GCode::readFromSerial(); GCode *code = GCode::peekCurrentCommand(); //UI_SLOW; // do longer timed user interface action UI_MEDIUM; // do check encoder - if(code) - { + if(code) { #if SDSUPPORT - if(sd.savetosd) - { + if(sd.savetosd) { if(!(code->hasM() && code->M == 29)) // still writing to file sd.writeCommand(code); else @@ -54,37 +96,32 @@ void Commands::commandLoop() #if ECHO_ON_EXECUTE code->echoCommand(); #endif - } - else + } else #endif - //Davinci Specific, STOP requested - if(!Printer::isMenuModeEx(MENU_MODE_STOP_REQUESTED)) Commands::executeGCode(code); + //Davinci Specific, STOP requested + if(!Printer::isMenuModeEx(MENU_MODE_STOP_REQUESTED)) Commands::executeGCode(code); code->popCurrentCommand(); } - } - else - { + } else { + GCode::keepAlive(Paused); UI_MEDIUM; } Printer::defaultLoopActions(); } } -void Commands::checkForPeriodicalActions(bool allowNewMoves) -{ +void Commands::checkForPeriodicalActions(bool allowNewMoves) { Printer::handleInterruptEvent(); - if(!executePeriodical) return; -//Davinci Specific, as we call a lot this function in subfunctions -#if FEATURE_WATCHDOG - HAL::pingWatchdog(); -#endif + EVENT_PERIODICAL; + if(!executePeriodical) return; // gets true every 100ms executePeriodical = 0; + EVENT_TIMER_100MS; Extruder::manageTemperatures(); - if(--counter250ms == 0) - { - if(manageMonitor <= 1 + NUM_EXTRUDER) + if(--counter500ms == 0) { + if(manageMonitor) writeMonitor(); - counter250ms = 5; + counter500ms = 5; + EVENT_TIMER_500MS; } //Davinci Specific, sensor management #if defined(TOP_SENSOR_PIN) @@ -112,7 +149,7 @@ void Commands::checkForPeriodicalActions(bool allowNewMoves) //play alarm playsound(1000,140); playsound(3000,240); - UI_STATUS_UPD(UI_TEXT_TOP_COVER_OPEN); + UI_STATUS_F(Com::translatedF(UI_TEXT_TOP_COVER_OPEN_ID)); countersensor=0; } } @@ -123,9 +160,9 @@ void Commands::checkForPeriodicalActions(bool allowNewMoves) //check if top was previously open if (Printer::btop_Cover_open) { //erase only if no other status - if (String(UI_TEXT_TOP_COVER_OPEN).equals(String(uid.statusMsg))) + if (String(Com::translatedF(UI_TEXT_TOP_COVER_OPEN_ID)).equals(String(uid.statusMsg))) { - UI_STATUS_UPD(""); + UI_STATUS_F(Com::translatedF(UI_TEXT_EMPTY_ID)); } Printer::btop_Cover_open=false; } @@ -139,7 +176,7 @@ void Commands::checkForPeriodicalActions(bool allowNewMoves) Printer::setMenuModeEx(MENU_MODE_STOP_REQUESTED,false); //commands to run when stop GCode::executeFString(PSTR(SD_RUN_ON_STOP)); - UI_STATUS_UPD(UI_TEXT_IDLE); + UI_STATUS_F(Com::translatedF(UI_TEXT_IDLE_ID)); delay_flag_change2=0; } else delay_flag_change2++; @@ -162,7 +199,7 @@ void Commands::checkForPeriodicalActions(bool allowNewMoves) } else delay_flag_change=0; // If called from queueDelta etc. it is an error to start a new move since it - // would invalidate old computation resulting in unpredicted behaviour. + // would invalidate old computation resulting in unpredicted behavior. // lcd controller can start new moves, so we disallow it if called from within // a move command. UI_SLOW(allowNewMoves); @@ -172,39 +209,34 @@ void Commands::checkForPeriodicalActions(bool allowNewMoves) /** \brief Waits until movement cache is empty. - Some commands expect no movement, before they can execute. This function - waits, until the steppers are stopped. In the meanwhile it buffers incoming - commands and manages temperatures. +Some commands expect no movement, before they can execute. This function +waits, until the steppers are stopped. In the meanwhile it buffers incoming +commands and manages temperatures. */ -void Commands::waitUntilEndOfAllMoves() -{ +void Commands::waitUntilEndOfAllMoves() { #ifdef DEBUG_PRINT debugWaitLoop = 8; #endif - while(PrintLine::hasLines()) - { + while(PrintLine::hasLines()) { GCode::readFromSerial(); checkForPeriodicalActions(false); + GCode::keepAlive(Processing); UI_MEDIUM; } } -void Commands::waitUntilEndOfAllBuffers() -{ +void Commands::waitUntilEndOfAllBuffers() { GCode *code = NULL; #ifdef DEBUG_PRINT debugWaitLoop = 9; #endif - while(PrintLine::hasLines() || (code != NULL)) - { + while(PrintLine::hasLines() || (code != NULL)) { GCode::readFromSerial(); code = GCode::peekCurrentCommand(); UI_MEDIUM; // do check encoder - if(code) - { + if(code) { #if SDSUPPORT - if(sd.savetosd) - { + if(sd.savetosd) { if(!(code->hasM() && code->M == 29)) // still writing to file sd.writeCommand(code); else @@ -212,8 +244,7 @@ void Commands::waitUntilEndOfAllBuffers() #if ECHO_ON_EXECUTE code->echoCommand(); #endif - } - else + } else #endif Commands::executeGCode(code); code->popCurrentCommand(); @@ -223,12 +254,10 @@ void Commands::waitUntilEndOfAllBuffers() } } -void Commands::printCurrentPosition(FSTRINGPARAM(s)) -{ +void Commands::printCurrentPosition(FSTRINGPARAM(s)) { float x, y, z; Printer::realPosition(x, y, z); - if (isnan(x) || isinf(x) || isnan(y) || isinf(y) || isnan(z) || isinf(z)) - { + if (isnan(x) || isinf(x) || isnan(y) || isinf(y) || isnan(z) || isinf(z)) { Com::printErrorFLN(s); // flag where the error condition came from } x += Printer::coordinateOffset[X_AXIS]; @@ -242,8 +271,9 @@ void Commands::printCurrentPosition(FSTRINGPARAM(s)) //Com::printFLN(PSTR(" OffY:"),Printer::offsetY); } -void Commands::printTemperatures(bool showRaw) -{ +void Commands::printTemperatures(bool showRaw) { + int error; +#if NUM_EXTRUDER > 0 float temp = Extruder::current->tempControl.currentTemperatureC; #if HEATED_BED_SENSOR_TYPE == 0 Com::printF(Com::tTColon,temp); @@ -254,20 +284,21 @@ void Commands::printTemperatures(bool showRaw) #if HAVE_HEATED_BED Com::printF(Com::tSpaceBColon,Extruder::getHeatedBedTemperature()); Com::printF(Com::tSpaceSlash,heatedBedController.targetTemperatureC,0); - if(showRaw) - { + if((error = heatedBedController.errorState()) > 0) { + Com::printF(PSTR(" DB:"),error); + } + if(showRaw) { Com::printF(Com::tSpaceRaw,(int)NUM_EXTRUDER); Com::printF(Com::tColon,(1023 << (2 - ANALOG_REDUCE_BITS)) - heatedBedController.currentTemperature); } - Com::printF(Com::tSpaceBAtColon,(pwm_pos[heatedBedController.pwmIndex])); // Show output of autotune when tuning! + Com::printF(Com::tSpaceBAtColon,(pwm_pos[heatedBedController.pwmIndex])); // Show output of auto tune when tuning! #endif #endif #if TEMP_PID - Com::printF(Com::tSpaceAtColon,(autotuneIndex == 255 ? pwm_pos[Extruder::current->id] : pwm_pos[autotuneIndex])); // Show output of autotune when tuning! + Com::printF(Com::tSpaceAtColon,(autotuneIndex == 255 ? pwm_pos[Extruder::current->id] : pwm_pos[autotuneIndex])); // Show output of auto tune when tuning! #endif #if NUM_EXTRUDER > 1 && MIXING_EXTRUDER == 0 - for(uint8_t i = 0; i < NUM_EXTRUDER; i++) - { + for(uint8_t i = 0; i < NUM_EXTRUDER; i++) { Com::printF(Com::tSpaceT,(int)i); Com::printF(Com::tColon,extruder[i].tempControl.currentTemperatureC); Com::printF(Com::tSpaceSlash,extruder[i].tempControl.targetTemperatureC,0); @@ -275,17 +306,28 @@ void Commands::printTemperatures(bool showRaw) Com::printF(Com::tSpaceAt,(int)i); Com::printF(Com::tColon,(pwm_pos[extruder[i].tempControl.pwmIndex])); // Show output of autotune when tuning! #endif - if(showRaw) - { + if((error = extruder[i].tempControl.errorState()) > 0) { + Com::printF(PSTR(" D"),(int)i); + Com::printF(Com::tColon,error); + } + if(showRaw) { Com::printF(Com::tSpaceRaw,(int)i); Com::printF(Com::tColon,(1023 << (2 - ANALOG_REDUCE_BITS)) - extruder[i].tempControl.currentTemperature); } } +#elif NUM_EXTRUDER == 1 + if((error = extruder[0].tempControl.errorState()) > 0) { + Com::printF(PSTR(" D0:"),error); + } + if(showRaw) { + Com::printF(Com::tSpaceRaw,(int)0); + Com::printF(Com::tColon,(1023 << (2 - ANALOG_REDUCE_BITS)) - extruder[0].tempControl.currentTemperature); + } #endif Com::println(); +#endif } -void Commands::changeFeedrateMultiply(int factor) -{ +void Commands::changeFeedrateMultiply(int factor) { if(factor < 25) factor = 25; if(factor > 500) factor = 500; Printer::feedrate *= (float)factor / (float)Printer::feedrateMultiply; @@ -293,8 +335,7 @@ void Commands::changeFeedrateMultiply(int factor) Com::printFLN(Com::tSpeedMultiply, factor); } -void Commands::changeFlowrateMultiply(int factor) -{ +void Commands::changeFlowrateMultiply(int factor) { if(factor < 25) factor = 25; if(factor > 200) factor = 200; Printer::extrudeMultiply = factor; @@ -305,35 +346,48 @@ void Commands::changeFlowrateMultiply(int factor) Com::printFLN(Com::tFlowMultiply, factor); } +#if FEATURE_FAN_CONTROL uint8_t fanKickstart; -void Commands::setFanSpeed(int speed,bool wait) -{ -#if FAN_PIN>-1 && FEATURE_FAN_CONTROL +#endif +#if FEATURE_FAN2_CONTROL +uint8_t fan2Kickstart; +#endif + +void Commands::setFanSpeed(int speed, bool immediately) { +#if FAN_PIN >- 1 && FEATURE_FAN_CONTROL + if(Printer::fanSpeed == speed) + return; speed = constrain(speed,0,255); Printer::setMenuMode(MENU_MODE_FAN_RUNNING,speed != 0); - if(wait) - Commands::waitUntilEndOfAllMoves(); // use only if neededthis to change the speed exactly at that point, but it may cause blobs if you do! - if(speed != pwm_pos[NUM_EXTRUDER + 2]) - { - Com::printFLN(Com::tFanspeed,speed); // send only new values to break update loops! -#if FAN_KICKSTART_TIME - if(fanKickstart == 0 && speed > pwm_pos[NUM_EXTRUDER + 2]) fanKickstart = FAN_KICKSTART_TIME/100; -#endif + Printer::fanSpeed = speed; + if(PrintLine::linesCount == 0 || immediately) { + if(Printer::mode == PRINTER_MODE_FFF) { + for(fast8_t i = 0; i < PRINTLINE_CACHE_SIZE; i++) + PrintLine::lines[i].secondSpeed = speed; // fill all printline buffers with new fan speed value + } + Printer::setFanSpeedDirectly(speed); } - pwm_pos[NUM_EXTRUDER + 2] = speed; + Com::printFLN(Com::tFanspeed,speed); // send only new values to break update loops! +#endif +} +void Commands::setFan2Speed(int speed) { +#if FAN2_PIN >- 1 && FEATURE_FAN2_CONTROL + speed = constrain(speed,0,255); + Printer::setFan2SpeedDirectly(speed); + Com::printFLN(Com::tFan2speed,speed); // send only new values to break update loops! #endif } -void Commands::reportPrinterUsage() -{ +void Commands::reportPrinterUsage() { #if EEPROM_MODE != 0 float dist = Printer::filamentPrinted * 0.001 + HAL::eprGetFloat(EPR_PRINTING_DISTANCE); Com::printF(Com::tPrintedFilament, dist, 2); Com::printF(Com::tSpacem); bool alloff = true; +#if NUM_EXTRUDER > 0 for(uint8_t i = 0; i < NUM_EXTRUDER; i++) if(tempController[i]->targetTemperatureC > 15) alloff = false; - +#endif int32_t seconds = (alloff ? 0 : (HAL::timeInMilliseconds() - Printer::msecondsPrinting) / 1000) + HAL::eprGetInt32(EPR_PRINTING_TIME); int32_t tmp = seconds / 86400; seconds -= tmp * 86400; @@ -350,8 +404,9 @@ void Commands::reportPrinterUsage() // Digipot methods for controling current and microstepping #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1 -int digitalPotWrite(int address, unsigned int value) // From Arduino DigitalPotControl example -{ +int digitalPotWrite(int address, uint16_t value) { // From Arduino DigitalPotControl example + if(value > 255) + value = 255; WRITE(DIGIPOTSS_PIN,LOW); // take the SS pin low to select the chip HAL::spiSend(address); // send in the address and value via SPI: HAL::spiSend(value); @@ -359,35 +414,45 @@ int digitalPotWrite(int address, unsigned int value) // From Arduino DigitalPotC //delay(10); } -void setMotorCurrent(uint8_t driver, unsigned int current) -{ +void setMotorCurrent(uint8_t driver, uint16_t current) { + if(driver > 4) return; const uint8_t digipot_ch[] = DIGIPOT_CHANNELS; digitalPotWrite(digipot_ch[driver], current); } + +void setMotorCurrentPercent( uint8_t channel, float level) { + uint16_t raw_level = ( level * 255 / 100 ); + setMotorCurrent(channel,raw_level); +} #endif -void motorCurrentControlInit() //Initialize Digipot Motor Current -{ +void motorCurrentControlInit() { //Initialize Digipot Motor Current #if DIGIPOTSS_PIN && DIGIPOTSS_PIN > -1 - const uint8_t digipot_motor_current[] = MOTOR_CURRENT; - HAL::spiInit(0); //SPI.begin(); SET_OUTPUT(DIGIPOTSS_PIN); +#ifdef MOTOR_CURRENT_PERCENT + const float digipot_motor_current[] = MOTOR_CURRENT_PERCENT; + for(int i = 0; i <= 4; i++) + //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]); + setMotorCurrentPercent(i,digipot_motor_current[i]); +#else + const uint8_t digipot_motor_current[] = MOTOR_CURRENT; for(int i = 0; i <= 4; i++) //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]); setMotorCurrent(i,digipot_motor_current[i]); #endif +#endif } #endif -#if STEPPER_CURRENT_CONTROL==CURRENT_CONTROL_LTC2600 +#if STEPPER_CURRENT_CONTROL == CURRENT_CONTROL_LTC2600 -void setMotorCurrent( uint8_t channel, unsigned short level ) -{ +void setMotorCurrent( uint8_t channel, unsigned short level ) { + if(channel >= LTC2600_NUM_CHANNELS) return; const uint8_t ltc_channels[] = LTC2600_CHANNELS; if(channel > LTC2600_NUM_CHANNELS) return; uint8_t address = ltc_channels[channel]; - char i; + fast8_t i; // NOTE: Do not increase the current endlessly. In case the engine reaches its current saturation, the engine and the driver can heat up and loss power. @@ -406,16 +471,14 @@ void setMotorCurrent( uint8_t channel, unsigned short level ) WRITE( LTC2600_CS_PIN, LOW ); // transfer command and address - for( i = 7; i >= 0; i-- ) - { + for( i = 7; i >= 0; i-- ) { WRITE( LTC2600_SDI_PIN, address & (0x01 << i)); WRITE( LTC2600_SCK_PIN, 1 ); WRITE( LTC2600_SCK_PIN, 0 ); } // transfer the data word - for( i = 15; i >= 0; i-- ) - { + for( i = 15; i >= 0; i-- ) { WRITE( LTC2600_SDI_PIN, level & (0x01 << i)); WRITE( LTC2600_SCK_PIN, 1 ); WRITE( LTC2600_SCK_PIN, 0 ); @@ -426,170 +489,453 @@ void setMotorCurrent( uint8_t channel, unsigned short level ) WRITE( LTC2600_CS_PIN, HIGH ); } // setLTC2600 +void setMotorCurrentPercent( uint8_t channel, float level) { + if(level > 100.0f) level = 100.0f; + uint16_t raw_level = static_cast( (long)level * 65535L / 100L ); + setMotorCurrent(channel,raw_level); +} -void motorCurrentControlInit() //Initialize LTC2600 Motor Current -{ - const unsigned int ltc_current[] = MOTOR_CURRENT; +void motorCurrentControlInit() { //Initialize LTC2600 Motor Current uint8_t i; - for(i=0; i -1 -void microstepMS(uint8_t driver, int8_t ms1, int8_t ms2) -{ - if(ms1 > -1) switch(driver) - { - case 0: - WRITE( X_MS1_PIN,ms1); - break; - case 1: - WRITE( Y_MS1_PIN,ms1); - break; - case 2: - WRITE( Z_MS1_PIN,ms1); - break; - case 3: - WRITE(E0_MS1_PIN,ms1); - break; - case 4: - WRITE(E1_MS1_PIN,ms1); - break; - } - if(ms2 > -1) switch(driver) - { - case 0: - WRITE( X_MS2_PIN,ms2); - break; - case 1: - WRITE( Y_MS2_PIN,ms2); - break; - case 2: - WRITE( Z_MS2_PIN,ms2); - break; - case 3: - WRITE(E0_MS2_PIN,ms2); - break; - case 4: - WRITE(E1_MS2_PIN,ms2); - break; - } +#if STEPPER_CURRENT_CONTROL == CURRENT_CONTROL_ALLIGATOR +void setMotorCurrent(uint8_t channel, unsigned short value) { + if(channel >= 7) // max channel (X,Y,Z,E0,E1,E2,E3) + return; + if(value > 255) + value=255; + + uint8_t externalDac_buf[2] = {0x10, 0x00}; + + if(channel > 3) + externalDac_buf[0] |= ( 7 - channel << 6); + else + externalDac_buf[0] |= ( 3 - channel << 6); + + externalDac_buf[0] |= (value >> 4); + externalDac_buf[1] |= (value << 4); + + // All SPI chip-select HIGH + WRITE(DAC0_SYNC, HIGH); + WRITE(DAC1_SYNC, HIGH); + WRITE(SPI_EEPROM1_CS, HIGH); + WRITE(SPI_EEPROM2_CS, HIGH); + WRITE(SPI_FLASH_CS, HIGH); + WRITE(SDSS, HIGH); + + if(channel > 3) { // DAC Piggy E1,E2,E3 + WRITE(DAC1_SYNC,LOW); + HAL::delayMicroseconds(2); + WRITE(DAC1_SYNC,HIGH); + HAL::delayMicroseconds(2); + WRITE(DAC1_SYNC,LOW); + } else { // DAC onboard X,Y,Z,E0 + WRITE(DAC0_SYNC,LOW); + HAL::delayMicroseconds(2); + WRITE(DAC0_SYNC,HIGH); + HAL::delayMicroseconds(2); + WRITE(DAC0_SYNC,LOW); + } + + HAL::delayMicroseconds(2); + HAL::spiSend(SPI_CHAN_DAC, externalDac_buf, 2); } -void microstepMode(uint8_t driver, uint8_t stepping_mode) -{ - switch(stepping_mode) - { - case 1: - microstepMS(driver,MICROSTEP1); - break; - case 2: - microstepMS(driver,MICROSTEP2); - break; - case 4: - microstepMS(driver,MICROSTEP4); - break; - case 8: - microstepMS(driver,MICROSTEP8); - break; - case 16: - microstepMS(driver,MICROSTEP16); - break; +void setMotorCurrentPercent( uint8_t channel, float level) { + uint16_t raw_level = ( level * 255 / 100 ); + setMotorCurrent(channel,raw_level); +} + +void motorCurrentControlInit() { //Initialize Motor Current + uint8_t externalDac_buf[2] = {0x20, 0x00};//all off + + // All SPI chip-select HIGH + WRITE(DAC0_SYNC, HIGH); + WRITE(DAC1_SYNC, HIGH); + WRITE(SPI_EEPROM1_CS, HIGH); + WRITE(SPI_EEPROM2_CS, HIGH); + WRITE(SPI_FLASH_CS, HIGH); + WRITE(SDSS, HIGH); + + // init onboard DAC + WRITE(DAC0_SYNC, LOW); + HAL::delayMicroseconds(2); + WRITE(DAC0_SYNC, HIGH); + HAL::delayMicroseconds(2); + WRITE(DAC0_SYNC, LOW); + + HAL::spiSend(SPI_CHAN_DAC,externalDac_buf, 2); + WRITE(DAC0_SYNC, HIGH); + +#if NUM_EXTRUDER > 1 + // init Piggy DAC + WRITE(DAC1_SYNC, LOW); + HAL::delayMicroseconds(2); + WRITE(DAC1_SYNC, HIGH); + HAL::delayMicroseconds(2); + WRITE(DAC1_SYNC, LOW); + + HAL::spiSend(SPI_CHAN_DAC,externalDac_buf, 2); + WRITE(DAC1_SYNC, HIGH); +#endif + +#ifdef MOTOR_CURRENT_PERCENT + const float digipot_motor_current[] = MOTOR_CURRENT_PERCENT; + for(int i = 0; i < NUM_EXTRUDER+3; i++) + setMotorCurrentPercent(i,digipot_motor_current[i]); +#else + const uint8_t digipot_motor_current[] = MOTOR_CURRENT; + for(uint8_t i = 0; i < NUM_EXTRUDER+3; i++) + setMotorCurrent(i,digipot_motor_current[i]); +#endif +} +#endif + + +#if STEPPER_CURRENT_CONTROL == CURRENT_CONTROL_MCP4728 +uint8_t _intVref[] = {MCP4728_VREF, MCP4728_VREF, MCP4728_VREF, MCP4728_VREF}; +uint8_t _gain[] = {MCP4728_GAIN, MCP4728_GAIN, MCP4728_GAIN, MCP4728_GAIN}; +uint8_t _powerDown[] = {0,0,0,0}; +int16_t dac_motor_current[] = {0,0,0,0}; + +uint8_t _intVrefEp[] = {MCP4728_VREF, MCP4728_VREF, MCP4728_VREF, MCP4728_VREF}; +uint8_t _gainEp[] = {MCP4728_GAIN, MCP4728_GAIN, MCP4728_GAIN, MCP4728_GAIN}; +uint8_t _powerDownEp[] = {0,0,0,0}; +int16_t _valuesEp[] = {0,0,0,0}; + +uint8_t dac_stepper_channel[] = MCP4728_STEPPER_ORDER; + +int dacSimpleCommand(uint8_t simple_command) { + HAL::i2cStartWait(MCP4728_GENERALCALL_ADDRESS + I2C_WRITE); + HAL::i2cWrite(simple_command); + HAL::i2cStop(); +} + +void dacReadStatus() { + HAL::delayMilliseconds(500); + HAL::i2cStartWait(MCP4728_I2C_ADDRESS | I2C_READ); + + for (int i = 0; i < 8; i++) { // 2 sets of 4 Channels (1 EEPROM, 1 Runtime) + uint8_t deviceID = HAL::i2cReadAck(); + uint8_t hiByte = HAL::i2cReadAck(); + uint8_t loByte = ((i < 7) ? HAL::i2cReadAck() : HAL::i2cReadNak()); + + uint8_t isEEPROM = (deviceID & 0B00001000) >> 3; + uint8_t channel = (deviceID & 0B00110000) >> 4; + if (isEEPROM == 1) { + _intVrefEp[channel] = (hiByte & 0B10000000) >> 7; + _gainEp[channel] = (hiByte & 0B00010000) >> 4; + _powerDownEp[channel] = (hiByte & 0B01100000) >> 5; + _valuesEp[channel] = word((hiByte & 0B00001111), loByte); + } else { + _intVref[channel] = (hiByte & 0B10000000) >> 7; + _gain[channel] = (hiByte & 0B00010000) >> 4; + _powerDown[channel] = (hiByte & 0B01100000) >> 5; + dac_motor_current[channel] = word((hiByte & 0B00001111), loByte); + } + } + + HAL::i2cStop(); +} + +void dacAnalogUpdate(bool saveEEPROM = false) { + uint8_t dac_write_cmd = MCP4728_CMD_SEQ_WRITE; + + HAL::i2cStartWait(MCP4728_I2C_ADDRESS + I2C_WRITE); + if (saveEEPROM) HAL::i2cWrite(dac_write_cmd); + + for (int i = 0; i < MCP4728_NUM_CHANNELS; i++) { + uint16_t level = dac_motor_current[i]; + + uint8_t highbyte = ( _intVref[i] << 7 | _gain[i] << 4 | (uint8_t)((level) >> 8) ); + uint8_t lowbyte = ( (uint8_t) ((level) & 0xff) ); + dac_write_cmd = MCP4728_CMD_MULTI_WRITE | (i << 1); + + if (!saveEEPROM) HAL::i2cWrite(dac_write_cmd); + HAL::i2cWrite(highbyte); + HAL::i2cWrite(lowbyte); + } + + HAL::i2cStop(); + + // Instruct the MCP4728 to reflect our updated value(s) on its DAC Outputs + dacSimpleCommand((uint8_t)MCP4728_CMD_GC_UPDATE); // MCP4728 General Command Software Update (Update all DAC Outputs to reflect settings) + + // if (saveEEPROM) dacReadStatus(); // Not necessary, just a read-back sanity check. +} + +void dacCommitEeprom() { + dacAnalogUpdate(true); + dacReadStatus(); // Refresh EEPROM Values with values actually stored in EEPROM. . +} + +void dacPrintSet(int dacChannelSettings[], const char* dacChannelPrefixes[]) { + for (int i = 0; i < MCP4728_NUM_CHANNELS; i++) { + uint8_t dac_channel = dac_stepper_channel[i]; // DAC Channel is a mapped lookup. + Com::printF(dacChannelPrefixes[i], ((float)dacChannelSettings[dac_channel] * 100 / MCP4728_VOUT_MAX)); + Com::printF(Com::tSpaceRaw); + Com::printFLN(Com::tColon,dacChannelSettings[dac_channel]); } } -void microstepReadings() -{ - Com::printFLN(Com::tMS1MS2Pins); - Com::printF(Com::tXColon,READ(X_MS1_PIN)); - Com::printFLN(Com::tComma,READ(X_MS2_PIN)); - Com::printF(Com::tYColon,READ(Y_MS1_PIN)); - Com::printFLN(Com::tComma,READ(Y_MS2_PIN)); - Com::printF(Com::tZColon,READ(Z_MS1_PIN)); - Com::printFLN(Com::tComma,READ(Z_MS2_PIN)); - Com::printF(Com::tE0Colon,READ(E0_MS1_PIN)); - Com::printFLN(Com::tComma,READ(E0_MS2_PIN)); - Com::printF(Com::tE1Colon,READ(E1_MS1_PIN)); - Com::printFLN(Com::tComma,READ(E1_MS2_PIN)); + +void dacPrintValues() { + const char* dacChannelPrefixes[] = {Com::tSpaceXColon, Com::tSpaceYColon, Com::tSpaceZColon, Com::tSpaceEColon}; + + Com::printFLN(Com::tMCPEpromSettings); + dacPrintSet(_valuesEp, dacChannelPrefixes); // Once for the EEPROM set + + Com::printFLN(Com::tMCPCurrentSettings); + dacPrintSet(dac_motor_current, dacChannelPrefixes); // And another for the RUNTIME set +} + +void setMotorCurrent( uint8_t xyz_channel, uint16_t level ) { + if (xyz_channel >= MCP4728_NUM_CHANNELS) return; + uint8_t stepper_channel = dac_stepper_channel[xyz_channel]; + dac_motor_current[stepper_channel] = level < MCP4728_VOUT_MAX ? level : MCP4728_VOUT_MAX; + dacAnalogUpdate(); +} + +void setMotorCurrentPercent( uint8_t channel, float level) { + uint16_t raw_level = ( level * MCP4728_VOUT_MAX / 100 ); + setMotorCurrent(channel,raw_level); +} + +void motorCurrentControlInit() { //Initialize MCP4728 Motor Current + HAL::i2cInit(400000); // Initialize the i2c bus. + dacSimpleCommand((uint8_t)MCP4728_CMD_GC_RESET); // MCP4728 General Command Reset + dacReadStatus(); // Load Values from EEPROM. + + for(int i = 0; i < MCP4728_NUM_CHANNELS; i++) { + setMotorCurrent(dac_stepper_channel[i], _valuesEp[i] ); // This is not strictly necessary, but serves as a good sanity check to ensure we're all on the same page. + } } #endif -void microstepInit() -{ +#if defined(X_MS1_PIN) && X_MS1_PIN > -1 +void microstepMS(uint8_t driver, int8_t ms1, int8_t ms2) { + if(ms1 > -1) switch(driver) { + case 0: +#if X_MS1_PIN > -1 + WRITE( X_MS1_PIN,ms1); +#endif + break; + case 1: +#if Y_MS1_PIN > -1 + WRITE( Y_MS1_PIN,ms1); +#endif + break; + case 2: +#if Z_MS1_PIN > -1 + WRITE( Z_MS1_PIN,ms1); +#endif + break; + case 3: +#if E0_MS1_PIN > -1 + WRITE(E0_MS1_PIN,ms1); +#endif + break; + case 4: +#if E1_MS1_PIN > -1 + WRITE(E1_MS1_PIN,ms1); +#endif + break; + } + if(ms2 > -1) switch(driver) { + case 0: +#if X_MS2_PIN > -1 + WRITE( X_MS2_PIN,ms2); +#endif + break; + case 1: +#if Y_MS2_PIN > -1 + WRITE( Y_MS2_PIN,ms2); +#endif + break; + case 2: +#if Z_MS2_PIN > -1 + WRITE( Z_MS2_PIN,ms2); +#endif + break; + case 3: +#if E0_MS2_PIN > -1 + WRITE(E0_MS2_PIN,ms2); +#endif + break; + case 4: +#if E1_MS2_PIN > -1 + WRITE(E1_MS2_PIN,ms2); +#endif + break; + } +} + +void microstepMode(uint8_t driver, uint8_t stepping_mode) { + switch(stepping_mode) { + case 1: + microstepMS(driver,MICROSTEP1); + break; + case 2: + microstepMS(driver,MICROSTEP2); + break; + case 4: + microstepMS(driver,MICROSTEP4); + break; + case 8: + microstepMS(driver,MICROSTEP8); + break; + case 16: + microstepMS(driver,MICROSTEP16); + break; + case 32: + microstepMS(driver,MICROSTEP32); + break; + } +} + +void microstepReadings() { + Com::printFLN(Com::tMS1MS2Pins); +#if X_MS1_PIN > -1 && X_MS2_PIN > -1 + Com::printF(Com::tXColon,READ(X_MS1_PIN)); + Com::printFLN(Com::tComma,READ(X_MS2_PIN)); +#elif X_MS1_PIN > -1 + Com::printFLN(Com::tXColon,READ(X_MS1_PIN)); +#endif +#if Y_MS1_PIN > -1 && Y_MS2_PIN > -1 + Com::printF(Com::tYColon,READ(Y_MS1_PIN)); + Com::printFLN(Com::tComma,READ(Y_MS2_PIN)); +#elif Y_MS1_PIN > -1 + Com::printFLN(Com::tYColon,READ(Y_MS1_PIN)); +#endif +#if Z_MS1_PIN > -1 && Z_MS2_PIN > -1 + Com::printF(Com::tZColon,READ(Z_MS1_PIN)); + Com::printFLN(Com::tComma,READ(Z_MS2_PIN)); +#elif Z_MS1_PIN > -1 + Com::printFLN(Com::tZColon,READ(Z_MS1_PIN)); +#endif +#if E0_MS1_PIN > -1 && E0_MS2_PIN > -1 + Com::printF(Com::tE0Colon,READ(E0_MS1_PIN)); + Com::printFLN(Com::tComma,READ(E0_MS2_PIN)); +#elif E0_MS1_PIN > -1 + Com::printFLN(Com::tE0Colon,READ(E0_MS1_PIN)); +#endif +#if E1_MS1_PIN > -1 && E1_MS2_PIN > -1 + Com::printF(Com::tE1Colon,READ(E1_MS1_PIN)); + Com::printFLN(Com::tComma,READ(E1_MS2_PIN)); +#elif E1_MS1_PIN > -1 + Com::printFLN(Com::tE1Colon,READ(E1_MS1_PIN)); +#endif +} +#endif + +void microstepInit() { #if defined(X_MS1_PIN) && X_MS1_PIN > -1 const uint8_t microstep_modes[] = MICROSTEP_MODES; +#if X_MS1_PIN > -1 + SET_OUTPUT(X_MS1_PIN); +#endif +#if Y_MS1_PIN > -1 + SET_OUTPUT(Y_MS1_PIN); +#endif +#if Z_MS1_PIN > -1 + SET_OUTPUT(Z_MS1_PIN); +#endif +#if E0_MS1_PIN > -1 + SET_OUTPUT(E0_MS1_PIN); +#endif +#if E1_MS1_PIN > -1 + SET_OUTPUT(E1_MS1_PIN); +#endif +#if X_MS2_PIN > -1 SET_OUTPUT(X_MS2_PIN); +#endif +#if Y_MS2_PIN > -1 SET_OUTPUT(Y_MS2_PIN); +#endif +#if Z_MS2_PIN > -1 SET_OUTPUT(Z_MS2_PIN); +#endif +#if E0_MS2_PIN > -1 SET_OUTPUT(E0_MS2_PIN); +#endif +#if E1_MS2_PIN > -1 SET_OUTPUT(E1_MS2_PIN); - for(int i=0; i<=4; i++) microstepMode(i,microstep_modes[i]); +#endif + for(int i = 0; i <= 4; i++) microstepMode(i, microstep_modes[i]); #endif } /** - \brief Execute the Arc command stored in com. +\brief Execute the Arc command stored in com. */ #if ARC_SUPPORT -void Commands::processArc(GCode *com) -{ +void Commands::processArc(GCode *com) { float position[Z_AXIS_ARRAY]; Printer::realPosition(position[X_AXIS],position[Y_AXIS],position[Z_AXIS]); if(!Printer::setDestinationStepsFromGCode(com)) return; // For X Y Z E F float offset[2] = {Printer::convertToMM(com->hasI() ? com->I : 0),Printer::convertToMM(com->hasJ() ? com->J : 0)}; float target[E_AXIS_ARRAY] = {Printer::realXPosition(),Printer::realYPosition(),Printer::realZPosition(),Printer::destinationSteps[E_AXIS]*Printer::invAxisStepsPerMM[E_AXIS]}; float r; - if (com->hasR()) - { + if (com->hasR()) { /* - We need to calculate the center of the circle that has the designated radius and passes - through both the current position and the target position. This method calculates the following - set of equations where [x,y] is the vector from current to target position, d == magnitude of - that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to - the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the - length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point - [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc. + We need to calculate the center of the circle that has the designated radius and passes + through both the current position and the target position. This method calculates the following + set of equations where [x,y] is the vector from current to target position, d == magnitude of + that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to + the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the + length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point + [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc. - d^2 == x^2 + y^2 - h^2 == r^2 - (d/2)^2 - i == x/2 - y/d*h - j == y/2 + x/d*h + d^2 == x^2 + y^2 + h^2 == r^2 - (d/2)^2 + i == x/2 - y/d*h + j == y/2 + x/d*h - O <- [i,j] - - | - r - | - - | - - | h - - | - [0,0] -> C -----------------+--------------- T <- [x,y] - | <------ d/2 ---->| + O <- [i,j] + - | + r - | + - | + - | h + - | + [0,0] -> C -----------------+--------------- T <- [x,y] + | <------ d/2 ---->| - C - Current position - T - Target position - O - center of circle that pass through both C and T - d - distance from C to T - r - designated radius - h - distance from center of CT to O + C - Current position + T - Target position + O - center of circle that pass through both C and T + d - distance from C to T + r - designated radius + h - distance from center of CT to O - Expanding the equations: + Expanding the equations: - d -> sqrt(x^2 + y^2) - h -> sqrt(4 * r^2 - x^2 - y^2)/2 - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + d -> sqrt(x^2 + y^2) + h -> sqrt(4 * r^2 - x^2 - y^2)/2 + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 - Which can be written: + Which can be written: - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 - Which we for size and speed reasons optimize to: + Which we for size and speed reasons optimize to: - h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) - i = (x - (y * h_x2_div_d))/2 - j = (y + (x * h_x2_div_d))/2 + h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) + i = (x - (y * h_x2_div_d))/2 + j = (y + (x * h_x2_div_d))/2 */ r = Printer::convertToMM(com->R); @@ -600,50 +946,45 @@ void Commands::processArc(GCode *com) double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d) // If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any // real CNC, and thus - for practical reasons - we will terminate promptly: - if(isnan(h_x2_div_d)) - { + if(isnan(h_x2_div_d)) { Com::printErrorFLN(Com::tInvalidArc); return; } // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) - if (com->G==3) - { + if (com->G == 3) { h_x2_div_d = -h_x2_div_d; } /* The counter clockwise circle lies to the left of the target direction. When offset is positive, - the left hand circle will be generated - when it is negative the right hand circle is generated. + the left hand circle will be generated - when it is negative the right hand circle is generated. - T <-- Target position + T <-- Target position - ^ - Clockwise circles with this center | Clockwise circles with this center will have - will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing! - \ | / + ^ + Clockwise circles with this center | Clockwise circles with this center will have + will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing! + \ | / center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative - | - | + | + | - C <-- Current position */ + C <-- Current position */ // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!), // even though it is advised against ever generating such circles in a single line of g-code. By // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of // travel and thus we get the unadvisably long arcs as prescribed. - if (r < 0) - { + if (r < 0) { h_x2_div_d = -h_x2_div_d; r = -r; // Finished with r. Set to positive for mc_arc } // Complete the operation by calculating the actual center of the arc - offset[0] = 0.5*(x-(y*h_x2_div_d)); - offset[1] = 0.5*(y+(x*h_x2_div_d)); + offset[0] = 0.5 * (x - (y * h_x2_div_d)); + offset[1] = 0.5 * (y + (x * h_x2_div_d)); - } - else // Offset mode specific computations - { + } else { // Offset mode specific computations r = hypot(offset[0], offset[1]); // Compute arc radius for arc } // Set clockwise/counter-clockwise sign for arc computations @@ -652,715 +993,916 @@ void Commands::processArc(GCode *com) PrintLine::arc(position, target, offset, r, isclockwise); } #endif - +extern bool runBedLeveling(GCode *com); /** - \brief Execute the G command stored in com. +\brief Execute the G command stored in com. */ -void Commands::processGCode(GCode *com) -{ +void Commands::processGCode(GCode *com) { uint32_t codenum; //throw away variable - switch(com->G) - { - case 0: // G0 -> G1 - case 1: // G1 - if(com->hasS()) Printer::setNoDestinationCheck(com->S != 0); - if(Printer::setDestinationStepsFromGCode(com)) // For X Y Z E F -#if NONLINEAR_SYSTEM - if (!PrintLine::queueDeltaMove(ALWAYS_CHECK_ENDSTOPS, true, true)) + switch(com->G) { + case 0: // G0 -> G1 + case 1: // G1 +#if defined(SUPPORT_LASER) && SUPPORT_LASER { - Com::printWarningFLN(PSTR("executeGCode / queueDeltaMove returns error")); - } + // disable laser for G0 moves + bool laserOn = LaserDriver::laserOn; + if(com->G == 0 && Printer::mode == PRINTER_MODE_LASER) { + LaserDriver::laserOn = false; + } +#endif // defined + if(com->hasS()) Printer::setNoDestinationCheck(com->S != 0); + if(Printer::setDestinationStepsFromGCode(com)) // For X Y Z E F +#if NONLINEAR_SYSTEM + if (!PrintLine::queueNonlinearMove(ALWAYS_CHECK_ENDSTOPS, true, true)) { + Com::printWarningFLN(PSTR("executeGCode / queueDeltaMove returns error")); + } #else - PrintLine::queueCartesianMove(ALWAYS_CHECK_ENDSTOPS, true); + PrintLine::queueCartesianMove(ALWAYS_CHECK_ENDSTOPS, true); #endif #if UI_HAS_KEYS - // ui can only execute motion commands if we are not waiting inside a move for an - // old move to finish. For normal response times, we always leave one free after - // sending a line. Drawback: 1 buffer line less for limited time. Since input cache - // gets filled while waiting, the lost is neglectible. - PrintLine::waitForXFreeLines(1, true); + // ui can only execute motion commands if we are not waiting inside a move for an + // old move to finish. For normal response times, we always leave one free after + // sending a line. Drawback: 1 buffer line less for limited time. Since input cache + // gets filled while waiting, the lost is neglectable. + PrintLine::waitForXFreeLines(1, true); #endif // UI_HAS_KEYS - break; -#if ARC_SUPPORT - case 2: // CW Arc - case 3: // CCW Arc MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: - processArc(com); - break; -#endif - case 4: // G4 dwell - Commands::waitUntilEndOfAllMoves(); - codenum = 0; - if(com->hasP()) codenum = com->P; // milliseconds to wait - if(com->hasS()) codenum = com->S * 1000; // seconds to wait - codenum += HAL::timeInMilliseconds(); // keep track of when we started waiting - while((uint32_t)(codenum-HAL::timeInMilliseconds()) < 2000000000 ) - { - GCode::readFromSerial(); - Commands::checkForPeriodicalActions(true); - //Davinci Specific, for immediate stop - if (Printer::isMenuModeEx(MENU_MODE_STOP_REQUESTED))break; - } - break; -#if FEATURE_RETRACTION && NUM_EXTRUDER > 0 - case 10: // G10 S<1 = long retract, 0 = short retract = default> retracts filament accoridng to stored setting -#if NUM_EXTRUDER > 1 - Extruder::current->retract(true, com->hasS() && com->S > 0); -#else - Extruder::current->retract(true, false); -#endif - break; - case 11: // G11 S<1 = long retract, 0 = short retract = default> = Undo retraction according to stored setting -#if NUM_EXTRUDER > 1 - Extruder::current->retract(false, com->hasS() && com->S > 0); -#else - Extruder::current->retract(false, false); -#endif - break; -#endif // FEATURE_RETRACTION - case 20: // G20 Units to inches - Printer::unitIsInches = 1; - break; - case 21: // G21 Units to mm - Printer::unitIsInches = 0; - break; - case 28: //G28 Home all Axis one at a time - { - uint8_t homeAllAxis = (com->hasNoXYZ() && !com->hasE()); - if(com->hasE()) - Printer::currentPositionSteps[E_AXIS] = 0; - if(homeAllAxis || !com->hasNoXYZ()) - Printer::homeAxis(homeAllAxis || com->hasX(),homeAllAxis || com->hasY(),homeAllAxis || com->hasZ()); - Printer::updateCurrentPosition(); - } - break; -#if FEATURE_Z_PROBE - case 29: // G29 3 points, build average or distortion compensation - { -#if DISTORTION_CORRECTION - float oldFeedrate = Printer::feedrate; - Printer::measureDistortion(); - Printer::feedrate = oldFeedrate; -#else - //Davinci Specific, Error management - float zMin_save=Printer::zMin ; - if(!Printer::isHomed()) Printer::homeAxis(true,true,true); - //to avoid hit on plates low, down bed a little - if (Printer::currentPosition[Z_AXIS] < Printer::zMin+5) Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - GCode::executeFString(Com::tZProbeStartScript); - bool oldAutolevel = Printer::isAutolevelActive(); - Printer::setAutolevelActive(false); - float sum = 0, last,oldFeedrate = Printer::feedrate; - Printer::moveTo(EEPROM::zProbeX1(),EEPROM::zProbeY1(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); - sum = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); - //Davinci Specific, better error management - if(sum < 0) - { - Printer::zMin = zMin_save; - Printer::setAutolevelActive(false); - if (Printer::realZPosition()<-200)Printer::homeAxis(false,false,true); - //to avoid hit on plates, low down bed a little - Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - break; - } - Printer::moveTo(EEPROM::zProbeX2(),EEPROM::zProbeY2(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); - last = Printer::runZProbe(false,false); - //Davinci Specific, better error management - if(last<0) - { - Printer::zMin = zMin_save; - Printer::setAutolevelActive(false); - if (Printer::realZPosition()<-200)Printer::homeAxis(false,false,true); - //to avoid hit on plates, low down bed a little - Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - break; - } - sum+= last; - Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); - last = Printer::runZProbe(false,true); - //Davinci Specific, better error management - if(last < 0) +#ifdef DEBUG_QUEUE_MOVE { - Printer::zMin = zMin_save; - Printer::setAutolevelActive(false); - if (Printer::realZPosition()<-200)Printer::homeAxis(false,false,true); - //to avoid hit on plates, low down bed a little - Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - break; - } - sum += last; - sum *= 0.33333333333333; - Com::printFLN(Com::tZProbeAverage,sum); - if(com->hasS() && com->S) - { -#if MAX_HARDWARE_ENDSTOP_Z -#if DRIVE_SYSTEM==DELTA - Printer::updateCurrentPosition(); - Printer::zLength += sum - Printer::currentPosition[Z_AXIS]; - Printer::updateDerivedParameter(); - Printer::homeAxis(true,true,true); -#else - Printer::currentPositionSteps[Z_AXIS] = sum * Printer::axisStepsPerMM[Z_AXIS]; - Printer::zLength = Printer::runZMaxProbe() + sum-ENDSTOP_Z_BACK_ON_HOME; -#endif - Com::printInfoFLN(Com::tZProbeZReset); - Com::printFLN(Com::tZProbePrinterHeight,Printer::zLength); -#else - Printer::currentPositionSteps[Z_AXIS] = sum * Printer::axisStepsPerMM[Z_AXIS]; - Com::printFLN(PSTR("Adjusted z origin")); -#endif - } - Printer::feedrate = oldFeedrate; - Printer::setAutolevelActive(oldAutolevel); - if(com->hasS() && com->S == 2) - EEPROM::storeDataIntoEEPROM(); - Printer::updateCurrentPosition(true); - printCurrentPosition(PSTR("G29 ")); - GCode::executeFString(Com::tZProbeEndScript); - Printer::feedrate = oldFeedrate; -#endif // DISTORTION_CORRECTION - } - break; - case 30: // G30 single probe set Z0 - { - uint8_t p = (com->hasP() ? (uint8_t)com->P : 3); - //bool oldAutolevel = Printer::isAutolevelActive(); - //Davinci Specific, better error management - if(!Printer::isHomed()) Printer::homeAxis(true,true,true); - //to avoid hit on plates, low down bed a little - if (Printer::currentPosition[Z_AXIS] < Printer::zMin+5) Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - //Printer::setAutolevelActive(false); - Printer::runZProbe(p & 1,p & 2); - //Printer::setAutolevelActive(oldAutolevel); - Printer::updateCurrentPosition(p & 1); - //printCurrentPosition(PSTR("G30 ")); - //Davinci Specific, better error management - if (Printer::realZPosition()<-200)Printer::homeAxis(false,false,true); - //to avoid hit on plates - Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - } - break; - case 31: // G31 display hall sensor output - Com::printF(Com::tZProbeState); - Com::print(Printer::isZProbeHit() ? 'H' : 'L'); - Com::println(); - break; -#if FEATURE_AUTOLEVEL - case 32: // G32 Auto-Bed leveling - { -#if DISTORTION_CORRECTION - Printer::distortion.disable(true); // if level has changed, distortion is also invalid + InterruptProtectedBlock noInts; + int lc = (int)PrintLine::linesCount; + int lp = (int)PrintLine::linesPos; + int wp = (int)PrintLine::linesWritePos; + int n = (wp - lp); + if(n < 0) n += PRINTLINE_CACHE_SIZE; + noInts.unprotect(); + if(n != lc) + Com::printFLN(PSTR("Buffer corrupted")); + } #endif -#if DRIVE_SYSTEM == DELTA - // It is not possible to go to the edges at the top, also users try - // it often and wonder why the coordinate system is then wrong. - // For that reason we ensure a correct behaviour by code. - Printer::homeAxis(true, true, true); - Printer::moveTo(IGNORE_COORDINATE, IGNORE_COORDINATE, EEPROM::zProbeBedDistance() + EEPROM::zProbeHeight(), IGNORE_COORDINATE, Printer::homingFeedrate[Z_AXIS]); +#if defined(SUPPORT_LASER) && SUPPORT_LASER + LaserDriver::laserOn = laserOn; + } +#endif // defined + break; +#if ARC_SUPPORT + case 2: // CW Arc + case 3: // CCW Arc MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: + processArc(com); + break; #endif - //Davinci Specific, better error management - float zMin_save=Printer::zMin; - if(!Printer::isHomed()) Printer::homeAxis(true,true,true); - //to avoid hit on plates, low down bed a little - if (Printer::currentPosition[Z_AXIS] < Printer::zMin+5) Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - GCode::executeFString(Com::tZProbeStartScript); - //bool iterate = com->hasP() && com->P>0; - Printer::coordinateOffset[X_AXIS] = Printer::coordinateOffset[Y_AXIS] = Printer::coordinateOffset[Z_AXIS] = 0; - Printer::setAutolevelActive(false); // iterate - float h1,h2,h3,hc,oldFeedrate = Printer::feedrate; - Printer::moveTo(EEPROM::zProbeX1(),EEPROM::zProbeY1(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); - h1 = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); - //Davinci Specific, better error management - if(h1 < 0) - { - Printer::zMin = zMin_save; - Printer::setAutolevelActive(true); - if (Printer::realZPosition()<-200)Printer::homeAxis(false,false,true); - //to avoid hit on plates, low down bed a little - Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - break; + case 4: // G4 dwell + Commands::waitUntilEndOfAllMoves(); + codenum = 0; + if(com->hasP()) codenum = com->P; // milliseconds to wait + if(com->hasS()) codenum = com->S * 1000; // seconds to wait + codenum += HAL::timeInMilliseconds(); // keep track of when we started waiting + while((uint32_t)(codenum-HAL::timeInMilliseconds()) < 2000000000 ) { + GCode::readFromSerial(); + Commands::checkForPeriodicalActions(true); + } + break; +#if FEATURE_RETRACTION && NUM_EXTRUDER > 0 + case 10: // G10 S<1 = long retract, 0 = short retract = default> retracts filament according to stored setting +#if NUM_EXTRUDER > 1 + Extruder::current->retract(true, com->hasS() && com->S > 0); +#else + Extruder::current->retract(true, false); +#endif + break; + case 11: // G11 S<1 = long retract, 0 = short retract = default> = Undo retraction according to stored setting +#if NUM_EXTRUDER > 1 + Extruder::current->retract(false, com->hasS() && com->S > 0); +#else + Extruder::current->retract(false, false); +#endif + break; +#endif // FEATURE_RETRACTION + case 20: // G20 Units to inches + Printer::unitIsInches = 1; + break; + case 21: // G21 Units to mm + Printer::unitIsInches = 0; + break; + case 28: { //G28 Home all Axis one at a time + uint8_t homeAllAxis = (com->hasNoXYZ() && !com->hasE()); + if(com->hasE()) + Printer::currentPositionSteps[E_AXIS] = 0; + if(homeAllAxis || !com->hasNoXYZ()) + Printer::homeAxis(homeAllAxis || com->hasX(),homeAllAxis || com->hasY(),homeAllAxis || com->hasZ()); + } + break; +#if FEATURE_Z_PROBE + case 29: { // G29 3 points, build average or distortion compensation +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE && Z_PROBE_REQUIRES_HEATING + float actTemp[NUM_EXTRUDER]; + for(int i = 0; i < NUM_EXTRUDER; i++) + actTemp[i] = extruder[i].tempControl.targetTemperatureC; + Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,RMath::max(EEPROM::zProbeHeight(),static_cast(ZHOME_HEAT_HEIGHT)),IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); + Commands::waitUntilEndOfAllMoves(); +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) { + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,false); } - Printer::moveTo(EEPROM::zProbeX2(),EEPROM::zProbeY2(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); - h2 = Printer::runZProbe(false,false); - //Davinci Specific, better error management - if(h2 < 0) - { - Printer::zMin = zMin_save; - Printer::setAutolevelActive(true); - if (Printer::realZPosition()<-200)Printer::homeAxis(false,false,true); - //to avoid hit on plates, low down bed a little - Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - break; + for(int i = 0; i < NUM_EXTRUDER; i++) { + if(extruder[i].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,true); } - Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); - h3 = Printer::runZProbe(false,true); - //Davinci Specific, better error management - if(h3 < 0) - { - Printer::zMin = zMin_save; - Printer::setAutolevelActive(true); - if (Printer::realZPosition()<-200)Printer::homeAxis(false,false,true); - //to avoid hit on plates, low down bed a little - Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,Printer::zMin+5,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); - break; +#else + if(extruder[Extruder::current->id].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[Extruder::current->id],static_cast(ZPROBE_MIN_TEMPERATURE)),Extruder::current->id,false,true); +#endif +#endif + bool ok = true; + +#if FEATURE_Z_PROBE + //Davinci Specific +#if DAVINCI == 4 + Check_turntable(); +#endif + Printer::zprobe_ok = true; + Printer::startProbing(true); +#endif + bool oldAutolevel = Printer::isAutolevelActive(); + Printer::setAutolevelActive(false); + float sum = 0, last,oldFeedrate = Printer::feedrate; + Printer::moveTo(EEPROM::zProbeX1(), EEPROM::zProbeY1(), IGNORE_COORDINATE, IGNORE_COORDINATE, EEPROM::zProbeXYSpeed()); + sum = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); + if(sum == ILLEGAL_Z_PROBE){ + ok = false; + //Davinci Specific + Printer::Z_probe[0]=-2000; + } + else Printer::Z_probe[0]=sum; + uid.refreshPage(); + if(ok) { + Printer::moveTo(EEPROM::zProbeX2(), EEPROM::zProbeY2(), IGNORE_COORDINATE, IGNORE_COORDINATE, EEPROM::zProbeXYSpeed()); + last = Printer::runZProbe(false,false); + if(last == ILLEGAL_Z_PROBE) { + ok = false; + //Davinci Specific + Printer::Z_probe[1]=-2000; + } + else Printer::Z_probe[1]=last; + uid.refreshPage(); + sum+= last; } - Printer::buildTransformationMatrix(h1,h2,h3); - //-(Rxx*Ryz*y-Rxz*Ryx*y+(Rxz*Ryy-Rxy*Ryz)*x)/(Rxy*Ryx-Rxx*Ryy) - // z = z-deviation from origin due to bed transformation - float z = -((Printer::autolevelTransformation[0] * Printer::autolevelTransformation[5] - - Printer::autolevelTransformation[2] * Printer::autolevelTransformation[3]) * - (float)Printer::currentPositionSteps[Y_AXIS] * Printer::invAxisStepsPerMM[Y_AXIS] + - (Printer::autolevelTransformation[2] * Printer::autolevelTransformation[4] - - Printer::autolevelTransformation[1] * Printer::autolevelTransformation[5]) * - (float)Printer::currentPositionSteps[X_AXIS] * Printer::invAxisStepsPerMM[X_AXIS]) / - (Printer::autolevelTransformation[1] * Printer::autolevelTransformation[3] - Printer::autolevelTransformation[0] * Printer::autolevelTransformation[4]); - Printer::zMin = 0; - if(com->hasS() && com->S < 3 && com->S > 0) - { + if(ok) { + Printer::moveTo(EEPROM::zProbeX3(), EEPROM::zProbeY3(), IGNORE_COORDINATE, IGNORE_COORDINATE, EEPROM::zProbeXYSpeed()); + last = Printer::runZProbe(false,true); + if(last == ILLEGAL_Z_PROBE) { + ok = false; + //Davinci Specific + Printer::Z_probe[2]=-2000; + } + else Printer::Z_probe[2]=last; + uid.refreshPage(); + sum += last; + } + if(ok) { + sum *= 0.33333333333333; + Com::printFLN(Com::tZProbeAverage, sum); + if(com->hasS() && com->S) { #if MAX_HARDWARE_ENDSTOP_Z #if DRIVE_SYSTEM == DELTA - /* Printer::offsetX = 0; - Printer::offsetY = 0; - Printer::moveToReal(0,0,cz,IGNORE_COORDINATE,Printer::homingFeedrate[X_AXIS]); - PrintLine::moveRelativeDistanceInSteps(Printer::offsetX-Printer::currentPositionSteps[X_AXIS],Printer::offsetY-Printer::currentPositionSteps[Y_AXIS],0,0,Printer::homingFeedrate[X_AXIS],true,ALWAYS_CHECK_ENDSTOPS); - Printer::offsetX = 0; - Printer::offsetY = 0;*/ - Printer::zLength += (h3 + z) - Printer::currentPosition[Z_AXIS]; + Printer::updateCurrentPosition(); + Printer::zLength += sum - Printer::currentPosition[Z_AXIS]; + Printer::updateDerivedParameter(); + Printer::homeAxis(true,true,true); #else - int32_t zBottom = Printer::currentPositionSteps[Z_AXIS] = (h3 + z) * Printer::axisStepsPerMM[Z_AXIS]; - Printer::zLength = Printer::runZMaxProbe() + zBottom * Printer::invAxisStepsPerMM[Z_AXIS] - ENDSTOP_Z_BACK_ON_HOME; -#endif - Com::printFLN(Com::tZProbePrinterHeight,Printer::zLength); -#else // max hardware endstop -#if DRIVE_SYSTEM != DELTA - Printer::currentPositionSteps[Z_AXIS] = (h3 + z) * Printer::axisStepsPerMM[Z_AXIS]; -#endif -#endif - Printer::setAutolevelActive(true); - if(com->S == 2) - EEPROM::storeDataIntoEEPROM(); - } - else - { -#if DRIVE_SYSTEM != DELTA - Printer::currentPositionSteps[Z_AXIS] = (h3 + z) * Printer::axisStepsPerMM[Z_AXIS]; -#endif - if(com->hasS() && com->S == 3) - EEPROM::storeDataIntoEEPROM(); - } - Printer::setAutolevelActive(true); - Printer::updateDerivedParameter(); - Printer::updateCurrentPosition(true); - printCurrentPosition(PSTR("G32 ")); -#if DRIVE_SYSTEM == DELTA - Printer::homeAxis(true, true, true); -#endif - Printer::feedrate = oldFeedrate; - } - break; -#endif -#endif - case 90: // G90 - Printer::relativeCoordinateMode = false; - if(com->internalCommand) - Com::printInfoFLN(PSTR("Absolute positioning")); - break; - case 91: // G91 - Printer::relativeCoordinateMode = true; - if(com->internalCommand) - Com::printInfoFLN(PSTR("Relative positioning")); - break; - case 92: // G92 - { - float xOff = Printer::coordinateOffset[X_AXIS]; - float yOff = Printer::coordinateOffset[Y_AXIS]; - float zOff = Printer::coordinateOffset[Z_AXIS]; - if(com->hasX()) xOff = Printer::convertToMM(com->X) - Printer::currentPosition[X_AXIS]; - if(com->hasY()) yOff = Printer::convertToMM(com->Y) - Printer::currentPosition[Y_AXIS]; - if(com->hasZ()) zOff = Printer::convertToMM(com->Z) - Printer::currentPosition[Z_AXIS]; - Printer::setOrigin(xOff, yOff, zOff); - if(com->hasE()) - { - Printer::currentPositionSteps[E_AXIS] = Printer::convertToMM(com->E) * Printer::axisStepsPerMM[E_AXIS]; - } - } - break; -#if DRIVE_SYSTEM == DELTA - case 100: // G100 Calibrate floor or rod radius - { - // Using manual control, adjust hot end to contact floor. - // G100 No action. Avoid accidental floor reset. - // G100 [X] [Y] [Z] set floor for argument passed in. Number ignored and may be absent. - // G100 R with X Y or Z flag error, sets only floor or radius, not both. - // G100 R[n] Add n to radius. Adjust to be above floor if necessary - // G100 R[0] set radius based on current z measurement. Moves to (0,0,0) - float currentZmm = Printer::currentPosition[Z_AXIS]; - if (currentZmm/Printer::zLength > 0.1) - { - Com::printErrorFLN(PSTR("Calibration code is limited to bottom 10% of Z height")); - break; - } - if (com->hasR()) - { - if (com->hasX() || com->hasY() || com->hasZ()) - Com::printErrorFLN(PSTR("Cannot set radius and floor at same time.")); - else if (com->R != 0) - { - //add r to radius - if (abs(com->R) <= 10) EEPROM::incrementRodRadius(com->R); - else Com::printErrorFLN(PSTR("Calibration movement is limited to 10mm.")); - } - else - { - // auto set radius. Head must be at 0,0 and touching - // Z offset will be corrected for. - if (Printer::currentPosition[X_AXIS] == 0 - && Printer::currentPosition[Y_AXIS] == 0) - { - if(Printer::isLargeMachine()) - { - // calculate radius assuming we are at surface - // If Z is greater than 0 it will get calculated out for correct radius - // Use either A or B tower as they acnhor x cartesian axis and always have - // Radius distance to center in simplest set up. - float h = Printer::deltaDiagonalStepsSquaredB.f; - unsigned long bSteps = Printer::currentDeltaPositionSteps[B_TOWER]; - // The correct Rod Radius would put us here at z==0 and B height is - // square root (rod length squared minus rod radius squared) - // Reverse that to get calculated Rod Radius given B height - h -= RMath::sqr((float)bSteps); - h = sqrt(h); - EEPROM::setRodRadius(h*Printer::invAxisStepsPerMM[Z_AXIS]); - } - else - { - // calculate radius assuming we are at surface - // If Z is greater than 0 it will get calculated out for correct radius - // Use either A or B tower as they acnhor x cartesian axis and always have - // Radius distance to center in simplest set up. - unsigned long h = Printer::deltaDiagonalStepsSquaredB.l; - unsigned long bSteps = Printer::currentDeltaPositionSteps[B_TOWER]; - // The correct Rod Radius would put us here at z==0 and B height is - // square root (rod length squared minus rod radius squared) - // Reverse that to get calculated Rod Radius given B height - h -= RMath::sqr(bSteps); - h = SQRT(h); - EEPROM::setRodRadius(h*Printer::invAxisStepsPerMM[Z_AXIS]); + Printer::currentPositionSteps[Z_AXIS] = sum * Printer::axisStepsPerMM[Z_AXIS]; + float zup = Printer::runZMaxProbe(); + if(zup == ILLEGAL_Z_PROBE) { + ok = false; + } else + Printer::zLength = zup + sum - ENDSTOP_Z_BACK_ON_HOME; +#endif // DELTA + Com::printInfoFLN(Com::tZProbeZReset); + Com::printFLN(Com::tZProbePrinterHeight,Printer::zLength); +#else + Printer::currentPositionSteps[Z_AXIS] = sum * Printer::axisStepsPerMM[Z_AXIS]; + Com::printFLN(PSTR("Adjusted z origin")); +#endif // max z endstop } + Printer::feedrate = oldFeedrate; + Printer::setAutolevelActive(oldAutolevel); + if(ok && com->hasS() && com->S == 2) + EEPROM::storeDataIntoEEPROM(); } - else - Com::printErrorFLN(PSTR("First move to touch at x,y=0,0 to auto-set radius.")); + Printer::updateCurrentPosition(true); + printCurrentPosition(PSTR("G29 ")); + Printer::finishProbing(); + Printer::feedrate = oldFeedrate; + if(!ok) { + //Davinci Specific + if (!(com->hasI()))GCode::fatalError(PSTR("G29 leveling failed!")); + else PrintLine::moveRelativeDistanceInSteps(0,0,10*Printer::axisStepsPerMM[Z_AXIS],0,Printer::homingFeedrate[0],true,false); + Printer::zprobe_ok = false; + Printer::homeAxis(true, true, true); + break; + } +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE && Z_PROBE_REQUIRES_HEATING +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) { + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,false); + } + for(int i = 0; i < NUM_EXTRUDER; i++) { + if(extruder[i].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,true); + } +#else + if(extruder[Extruder::current->id].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[Extruder::current->id],static_cast(ZPROBE_MIN_TEMPERATURE)),Extruder::current->id,false,true); +#endif +#endif } - } - else - { - bool tooBig = false; - if (com->hasX()) - { - if (abs(com->X) <= 10) - EEPROM::setTowerXFloor(com->X + currentZmm + Printer::xMin); - else tooBig = true; + break; + case 30: + { // G30 single probe set Z0 +#if DAVINCI == 4 + Check_turntable(); +#endif + uint8_t p = (com->hasP() ? (uint8_t)com->P : 3); + if(Printer::runZProbe(p & 1,p & 2) == ILLEGAL_Z_PROBE) { + GCode::fatalError(PSTR("G30 probing failed!")); + //Davinci Specific + Printer::zprobe_ok = false; + Printer::homeAxis(true, true, true); + break; + } + Printer::updateCurrentPosition(p & 1); } - if (com->hasY()) - { - if (abs(com->Y) <= 10) - EEPROM::setTowerYFloor(com->Y + currentZmm + Printer::yMin); - else tooBig = true; + break; + case 31: // G31 display hall sensor output + Endstops::update(); + Endstops::update(); + Com::printF(Com::tZProbeState); + Com::printF(Endstops::zProbe() ? Com::tHSpace : Com::tLSpace); + Com::println(); + break; +#if FEATURE_AUTOLEVEL + case 32: // G32 Auto-Bed leveling + { +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE && Z_PROBE_REQUIRES_HEATING + float actTemp[NUM_EXTRUDER]; + for(int i = 0; i < NUM_EXTRUDER; i++) + actTemp[i] = extruder[i].tempControl.targetTemperatureC; + Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,RMath::max(EEPROM::zProbeHeight(),static_cast(ZHOME_HEAT_HEIGHT)),IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); + Commands::waitUntilEndOfAllMoves(); +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) { + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,false); } - if (com->hasZ()) - { - if (abs(com->Z) <= 10) - EEPROM::setTowerZFloor(com->Z + currentZmm + Printer::zMin); - else tooBig = true; + for(int i = 0; i < NUM_EXTRUDER; i++) { + if(extruder[i].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,true); } - if (tooBig) - Com::printErrorFLN(PSTR("Calibration movement is limited to 10mm.")); - } - // after adjusting zero, physical position is out of sync with memory position - // this could cause jerky movement or push head into print surface. - // moving gets back into safe zero'ed position with respect to newle set floor or Radius. - Printer::moveTo(IGNORE_COORDINATE,IGNORE_COORDINATE,12.0,IGNORE_COORDINATE,IGNORE_COORDINATE); - break; - } - case 131: // G131 Remove offset - { - float cx,cy,cz; - Printer::realPosition(cx,cy,cz); - float oldfeedrate = Printer::feedrate; - Printer::offsetX = 0; - Printer::offsetY = 0; - Printer::moveToReal(cx,cy,cz,IGNORE_COORDINATE,Printer::homingFeedrate[X_AXIS]); - Printer::feedrate = oldfeedrate; - Printer::updateCurrentPosition(); - } - break; - case 132: // G132 Calibrate endstop offsets - { -// This has the probably unintended side effect of turning off leveling. - Printer::setAutolevelActive(false); // don't let transformations change result! - Printer::coordinateOffset[X_AXIS] = 0; - Printer::coordinateOffset[Y_AXIS] = 0; - Printer::coordinateOffset[Z_AXIS] = 0; -// I think this is coded incorrectly, as it depends on the biginning position of the -// of the hot end, and so should first move to x,y,z= 0,0,0, but as that may not -// be possible if the printer is not in the homes/zeroed state, the printer -// cannot safely move to 0 z coordinate without crashong into the print surface. -// so other than commenting, I'm not meddling. -// but you will always get different counts from different positions. - Printer::deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS]); - int32_t m = RMath::max(Printer::stepsRemainingAtXHit,RMath::max(Printer::stepsRemainingAtYHit,Printer::stepsRemainingAtZHit)); - int32_t offx = m-Printer::stepsRemainingAtXHit; - int32_t offy = m-Printer::stepsRemainingAtYHit; - int32_t offz = m-Printer::stepsRemainingAtZHit; - Com::printFLN(Com::tTower1,offx); - Com::printFLN(Com::tTower2,offy); - Com::printFLN(Com::tTower3,offz); +#else + if(extruder[Extruder::current->id].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[Extruder::current->id],static_cast(ZPROBE_MIN_TEMPERATURE)),Extruder::current->id,false,true); +#endif +#endif +#if DAVINCI == 4 + Check_turntable(); +#endif + if(!runBedLeveling(com)) { + //Davinci Specific + if (!(com->hasI()))GCode::fatalError(PSTR("G32 leveling failed!")); + else PrintLine::moveRelativeDistanceInSteps(0,0,10*Printer::axisStepsPerMM[Z_AXIS],0,Printer::homingFeedrate[0],true,false); + Printer::zprobe_ok = false; + Printer::homeAxis(true, true, true); + break; + } +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE && Z_PROBE_REQUIRES_HEATING +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) { + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,false); + } + for(int i = 0; i < NUM_EXTRUDER; i++) { + if(extruder[i].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,true); + } +#else + if(extruder[Extruder::current->id].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[Extruder::current->id],static_cast(ZPROBE_MIN_TEMPERATURE)),Extruder::current->id,false,true); +#endif +#endif + } + break; +#endif +#if DISTORTION_CORRECTION + case 33: { + if(com->hasL()) { // G33 L0 - List distortion matrix + Printer::distortion.showMatrix(); + } else if(com->hasR()) { // G33 R0 - Reset distortion matrix + Printer::distortion.resetCorrection(); + } else if(com->hasX() || com->hasY() || com->hasZ()) { // G33 X Y Z - Set correction for nearest point + if(com->hasX() && com->hasY() && com->hasZ()) { + Printer::distortion.set(com->X, com->Y, com->Z); + } else { + Com::printErrorFLN(PSTR("You need to define X, Y and Z to set a point!")); + } + } else { // G33 +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE && Z_PROBE_REQUIRES_HEATING + float actTemp[NUM_EXTRUDER]; + for(int i = 0; i < NUM_EXTRUDER; i++) + actTemp[i] = extruder[i].tempControl.targetTemperatureC; + Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,RMath::max(EEPROM::zProbeHeight(),static_cast(ZHOME_HEAT_HEIGHT)),IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); + Commands::waitUntilEndOfAllMoves(); +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) { + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,false); + } + for(int i = 0; i < NUM_EXTRUDER; i++) { + if(extruder[i].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,true); + } +#else + if(extruder[Extruder::current->id].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[Extruder::current->id],static_cast(ZPROBE_MIN_TEMPERATURE)),Extruder::current->id,false,true); +#endif +#endif + float oldFeedrate = Printer::feedrate; + if(!Printer::measureDistortion()) { + GCode::fatalError(PSTR("G33 failed!")); + break; + } + Printer::feedrate = oldFeedrate; +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE && Z_PROBE_REQUIRES_HEATING +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) + Extruder::setTemperatureForExtruder(actTemp[i],i,false,false); + for(int i = 0; i < NUM_EXTRUDER; i++) + Extruder::setTemperatureForExtruder(actTemp[i],i,false, actTemp[i] > MAX_ROOM_TEMPERATURE); +#else + Extruder::setTemperatureForExtruder(actTemp[Extruder::current->id], Extruder::current->id, false, actTemp[Extruder::current->id] > MAX_ROOM_TEMPERATURE); +#endif +#endif + } + } + break; +#endif +#endif +//Davinci AiO specific +#if DAVINCI == 4 + case 50: //G50 : reset origin position + getMotorDriver(0)->setCurrentAs(0); + break; +#endif + case 90: // G90 + Printer::relativeCoordinateMode = false; + if(com->internalCommand) + Com::printInfoFLN(PSTR("Absolute positioning")); + break; + case 91: // G91 + Printer::relativeCoordinateMode = true; + if(com->internalCommand) + Com::printInfoFLN(PSTR("Relative positioning")); + break; + case 92: { // G92 + float xOff = Printer::coordinateOffset[X_AXIS]; + float yOff = Printer::coordinateOffset[Y_AXIS]; + float zOff = Printer::coordinateOffset[Z_AXIS]; + if(com->hasX()) xOff = Printer::convertToMM(com->X) - Printer::currentPosition[X_AXIS]; + if(com->hasY()) yOff = Printer::convertToMM(com->Y) - Printer::currentPosition[Y_AXIS]; + if(com->hasZ()) zOff = Printer::convertToMM(com->Z) - Printer::currentPosition[Z_AXIS]; + Printer::setOrigin(xOff, yOff, zOff); + if(com->hasE()) { + Printer::destinationSteps[E_AXIS] = Printer::currentPositionSteps[E_AXIS] = Printer::convertToMM(com->E) * Printer::axisStepsPerMM[E_AXIS]; + } + } + break; +#if DRIVE_SYSTEM == DELTA + case 100: { // G100 Calibrate floor or rod radius + // Using manual control, adjust hot end to contact floor. + // G100 No action. Avoid accidental floor reset. + // G100 [X] [Y] [Z] set floor for argument passed in. Number ignored and may be absent. + // G100 R with X Y or Z flag error, sets only floor or radius, not both. + // G100 R[n] Add n to radius. Adjust to be above floor if necessary + // G100 R[0] set radius based on current z measurement. Moves to (0,0,0) + float currentZmm = Printer::currentPosition[Z_AXIS]; + if (currentZmm/Printer::zLength > 0.1) { + Com::printErrorFLN(PSTR("Calibration code is limited to bottom 10% of Z height")); + break; + } + if (com->hasR()) { + if (com->hasX() || com->hasY() || com->hasZ()) + Com::printErrorFLN(PSTR("Cannot set radius and floor at same time.")); + else if (com->R != 0) { + //add r to radius + if (abs(com->R) <= 10) EEPROM::incrementRodRadius(com->R); + else Com::printErrorFLN(PSTR("Calibration movement is limited to 10mm.")); + } else { + // auto set radius. Head must be at 0,0 and touching + // Z offset will be corrected for. + if (Printer::currentPosition[X_AXIS] == 0 + && Printer::currentPosition[Y_AXIS] == 0) { + if(Printer::isLargeMachine()) { + // calculate radius assuming we are at surface + // If Z is greater than 0 it will get calculated out for correct radius + // Use either A or B tower as they anchor x Cartesian axis and always have + // Radius distance to center in simplest set up. + float h = Printer::deltaDiagonalStepsSquaredB.f; + unsigned long bSteps = Printer::currentNonlinearPositionSteps[B_TOWER]; + // The correct Rod Radius would put us here at z==0 and B height is + // square root (rod length squared minus rod radius squared) + // Reverse that to get calculated Rod Radius given B height + h -= RMath::sqr((float)bSteps); + h = sqrt(h); + EEPROM::setRodRadius(h*Printer::invAxisStepsPerMM[Z_AXIS]); + } else { + // calculate radius assuming we are at surface + // If Z is greater than 0 it will get calculated out for correct radius + // Use either A or B tower as they acnhor x cartesian axis and always have + // Radius distance to center in simplest set up. + unsigned long h = Printer::deltaDiagonalStepsSquaredB.l; + unsigned long bSteps = Printer::currentNonlinearPositionSteps[B_TOWER]; + // The correct Rod Radius would put us here at z==0 and B height is + // square root (rod length squared minus rod radius squared) + // Reverse that to get calculated Rod Radius given B height + h -= RMath::sqr(bSteps); + h = SQRT(h); + EEPROM::setRodRadius(h*Printer::invAxisStepsPerMM[Z_AXIS]); + } + } else + Com::printErrorFLN(PSTR("First move to touch at x,y=0,0 to auto-set radius.")); + } + } else { + bool tooBig = false; + if (com->hasX()) { + if (abs(com->X) <= 10) + EEPROM::setTowerXFloor(com->X + currentZmm + Printer::xMin); + else tooBig = true; + } + if (com->hasY()) { + if (abs(com->Y) <= 10) + EEPROM::setTowerYFloor(com->Y + currentZmm + Printer::yMin); + else tooBig = true; + } + if (com->hasZ()) { + if (abs(com->Z) <= 10) + EEPROM::setTowerZFloor(com->Z + currentZmm + Printer::zMin); + else tooBig = true; + } + if (tooBig) + Com::printErrorFLN(PSTR("Calibration movement is limited to 10mm.")); + } + // after adjusting zero, physical position is out of sync with memory position + // this could cause jerky movement or push head into print surface. + // moving gets back into safe zero'ed position with respect to newle set floor or Radius. + Printer::moveTo(IGNORE_COORDINATE,IGNORE_COORDINATE,12.0,IGNORE_COORDINATE,IGNORE_COORDINATE); + break; + } + case 131: { // G131 Remove offset + float cx,cy,cz; + Printer::realPosition(cx,cy,cz); + float oldfeedrate = Printer::feedrate; + Printer::offsetX = 0; + Printer::offsetY = 0; + Printer::moveToReal(cx,cy,cz,IGNORE_COORDINATE,Printer::homingFeedrate[X_AXIS]); + Printer::feedrate = oldfeedrate; + Printer::updateCurrentPosition(); + } + break; + case 132: { // G132 Calibrate endstop offsets + // This has the probably unintended side effect of turning off leveling. + Printer::setAutolevelActive(false); // don't let transformations change result! + Printer::coordinateOffset[X_AXIS] = 0; + Printer::coordinateOffset[Y_AXIS] = 0; + Printer::coordinateOffset[Z_AXIS] = 0; + // I think this is coded incorrectly, as it depends on the biginning position of the + // of the hot end, and so should first move to x,y,z= 0,0,0, but as that may not + // be possible if the printer is not in the homes/zeroed state, the printer + // cannot safely move to 0 z coordinate without crashong into the print surface. + // so other than commenting, I'm not meddling. + // but you will always get different counts from different positions. + Printer::deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS]); + int32_t m = RMath::max(Printer::stepsRemainingAtXHit,RMath::max(Printer::stepsRemainingAtYHit,Printer::stepsRemainingAtZHit)); + int32_t offx = m - Printer::stepsRemainingAtXHit; + int32_t offy = m - Printer::stepsRemainingAtYHit; + int32_t offz = m - Printer::stepsRemainingAtZHit; + Com::printFLN(Com::tTower1, offx); + Com::printFLN(Com::tTower2, offy); + Com::printFLN(Com::tTower3, offz); #if EEPROM_MODE != 0 - if(com->hasS() && com->S > 0) - { - EEPROM::setDeltaTowerXOffsetSteps(offx); - EEPROM::setDeltaTowerYOffsetSteps(offy); - EEPROM::setDeltaTowerZOffsetSteps(offz); - } + if(com->hasS() && com->S > 0) { + EEPROM::setDeltaTowerXOffsetSteps(offx); + EEPROM::setDeltaTowerYOffsetSteps(offy); + EEPROM::setDeltaTowerZOffsetSteps(offz); + } #endif - Printer::homeAxis(true,true,true); - } - break; - case 133: // G133 Measure steps to top - { - bool oldAuto = Printer::isAutolevelActive(); - Printer::setAutolevelActive(false); // don't let transformations change result! - Printer::currentPositionSteps[X_AXIS] = 0; - Printer::currentPositionSteps[Y_AXIS] = 0; - Printer::currentPositionSteps[Z_AXIS] = 0; - Printer::coordinateOffset[X_AXIS] = 0; - Printer::coordinateOffset[Y_AXIS] = 0; - Printer::coordinateOffset[Z_AXIS] = 0; - Printer::currentDeltaPositionSteps[A_TOWER] = 0; - Printer::currentDeltaPositionSteps[B_TOWER] = 0; - Printer::currentDeltaPositionSteps[C_TOWER] = 0; -// similar to comment above, this will get a different answer from any different starting point -// so it is unclear how this is helpful. It must start at a well defined point. - Printer::deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS]); - int32_t offx = HOME_DISTANCE_STEPS-Printer::stepsRemainingAtXHit; - int32_t offy = HOME_DISTANCE_STEPS-Printer::stepsRemainingAtYHit; - int32_t offz = HOME_DISTANCE_STEPS-Printer::stepsRemainingAtZHit; - Com::printFLN(Com::tTower1,offx); - Com::printFLN(Com::tTower2,offy); - Com::printFLN(Com::tTower3,offz); - Printer::setAutolevelActive(oldAuto); - Printer::homeAxis(true,true,true); - } - break; - case 134: // G134 - Com::printF(PSTR("CompDelta:"),Printer::currentDeltaPositionSteps[A_TOWER]); - Com::printF(Com::tComma,Printer::currentDeltaPositionSteps[B_TOWER]); - Com::printFLN(Com::tComma,Printer::currentDeltaPositionSteps[C_TOWER]); + PrintLine::moveRelativeDistanceInSteps(0, 0, -5*Printer::axisStepsPerMM[Z_AXIS], 0, Printer::homingFeedrate[Z_AXIS], true, true); + Printer::homeAxis(true,true,true); + } + break; + case 133: { // G133 Measure steps to top + bool oldAuto = Printer::isAutolevelActive(); + Printer::setAutolevelActive(false); // don't let transformations change result! + Printer::currentPositionSteps[X_AXIS] = 0; + Printer::currentPositionSteps[Y_AXIS] = 0; + Printer::currentPositionSteps[Z_AXIS] = 0; + Printer::coordinateOffset[X_AXIS] = 0; + Printer::coordinateOffset[Y_AXIS] = 0; + Printer::coordinateOffset[Z_AXIS] = 0; + Printer::currentNonlinearPositionSteps[A_TOWER] = 0; + Printer::currentNonlinearPositionSteps[B_TOWER] = 0; + Printer::currentNonlinearPositionSteps[C_TOWER] = 0; + // similar to comment above, this will get a different answer from any different starting point + // so it is unclear how this is helpful. It must start at a well defined point. + Printer::deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS]); + int32_t offx = HOME_DISTANCE_STEPS - Printer::stepsRemainingAtXHit; + int32_t offy = HOME_DISTANCE_STEPS - Printer::stepsRemainingAtYHit; + int32_t offz = HOME_DISTANCE_STEPS - Printer::stepsRemainingAtZHit; + Com::printFLN(Com::tTower1,offx); + Com::printFLN(Com::tTower2,offy); + Com::printFLN(Com::tTower3,offz); + Printer::setAutolevelActive(oldAuto); + PrintLine::moveRelativeDistanceInSteps(0, 0, Printer::axisStepsPerMM[Z_AXIS] * -ENDSTOP_Z_BACK_MOVE, 0, Printer::homingFeedrate[Z_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, false); + Printer::homeAxis(true,true,true); + } + break; + case 135: // G135 + Com::printF(PSTR("CompDelta:"),Printer::currentNonlinearPositionSteps[A_TOWER]); + Com::printF(Com::tComma,Printer::currentNonlinearPositionSteps[B_TOWER]); + Com::printFLN(Com::tComma,Printer::currentNonlinearPositionSteps[C_TOWER]); #ifdef DEBUG_REAL_POSITION - Com::printF(PSTR("RealDelta:"),Printer::realDeltaPositionSteps[A_TOWER]); - Com::printF(Com::tComma,Printer::realDeltaPositionSteps[B_TOWER]); - Com::printFLN(Com::tComma,Printer::realDeltaPositionSteps[C_TOWER]); + Com::printF(PSTR("RealDelta:"),Printer::realDeltaPositionSteps[A_TOWER]); + Com::printF(Com::tComma,Printer::realDeltaPositionSteps[B_TOWER]); + Com::printFLN(Com::tComma,Printer::realDeltaPositionSteps[C_TOWER]); #endif - Printer::updateCurrentPosition(); - Com::printF(PSTR("PosFromSteps:")); - printCurrentPosition(PSTR("G134 ")); - break; + Printer::updateCurrentPosition(); + Com::printF(PSTR("PosFromSteps:")); + printCurrentPosition(PSTR("G134 ")); + break; #endif // DRIVE_SYSTEM - default: - if(Printer::debugErrors()) - { - Com::printF(Com::tUnknownCommand); - com->printCommand(); - } +#if FEATURE_Z_PROBE && NUM_EXTRUDER > 1 + case 134: + { // - G134 Px Sx Zx - Calibrate nozzle height difference (need z probe in nozzle!) Px = reference extruder, Sx = only measure extrude x against reference, Zx = add to measured z distance for Sx for correction. + float z = com->hasZ() ? com->Z : 0; + int p = com->hasP() ? com->P : 0; + int s = com->hasS() ? com->S : -1; + int startExtruder = Extruder::current->id; + extruder[p].zOffset = 0; + float mins[NUM_EXTRUDER],maxs[NUM_EXTRUDER],avg[NUM_EXTRUDER]; + for(int i = 0; i < NUM_EXTRUDER; i++) { // silence unnecessary compiler warning + avg[i] = 0; + } + bool bigError = false; + +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE + float actTemp[NUM_EXTRUDER]; + for(int i = 0; i < NUM_EXTRUDER; i++) + actTemp[i] = extruder[i].tempControl.targetTemperatureC; + Printer::moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,ZHOME_HEAT_HEIGHT,IGNORE_COORDINATE,Printer::homingFeedrate[Z_AXIS]); + Commands::waitUntilEndOfAllMoves(); +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) { + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,false); + } + for(int i = 0; i < NUM_EXTRUDER; i++) { + if(extruder[i].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[i],static_cast(ZPROBE_MIN_TEMPERATURE)),i,false,true); + } +#else + if(extruder[Extruder::current->id].tempControl.currentTemperatureC < ZPROBE_MIN_TEMPERATURE) + Extruder::setTemperatureForExtruder(RMath::max(actTemp[Extruder::current->id],static_cast(ZPROBE_MIN_TEMPERATURE)),Extruder::current->id,false,true); +#endif +#endif + +#ifndef G134_REPETITIONS +#define G134_REPETITIONS 3 +#endif +#ifndef G134_PRECISION +#define G134_PRECISION 0.05 +#endif + Printer::startProbing(true); + for(int r = 0; r < G134_REPETITIONS && !bigError; r++) { + Extruder::selectExtruderById(p); + float refHeight = Printer::runZProbe(false,false); + if(refHeight == ILLEGAL_Z_PROBE) { + bigError = true; + break; + } + for(int i = 0; i < NUM_EXTRUDER && !bigError; i++) { + if(i == p) continue; + if(s >= 0 && i != s) continue; + extruder[i].zOffset = 0; + Extruder::selectExtruderById(i); + float height = Printer::runZProbe(false,false); + if(height == ILLEGAL_Z_PROBE) { + bigError = true; + break; + } + float off = (height - refHeight + z); + if(r == 0) { + avg[i] = mins[i] = maxs[i] = off; + } else { + avg[i] += off; + if(off < mins[i]) mins[i] = off; + if(off > maxs[i]) maxs[i] = off; + if(maxs[i] - mins[i] > G134_PRECISION) { + Com::printErrorFLN(PSTR("Deviation between measurements were too big, please repeat.")); + bigError = true; + break; + } + } + } + } + if(!bigError) { + for(int i = 0; i < NUM_EXTRUDER; i++) { + if(s >= 0 && i != s) continue; + extruder[i].zOffset = avg[i] * Printer::axisStepsPerMM[Z_AXIS] / G134_REPETITIONS; + } +#if EEPROM_MODE != 0 + EEPROM::storeDataIntoEEPROM(0); +#endif + } + Extruder::selectExtruderById(startExtruder); + Printer::finishProbing(); +#if defined(Z_PROBE_MIN_TEMPERATURE) && Z_PROBE_MIN_TEMPERATURE +#if ZHOME_HEAT_ALL + for(int i = 0; i < NUM_EXTRUDER; i++) + Extruder::setTemperatureForExtruder(actTemp[i],i,false,false); + for(int i = 0; i < NUM_EXTRUDER; i++) + Extruder::setTemperatureForExtruder(actTemp[i],i,false, actTemp[i] > MAX_ROOM_TEMPERATURE); +#else + Extruder::setTemperatureForExtruder(actTemp[Extruder::current->id], Extruder::current->id, false, actTemp[Extruder::current->id] > MAX_ROOM_TEMPERATURE); +#endif +#endif + } + break; +#endif +#if defined(NUM_MOTOR_DRIVERS) && NUM_MOTOR_DRIVERS > 0 + case 201: + commandG201(*com); + break; + case 202: + commandG202(*com); + break; + case 203: + commandG203(*com); + break; + case 204: + commandG204(*com); + break; +#endif // defined + default: + if(!EVENT_UNHANDLED_G_CODE(com) && Printer::debugErrors()) { + Com::printF(Com::tUnknownCommand); + com->printCommand(); + } } previousMillisCmd = HAL::timeInMilliseconds(); } /** - \brief Execute the G command stored in com. +\brief Execute the G command stored in com. */ -void Commands::processMCode(GCode *com) -{ - uint32_t codenum; //throw away variable - switch( com->M ) - { - -#if SDSUPPORT - case 20: // M20 - list SD card - sd.ls(); - break; - case 21: // M21 - init SD card - sd.mount(); - break; - case 22: //M22 - release SD card - sd.unmount(); - break; - case 23: //M23 - Select file - if(com->hasString()) - { - sd.fat.chdir(); - sd.selectFile(com->text); - } - break; - case 24: //M24 - Start SD print - sd.startPrint(); - break; - case 25: //M25 - Pause SD print - sd.pausePrint(); - break; - case 26: //M26 - Set SD index - if(com->hasS()) - sd.setIndex(com->S); - break; - case 27: //M27 - Get SD status - sd.printStatus(); - break; - case 28: //M28 - Start SD write - if(com->hasString()) - sd.startWrite(com->text); - break; - case 29: //M29 - Stop SD write - //processed in write to file routine above - //savetosd = false; - break; - case 30: // M30 filename - Delete file - if(com->hasString()) - { - sd.fat.chdir(); - sd.deleteFile(com->text); - } - break; - case 32: // M32 directoryname - if(com->hasString()) - { - sd.fat.chdir(); - sd.makeDirectory(com->text); - } - break; -#endif - case 42: //M42 -Change pin status via gcode - if (com->hasP()) - { - int pin_number = com->P; - for(uint8_t i = 0; i < (uint8_t)sizeof(sensitive_pins); i++) - { - if (pgm_read_byte(&sensitive_pins[i]) == pin_number) - { - pin_number = -1; - break; - } - } - if (pin_number > -1) - { +void Commands::processMCode(GCode *com) { + switch( com->M ) { + case 3: // Spindle/laser on +#if defined(SUPPORT_LASER) && SUPPORT_LASER + if(Printer::mode == PRINTER_MODE_LASER) { if(com->hasS()) - { - if(com->S >= 0 && com->S <= 255) - { - pinMode(pin_number, OUTPUT); - digitalWrite(pin_number, com->S); - analogWrite(pin_number, com->S); - Com::printF(Com::tSetOutputSpace, pin_number); - Com::printFLN(Com::tSpaceToSpace,(int)com->S); + LaserDriver::intensity = constrain(com->S,0,255); + LaserDriver::laserOn = true; + Com::printFLN(PSTR("LaserOn:"),(int)LaserDriver::intensity); + } +#endif // defined +#if defined(SUPPORT_CNC) && SUPPORT_CNC + if(Printer::mode == PRINTER_MODE_CNC) { + waitUntilEndOfAllMoves(); + CNCDriver::spindleOnCW(com->hasS() ? com->S : 0); + } +#endif // defined + break; + case 4: // Spindle CCW +#if defined(SUPPORT_CNC) && SUPPORT_CNC + if(Printer::mode == PRINTER_MODE_CNC) { + waitUntilEndOfAllMoves(); + CNCDriver::spindleOnCCW(com->hasS() ? com->S : 0); + } +#endif // defined + break; + case 5: // Spindle/laser off +#if defined(SUPPORT_LASER) && SUPPORT_LASER + if(Printer::mode == PRINTER_MODE_LASER) { + LaserDriver::laserOn = false; + } +#endif // defined +#if defined(SUPPORT_CNC) && SUPPORT_CNC + if(Printer::mode == PRINTER_MODE_CNC) { + waitUntilEndOfAllMoves(); + CNCDriver::spindleOff(); + } +#endif // defined + break; +#if SDSUPPORT + case 20: // M20 - list SD card +#if JSON_OUTPUT + if (com->hasString() && com->text[1] == '2') { // " S2 P/folder" + if (com->text[3] == 'P') { + sd.lsJSON(com->text + 4); + } + } else sd.ls(); +#else + sd.ls(); +#endif + break; + case 21: // M21 - init SD card + sd.mount(); + break; + case 22: //M22 - release SD card + sd.unmount(); + break; + case 23: //M23 - Select file + if(com->hasString()) { + sd.fat.chdir(); + sd.selectFile(com->text); + } + break; + case 24: //M24 - Start SD print + sd.startPrint(); + break; + case 25: //M25 - Pause SD print + sd.pausePrint(); + break; + case 26: //M26 - Set SD index + if(com->hasS()) + sd.setIndex(com->S); + break; + case 27: //M27 - Get SD status + sd.printStatus(); + break; + case 28: //M28 - Start SD write + if(com->hasString()) + sd.startWrite(com->text); + break; + case 29: //M29 - Stop SD write + //processed in write to file routine above + //savetosd = false; + break; + case 30: // M30 filename - Delete file + if(com->hasString()) { + sd.fat.chdir(); + sd.deleteFile(com->text); + } + break; + case 32: // M32 directoryname + if(com->hasString()) { + sd.fat.chdir(); + sd.makeDirectory(com->text); + } + break; +#endif +#if JSON_OUTPUT && SDSUPPORT + case 36: // M36 JSON File Info + if (com->hasString()) { + sd.JSONFileInfo(com->text); + } + break; +#endif + case 42: //M42 -Change pin status via gcode + if (com->hasP()) { + int pin_number = com->P; + for(uint8_t i = 0; i < (uint8_t)sizeof(sensitive_pins); i++) { + if (pgm_read_byte(&sensitive_pins[i]) == pin_number) { + pin_number = -1; + break; } - else - Com::printErrorFLN(PSTR("Illegal S value for M42")); } - else - { - pinMode(pin_number, INPUT_PULLUP); - Com::printF(Com::tReadInput, pin_number); - Com::printFLN(Com::tSpaceIsSpace, digitalRead(pin_number)); + if (pin_number > -1) { + if(com->hasS()) { + if(com->S >= 0 && com->S <= 255) { + pinMode(pin_number, OUTPUT); + digitalWrite(pin_number, com->S); + analogWrite(pin_number, com->S); + Com::printF(Com::tSetOutputSpace, pin_number); + Com::printFLN(Com::tSpaceToSpace,(int)com->S); + } else + Com::printErrorFLN(PSTR("Illegal S value for M42")); + } else { + pinMode(pin_number, INPUT_PULLUP); + Com::printF(Com::tSpaceToSpace, pin_number); + Com::printFLN(Com::tSpaceIsSpace, digitalRead(pin_number)); + } + } else { + Com::printErrorFLN(PSTR("Pin can not be set by M42, is in sensitive pins! ")); } } - else - { - Com::printErrorFLN(PSTR("Pin can not be set by M42, may in invalid or in use. ")); - } - } - break; + break; //Davinci Specific, Stop Printing - case 50://kill print - uid.executeAction(UI_ACTION_SD_STOP,true); - break; - case 80: // M80 - ATX Power On -#if PS_ON_PIN>-1 - Commands::waitUntilEndOfAllMoves(); - previousMillisCmd = HAL::timeInMilliseconds(); - SET_OUTPUT(PS_ON_PIN); //GND - Printer::setPowerOn(true); - WRITE(PS_ON_PIN, (POWER_INVERTING ? HIGH : LOW)); + case 50://kill print + uid.executeAction(UI_ACTION_SD_STOP,true); + break; +#if DAVINCI == 4 + case 17: + getMotorDriver(0)->disable(); + break; + case 18: + getMotorDriver(0)->enable(); + break; + case 19: //M19 home motor + if (Home_motor(0, TURNTABLE_HOME_SPEED, TABLE_HOME_PIN, TURNTABLE_PERIMETER+1) ) Com::printFLN("Success Home motor ",0); + else Com::printFLN("Failed Home motor ",0); + break; +//Davinci AiO Specific +#if DAVINCI == 4 + case 60: + //M60 Tn is reading ldr as no ldr - just return fake value, hope 500 is ok + Com::printFLN("",500); + break; #endif - break; - case 81: // M81 - ATX Power Off -#if PS_ON_PIN>-1 - Commands::waitUntilEndOfAllMoves(); - SET_OUTPUT(PS_ON_PIN); //GND - Printer::setPowerOn(false); - WRITE(PS_ON_PIN,(POWER_INVERTING ? LOW : HIGH)); + case 70: + if (com->hasT() && com->T == 1) WRITE(LASER2_PIN, LOW); + else WRITE(LASER1_PIN, LOW); + break; + case 71: + if (com->hasT() && com->T == 1) WRITE(LASER2_PIN, HIGH); + else WRITE(LASER1_PIN, HIGH); + break; + case 72: + if (com->hasT() && com->T == 1) WRITE(LED_LASER2_PIN, LOW); + else WRITE(LED_LASER1_PIN, LOW); + break; + case 73: + if (com->hasT() && com->T == 1) WRITE(LED_LASER2_PIN, HIGH); + else WRITE(LED_LASER1_PIN, HIGH); + break; #endif - break; - case 82: // M82 - Printer::relativeExtruderCoordinateMode = false; - break; - case 83: // M83 - Printer::relativeExtruderCoordinateMode = true; - break; - case 84: // M84 - if(com->hasS()) - { - stepperInactiveTime = com->S * 1000; - } - else - { + case 80: // M80 - ATX Power On +#if PS_ON_PIN>-1 Commands::waitUntilEndOfAllMoves(); - Printer::kill(true); - } - break; - case 85: // M85 - if(com->hasS()) - maxInactiveTime = (int32_t)com->S * 1000; - else - maxInactiveTime = 0; - break; - case 92: // M92 - if(com->hasX()) Printer::axisStepsPerMM[X_AXIS] = com->X; - if(com->hasY()) Printer::axisStepsPerMM[Y_AXIS] = com->Y; - if(com->hasZ()) Printer::axisStepsPerMM[Z_AXIS] = com->Z; - Printer::updateDerivedParameter(); - if(com->hasE()) - { - Extruder::current->stepsPerMM = com->E; - Extruder::selectExtruderById(Extruder::current->id); - } - break; - case 99: // M99 S