diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml new file mode 100644 index 00000000..07382034 --- /dev/null +++ b/.github/workflows/compile-examples.yml @@ -0,0 +1,154 @@ +name: Compile Examples + +on: + pull_request: + paths: + - ".github/workflows/compile-examples.yml" + - "cores/**" + - "libraries/**" + - "variants/**" + - "boards.txt" + - "platform.txt" + push: + paths: + - ".github/workflows/compile-examples.yml" + - "cores/**" + - "libraries/**" + - "variants/**" + - "boards.txt" + - "platform.txt" + +jobs: + compile-test: + runs-on: ubuntu-latest + + env: + # sketch paths to compile (recursive) for all boards + UNIVERSAL_SKETCH_PATHS: | + - extras/examples + - libraries/Wire + - libraries/SPI + - libraries/SoftwareSerial + - libraries/EEPROM + - ~/Arduino/libraries/Servo/examples + - ~/Arduino/libraries/LiquidCrystal/examples + - ~/Arduino/libraries/MFRC522/examples + - ~/Arduino/libraries/Ethernet/examples + - ~/Arduino/libraries/Adafruit_MQTT_Library/examples/mqtt_ethernet + - ~/Arduino/libraries/ArduinoBearSSL/examples/SHA1 + - ~/Arduino/libraries/ArduinoBearSSL/examples/SHA256 + - ~/Arduino/libraries/Arduino_LSM9DS1/examples + - ~/Arduino/libraries/SD/examples + - ~/Arduino/libraries/Arduino_JSON/examples + - ~/Arduino/libraries/TFT/examples/Arduino/TFTBitmapLogo + - ~/Arduino/libraries/TFT/examples/Arduino/TFTColorPicker + - ~/Arduino/libraries/TFT/examples/Arduino/TFTDisplayText + - ~/Arduino/libraries/TFT/examples/Arduino/TFTEtchASketch + - ~/Arduino/libraries/TFT/examples/Arduino/TFTGraph + - ~/Arduino/libraries/TFT/examples/Arduino/TFTPong + - ~/Arduino/libraries/Arduino_CRC32/examples + - ~/Arduino/libraries/Arduino_LSM6DS3/examples + - ~/Arduino/libraries/Stepper/examples + - ~/Arduino/libraries/Arduino_HTS221/examples + - ~/Arduino/libraries/Arduino_DebugUtils/examples + - ~/Arduino/libraries/Arduino_LPS22HB/examples + - ~/Arduino/libraries/ArduinoDMX/examples + - ~/Arduino/libraries/ArduinoRS485/examples + SKETCHES_REPORTS_PATH: sketches-reports + + strategy: + fail-fast: false + + matrix: + board: [ + {"fqbn": "arduino:megaavr:uno2018:mode=on", "type": "UnoWiFiRev2"}, + {"fqbn": "arduino:megaavr:uno2018:mode=off", "type": "UnoWiFiRev2"}, + {"fqbn": "arduino:megaavr:nona4809", "type": "NanoEvery"} + ] + + # make board type-specific customizations to the matrix jobs + include: + # Uno WiFi Rev2 + - board: + type: "UnoWiFiRev2" + additional-sketch-paths: | + - ~/Arduino/libraries/WiFiNINA/examples + - ~/Arduino/libraries/ArduinoMqttClient/examples + - ~/Arduino/libraries/Arduino_OAuth/examples/Tweeter + # Nano Every + - board: + type: "NanoEvery" + additional-sketch-paths: + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # The source files are in a subfolder of the ArduinoCore-API repository, so it's not possible to clone it directly to the final destination in the core + - name: Checkout ArduinoCore-API + uses: actions/checkout@v2 + with: + repository: arduino/ArduinoCore-API + path: extras/ArduinoCore-API + + - name: Install ArduinoCore-API + run: mv "$GITHUB_WORKSPACE/extras/ArduinoCore-API/api" "$GITHUB_WORKSPACE/cores/arduino" + + - name: Checkout Basic examples + uses: actions/checkout@v2 + with: + repository: arduino/arduino-examples + path: extras + + - name: Delete incompatible examples + run: | + # These boards do not support native USB + rm -r "$GITHUB_WORKSPACE/extras/examples/09.USB" + # The next command can be removed after the core integration with ArduinoCore-API + rm -r "$GITHUB_WORKSPACE/extras/examples/10.StarterKit_BasicKit/p11_CrystalBall" + # CapacitiveSensor library does not support megaAVR core yet + rm -r "$GITHUB_WORKSPACE/extras/examples/10.StarterKit_BasicKit/p13_TouchSensorLamp" + - name: Compile examples + uses: arduino/compile-sketches@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fqbn: ${{ matrix.board.fqbn }} + libraries: | + - name: Adafruit MQTT Library + - name: Servo + - name: LiquidCrystal + - name: MFRC522 + - name: Ethernet + - name: ArduinoBearSSL + - name: Arduino_LSM9DS1 + - name: TFT + - name: ArduinoMqttClient + - name: Arduino_CRC32 + - name: Arduino_LSM6DS3 + - name: Stepper + - name: SD + - name: Arduino_JSON + - name: Arduino_HTS221 + - name: Arduino_DebugUtils + - name: Arduino_LPS22HB + - name: ArduinoDMX + - name: ArduinoRS485 + - name: Arduino_OAuth + - name: WiFiNINA + platforms: | + # Use Board Manager to install the latest release of Arduino megaAVR Boards to get the toolchain + - name: "arduino:megaavr" + # Overwrite the Board Manager installation with the local platform + - source-path: "./" + name: "arduino:megaavr" + sketch-paths: | + ${{ env.UNIVERSAL_SKETCH_PATHS }} + ${{ matrix.additional-sketch-paths }} + enable-deltas-report: 'true' + sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} + + - name: Save memory usage change report as artifact + uses: actions/upload-artifact@v2 + with: + path: ${{ env.SKETCHES_REPORTS_PATH }} + name: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/.github/workflows/compile-muxto.yml b/.github/workflows/compile-muxto.yml new file mode 100644 index 00000000..881699af --- /dev/null +++ b/.github/workflows/compile-muxto.yml @@ -0,0 +1,105 @@ +name: Compile MuxTO + +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/compile-muxto.yml" + - "firmwares/MuxTO/**" + pull_request: + paths: + - ".github/workflows/compile-muxto.yml" + - "firmwares/MuxTO/**" + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms). + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +env: + BINARY_FILENAME: MuxTO.ino.bin + BINARY_ARTIFACT_NAME: MuxTO + +jobs: + build: + name: Build firmware + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + board: + - fqbn: arduino:samd:muxto:float=default,config=enabled,clock=internal_usb,timer=timer_732Hz,bootloader=4kb,serial=two_uart,usb=cdc + platforms: | + # Install MattairTech_Arduino:samd via Boards Manager for the toolchain + - name: MattairTech_Arduino:samd + source-url: https://www.mattairtech.com/software/arduino/package_MattairTech_index.json + # This needs to match with the version of MattairTech_Arduino:samd the Arduino fork is based on in order to get the right tool versions + version: 1.6.17 + # Install officila samd version for compiler support + - name: arduino:samd + # Install the platform with MuxTO support + - name: arduino:samd + source-url: https://github.com/arduino/ArduinoCore-samd.git + version: muxto + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable + echo "BINARY_OUTPUT_PATH=${{ runner.temp }}/output" >> "$GITHUB_ENV" + echo "SKETCHES_REPORTS_PATH=${{ runner.temp }}/sketches-reports" >> "$GITHUB_ENV" + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Compile firmware + uses: arduino/compile-sketches@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fqbn: ${{ matrix.board.fqbn }} + platforms: ${{ matrix.board.platforms }} + libraries: | + - + sketch-paths: | + - firmwares/MuxTO + cli-compile-flags: | + - --output-dir=${{ env.BINARY_OUTPUT_PATH }} + enable-deltas-report: true + sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} + + - name: Save firmware binary as workflow artifact + uses: actions/upload-artifact@v2 + with: + if-no-files-found: error + path: ${{ env.BINARY_OUTPUT_PATH }}/${{ env.BINARY_FILENAME }} + name: ${{ env.BINARY_ARTIFACT_NAME }} + + - name: Save sketches report as workflow artifact + uses: actions/upload-artifact@v2 + with: + if-no-files-found: error + path: ${{ env.SKETCHES_REPORTS_PATH }} + name: sketches-reports + + size: + name: Check firmware size + needs: build + runs-on: ubuntu-latest + steps: + - name: Download binary artifact + uses: actions/download-artifact@v2 + with: + name: ${{ env.BINARY_ARTIFACT_NAME }} + + # The normal size check done by Arduino CLI is not working correctly, so it's necessary to check the size directly + - name: Check firmware binary size + run: | + BINARY_SIZE="$(stat --printf="%s" "${{ github.workspace }}/${{ env.BINARY_FILENAME }}")" + MAX_BINARY_SIZE=$((12 * 1024)) + echo "File size: ${BINARY_SIZE}/${MAX_BINARY_SIZE} B" + if [[ $BINARY_SIZE -gt $MAX_BINARY_SIZE ]]; then + echo "::error::Binary size of $BINARY_SIZE B exceeds the available memory ($MAX_BINARY_SIZE B)" + exit 1 + fi diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..d7e23178 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,107 @@ +name: release + +on: + push: + tags: + - "[0-9]+.[0-9]+.[0-9]+*" + +jobs: + core-pre-release-from-tag: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Checkout ArduinoCore-API + uses: actions/checkout@v2 + with: + repository: arduino/ArduinoCore-API + path: extras/ArduinoCore-API + + - name: Check if API should be compiled in the core + id: checkapi + run: | + if [[ $(grep -r api platform.txt) ]]; then echo "::set-output name=IS_API::true"; fi + + - name: Checkout latest tag of ArduinoCore-API and add it to the core + run: | + cd extras/ArduinoCore-API + git fetch --tags + git checkout $(git describe --tags $(git rev-list --tags --max-count=1)) + cd ../.. + mv "$GITHUB_WORKSPACE/extras/ArduinoCore-API/api" "$GITHUB_WORKSPACE/cores/arduino" + if: steps.checkapi.outputs.IS_API == 'true' + + - name: Remove ArduinoCore-API + run: rm -r "$GITHUB_WORKSPACE/extras/ArduinoCore-API" + + - name: Set env + run: echo "TAG_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Get repo name + run: echo "REPOSITORY_NAME=$(echo ${{ github.repository }} | cut -d "/" -f2-)" >> $GITHUB_ENV + + - name: Package the new core + run: | + extras/pack.release.bash $TAG_VERSION $REPOSITORY_NAME + cd extras + mkdir staging + echo $PWD + mv ../*.json staging/ + mv ../*.tar.bz2 staging/ + cd .. + + - name: Get architecture name + run: | + echo "ARCHITECTURE=$(cat extras/package_index.json.NewTag.template | jq ".packages[0].platforms[0].architecture" | sed 's/\"//g')" >> $GITHUB_ENV + + - name: Upload package_*_index.json and *.tar.bz2 file to Arduino downloads servers + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: | + aws s3 sync extras/staging/ s3://${{ secrets.ARDUINO_DOWNLOADS_BUCKET }}/packages/staging/ --exclude "*" --include *.json + aws s3 sync extras/staging/ s3://${{ secrets.ARDUINO_DOWNLOADS_BUCKET }}/cores/staging/ --exclude "*" --include *.tar.bz2 + + - name: Checkout Basic examples + uses: actions/checkout@v2 + with: + repository: arduino/arduino-examples + path: extras/arduino-examples + + - name: Install Arduino CLI + uses: arduino/setup-arduino-cli@v1.1.1 + with: + version: "0.14.0" + + - name: Download and verify new core + run: | + export PATH=$PATH:$PWD + arduino-cli version + cp extras/staging/package_${REPOSITORY_NAME}_${TAG_VERSION}_index.json . + export ARDUINO_DIRECTORIES_DATA=$PWD + export ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS=file://$PWD/package_${REPOSITORY_NAME}_${TAG_VERSION}_index.json + arduino-cli config init + arduino-cli config dump -v + arduino-cli core update-index -v + arduino-cli core install arduino:${ARCHITECTURE}@${TAG_VERSION} + INDEX=0 + arduino-cli board listall --format=json > boardlist.json + N=$(jq '.boards | length' boardlist.json) + let N=N-1 + echo $N + for INDEX in $(seq 0 1 $N); do arduino-cli compile --fqbn $(cat boardlist.json | jq ".boards[$INDEX].FQBN" | sed 's/\"//g') $PWD/extras/arduino-examples/examples/01.Basics/Blink; done + + # See: https://github.com/rtCamp/action-slack-notify + - name: Slack notification of core pre-release + uses: rtCamp/action-slack-notify@v2.1.0 + env: + SLACK_CHANNEL: core_releases + SLACK_COLOR: good + SLACK_USERNAME: ArduinoBot + SLACK_ICON: https://github.com/arduino.png?size=48 + SLACK_TITLE: Arduino core pre-release + SLACK_MESSAGE: 'Version ${{ env.TAG_VERSION }} of core ${{ env.REPOSITORY_NAME }} is now available' + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + MSG_MINIMAL: true \ No newline at end of file diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml new file mode 100644 index 00000000..1e37a511 --- /dev/null +++ b/.github/workflows/report-size-deltas.yml @@ -0,0 +1,16 @@ +name: Report PR Size Deltas + +on: + schedule: + - cron: '*/5 * * * *' + +jobs: + report: + runs-on: ubuntu-latest + + steps: + - name: Comment size deltas reports to PRs + uses: arduino/report-size-deltas@v1 + with: + # The name of the workflow artifact created by the sketch compilation workflow + sketches-reports-source: sketches-reports diff --git a/README.md b/README.md index f5ace4fd..4090cd7e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Arduino Core for ATMEGA4809 CPU +[![Compile MuxTO status](https://github.com/arduino/ArduinoCore-megaavr/actions/workflows/compile-muxto.yml/badge.svg)](https://github.com/arduino/ArduinoCore-megaavr/actions/workflows/compile-muxto.yml) + This repository contains the source code and configuration files of the Arduino Core for Microchip's ATMEGA4809 processor (used on the Arduino Uno WiFi Rev2 boards). diff --git a/boards.txt b/boards.txt index a3345086..504c40af 100644 --- a/boards.txt +++ b/boards.txt @@ -1,15 +1,20 @@ -# See: http://code.google.com/p/arduino/wiki/Platforms +# See: https://arduino.github.io/arduino-cli/latest/platform-specification/ ############################################################## -uno2018.name=Arduino Uno WiFi Rev2 +uno2018.name=Arduino UNO WiFi Rev2 uno2018.vid.0=0x03eb uno2018.pid.0=0x2145 +uno2018.upload_port.0.vid=0x03eb +uno2018.upload_port.0.pid=0x2145 +uno2018.upload_port.1.board=uno2018 uno2018.upload.tool=avrdude +uno2018.upload.tool.default=avrdude +uno2018.upload.tool.network=arduino_ota uno2018.upload.protocol=xplainedmini_updi -uno2018.upload.maximum_size=49152 +uno2018.upload.maximum_size=48640 uno2018.upload.maximum_data_size=6144 uno2018.upload.speed=115200 uno2018.upload.extra_params=-Pusb @@ -25,6 +30,7 @@ uno2018.build.extra_flags={build.328emulation} -DMILLIS_USE_TIMERB3 #uno2018.build.extra_flags=-B{runtime.tools.atpack.path}/gcc/dev/{build.mcu} uno2018.bootloader.tool=avrdude +uno2018.bootloader.tool.default=avrdude uno2018.bootloader.file=atmega4809_uart_bl.hex uno2018.bootloader.SYSCFG0=0xC9 uno2018.bootloader.BOOTEND=0x02 @@ -43,8 +49,13 @@ nona4809.name=Arduino Nano Every nona4809.vid.0=0x2341 nona4809.pid.0=0x0058 +nona4809.upload_port.0.vid=0x2341 +nona4809.upload_port.0.pid=0x0058 +nona4809.upload_port.1.board=nona4809 nona4809.upload.tool=avrdude +nona4809.upload.tool.default=avrdude +nona4809.upload.tool.network=arduino_ota nona4809.upload.protocol=jtag2updi nona4809.upload.maximum_size=49152 nona4809.upload.maximum_data_size=6144 @@ -62,6 +73,7 @@ nona4809.build.extra_flags={build.328emulation} -DMILLIS_USE_TIMERB3 -DNO_EXTERN #nona4809.build.extra_flags=-B{runtime.tools.atpack.path}/gcc/dev/{build.mcu} nona4809.bootloader.tool=avrdude +nona4809.bootloader.tool.default=avrdude nona4809.bootloader.file=atmega4809_uart_bl.hex nona4809.bootloader.SYSCFG0=0xC9 nona4809.bootloader.BOOTEND=0x00 diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 1892a7a1..c40dcb20 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -83,10 +83,11 @@ unsigned long microsecondsToClockCycles(unsigned long microseconds); // Get the bit location within the hardware port of the given virtual pin. // This comes from the pins_*.c file for the active board configuration. -extern const uint8_t PROGMEM digital_pin_to_port[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask[]; -extern const uint8_t PROGMEM digital_pin_to_bit_position[]; -extern const uint8_t PROGMEM digital_pin_to_timer[]; +extern const uint8_t digital_pin_to_port[]; +extern const uint8_t digital_pin_to_bit_mask[]; +extern const uint8_t digital_pin_to_bit_position[]; +extern const uint8_t digital_pin_to_timer[]; +extern const uint8_t analog_pin_to_channel[]; // Get the bit location within the hardware port of the given virtual pin. // This comes from the pins_*.c file for the active board configuration. @@ -115,12 +116,12 @@ extern const uint8_t PROGMEM digital_pin_to_timer[]; void setup_timers(); bool isDoubleBondedActive(uint8_t pin); -#define digitalPinToPort(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_port + pin) : NOT_A_PIN ) -#define digitalPinToBitPosition(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_bit_position + pin) : NOT_A_PIN ) -#define analogPinToBitPosition(pin) ( (pin < NUM_ANALOG_INPUTS) ? pgm_read_byte(digital_pin_to_bit_position + pin + ANALOG_INPUT_OFFSET) : NOT_A_PIN ) -#define digitalPinToBitMask(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_bit_mask + pin) : NOT_A_PIN ) -#define analogPinToBitMask(pin) ( (pin < NUM_ANALOG_INPUTS) ? pgm_read_byte(digital_pin_to_bit_mask + pin + ANALOG_INPUT_OFFSET) : NOT_A_PIN ) -#define digitalPinToTimer(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_timer + pin) : NOT_ON_TIMER ) +#define digitalPinToPort(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_port[pin] : NOT_A_PIN ) +#define digitalPinToBitPosition(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_bit_position[pin] : NOT_A_PIN ) +#define digitalPinToBitMask(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_bit_mask[pin] : NOT_A_PIN ) +#define digitalPinToTimer(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_timer[pin] : NOT_ON_TIMER ) +#define analogPinToBitPosition(pin) ( (digitalPinToAnalogInput(pin) != NOT_A_PIN) ? digital_pin_to_bit_position[pin + ANALOG_INPUT_OFFSET] : NOT_A_PIN ) +#define analogPinToBitMask(pin) ( (digitalPinToAnalogInput(pin) != NOT_A_PIN) ? digital_pin_to_bit_mask[pin + ANALOG_INPUT_OFFSET] : NOT_A_PIN ) #define portToPortStruct(port) ( (port < NUM_TOTAL_PORTS) ? ((PORT_t *)&PORTA + port) : NULL) #define digitalPinToPortStruct(pin) ( (pin < NUM_TOTAL_PINS) ? ((PORT_t *)&PORTA + digitalPinToPort(pin)) : NULL) @@ -143,11 +144,21 @@ bool isDoubleBondedActive(uint8_t pin); #ifdef UNO_WIFI_REV2_328MODE #include #endif +#ifdef AVR_NANO_4809_328MODE +#include +#endif #if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL) #error "Targets with both UART0 and CDC serial not supported" #endif #endif +#ifdef __cplusplus +extern "C" { +#endif #include "pins_arduino.h" +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/cores/arduino/NANO_Compat.cpp b/cores/arduino/NANO_compat.cpp similarity index 99% rename from cores/arduino/NANO_Compat.cpp rename to cores/arduino/NANO_compat.cpp index f199125d..997d36e3 100644 --- a/cores/arduino/NANO_Compat.cpp +++ b/cores/arduino/NANO_compat.cpp @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "NANO_Compat.h" +#include "NANO_compat.h" #ifdef AVR_NANO_4809_328MODE diff --git a/cores/arduino/NANO_Compat.h b/cores/arduino/NANO_compat.h similarity index 100% rename from cores/arduino/NANO_Compat.h rename to cores/arduino/NANO_compat.h diff --git a/cores/arduino/UART.cpp b/cores/arduino/UART.cpp index fa8098c4..473f59b9 100644 --- a/cores/arduino/UART.cpp +++ b/cores/arduino/UART.cpp @@ -88,7 +88,6 @@ void serialEventRun(void) void UartClass::_tx_data_empty_irq(void) { // Check if tx buffer already empty. - // This interrupt-handler can be called "manually" from flush(); if (_tx_buffer_head == _tx_buffer_tail) { // Buffer empty, so disable "data register empty" interrupt (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); @@ -107,8 +106,6 @@ void UartClass::_tx_data_empty_irq(void) (*_hwserial_module).TXDATAL = c; - while(!((*_hwserial_module).STATUS & USART_DREIF_bm)); - if (_tx_buffer_head == _tx_buffer_tail) { // Buffer empty, so disable "data register empty" interrupt (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); @@ -121,6 +118,23 @@ void UartClass::_tx_data_empty_irq(void) } } +// To invoke data empty "interrupt" via a call, use this method +void UartClass::_poll_tx_data_empty(void) +{ + if ( (!(SREG & CPU_I_bm)) || (!((*_hwserial_module).CTRLA & USART_DREIE_bm)) ) { + // Interrupts are disabled either globally or for data register empty, + // so we'll have to poll the "data register empty" flag ourselves. + // If it is set, pretend an interrupt has happened and call the handler + //to free up space for us. + + // Invoke interrupt handler only if conditions data register is empty + if ((*_hwserial_module).STATUS & USART_DREIF_bm) { + _tx_data_empty_irq(); + } + } + // In case interrupts are enabled, the interrupt routine will be invoked by itself +} + // Public Methods ////////////////////////////////////////////////////////////// void UartClass::begin(unsigned long baud, uint16_t config) @@ -140,23 +154,15 @@ void UartClass::begin(unsigned long baud, uint16_t config) uint8_t oldSREG = SREG; cli(); - baud_setting = (((8 * F_CPU_CORRECTED) / baud) + 1) / 2; + baud_setting = (((8 * F_CPU) / baud) + 1) / 2; // Disable CLK2X (*_hwserial_module).CTRLB &= (~USART_RXMODE_CLK2X_gc); (*_hwserial_module).CTRLB |= USART_RXMODE_NORMAL_gc; _written = false; - //Set up the rx pin - pinMode(_hwserial_rx_pin, INPUT_PULLUP); - - //Set up the tx pin - digitalWrite(_hwserial_tx_pin, HIGH); - pinMode(_hwserial_tx_pin, OUTPUT); - int8_t sigrow_val = SIGROW.OSC16ERR5V; - baud_setting *= (1024 + sigrow_val); - baud_setting /= (1024 - abs(sigrow_val)); + baud_setting += (baud_setting * sigrow_val) / 1024; // assign the baud_setting, a.k.a. BAUD (USART Baud Rate Register) (*_hwserial_module).BAUD = (int16_t) baud_setting; @@ -169,6 +175,13 @@ void UartClass::begin(unsigned long baud, uint16_t config) (*_hwserial_module).CTRLA |= USART_RXCIE_bm; + //Set up the rx pin + pinMode(_hwserial_rx_pin, INPUT_PULLUP); + + //Set up the tx pin + digitalWrite(_hwserial_tx_pin, HIGH); + pinMode(_hwserial_tx_pin, OUTPUT); + // Restore SREG content SREG = oldSREG; } @@ -253,9 +266,7 @@ void UartClass::flush() // If interrupts are globally disabled or the and DR empty interrupt is disabled, // poll the "data register empty" interrupt flag to prevent deadlock - if ( (!(SREG & CPU_I_bm)) || (!((*_hwserial_module).CTRLA & USART_DREIE_bm)) ) { - _tx_data_empty_irq(); - } + _poll_tx_data_empty(); } // If we get here, nothing is queued anymore (DREIE is disabled) and // the hardware finished transmission (TXCIF is set). @@ -294,18 +305,9 @@ size_t UartClass::write(uint8_t c) tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE; //If the output buffer is full, there's nothing for it other than to - //wait for the interrupt handler to empty it a bit + //wait for the interrupt handler to empty it a bit (or emulate interrupts) while (i == _tx_buffer_tail) { - if ( ( !(SREG & CPU_I_bm) ) || ( !((*_hwserial_module).CTRLA & USART_DREIE_bm) ) ) { - // Interrupts are disabled either globally or for data register empty, - // so we'll have to poll the "data register empty" flag ourselves. - // If it is set, pretend an interrupt has happened and call the handler - //to free up space for us. - - _tx_data_empty_irq(); - } else { - // nop, the interrupt handler will free up space for us - } + _poll_tx_data_empty(); } _tx_buffer[_tx_buffer_head] = c; diff --git a/cores/arduino/UART.h b/cores/arduino/UART.h index ef966e9f..797ae932 100644 --- a/cores/arduino/UART.h +++ b/cores/arduino/UART.h @@ -27,6 +27,8 @@ #include "api/HardwareSerial.h" #include "pins_arduino.h" +using namespace arduino; + // Define constants and variables for buffering incoming serial data. We're // using a ring buffer (I think), in which head is the index of the location // to which to write the next incoming character and tail is the index of the @@ -164,11 +166,16 @@ class UartClass : public HardwareSerial inline size_t write(unsigned int n) { return write((uint8_t)n); } inline size_t write(int n) { return write((uint8_t)n); } using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool() { return true; } + explicit operator bool() { return true; } + + void bind(UartClass& ser) {bound = &ser; } // Interrupt handlers - Not intended to be called externally inline void _rx_complete_irq(void); void _tx_data_empty_irq(void); + private: + void _poll_tx_data_empty(void); + UartClass* bound = NULL; }; #if defined(HWSERIAL0) diff --git a/cores/arduino/UART0.cpp b/cores/arduino/UART0.cpp index b8f1f34c..522b6844 100644 --- a/cores/arduino/UART0.cpp +++ b/cores/arduino/UART0.cpp @@ -51,7 +51,7 @@ ISR(HWSERIAL0_DRE_VECTOR) Serial._tx_data_empty_irq(); } #else -#error "Don't know what the Data Received interrupt vector is called for Serial" +#error "Don't know what the Data Register Empty interrupt vector is called for Serial" #endif #if defined(HWSERIAL0) diff --git a/cores/arduino/UART_private.h b/cores/arduino/UART_private.h index 0bca2d3c..2fa93694 100644 --- a/cores/arduino/UART_private.h +++ b/cores/arduino/UART_private.h @@ -66,6 +66,9 @@ void UartClass::_rx_complete_irq(void) _rx_buffer[_rx_buffer_head] = c; _rx_buffer_head = i; } + if (bound != NULL) { + bound->write(c); + } } else { // Parity error, read byte but discard it (*_hwserial_module).RXDATAL; diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.cpp similarity index 87% rename from cores/arduino/WInterrupts.c rename to cores/arduino/WInterrupts.cpp index 64cd9ae6..55155f4c 100644 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.cpp @@ -32,9 +32,10 @@ #include "wiring_private.h" -static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; +static volatile voidFuncPtrParam intFunc[EXTERNAL_NUM_INTERRUPTS]; +static void* args[EXTERNAL_NUM_INTERRUPTS]; -void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { +void attachInterruptParam(pin_size_t pin, void (*userFunc)(void*), PinStatus mode, void* params) { /* Get bit position and check pin validity */ uint8_t bit_pos = digitalPinToBitPosition(pin); @@ -46,24 +47,27 @@ void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { /* Check interrupt number and apply function pointer to correct array index */ if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { intFunc[interruptNum] = userFunc; + args[interruptNum] = params; // Configure the interrupt mode (trigger on low input, any change, rising // edge, or falling edge). The mode constants were chosen to correspond // to the configuration bits in the hardware register, so we simply apply // the setting in the pin control register + int isc_mode; + switch (mode) { case CHANGE: - mode = PORT_ISC_BOTHEDGES_gc; + isc_mode = PORT_ISC_BOTHEDGES_gc; break; case FALLING: - mode = PORT_ISC_FALLING_gc; + isc_mode = PORT_ISC_FALLING_gc; break; case RISING: - mode = PORT_ISC_RISING_gc; + isc_mode = PORT_ISC_RISING_gc; break; case LOW: - mode = PORT_ISC_LEVEL_gc; + isc_mode = PORT_ISC_LEVEL_gc; break; default: // AVR doesn't support level triggered interrupts @@ -80,10 +84,14 @@ void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { *pin_ctrl_reg &= ~(PORT_ISC_gm); /* Apply ISC setting */ - *pin_ctrl_reg |= mode; + *pin_ctrl_reg |= isc_mode; } } +void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { + attachInterruptParam(pin, (voidFuncPtrParam)userFunc, mode, NULL); +} + void detachInterrupt(uint8_t pin) { /* Get bit position and check pin validity */ uint8_t bit_pos = digitalPinToBitPosition(pin); @@ -127,7 +135,7 @@ static void port_interrupt_handler(uint8_t port) { if(intFunc[interrupt_num] != 0){ /* Call function */ - intFunc[interrupt_num](); + intFunc[interrupt_num](args[interrupt_num]); } } bit_pos++; diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index c5a715b5..36ddc680 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -23,7 +23,6 @@ */ #include "wiring_private.h" -#include "pins_arduino.h" #include "Arduino.h" uint8_t analog_reference = DEFAULT; @@ -146,6 +145,8 @@ void analogWrite(uint8_t pin, int val) uint16_t* timer_cmp_out; TCB_t *timer_B; + uint8_t savedSREG; + /* Find out Port and Pin to correctly handle port mux, and timer. */ switch (digital_pin_timer) { @@ -154,7 +155,10 @@ void analogWrite(uint8_t pin, int val) timer_cmp_out = ((uint16_t*) (&TCA0.SINGLE.CMP0BUF)) + bit_pos; /* Configure duty cycle for correct compare channel */ - (*timer_cmp_out) = (val); + savedSREG = SREG; + cli(); + (*timer_cmp_out) = (val); // non-atomic 16-bit write operation + SREG = savedSREG; /* Enable output on pin */ TCA0.SINGLE.CTRLB |= (1 << (TCA_SINGLE_CMP0EN_bp + bit_pos)); @@ -171,7 +175,12 @@ void analogWrite(uint8_t pin, int val) timer_B = ((TCB_t *)&TCB0 + (digital_pin_timer - TIMERB0)); /* set duty cycle */ - timer_B->CCMPH = val; + // (16-bit read/write operation are non-atomic and use a temporary register) + savedSREG = SREG; + cli(); + timer_B->CCMPL = timer_B->CCMPL; // copy CCMPL into temporary register + timer_B->CCMPH = val; // set CCMPH value + copy temporary register content into CCMPL + SREG = savedSREG; /* Enable Timer Output */ timer_B->CTRLB |= (TCB_CCMPEN_bm); diff --git a/cores/test/CMakeLists.txt b/cores/test/CMakeLists.txt index 2605c248..bea90144 100644 --- a/cores/test/CMakeLists.txt +++ b/cores/test/CMakeLists.txt @@ -25,7 +25,7 @@ set(TEST_TARGET testArduinoCore-megaavr) set(TEST_SRCS src/test_main.cpp - ../arduino/NANO_Compat.cpp + ../arduino/NANO_compat.cpp ) ########################################################################## diff --git a/cores/test/src/test_main.cpp b/cores/test/src/test_main.cpp index 41adfe12..4b0d36da 100644 --- a/cores/test/src/test_main.cpp +++ b/cores/test/src/test_main.cpp @@ -19,11 +19,11 @@ #define CATCH_CONFIG_MAIN #include -#include "../../arduino/NANO_Compat.h" +#include "../../arduino/NANO_compat.h" /*****************************************************************************/ -SCENARIO("Testing Arduino Nano 4809 DDRB compatibility class", "NANO_Compat::DDRBClass") { +SCENARIO("Testing Arduino Nano 4809 DDRB compatibility class", "NANO_compat::DDRBClass") { PORT_t portb, porte; DDRBClass DDRB(&portb, &porte); @@ -63,7 +63,7 @@ SCENARIO("Testing Arduino Nano 4809 DDRB compatibility class", "NANO_Compat::DDR /*****************************************************************************/ -SCENARIO("Testing Arduino Nano 4809 PORTB compatibility class", "NANO_Compat::PORTBClass") { +SCENARIO("Testing Arduino Nano 4809 PORTB compatibility class", "NANO_compat::PORTBClass") { PORT_t portb, porte; PORTBClass PORTB(&portb, &porte); @@ -103,7 +103,7 @@ SCENARIO("Testing Arduino Nano 4809 PORTB compatibility class", "NANO_Compat::PO /*****************************************************************************/ -SCENARIO("Testing Arduino Nano 4809 DDRC compatibility class", "NANO_Compat::DDRCClass") { +SCENARIO("Testing Arduino Nano 4809 DDRC compatibility class", "NANO_compat::DDRCClass") { PORT_t porta, portd; DDRCClass DDRC(&porta, &portd); @@ -149,7 +149,7 @@ SCENARIO("Testing Arduino Nano 4809 DDRC compatibility class", "NANO_Compat::DDR /*****************************************************************************/ -SCENARIO("Testing Arduino Nano 4809 PORTC compatibility class", "NANO_Compat::PORTCClass") { +SCENARIO("Testing Arduino Nano 4809 PORTC compatibility class", "NANO_compat::PORTCClass") { PORT_t porta, portd; PORTCClass PORTC(&porta, &portd); @@ -195,7 +195,7 @@ SCENARIO("Testing Arduino Nano 4809 PORTC compatibility class", "NANO_Compat::PO /*****************************************************************************/ -SCENARIO("Testing Arduino Nano 4809 DDRD compatibility class", "NANO_Compat::DDRDClass") { +SCENARIO("Testing Arduino Nano 4809 DDRD compatibility class", "NANO_compat::DDRDClass") { PORT_t porta, portb, portc, portf; DDRDClass DDRD(&porta, &portb, &portc, &portf); @@ -245,7 +245,7 @@ SCENARIO("Testing Arduino Nano 4809 DDRD compatibility class", "NANO_Compat::DDR /*****************************************************************************/ -SCENARIO("Testing Arduino Nano 4809 PORTD compatibility class", "NANO_Compat::PORTDClass") { +SCENARIO("Testing Arduino Nano 4809 PORTD compatibility class", "NANO_compat::PORTDClass") { PORT_t porta, portb, portc, portf; PORTDClass PORTD(&porta, &portb, &portc, &portf); diff --git a/drivers/atmelinf.cat b/drivers/atmelinf.cat index 06df75ea..7fa54c00 100644 Binary files a/drivers/atmelinf.cat and b/drivers/atmelinf.cat differ diff --git a/drivers/mEDBG_Virtual_Com_Port.inf b/drivers/mEDBG_Virtual_Com_Port.inf index f69bf51d..7fff7f14 100644 --- a/drivers/mEDBG_Virtual_Com_Port.inf +++ b/drivers/mEDBG_Virtual_Com_Port.inf @@ -19,9 +19,11 @@ DriverVer=06/14/2013,6.0.0.1 [ATMEL] %ATMEL_CDC%=Reader, USB\VID_03EB&PID_2145&MI_01 +%ARDUINO_NANO_EVERY_CDC%=Reader, USB\VID_2341&PID_0058 [ATMEL.NTamd64] %ATMEL_CDC%=DriverInstall, USB\VID_03EB&PID_2145&MI_01 +%ARDUINO_NANO_EVERY_CDC%=Reader, USB\VID_2341&PID_0058 ;---------------------------------------------------------- @@ -86,5 +88,6 @@ ServiceBinary=%12%\usbser.sys [Strings] ATMEL = "Atmel Corp." ATMEL_CDC = "mEDBG Virtual COM Port" +ARDUINO_NANO_EVERY_CDC = "Arduino NANO Every" Serial.SvcDesc = "USB Serial emulation driver" diff --git a/extras/pack.release.bash b/extras/pack.release.bash index a2999d50..3321340b 100755 --- a/extras/pack.release.bash +++ b/extras/pack.release.bash @@ -1,6 +1,6 @@ #!/bin/bash -ex -# pack.*.bash - Bash script to help packaging avr core releases. +# pack.*.bash - Bash script to help packaging samd core releases. # Copyright (c) 2015 Arduino LLC. All right reserved. # # This library is free software; you can redistribute it and/or @@ -17,17 +17,40 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# Version check removed because version string passed from jenkins was incorrect +VERSION_FROM_TAG=$1 +CORE_NAME=$2 +echo $VERSION_FROM_TAG +echo $CORE_NAME VERSION=`grep version= platform.txt | sed 's/version=//g'` +echo $VERSION + +if [ $VERSION != $VERSION_FROM_TAG ]; then + exit 0 +fi PWD=`pwd` FOLDERNAME=`basename $PWD` THIS_SCRIPT_NAME=`basename $0` +FILENAME=core-$CORE_NAME-$VERSION.tar.bz2 +echo $FILENAME -rm -f avr-$VERSION.tar.bz2 +rm -f *.tar.bz2 +rm -f *.json cd .. -tar --transform "s|$FOLDERNAME|$FOLDERNAME-$VERSION|g" --exclude=extras/** --exclude=.git* --exclude=.idea -cjf avr-$VERSION.tar.bz2 $FOLDERNAME +tar --exclude=extras/** --exclude=.git* --exclude=.idea -cjhf $FILENAME $FOLDERNAME cd - -mv ../avr-$VERSION.tar.bz2 . +mv ../$FILENAME . + +CHKSUM=`sha256sum $FILENAME | awk '{ print $1 }'` +SIZE=`wc -c $FILENAME | awk '{ print $1 }'` +cat extras/package_index.json.NewTag.template | +# sed "s/%%BUILD_NUMBER%%/${BUILD_NUMBER}/" | +# sed "s/%%CURR_TIME%%/${CURR_TIME_SED}/" | +sed "s/%%VERSION%%/${VERSION}/" | +sed "s/%%FILENAME%%/${FILENAME}/" | +sed "s/%%CHECKSUM%%/${CHKSUM}/" | +sed "s/%%SIZE%%/${SIZE}/" > package_${CORE_NAME}_${VERSION}_index.json \ No newline at end of file diff --git a/extras/package_index.json.NewTag.template b/extras/package_index.json.NewTag.template new file mode 100644 index 00000000..fcc12676 --- /dev/null +++ b/extras/package_index.json.NewTag.template @@ -0,0 +1,54 @@ +{ + "packages": [ + { + "name": "arduino", + "maintainer": "Arduino Betatesting", + "websiteURL": "http://www.arduino.cc/", + "email": "packages@arduino.cc", + "help": { + "online": "http://www.arduino.cc/en/Reference/HomePage" + }, + "platforms": [ + { + "name": "Arduino megaAVR Boards - Pre-release", + "architecture": "megaavr", + "version": "%%VERSION%%", + "category": "Arduino", + "url": "http://downloads.arduino.cc/cores/staging/%%FILENAME%%", + "archiveFileName": "%%FILENAME%%", + "checksum": "SHA-256:%%CHECKSUM%%", + "size": "%%SIZE%%", + "help": { + "online": "https://github.com/arduino/ArduinoCore-megaavr/issues" + }, + "boards": [ + { + "name": "Arduino UNO WiFi Rev2" + }, + { + "name": "Arduino Nano Every" + } + ], + "toolsDependencies": [ + { + "packager": "arduino", + "name": "avr-gcc", + "version": "7.3.0-atmel3.6.1-arduino5" + }, + { + "packager": "arduino", + "name": "avrdude", + "version": "6.3.0-arduino17" + }, + { + "packager": "arduino", + "name": "arduinoOTA", + "version": "1.3.0" + } + ] + } + ], + "tools": [] + } + ] +} diff --git a/firmwares/MuxTO/JICE_io.cpp b/firmwares/MuxTO/JICE_io.cpp new file mode 100644 index 00000000..91a09281 --- /dev/null +++ b/firmwares/MuxTO/JICE_io.cpp @@ -0,0 +1,41 @@ +/* + stk_io.cpp + + Created: 18-11-2017 15:20:29 + Author: JMR_2 +*/ + +// Includes +#include +#include "JICE_io.h" +#include "sys.h" + +namespace { +// *** Baud rate lookup table for UBRR0 register *** +// Indexed by valid values for PARAM_BAUD_RATE_VAL (defined in JTAG2.h) +uint16_t baud_tbl[8] = {baud(2400), baud(4800), baud(9600), baud(19200), baud(38400), baud(57600), baud(115200), baud(14400)}; +} + +// Functions +uint8_t JICE_io::put(char c) { + SERIALCOM.write(c); + return c; +} + +uint8_t JICE_io::get(void) { + //while (!SERIALCOM.available()); + uint8_t c = SERIALCOM.read(); + return c; +} + +void JICE_io::init(void) { + SERIALCOM.begin(115200); +} + +void JICE_io::flush(void) { + SERIALCOM.flush(); +} + +void JICE_io::set_baud(JTAG2::baud_rate rate) { + +} diff --git a/firmwares/MuxTO/JICE_io.h b/firmwares/MuxTO/JICE_io.h new file mode 100644 index 00000000..da009e85 --- /dev/null +++ b/firmwares/MuxTO/JICE_io.h @@ -0,0 +1,27 @@ +/* + stk_io.h + + Created: 18-11-2017 14:55:53 + Author: JMR_2 +*/ + + +#ifndef JICE_IO_H_ +#define JICE_IO_H_ + +#include +#include "JTAG2.h" + +#warning "modify this to match your USB serial port name" +#define SERIALCOM SerialUSB + +namespace JICE_io { +// Function prototypes +uint8_t put(char c); +uint8_t get(void); +void init(void); +void flush(void); +void set_baud(JTAG2::baud_rate rate); +} + +#endif /* JICE_IO_H_ */ diff --git a/firmwares/MuxTO/JTAG2.cpp b/firmwares/MuxTO/JTAG2.cpp new file mode 100644 index 00000000..8536123d --- /dev/null +++ b/firmwares/MuxTO/JTAG2.cpp @@ -0,0 +1,369 @@ +/* + STK500.cpp + + Created: 08-12-2017 19:47:27 + Author: JMR_2 +*/ + +#include "Arduino.h" +#include "JTAG2.h" +#include "JICE_io.h" +#include "NVM.h" +#include "crc16.h" +#include "UPDI_hi_lvl.h" + +// *** Writeable Parameter Values *** +uint8_t JTAG2::PARAM_EMU_MODE_VAL; +JTAG2::baud_rate JTAG2::PARAM_BAUD_RATE_VAL; + +// *** STK500 packet *** +JTAG2::packet_t JTAG2::packet; + +namespace { +// *** Private variables *** +uint8_t flash_pagesize; +uint8_t eeprom_pagesize; + +// *** Local functions declaration *** +void NVM_fuse_write (uint16_t address, uint8_t data); +void NVM_buffered_write(uint16_t address, uint16_t lenght, uint8_t buff_size, uint8_t write_type); +} + +// *** Packet functions *** +bool JTAG2::receive() { + if (JICE_io::get() != MESSAGE_START) { + return false; + } + uint16_t crc = CRC::next(MESSAGE_START); + for (uint16_t i = 0; i < 6; i++) { + crc = CRC::next(packet.raw[i] = JICE_io::get(), crc); + } + if (packet.size_word[0] > sizeof(packet.body)) { + return false; + } + if (JICE_io::get() != TOKEN) { + return false; + } + crc = CRC::next(TOKEN, crc); + for (uint16_t i = 0; i < packet.size; i++) { + crc = CRC::next(packet.body[i] = JICE_io::get(), crc); + } + uint16_t packet_crc = (JICE_io::get() | ((uint16_t)JICE_io::get() << 8)); + if (packet_crc != crc) { + return false; + } + return true; +} + +void JTAG2::answer() { + uint16_t crc = CRC::next(JICE_io::put(MESSAGE_START)); + for (uint16_t i = 0; i < 6; i++) { + crc = CRC::next(JICE_io::put(packet.raw[i]), crc); + } + crc = CRC::next(JICE_io::put(TOKEN), crc); + for (uint16_t i = 0; i < packet.size_word[0]; i++) { + crc = CRC::next(JICE_io::put(packet.body[i]), crc); + } + JICE_io::put(crc); + JICE_io::put(crc >> 8); +} + +void JTAG2::delay_exec() { + // wait for transmission complete + JICE_io::flush(); + // set baud rate + JICE_io::set_baud(PARAM_BAUD_RATE_VAL); +} + +// *** Set status function *** +void JTAG2::set_status(uint8_t status_code) { + packet.size_word[0] = 1; + packet.body[0] = status_code; +} + +// *** General command functions *** +// *** Signature response message *** +uint8_t JTAG2::sgn_resp[29] { 0x86, 1, + 1, PARAM_FW_VER_M_MIN_VAL, PARAM_FW_VER_M_MAJ_VAL, PARAM_HW_VER_M_VAL, + 1, PARAM_FW_VER_S_MIN_VAL, PARAM_FW_VER_S_MAJ_VAL, PARAM_HW_VER_S_VAL, + 0, 0, 0, 0, 0, 0, + 'J', 'T', 'A', 'G', 'I', 'C', 'E', ' ', 'm', 'k', 'I', 'I', 0 +}; +void JTAG2::sign_on() { + // Initialize JTAGICE2 variables + JTAG2::PARAM_EMU_MODE_VAL = 0x02; + JTAG2::PARAM_BAUD_RATE_VAL = JTAG2::baud_19200; + /* Initialize or enable UPDI */ + UPDI_io::put(UPDI_io::double_break); + UPDI::stcs(UPDI::reg::Control_B, 8); + UPDI::stcs(UPDI::reg::Control_A, 0x80); + // Send sign on message + packet.size_word[0] = sizeof(sgn_resp); + for (uint8_t i = 0; i < sizeof(sgn_resp); i++) { + packet.body[i] = sgn_resp[i]; + } +} + +void JTAG2::get_parameter() { + uint8_t & status = packet.body[0]; + uint8_t & parameter = packet.body[1]; + switch (parameter) { + case PARAM_HW_VER: + packet.size_word[0] = 3; + packet.body[1] = PARAM_HW_VER_M_VAL; + packet.body[2] = PARAM_HW_VER_S_VAL; + break; + case PARAM_FW_VER: + packet.size_word[0] = 5; + packet.body[1] = PARAM_FW_VER_M_MIN_VAL; + packet.body[2] = PARAM_FW_VER_M_MAJ_VAL; + packet.body[3] = PARAM_FW_VER_S_MIN_VAL; + packet.body[4] = PARAM_FW_VER_S_MAJ_VAL; + break; + case PARAM_EMU_MODE: + packet.size_word[0] = 2; + packet.body[1] = PARAM_EMU_MODE_VAL; + break; + case PARAM_BAUD_RATE: + packet.size_word[0] = 2; + packet.body[1] = PARAM_BAUD_RATE_VAL; + break; + case PARAM_VTARGET: + packet.size_word[0] = 3; + packet.body[1] = PARAM_VTARGET_VAL & 0xFF; + packet.body[2] = PARAM_VTARGET_VAL >> 8; + break; + default: + set_status(RSP_ILLEGAL_PARAMETER); + return; + } + status = RSP_PARAMETER; + return; +} + +void JTAG2::set_parameter() { + uint8_t & parameter = packet.body[1]; + switch (parameter) { + case PARAM_EMU_MODE: + PARAM_EMU_MODE_VAL = packet.body[2]; + break; + case PARAM_BAUD_RATE: + PARAM_BAUD_RATE_VAL = (baud_rate)packet.body[2]; + break; + default: + set_status(RSP_ILLEGAL_PARAMETER); + return; + } + set_status(RSP_OK); +} + +void JTAG2::set_device_descriptor() { + flash_pagesize = packet.body[244]; + eeprom_pagesize = packet.body[246]; + set_status(RSP_OK); +} + +// *** Target mode set functions *** +// *** Sets MCU in program mode, if possibe *** +void JTAG2::enter_progmode() { + // Reset the MCU now, to prevent the WDT (if active) to reset it at an unpredictable moment + UPDI::CPU_reset(); + // Now we have time to enter program mode (this mode also disables the WDT) + const uint8_t system_status = UPDI::CPU_mode<0xEF>(); + switch (system_status) { + // in normal operation mode + case 0x82: + // Write NVN unlock key (allows read access to all addressing space) + UPDI::write_key(UPDI::NVM_Prog); + // Request reset + UPDI::CPU_reset(); + // Wait for NVM unlock state + //while (UPDI::CPU_mode() != 0x08); + // already in program mode + case 0x08: + // better clear the page buffer, just in case. + UPDI::sts_b(NVM::NVM_base | NVM::CTRLA, NVM::PBC); + // Turn on LED to indicate program mode + set_status(RSP_OK); + break; + // in other modes fail and inform host of wrong mode + default: + packet.size_word[0] = 2; + packet.body[0] = RSP_ILLEGAL_MCU_STATE; + packet.body[1] = system_status; // 0x01; + } +} + +// *** Sets MCU in normal runnning mode, if possibe *** +void JTAG2::leave_progmode() { + const uint8_t system_status = UPDI::CPU_mode<0xEF>(); + switch (system_status) { + // in program mode + case 0x08: + // Request reset + UPDI::CPU_reset(); + // Wait for normal mode + // while (UPDI::CPU_mode<0xEF>() != 0x82); + // already in normal mode + case 0x82: + // Turn off LED to indicate normal mode + set_status(RSP_OK); + break; + // in other modes fail and inform host of wrong mode + default: + packet.size_word[0] = 2; + packet.body[0] = RSP_ILLEGAL_MCU_STATE; + packet.body[1] = system_status; // 0x01; + } +} + +// *** Read/Write/Erase functions *** + +void JTAG2::read_mem() { + if (UPDI::CPU_mode() != 0x08) { + // fail if not in program mode + packet.size_word[0] = 2; + packet.body[0] = RSP_ILLEGAL_MCU_STATE; + packet.body[1] = 0x01; + } + else { + // in program mode + const uint16_t NumBytes = (packet.body[3] << 8) | packet.body[2]; + // Get physical address for reading + const uint16_t address = (packet.body[7] << 8) | packet.body[6]; + // Set UPDI pointer to address + UPDI::stptr_w(address); + // Read block + UPDI::rep(NumBytes - 1); + packet.body[1] = UPDI::ldinc_b(); + for (uint16_t i = 2; i <= NumBytes; i++) { + packet.body[i] = UPDI_io::get(); + } + packet.size_word[0] = NumBytes + 1; + packet.body[0] = RSP_MEMORY; + } +} + +void JTAG2::write_mem() { + if (UPDI::CPU_mode() != 0x08) { + // fail if not in program mode + packet.size_word[0] = 2; + packet.body[0] = RSP_ILLEGAL_MCU_STATE; + packet.body[1] = 0x01; + } + else { + // in program mode + const uint8_t mem_type = packet.body[1]; + const uint16_t address = packet.body[6] | (packet.body[7] << 8); + const uint16_t lenght = packet.body[2] | (packet.body[3] << 8); /* number of bytes to write */ + const bool is_flash = ((mem_type == MTYPE_FLASH) || (mem_type == MTYPE_BOOT_FLASH)); + const uint8_t buff_size = is_flash ? flash_pagesize : eeprom_pagesize; + const uint8_t write_cmnd = is_flash ? NVM::WP : NVM::ERWP; + switch (mem_type) { + case MTYPE_FUSE_BITS: + case MTYPE_LOCK_BITS: + NVM_fuse_write (address, packet.body[10]); + break; + case MTYPE_FLASH: + case MTYPE_BOOT_FLASH: + case MTYPE_EEPROM_XMEGA: + case MTYPE_USERSIG: + NVM_buffered_write(address, lenght, buff_size, write_cmnd); + break; + default: + set_status(RSP_ILLEGAL_MEMORY_TYPE); + return; + } + set_status(RSP_OK); + } +} + +void JTAG2::erase() { + const uint8_t erase_type = packet.body[1]; + const uint16_t address = packet.body[2] | (packet.body[3] << 8); + switch (erase_type) { + case 0: + // Write Chip Erase key + UPDI::write_key(UPDI::Chip_Erase); + // Request reset + UPDI::CPU_reset(); + // Erase chip process exits program mode, reenter... + enter_progmode(); + break; + case 4: + case 5: + NVM::wait(); + UPDI::sts_b(address, 0xFF); + NVM::command(NVM::ER); + set_status(RSP_OK); + break; + case 6: + case 7: + break; + default: + set_status(RSP_FAILED); + } +} + +// *** Local functions definition *** +namespace { +void NVM_fuse_write (uint16_t address, uint8_t data) { + // Setup UPDI pointer + UPDI::stptr_w(NVM::NVM_base + NVM::DATA_lo); + // Send data to the NVM controller + UPDI::stinc_b(data); + UPDI::stinc_b(0x00); + // Send address to the NVM controller + UPDI::stinc_b(address & 0xFF); + UPDI::stinc_b(address >> 8); + // Execute fuse write + NVM::command(NVM::WFU); +} + +void NVM_buffered_write(const uint16_t address, const uint16_t length, const uint8_t buff_size, const uint8_t write_cmnd) { + uint8_t current_byte_index = 10; /* Index of the first byte to send inside the JTAG2 command body */ + uint16_t bytes_remaining = length; /* number of bytes to write */ + + // Sends a block of bytes from the command body to memory, using the UPDI interface + // On entry, the UPDI pointer must already point to the desired address + // On exit, the UPDI pointer points to the next byte after the last one written + // Returns updated index into the command body, pointing to the first unsent byte. + auto updi_send_block = [] (uint8_t count, uint8_t index) { + count--; + NVM::wait(); + UPDI::rep(count); + UPDI::stinc_b(JTAG2::packet.body[index]); + for (uint8_t i = count; i; i--) { + UPDI_io::put(JTAG2::packet.body[++index]); + UPDI_io::get(); + } + return ++index; + }; + + // Setup UPDI pointer for block transfer + UPDI::stptr_w(address); + /* Check address alignment, calculate number of unaligned bytes to send */ + uint8_t unaligned_bytes = (-address & (buff_size - 1)); + if (unaligned_bytes > bytes_remaining) unaligned_bytes = bytes_remaining; + /* If there are unaligned bytes, they must be sent first */ + if (unaligned_bytes) { + // Send unaligned block + current_byte_index = updi_send_block(unaligned_bytes, current_byte_index); + bytes_remaining -= unaligned_bytes; + NVM::command(write_cmnd); + } + while (bytes_remaining) { + /* Send a buff_size amount of bytes */ + if (bytes_remaining >= buff_size) { + current_byte_index = updi_send_block(buff_size, current_byte_index); + bytes_remaining -= buff_size; + } + /* Send a NumBytes amount of bytes */ + else { + current_byte_index = updi_send_block(bytes_remaining, current_byte_index); + bytes_remaining = 0; + } + NVM::command(write_cmnd); + } +} +} diff --git a/firmwares/MuxTO/JTAG2.h b/firmwares/MuxTO/JTAG2.h new file mode 100644 index 00000000..5a85942f --- /dev/null +++ b/firmwares/MuxTO/JTAG2.h @@ -0,0 +1,157 @@ +/* + packet.h + + Created: 12-11-2017 11:10:31 + Author: JMR_2 +*/ + + +#ifndef JTAG2_H_ +#define JTAG2_H_ + +#include +#include "sys.h" + +namespace JTAG2 { + +// *** Parameter IDs *** +enum parameter { + PARAM_HW_VER = 0x01, + PARAM_FW_VER = 0x02, + PARAM_EMU_MODE = 0x03, + PARAM_BAUD_RATE = 0x05, + PARAM_VTARGET = 0x06 +}; + +// *** valid values for PARAM_BAUD_RATE_VAL +enum baud_rate { + baud_2400 = 0x01, + baud_4800, + baud_9600, + baud_19200, // default + baud_38400, + baud_57600, + baud_115200, + baud_14400 +}; + +// *** Parameter Values *** +constexpr uint8_t PARAM_HW_VER_M_VAL = 0x01; +constexpr uint8_t PARAM_HW_VER_S_VAL = 0x01; +constexpr uint8_t PARAM_FW_VER_M_MIN_VAL = 0x07; +constexpr uint8_t PARAM_FW_VER_M_MAJ_VAL = 0x01; +constexpr uint8_t PARAM_FW_VER_S_MIN_VAL = 0x07; +constexpr uint8_t PARAM_FW_VER_S_MAJ_VAL = 0x06; +extern uint8_t PARAM_EMU_MODE_VAL; +extern baud_rate PARAM_BAUD_RATE_VAL; +constexpr uint16_t PARAM_VTARGET_VAL = 5000; + +// *** General command constants *** +enum cmnd { + CMND_SIGN_OFF = 0x00, + CMND_GET_SIGN_ON = 0x01, + CMND_SET_PARAMETER = 0x02, + CMND_GET_PARAMETER = 0x03, + CMND_WRITE_MEMORY = 0x04, + CMND_READ_MEMORY = 0x05, + CMND_GO = 0x08, + CMND_RESET = 0x0b, + CMND_SET_DEVICE_DESCRIPTOR = 0x0c, + CMND_GET_SYNC = 0x0f, + CMND_ENTER_PROGMODE = 0x14, + CMND_LEAVE_PROGMODE = 0x15, + CMND_XMEGA_ERASE = 0x34 +}; +// *** JTAG Mk2 Single byte status responses *** +enum response { + // Success + RSP_OK = 0x80, + RSP_PARAMETER = 0x81, + RSP_MEMORY = 0x82, + // Error + RSP_FAILED = 0xA0, + RSP_ILLEGAL_PARAMETER = 0xA1, + RSP_ILLEGAL_MEMORY_TYPE = 0xA2, + RSP_ILLEGAL_MEMORY_RANGE = 0xA3, + RSP_ILLEGAL_MCU_STATE = 0xA5, + RSP_ILLEGAL_VALUE = 0xA6, + RSP_ILLEGAL_BREAKPOINT = 0xA8, + RSP_ILLEGAL_JTAG_ID = 0xA9, + RSP_ILLEGAL_COMMAND = 0xAA, + RSP_NO_TARGET_POWER = 0xAB, + RSP_DEBUGWIRE_SYNC_FAILED = 0xAC, + RSP_ILLEGAL_POWER_STATE = 0xAD +}; + +// *** memory types for CMND_{READ,WRITE}_MEMORY *** +enum mem_type { + MTYPE_IO_SHADOW = 0x30, // cached IO registers? + MTYPE_SRAM = 0x20, // target's SRAM or [ext.] IO registers + MTYPE_EEPROM = 0x22, // EEPROM, what way? + MTYPE_EVENT = 0x60, // ICE event memory + MTYPE_SPM = 0xA0, // flash through LPM/SPM + MTYPE_FLASH_PAGE = 0xB0, // flash in programming mode + MTYPE_EEPROM_PAGE = 0xB1, // EEPROM in programming mode + MTYPE_FUSE_BITS = 0xB2, // fuse bits in programming mode + MTYPE_LOCK_BITS = 0xB3, // lock bits in programming mode + MTYPE_SIGN_JTAG = 0xB4, // signature in programming mode + MTYPE_OSCCAL_BYTE = 0xB5, // osccal cells in programming mode + MTYPE_CAN = 0xB6, // CAN mailbox + MTYPE_FLASH = 0xc0, // xmega (app.) flash + MTYPE_BOOT_FLASH = 0xc1, // xmega boot flash + MTYPE_EEPROM_XMEGA = 0xc4, // xmega EEPROM in debug mode + MTYPE_USERSIG = 0xc5, // xmega user signature + MTYPE_PRODSIG = 0xc6 // xmega production signature +}; + +// *** STK500 packet *** +constexpr uint8_t MESSAGE_START = 0x1B; +constexpr int MAX_BODY_SIZE = 450; // Note: should not be reduced to less than 300 bytes. +union __attribute__((packed)) packet_t { + uint8_t raw[6 + MAX_BODY_SIZE]; + struct __attribute__((packed)) { + union { + uint16_t number; + uint8_t number_byte[2]; + }; + union { + uint32_t size; + uint16_t size_word[2]; + uint8_t size_byte[4]; + }; + uint8_t body[MAX_BODY_SIZE]; + }; +} extern packet; +constexpr uint8_t TOKEN = 0x0E; + +// *** Signature response *** +extern uint8_t sgn_resp[29]; +// *** Parameter initialization *** +void init(); + +// *** Packet functions *** +bool receive(); +void answer(); +void delay_exec(); + +// *** Set status function *** +void set_status(uint8_t) __attribute__ ((noinline)); + +// *** General command functions *** +void sign_on(); +void get_parameter(); +void set_parameter(); +void set_device_descriptor(); + +// *** ISP command functions *** +void enter_progmode(); +void leave_progmode(); +void read_signature(); +void read_mem(); +void write_mem(); +void erase(); +} + + + +#endif /* STK_H_ */ diff --git a/firmwares/MuxTO/MuxTO.bin b/firmwares/MuxTO/MuxTO.bin new file mode 100755 index 00000000..b2902861 Binary files /dev/null and b/firmwares/MuxTO/MuxTO.bin differ diff --git a/firmwares/MuxTO/MuxTO.hex b/firmwares/MuxTO/MuxTO.hex new file mode 100644 index 00000000..012215d9 --- /dev/null +++ b/firmwares/MuxTO/MuxTO.hex @@ -0,0 +1,770 @@ +:1010000000100020A91C00008D1C0000A51C000081 +:1010100000000000000000000000000000000000D0 +:101020000000000000000000000000008D1C000017 +:1010300000000000000000008D1C0000191D0000D1 +:101040008D1C00008D1C00008D1C00008D1C0000FC +:101050008D1C00008D1C00008D1C0000911C0000E8 +:101060008D1C0000191C0000091C00008D1C0000D4 +:101070008D1C00008D1C00008D1C00008D1C0000CC +:101080008D1C00008D1C00008D1C000010B5064C4E +:101090002378002B07D1054B002B02D0044800E039 +:1010A00000BF0123237010BD80010020000000005C +:1010B0007C3E0000044B10B5002B03D003490448CC +:1010C00000E000BF10BDC046000000008401002009 +:1010D0007C3E0000E12110B50248490201F080F990 +:1010E00010BDC0465C0400207047000010B504002D +:1010F0000100024801F0F6F8200010BD5C04002059 +:1011000010B5024801F020F9C0B210BD5C04002007 +:1011100010B5024801F0F6F810BDC0465C0400208E +:10112000F8B5451E07000C0000F0B6FC0600EDB255 +:101130000F4800F089FC03231842F9D1300000F079 +:10114000C5FC280000F058FC0A4E3D193319987967 +:1011500000F0CDFCEDB20134E4B2AC4206D033195C +:10116000987900F0E1FC00F0FDFCF4E72000F8BD08 +:1011700002100000A001002070B5FFF7C1FF1B287E +:1011800001D0002070BD224900F0C0FC0026040000 +:10119000FFF7B6FF1F4D2100A85500F0B7FC013640 +:1011A0000400062EF4D1E122EB78A9781B0252004C +:1011B0000B439342E5D8FFF7A3FF0E28E1D12100AE +:1011C00000F0A4FC00260400EA78AB7812021A436F +:1011D0002B791B041A436B791B0613439E420AD2D8 +:1011E000FFF78EFFAB192100987100F08FFC0136DC +:1011F0000400B6B2E8E7FFF783FF0500FFF780FFC2 +:1012000003022B439BB21B1B58425841C0B2B9E7A3 +:10121000FFFF0000A001002070B51B20FFF766FF54 +:10122000184900F073FC00250400174E705DFFF7AD +:101230005DFF210000F06AFC01350400062DF4D1A9 +:101240000E20FFF753FF210000F060FC0025040092 +:10125000F378B2781B021343AB420AD97319987919 +:10126000FFF744FF210000F051FC01350400ADB24E +:10127000EEE7E0B22412FFF739FFE0B2FFF736FFE6 +:1012800070BDC046FFFF0000A001002010B5FFF7B1 +:101290003FFF024B1878FFF727FF10BD9F0100208A +:1012A0000122034B9A7000229871DA707047C04691 +:1012B000A001002010B5022404220E4B01201C7056 +:1012C0000D4B1A7000F05CFC0821032000F0A0FB1D +:1012D0008021200000F09CFB00231D21074A0848C4 +:1012E0009170D370074A195CD15401331D2BFAD188 +:1012F00010BDC0469E0100209F010020A0010020DB +:1013000060000020A601002010B51D4BD8790138DF +:10131000052830D802F0B2FA030B192F2127032237 +:101320009A700022DA700132DA711A720AE005222C +:101330009A7000220121DA700732DA715A72013A8A +:1013400019729A7281229A7118E002229A70002210 +:10135000DA700C4A1278DA71F4E702229A700022ED +:10136000DA70094AF6E703229A700022DA708832AE +:10137000DA71753AD9E7A120FFF792FF10BDC04698 +:10138000A00100209E0100209F01002010B5094B04 +:10139000DA79032A03D0052A08D0A12003E01A7ABB +:1013A000054B80201A70FFF77BFF10BD1A7A034BA4 +:1013B000F7E7C046A00100209E0100209F01002009 +:1013C000074B10B51A00FA321178064AFC33117037 +:1013D0001A78054B80201A70FFF762FF10BDC046D7 +:1013E000A00100209C0100209D0100200B2010B5D1 +:1013F00000F01DFBEF23184008280AD082280AD0ED +:101400000222074B9A700022DA70A5329A71D871C5 +:1014100004E000F0E1FA8020FFF742FF10BDC04673 +:10142000A001002070B50B2000F001FB174C08282C +:1014300008D00223A3700023E370A533A371A43B5B +:10144000E37170BD637A257A1B021D43637B207BA9 +:101450001B022EB21843013E00F038FBF0B200F040 +:10146000CBFA00F029FB0226E071AE4206D800F06C +:1014700079FBA31901369871B6B2F6E70135ABB224 +:101480001B0AE3708223A570A371DAE7A001002094 +:1014900070B50500552000F047FBE02000F044FB4C +:1014A0000824013C2878E4B200F03EFB0135002C12 +:1014B000F7D170BD10B500F08FFA0B2000F0B7FA2D +:1014C000EF231840082806D082280DD10B48FFF7DB +:1014D000DFFF00F081FA80200421400100F0C5FA0E +:1014E0008020FFF7DDFE10BD0222054B9A7000221E +:1014F000DA70A5329A71D871F5E7C04691000020E4 +:10150000A001002070B5164AD379052B05D8032B0E +:101510000FD8002B05D0A0201EE0063B012BFAD8E7 +:1015200070BD1048FFF7B4FF00F056FAFFF7C2FF96 +:10153000F6E70326157A547A0B4800F085FA304214 +:10154000FAD12002FF21284300F08FFA80200221E7 +:10155000400100F08AFA8020FFF7A2FEE0E7C046D3 +:10156000A0010020890000200210000070B50500D5 +:1015700000F092FA040080202900400100F075FA82 +:10158000200000F0A3FA70BDF7B50B2000F04FFA71 +:10159000394B082808D002229A700022DA70A5324E +:1015A0009A71A43ADA71F7BDDA79587B11001D7B84 +:1015B000000240310543C9B22EB2012929D82F4A71 +:1015C000177801220092587A1C7A0002044323B251 +:1015D00028000193764200F079FA781E0640F6B2B0 +:1015E000A64201DD6B461E790A25002E09D029008E +:1015F0003000FFF795FD0500A41BA4B20098FFF78B +:10160000B5FF002C2FD0BEB2BC422ED3290038002B +:10161000EFE71B490F78B32A05D8B12A0ED8A220CC +:10162000FFF73EFEBFE7C12A03D8BF2AF7D903223E +:10163000C8E73C32D2B2012AF1D8F8E71C7C114845 +:1016400000F044FA200000F052FA002000F04FFAB7 +:10165000F0B200F04CFA280A00F049FA8020072185 +:10166000400100F002FA8020DAE72900E0B2FFF73B +:1016700057FD00240500C1E7A00100209C010020C7 +:101680009D0100200610000010B50121002000F08F +:10169000F1FBFFF71FFD00F0ABFA054B05481A8878 +:1016A000054B196801F0FEFFFFF704FE10BDC046B0 +:1016B00086000020BC03002080000020AF4BF7B55F +:1016C0001B78002B00D0FFE0AD4E300001F0E0FEB3 +:1016D000AC4C051E1BD0EFF3108372B6AA4F20004E +:1016E0003B6000F0FDFDA84203DA200000F0F8FDA9 +:1016F00005003B6883F31088A44F2A0039003000AE +:1017000000F0DDFD2A003900200000F001FE20007D +:1017100000F0F2FD051E1BD0EFF3108372B69A4F56 +:1017200030003B6001F0C5FEA84203DA300001F052 +:10173000C0FE05003B6883F31088944F2A003900EF +:10174000200000F04EFE2A003900300000F08AFC34 +:10175000200000F06BFE8E4F3B7883420FD0F022CA +:101760008C4D20002B8893432B8000F05FFE0122DC +:10177000894B38701A70904239D002283CD0200032 +:1017800000F05AFE854F3B78834215D00F22814DE1 +:1017900020002B8893432B8000F04EFE01227E4BCD +:1017A00038701A7090422AD0022828D0002803D11D +:1017B00003232A8813432B80200000F043FE784F38 +:1017C0003B78834223D0734D764A2B882000134008 +:1017D0002B8000F037FE01226F4B387005381A70ED +:1017E000032814D82A8802F049F80E5B5E601023A3 +:1017F0002A8813432B80C2E730232A88F9E72B88F5 +:1018000018432880D8E780235B0013432B8096235E +:10181000654DDB002A689A4215D1200000F018FEC1 +:10182000019000280FD100F085FA604F3B68C01A84 +:10183000C82808D90123514A137000F07BFA5C4B89 +:101840001860019B3B60200000F0EAFD2B68594FB7 +:1018500098422DD0200000F0FBFD3870200000F0F1 +:10186000F7FD00282FD0200000F0DAFD28603000BE +:1018700001F000FE96232968DB00994223D0002462 +:10188000444B30001A8801F00DFF434B59210820CA +:101890001C7000F0BDF82100082000F0B9F812E03B +:1018A00080239B00B1E7C023FBE78023DB00ACE78C +:1018B000394B1B78002BCDD1200000F0C9FD00234F +:1018C000FB569842C6D1F7BD2C4B1B78002BFAD0A3 +:1018D000364C2368002B1CD100F02CFA344B1B68CB +:1018E000C01A354B98421CD8FFF746FC0028EAD0B6 +:1018F000324B987915281CD801F0C0FF2F1F2926DC +:1019000067641D1D381D1D2C3C1D1D381D1D1D1D12 +:101910002C3200F00FFA2368C01AFA235B009842B9 +:10192000DAD90023154A137001221F4B52421A6064 +:10193000C9E734284CD0A02019E0FFF7BBFCFFF723 +:101940006BFCFFF7A3FCBEE7FFF7DEFCF7E7FFF752 +:101950001DFDF4E7FFF7AEFDF1E70422184B1A7006 +:10196000FFF744FD00F0E6F92060E8E78020FFF78C +:1019700097FCE4E7FFF724FDE1E7C046B103002050 +:10198000BC0300205C0400206C03002071030020D5 +:1019900088000020860000207003002068030020DB +:1019A00085000020FFF0FFFF80000020B40300202E +:1019B000B80300208400002060EA0000A00100209D +:1019C0009F010020FFF72EFDB9E7FFF7DDFDB6E729 +:1019D000FFF798FDB3E7C04610B55921082000F085 +:1019E00017F80021082000F013F80E240B2000F057 +:1019F0001EF82042FAD010BD10B50400552000F0AA +:101A000093F8A02000F090F8200000F08DF810BDB1 +:101A100070B5040055200D0000F086F82000403815 +:101A2000C0B200F081F8280000F07EF870BD10B55B +:101A30000400552000F078F820008038C0B200F093 +:101A400073F800F08FF810BD10B50400552000F0B9 +:101A50006BF8042000F068F8E0B200F065F8200AA6 +:101A600000F062F800F07EF810BD70B504000D00C3 +:101A7000552000F059F8442000F056F8E0B200F08C +:101A800053F8200A00F050F800F06CF8280000F03D +:101A90004BF800F067F870BD10B5552000F044F821 +:101AA000292000F041F800F05DF8040000F05AF839 +:101AB0000002204380B210BD10B5552000F034F86C +:101AC000242000F031F800F04DF810BD10B50400EE +:101AD000552000F029F8692000F026F8E0B200F067 +:101AE00023F8200A00F020F800F03CF810BD10B5F3 +:101AF0000400552000F018F8642000F015F82000CC +:101B000000F012F800F02EF810BD0000FF2248404F +:101B1000044BC0B24000C35A09125940C8B29343A3 +:101B200018437047703B000070B50D4D0100040074 +:101B3000280001F04BFD280001F0AFFC00F0FAF89E +:101B40000600280001F0A4FC002804D100F0F2F8FF +:101B5000801B1328F5D9280001F0B0FC200070BDCF +:101B60000004002010B5054C200001F091FC002875 +:101B7000F9D0200001F0A2FCC0B210BD000400208A +:101B8000962170B5174C0500174A2000490001F056 +:101B900089FD002D1BD0012D0DD10021200001F069 +:101BA00015FD200001F079FC0021200001F00EFD60 +:101BB000200001F072FC0F2000F0C2F8200001F0BC +:101BC00067FC051E05D0200001F078FCF6E729002F +:101BD000EBE7E1212000054A890201F063FD2800BE +:101BE00070BDC04600040020130400003104000052 +:101BF000E12110B5024A0348890201F053FD10BDEE +:101C0000310400000004002010B5024801F09EFCE1 +:101C100010BDC046BC03002010B5024801F096FC80 +:101C200010BDC04600040020F7B5002601240F4D6A +:101C30000F49280000F038FA0E4F0F49380000F025 +:101C400033FA0E490E4800F02FFA390023000196AE +:101C5000022200940B4801F04DFC29000196032359 +:101C600004220094084801F045FCF7BD440400201C +:101C70000008004248040020000C0042001000420E +:101C80004C040020BC03002000040020FEE70000FC +:101C9000034B10B51B68002B00D0984710BDC04601 +:101CA000500400200DBEFEE7134A1448110010B581 +:101CB000134B824202D0934212D11300824212D1BE +:101CC0000222104B5A62104B0832DA700F4B20324E +:101CD0009A7300F061F801F04DFDFEE710CB10C1E2 +:101CE0008142FBD3EAE70A4A8B42E9D00021094B43 +:101CF0009A42E5D202C2FBE70000002080010020EA +:101D0000803E0000FC70004100500041004800414E +:101D1000800100204408002010B500F02AF80028B7 +:101D200001D100F01BF810BD014B18607047C04690 +:101D300050040020014B18687047C046540400202E +:101D400070B5041E07D0044D2E6800F011F82B6802 +:101D50009B1BA342F9D370BD5404002010B5034A65 +:101D600013680133136000F08FF910BD5404002094 +:101D70007047002070470000024A53785BB2002B86 +:101D8000FBDB7047000C004010230249CA681A426E +:101D9000FCD0704700080040822210B5154B164C4D +:101DA0005A60A38C023A9343A384FFF7EDFF80228D +:101DB000124B92001B689B0E9B021343A362104BB5 +:101DC000E36292235B00A384FFF7DEFF0223A28C71 +:101DD0001343A384FFF7D8FF80230A4C5B00A36062 +:101DE000FFF7CAFF084B6360FFF7C6FF074B084ABF +:101DF0001A6010BD004000410008004024608000CF +:101E000080BB0A7C000C0040000703009C000020FF +:101E1000006CDC02C0201249124B134A10B54B6013 +:101E2000136A00061B021B0A0343136200240723E4 +:101E30008C600B608021136A09061B021B0A0B438E +:101E400013620A4B196A1A6A1143094A0A431A6251 +:101E500020001A21013400F00DF8072CF8D110BD34 +:101E600010E000E07FBB000000ED00E00004004057 +:101E7000FC05000010B500F053F810BDF7B50C22BA +:101E80004243244D0191535D042B2DD00027AA1805 +:101E90005278214EDB01D418A419204E24789E5983 +:101EA000E4B2BE4203D0013797407E1EB7411B4EBD +:101EB0009E193669B44600266146B14203D0013608 +:101EC0009640711E8E41002F17D10C37784301992F +:101ED0002D18686801290DD1012E06D1410706D4BD +:101EE000D3180D4A9B181C70F7BD0107F8D50421C3 +:101EF0000C43F5E704218C43F2E701209040019A5E +:101F0000012A03D1054A9B189861EDE7034A9B1803 +:101F10005861E9E7703D0000404400410044004141 +:101F20000C225043494B70B5C65C1B185C78DD78B9 +:101F3000042E00D187E0081F172842D801F09EFC2C +:101F40000C313131414141413333393D3D41414112 +:101F50004141413F418341830023002E33D0F001B2 +:101F60003B4E221892191678042232404E1F022E40 +:101F70003BD82D0701D540252A4372B6002901D050 +:101F80001A2935D10123A340324941184B608B6196 +:101F900004239A432E4923185B181A7062B6002056 +:101FA00070BD0123D9E706232B405A1E9341043309 +:101FB000D3E701232B400233CFE70623CDE70723E6 +:101FC000CBE70923C9E7022CC9D10629C7D0224A89 +:101FD00010780028C3D01670204A1078A0431070E3 +:101FE000D079C0090128FBD0B9E702263243C0E707 +:101FF0008D1E012D0CD80123A340164D45196B6091 +:10200000032903D16B6104231A43C3E7AB61FAE7E9 +:10201000012904D1A1400F4BC3189960B8E71049BA +:1020200065082D186D18E10707D50F2629781B01C3 +:1020300031400B432B700123E6E70F262978B1438B +:1020400019432970F7E701204042A9E7703D0000DD +:102050004044004100440041580400200028004250 +:1020600030440041F8B505000E0017000024BC42C2 +:1020700008D02B682800315D1B689847002801D0E4 +:102080000134F4E72000F8BD054A10B51368591C67 +:1020900005D0013B1360002B01D1024B984710BDC6 +:1020A000A000002001000020016070479446F0B5B8 +:1020B00005AC25789C1E621E944162460668920714 +:1020C000376824063A4322430724326000682140DF +:1020D000AD01002442682943022B00D05C030A436F +:1020E00022434260F0BD30B5C0250368AD031C68D3 +:1020F00012052A402243C0240904A40221400A43B5 +:102100001A6003685A6814435C6030BD012302689A +:1021100011680B43136003681A68D207FCD4DA69AC +:10212000D207F9D470470223026811680B43136089 +:102130000268D3699B07FCD4704703681A7ED207F4 +:1021400002D41A7E9207FCD57047002203685A8396 +:1021500070470368187E4007C00F70470368187EF9 +:10216000C0097047802302685B42117E0B431376DF +:1021700070470368187EC007C00F70470368188D4A +:10218000C0B2704703681A7ED207FCD589B201201D +:1021900019857047012203689A7570470122036808 +:1021A0001A7570470368194A30B5934227D0184A08 +:1021B000934227D0174A934220D10B2310210325A5 +:1021C00001229A402B40AB40C224FC359D4012486E +:1021D000A40002600259AA43C0259D402B0013436E +:1021E00080220351D2010D4B0A435A800C4A1168D8 +:1021F0000C4A11605A7852B2002AFBDB30BD092329 +:102200000E21DCE70A230F21D9E7C046000800426F +:10221000000C00420010004200E100E0000C004011 +:102220009C000020A4000020F8B504000F00160058 +:102230001D00FFF7B7FF2000FFF768FF1C21BB0060 +:102240000B4071072268090C0B431360842322683A +:102250009375012F1AD11021012E00D008390C4B93 +:1022600069431868C00001F013FB0722216802408F +:102270008B895203DB04DB0C13438B81226803043C +:102280009089DB0C400B400318439081F8BDC04699 +:10229000A400002010B50400FFF74CFDE0602368A7 +:1022A00020005B699847002808DAFFF743FDE368E0 +:1022B000C01AA3689842F2D30120404210BDF8B57D +:1022C00006000D0017000024BC4207D03000FFF7C5 +:1022D000E1FF002802DB28550134F5E72000F8BDB6 +:1022E0003F20704713B56B460268D97107335468B5 +:1022F00019000122A04716BD10B50221006900F0A7 +:10230000ADFC10BD10B50321006900F0BDFC10BD8F +:1023100010B5130004000A000069032100F0ACFDB1 +:10232000002801D10123636010BD000010B5054CE9 +:1023300003002068421C04D11A68180052699047B3 +:10234000206010BDF0000020074A0300106810B59F +:10235000411C03D001235B42136010BD02211869A8 +:1023600000F07CFDF9E7C046F000002010B50378CE +:102370003A22023303700249024800F029FE10BDE0 +:10238000B40000207804002010B5027800244378BF +:10239000A12A09D1212B05D10E490F489A3A00F004 +:1023A00017FE0134200010BD212AFBD1202B05D1BE +:1023B00008491A3A084800F0ABFCF3E7222B05D095 +:1023C000232BEFD14288054B1A60EBE78278014B53 +:1023D000DA71E7E7AC00002078040020A8000020B4 +:1023E0007047F7B5050017000191FFF7A3FC002423 +:1023F000E860BC4211D2019A022128693B1B1219E4 +:1024000000F0C0FC061E01D0A419F2E7FFF792FC11 +:10241000EB68C01AAB689842F6D32000FEBD0000FE +:10242000014B18687047C046AC000020014B18797A +:10243000C0B27047AC000020014B5879C0B2704761 +:10244000AC000020014B9879C0B27047AC0000206E +:10245000024BD879012318407047C046AC000020D9 +:10246000FA220021054B92009A60054A08321A6050 +:10247000044A59601A6119767047C0465C0400200E +:10248000C43D000078040020704770B50F26CB1DB6 +:1024900002003240D5B22C0000093034092A00DD98 +:1024A00007341C705A1E994200D170BD1300EFE72B +:1024B00010B5040001F082F9200010BD70B582292A +:1024C0001FD1C3B22A4D5A01AA189169294C800123 +:1024D0000C40C021890521439161274908334018E8 +:1024E0005061802228685B01C1180C795242224356 +:1024F0000A7170211A5C8A43110030220A431A546F +:1025000070BD0029FCD1C026C1B219484B01C318C7 +:102510009A68184DB6052A4032439A60083104681B +:1025200048010721154A5A60025D8A4311000122C1 +:102530000A43702102559A692A4032439A610E4A31 +:102540005A61025D8A43110010220A4302559A68BB +:102550000B4920181140802252030A439A609A685E +:10256000920B92039A604023427913434371C7E769 +:1025700030070020FFFFFF8FA40400206405002027 +:10258000FF3F00F070B50400012320CC00212A7821 +:102590002000134380222B70520001F002FAAB7826 +:1025A000DB07FCD46C6270BD1F22144B70B51B6836 +:1025B000590B9C0C9B0111405B0F22401F2900D13D +:1025C0001A391F2A00D1023A072B00D1043B1F25DC +:1025D00000688E01048D0A492A402140314301855B +:1025E000018D14000A00AA4322430285028D1903BB +:1025F000044B13400B43038570BDC046246080002C +:102600003FF8FFFFFF8FFFFFEFF31083036001230D +:10261000436072B670470368002B02D162B6BFF305 +:102620006F8F7047836973B50400002B18D10600C3 +:10263000683635786846FFF7E7FF019BEDB2013B4E +:1026400002D33578EDB2FAE768460193FFF7E3FF6E +:10265000002D01D1002076BD606E236EC01AFAE70E +:102660006846FFF7D1FF22000025019BB432013BF1 +:1026700002D31578EDB2FAE768460193FFF7CBFF76 +:10268000002DE7D02300AC34B03318682368E5E7A9 +:1026900010B543694468DBB25A01A2189168094831 +:1026A00008330840802149030143916091685B0130 +:1026B000890B890391602268D318402219790A4353 +:1026C0001A7110BDFF3F00F0F7B504006846FFF730 +:1026D0009BFF0026019B5A1E0192002B05D0200073 +:1026E000083001F0A6F80600F4E76846FFF793FF0C +:1026F000A5696846002D49D1FFF786FF2000019BA0 +:102700006830013B5A1C0BD00278591E002A05D1B3 +:1027100068460193FFF77FFF2800FEBD0B00F1E73D +:1027200068460193FFF777FF236EB5420ED0626EC5 +:102730009A420BD920005A1CE31822660133D97F34 +:102740000830C9B201F04DF80135EDE7626E9A42EA +:10275000E2D10023236601336846A361FFF754FFEB +:10276000270022000021019B6837013BB532581C2D +:10277000CED0397010785E1E002805D02000117070 +:102780000193FFF785FFEBE73300F0E7FFF73CFF2E +:102790002000019BB430013B5A1C06D00278591E20 +:1027A000D5B2002AB4D00B00F6E7684601930025A5 +:1027B000FFF731FF22002100AC321368B031B5427F +:1027C00002D0086898421DD809689942A4D1002314 +:1027D00068461360A361FFF717FF2700220000215E +:1027E000019BB437013BB532581C00D190E73970DA +:1027F00010785E1E002811D0200011700193FFF7A1 +:1028000047FFEAE72000591CE31811606C33197880 +:102810000830C9B200F0E5FF0135CBE73300E3E74C +:1028200010B50400FFF750FF2000083001F00FF84A +:1028300010BD10B50400FFF747FF2000083000F07E +:10284000F2FF10BDF0B585B0160001910500FFF74D +:102850003BFF02A8FFF7D8FE0024039B5A1E0392F9 +:10286000002B0FD0B442F8D22F000837380000F008 +:10287000DAFF0028F1D0380000F0C4FF019B1855A2 +:102880000134EFE702A8FFF7C6FE200005B0F0BD57 +:10289000F7B542694368D2B21100040008311868E4 +:1028A00049014118C979C90712D552019B189A6884 +:1028B0009204910C002A0CD12000FFF7E9FE636816 +:1028C0001A686369DBB208335B01D3187F22DA71BF +:1028D000F7BDE269002A21D1220001256C32616630 +:1028E0006846E5615A60FFF78FFE26002000210050 +:1028F000019B6836013BB430B5315A1C33D035707A +:1029000002785F1ED2B20A700A78002A04D1200031 +:102910000193FFF7BDFEE8E73B00EEE72200B0328F +:1029200011600022E2612200203268465A60FFF7FF +:102930006BFE0125260020002100019BB436013BDF +:102940006830B5315A1C0ED0357002785F1ED2B295 +:102950000A700A78002A04D120000193FFF798FE3C +:10296000E8E73B00EEE768460193FFF754FEA6E771 +:1029700013B56A4600230C00D01DD371FFF7F6FC97 +:10298000236818186B462060D87916BD03290ED12C +:1029900080220E4B62311B68FF31585C5242024369 +:1029A0005A5468226339FF32FF399954704701291C +:1029B000FCD18022054B24311B68FF31585C524208 +:1029C00002435A5428222339FF32EDE73007002012 +:1029D00070B50024274B0121050020001C70FFF773 +:1029E00049FA01212000FFF749FA234B0121200079 +:1029F0001C70FFF73FFA01212000FFF73FFA202368 +:102A00001E4A0520D1690B43D3610F21FFF788FAD5 +:102A10000F210620FFF784FA194B1A4A5A805A7878 +:102A200052B2002AFBDB1848FFF77EF9174C200052 +:102A3000FFF7A8FD2000FFF7B7FD7F212368C12025 +:102A40001A7880000A401A70042219780A430C216F +:102A50001A701A898A430E491A810A581202120AF8 +:102A60000A5080220A6019787E3A0A431A700123BC +:102A70002B7070BD990400209804002000040040D1 +:102A8000000C0040064000004134000030070020E8 +:102A900000E100E00078002810D00121084B1B68FD +:102AA0001A898A431A810822198B0A431A8304223D +:102AB000198B0A431A830022024B1A607047C046E2 +:102AC00030070020280700200A000E498B699B0B65 +:102AD0009B038B610B680221FF331972987982394D +:102AE00001439971197A8907FCD57F20064B024072 +:102AF000997A8143114380229972997A52420A430A +:102B00009A727047300700200050004100200B7976 +:102B100010B583420AD10800FFF736FC002805D122 +:102B2000034A013093699B0B9B03936110BDC04620 +:102B300030070020F7B50D001100832A19D1EBB240 +:102B4000384C5A01A21891693748AD010840C0219C +:102B5000890501439161354920686D18702108335A +:102B600055615B011A5C8A43110040220A431A54E2 +:102B7000F7BD022A52D12E4BAA00D058002802D00D +:102B800003685B699847B82000F014FE0400294BE5 +:102B9000FF260360234B4360083000F013FE29003A +:102BA00022000023606868323140A3616561E361FF +:102BB000236663664901137053649364443213724D +:102BC000411853728B68184AAD001A40C0239B0508 +:102BD00013438B606269036832401100019207223F +:102BE00008314901CF5C9743BC460327624617432F +:102BF000CF542700019A203752018218576062692A +:102C00002000324052019B1801229B19997A0A43F5 +:102C10009A72FFF73DFD064BEC50A9E72800FFF73D +:102C20004DFCA5E730070020FFFFFF8F6405002063 +:102C30007C040020F43D000070B505000124064B23 +:102C4000A200D258002A05D021002800FFF772FF09 +:102C50000134F4E770BDC046F4000020084B8A0040 +:102C6000D05810B5002803D003689B68984710BD62 +:102C7000044BC9B24901591888688004800CF6E7F2 +:102C80007C0400203007002010B50C00FFF7E6FFA1 +:102C900000280CD0064BE4B2196880230834640184 +:102CA0000C1962795B42134363710223E37110BD17 +:102CB0003007002070B5CBB2124A13485C0189017D +:102CC0008918021951609168104D08330D40802118 +:102CD00089022943402591609168890B890391609D +:102CE00001685A018A1816793543157195796D0670 +:102CF000FCD55B01C918CB79DB07FCD500198068CE +:102D0000C0B270BD6405002030070020FF3F00F016 +:102D100070B5140040220B4B0D001B68FF3359792E +:102D20000A435A710021FFF7C5FFA04200D92000D5 +:102D300000230549A34203D0CA5CEA540133F9E7F2 +:102D400070BDC046300700206405002010B50C4857 +:102D5000C9B24901421893689B049B0C3F2B0BD9C5 +:102D60009468403B9B04A40B9B0CA40323439360F7 +:102D700041188868C0B210BD93689B0B9B03F6E7AF +:102D800030070020F0B51C002F4B85B01B680600F3 +:102D90000D000192002B54D02C4F3B78D8B2002B61 +:102DA00002D10100FFF76AF864233B70284BAA00A8 +:102DB000D058002808D0036822005B680199984722 +:102DC0000400200005B0F0BD29003000FFF746FFE9 +:102DD000844204D929003000FFF740FF0400290095 +:102DE0003000FFF7B3FF0121EBB21A4F03935B01F1 +:102DF0000293029A3B6801989B18FF335A7A0A4360 +:102E00005A72154BA9012200C91800F0C1FD002C0F +:102E1000D7D029003000FFF721FF0028D1D1402171 +:102E2000039B3A6808335B01D31818790143197181 +:102E30000121D971029BD318FF339A7A0A439A72FF +:102E4000BFE701246442BCE7280700209804002063 +:102E50007C040020300700206405002013B56B4679 +:102E6000DC1D22000123FFF78DFF012801D120780E +:102E700016BD01204042FBE7F0B51C003A4B85B07F +:102E80001B680E000192002B3FD08023DB019C4287 +:102E90003BD8364D2B78D8B2002B02D10100FEF77B +:102EA000EDFF642300272B70314BB201D31802933E +:102EB000002C2CD02F4B1B680393FF2333401D00A5 +:102EC00000930835039B6D015D19AB79DB0921D0B7 +:102ED000294B2A49186800F0DBFC294B172158437D +:102EE00000F0D6FC274BEA79920713D49A5D002AAA +:102EF00001D10138F7D201229A55009B5A011D4B8E +:102F00009B189A69920B92039A6101277F423800BD +:102F100005B0F0BD00221B4B25009A553F2C00D96F +:102F20003F252A000199029800F032FD009BA90478 +:102F30005A01104B890C9B18029A7F195A619A69A1 +:102F4000641B920B92030A439A61009B039A083315 +:102F50005B01D3180222DA715979823A0A435A7115 +:102F6000019B5B190193A3E7280700209904002027 +:102F7000A4040020300700209C00002040420F00E5 +:102F8000701101009B04002070B50C001D000D4B5A +:102F9000A601F618110030002A0000F0F9FCE4B296 +:102FA000094A640114196661A369084928000B40A5 +:102FB000A361A169AB04890B9B0C89031943A1612F +:102FC00070BDC046A404002030070020FF3F00F081 +:102FD000F7B5104B0F001B7814000190002B0CD19B +:102FE0000D4B16001D78002D09D00C4E0C4835886D +:102FF00028182D1900F0CCFC35802000FEBD002ED5 +:10300000FBD033007A1900210198FFF7BDFF2D187E +:10301000361AF4E7240600202507002026070020A2 +:1030200025060020F8B500200D00140000AF012A8D +:1030300027D9D31D6A46DB08DB00D31A9D4608005A +:1030400000F072FD6E460323022200210130400091 +:1030500030707370A2420DD2287800280AD0531C19 +:10306000DBB20135B0549C4203D00232F154D2B2EB +:10307000F0E7220031000448FFF7AAFF431E984101 +:10308000C0B2BD46F8BDC04678040020F0B50025AA +:10309000012785B0184B0E0069461F70040000958B +:1030A000FFF766FC154B01A90B806A3BFF3BCB7118 +:1030B0005A330B72009B320009334B800E4B8D71DB +:1030C0004F7108711D70092E0FD00D4E09223770F7 +:1030D0000C4F200000953D80FFF77AFF69462000E5 +:1030E000FFF746FC3A88084935702000FFF770FF6B +:1030F000012005B0F0BDC0462406002009020000F2 +:1031000025070020260700202506002070B5CB7873 +:1031100005000E0092B0022B09D1C9882648FFF79E +:10312000B5FF441EA041C4B2200012B070BD012BF7 +:103130000BD1CA882149112A11D8D2B2002A0ED047 +:103140002800FFF745FF0124EEE70024032BEBD115 +:103150008B78A34205D1CA881949032AEDD90A7888 +:10316000EEE7022B06D18A7916492800FFF75AFFAD +:103170000400D9E7012B02D18A791349F5E7032B23 +:10318000D2D1124B01A91868FFF77FF9104B03A9A0 +:103190001868FFF77AF90F4B05A91868FFF775F95A +:1031A0000D4B07A91868FFF770F96B460533DC77FC +:1031B000B27901A9D9E7C04678040020343E000066 +:1031C000243E0000103E0000283E00000CA08000BD +:1031D00040A0800044A0800048A0800073B5060095 +:1031E00048780D000B2810D800F048FB061B0F3163 +:1031F0000F474C7450536D70097801AA002906D10D +:10320000022311803000FFF7BFFE012076BD0023AE +:103210001380314B1B78012B00D113700223002146 +:10322000F0E78A780023012A09D16A4693802B4B64 +:103230001B78012B00D11371022301AAEFE7264A64 +:103240001370274A93699B0B9B039361DDE78C788E +:10325000012C07D1214B01AA1C70224B1B78137043 +:103260002300DCE7002C08D101201B4B1C4A1870FE +:1032700093699B0B9B039361C8E73000A978FFF724 +:1032800023FCC2E73000FFF741FFBFE70123164AE6 +:10329000C5E70B780020DB06B8D13000FFF7CCFC87 +:1032A0002A200221AA78104BFF301A600C4A1368BA +:1032B0001C5C21434A241954FF34195D2938FF3816 +:1032C00001431955D4E70123084AA8E78A78074B38 +:1032D0001A60B6E7002099E79A040020A2040020B3 +:1032E00030070020E83D0000280700202C070020C0 +:1032F0004B4BF7B51C780700002C00D08FE0494EEF +:1033000033689B8B1B070ED521002000FFF7D6F8F2 +:10331000326810231100FF31887A03438B72424BCD +:103320001C600823938333689A8B52071FD50422AD +:103330009A833E4A1378002B0AD01378013BDBB204 +:1033400013701378D8B2002B02D10121FEF796FD3D +:10335000374A1378002B0AD01378013BDBB2137085 +:103360001378D8B2002B02D10121FEF787FD336814 +:10337000FF331A7AD2061ED510221A7259793032CA +:103380000A435A7160232B4938000A781A423BD10C +:10339000FFF724FF3368FF33002838D08022997963 +:1033A00052420A439A711A7A520604D540221A727E +:1033B000597A0A435A72336807241D8C01239D43AE +:1033C000EDB20193E1B2002D29D0002C27D02B00C3 +:1033D0002341019A134215D02300326808335B0160 +:1033E000D318DA79D20702D4DB799B0707D5124BC1 +:1033F000A200D05800280ED003681B689847019B94 +:10340000A3409D43013CDDE7FFF780FBC2E720219D +:103410000A4A9171C7E73800FFF7B8FAEFE7F7BD3E +:1034200025070020300700202807002099040020ED +:1034300098040020640500207C040020FF50004117 +:1034400010B50248FFF754FF10BDC04678040020B5 +:10345000014B024A1A6070473007002000500041BB +:103460000120704710B50368014A1B6A984710BDD8 +:103470001304000010B504000069FEF747FE2000A9 +:10348000143000F0BBF92000203000F0B7F910BD77 +:1034900010B5143000F0C7F910BD10B504002000BD +:1034A000203000F0C0F90028F9D12069FEF745FE70 +:1034B00010BD10B5203000F0BCF910BD70B506008D +:1034C00004001436300000F09DF9230030331B78DF +:1034D0000500FF2B07D0300000F0ABF90A2802DD11 +:1034E000A36BE26B1A60280070BD10B5143000F0B9 +:1034F000AEF910BDF7B51D0008AB1B7804000093B2 +:1035000009AB1B781600019300234360FA239B004C +:1035100083600D4B0F0008330360143000F052F944 +:103520002000203000F04EF92300009A2C33276150 +:103530009A70019A1E70DA7022005D70FF2330329B +:10354000200013701374FEBD483E000070B50400E7 +:103550000069FEF7FEFD002815D025002069FEF762 +:103560000DFE14350100280000F03BF92300303334 +:103570001B78FF2B07D0280000F05BF9092802DC3C +:10358000636BE26B1A602069FEF7F3FD00280DD033 +:1035900025002035280000F046F9002812D0280028 +:1035A00000F030F9C1B22069FEF7ECFD2069FEF7AA +:1035B000D5FD002805D02069FEF7D4FD2069FEF76F +:1035C000C4FD70BD2069FEF7E9FDEFE7F8B5040022 +:1035D00000690D002600FEF7CCFD2036002834D10E +:1035E0003F27300000F03EF9002825D0EFF310838C +:1035F0000122134211D1EFF305831A003A403B42F6 +:10360000EFD0103A53B2002A10DA0F221340083BD1 +:10361000134A9B089B009B181B682069FEF7A9FDB5 +:103620000028DED02000FFF791FFDAE79B080D4A63 +:10363000C0339B009B58F0E73000290000F0D1F820 +:103640002069FEF7A7FD0120F8BD300000F0EBF87F +:103650000028C5D129002069FEF794FDF3E7C04694 +:103660001CED00E000E100E0F0231B011940802385 +:1036700006209B0099420AD00133FF330130994262 +:1036800005D0802300205B00994200D105307047AF +:103690000F2001400020012903D00239481E81413A +:1036A000481C70470300F0B5040085B003912C332B +:1036B0000E2118781500FEF733FC230026002D3369 +:1036C00018780E212F36FEF72BFC3378022B07D10A +:1036D000230040331878FF2802D00E21FEF720FC8B +:1036E000270030373878FF2814D00121FEF7C2FBBD +:1036F0000C213B781B4A59438B5C521851780122AC +:103700008A401948DB01181860631848E2631B18E7 +:10371000A3631A600122039B11002069FEF784FD58 +:1037200029002000FFF7A0FF290007002000FFF775 +:10373000AFFFF0221540303D6A4255410300390089 +:10374000206901220095FEF7B1FC23002E331A7880 +:1037500031782069FEF7C7FC2069FEF7E4FC05B06C +:10376000F0BDC046703D00001844004114440041C3 +:103770007047000010B5FEF74DFB00F0D1F8FFF7E1 +:10378000F7FF0120FEF7DCFA084C2000FFF720F9D4 +:103790002000FFF77FF9FDF777FFFDF78FFF044B60 +:1037A000002BFAD000E000BFF7E7C0467804002005 +:1037B0000000000010B500F0D7F810BD10B500F003 +:1037C000DDF810BD10B50400802000F0CDF8802297 +:1037D0000021206000F0E5F8002320006360A36072 +:1037E00010BD7F22436810B50133134082689A42AE +:1037F00003D042680468A154436010BD00234360B5 +:1038000083607047826843689A4209D07F21836849 +:103810000268D25C836801330B40836010007047FC +:1038200001204042FBE743688068181A00D58030C9 +:103830007047426883689A4204DB43688068C01A14 +:103840007F30704783684068181A0138F9E782684A +:1038500043689A4203D083680268D05C70470120B5 +:103860004042FBE703007F2240689B680130104024 +:10387000C01A43425841C0B27047000002B47146BA +:1038800049084900095C49008E4402BC7047C046A3 +:10389000002934D00123002210B488422CD3012403 +:1038A0002407A14204D2814202D209011B01F8E798 +:1038B000E400A14204D2814202D249005B00F8E751 +:1038C000884201D3401A1A434C08A04202D3001B7D +:1038D0005C0822438C08A04202D3001B9C082243B0 +:1038E000CC08A04202D3001BDC082243002803D0EE +:1038F0001B0901D00909E3E7101C10BC704701B592 +:10390000002000F00BF802BD0029F8D003B5FFF746 +:10391000C1FF0EBC4243891A1847C0467047C046D3 +:1039200070B500260C4D0D4C641BA410A64209D1A5 +:10393000002600F011F90A4D0A4C641BA410A6429F +:1039400005D170BDB300EB5898470136EEE7B300E0 +:10395000EB5898470136F2E7680100206801002023 +:10396000680100207801002010B5034B01001868A1 +:1039700000F06AF810BDC0460401002010B5034BEA +:103980000100186800F016F810BDC04604010020C0 +:10399000002310B59A4200D110BDCC5CC454013351 +:1039A000F8E703001218934200D1704719700133F1 +:1039B000F9E7000070B50500002910D00C1F23683E +:1039C000002B00DAE418280000F0B5F81D4A13684F +:1039D000002B05D163601460280000F0ADF870BDC5 +:1039E000A34209D9216860188342F3D118685B6843 +:1039F00041182160EEE713005A68002A01D0A24264 +:103A0000F9D919685818A0420BD12068091858181C +:103A100019608242E0D110685268411819605A60FA +:103A2000DAE7A04202D90C232B60D5E721686018A1 +:103A3000824203D1106852684118216062605C6064 +:103A4000CAE7C04634080020F8B50323CD1C9D43C7 +:103A5000083506000C2D1FD20C25A9421ED83000B7 +:103A600000F069F825490A681400002C1AD1244F87 +:103A70003B68002B04D12100300000F043F838608F +:103A80002900300000F03EF8431C2AD10C233000FE +:103A9000336000F051F803E0002DDEDA0C233360D0 +:103AA0000020F8BD23685B1B18D40B2B03D92360BF +:103AB000E418256003E06368A2420DD10B6030007A +:103AC00000F03AF8200007220B30231D9043C21A61 +:103AD000E7D01B1AA350E4E75360F0E722006468C4 +:103AE000C3E70323C41C9C43A042E2D0211A300048 +:103AF00000F008F8431CDCD1C8E7C04634080020B9 +:103B000038080020002370B5064C0500080023602B +:103B100000F014F8431C03D12368002B00D02B6065 +:103B200070BDC046400800200023C25C0133002A5B +:103B3000FBD1581E7047704770470000044A136855 +:103B4000002B03D01818106018007047014BF9E7DC +:103B50003C08002044080020F8B5C046F8BC08BC6A +:103B60009E467047F8B5C046F8BC08BC9E467047F4 +:103B70000000891112239B322446AD573665BF746D +:103B8000488CC19D5AAFD3BE6CCAE5DB7EE9F7F81D +:103B90008110080193331A22A5562C47B7753E644D +:103BA000C99C408DDBBF52AEEDDA64CBFFF976E8FD +:103BB00002218B30100299132667AF763444BD552D +:103BC0004AADC3BC588ED19F6EEBE7FA7CC8F5D9DD +:103BD00083310A2091121803A7772E66B5543C450D +:103BE000CBBD42ACD99E508FEFFB66EAFDD874C9BD +:103BF00004428D5316619F702004A9153227BB36ED +:103C00004CCEC5DF5EEDD7FC6888E1997AABF3BA9C +:103C100085520C4397711E60A1142805B3373A26CC +:103C2000CDDE44CFDFFD56ECE9986089FBBB72AA7C +:103C300006638F7214409D512225AB343006B917AC +:103C40004EEFC7FE5CCCD5DD6AA9E3B8788AF19B5C +:103C500087730E6295501C41A3352A24B11638078C +:103C6000CFFF46EEDDDC54CDEBB962A8F99A708B3C +:103C7000088481951AA793B62CC2A5D33EE1B7F06C +:103C80004008C919522BDB3A644EED5F766DFF7C1C +:103C9000899400859BB712A6ADD224C3BFF136E04C +:103CA000C1184809D33B5A2AE55E6C4FF77D7E6CFC +:103CB0000AA583B4188691972EE3A7F23CC0B5D12C +:103CC0004229CB38500AD91B666FEF7E744CFD5DDC +:103CD0008BB502A499961087AFF326E2BDD034C10C +:103CE000C3394A28D11A580BE77F6E6EF55C7C4DBC +:103CF0000CC685D71EE597F42880A1913AA3B3B2EC +:103D0000444ACD5B5669DF78600CE91D722FFB3E9B +:103D10008DD604C79FF516E4A9902081BBB332A2CB +:103D2000C55A4C4BD7795E68E11C680DF33F7A2E7B +:103D30000EE787F61CC495D52AA1A3B03882B193AB +:103D4000466BCF7A5448DD59622DEB3C700EF91F5B +:103D50008FF706E69DD414C5ABB122A0B99230838B +:103D6000C77B4E6AD5585C49E33D6A2CF11E780F3B +:103D7000000219087F00000080000280000E190870 +:103D80003F40000080061080000F19083F700000BF +:103D900019070180001619081F40000080160680D0 +:103DA000001719080F40000080161280001819082B +:103DB0000F80000080161280001919080F80000083 +:103DC000801612800000000000000000E5220000C4 +:103DD00011230000E122000005230000F922000069 +:103DE000492300002D230000000000000000000017 +:103DF0000000000091280000452800003328000042 +:103E00002128000089240000B1240000252600009C +:103E100041726475696E6F204E616E6F20457665E4 +:103E2000727900000403090441726475696E6F20A1 +:103E30004C4C430012011001020000404123580085 +:103E4000000101020301000000000000000000006A +:103E5000CD35000065200000B33400009B34000025 +:103E600091340000BD340000EB34000065340000E4 +:103E7000A536000075340000613400000000000029 +:103E800010B572B68122114B92000433934213D3C2 +:103E90000F4A01211000147D0C42FCD02021148B0C +:103EA000FF319B085B0021431183D361094B1380D1 +:103EB0000123027D1A42FCD0BFF34F8F064B074A05 +:103EC000DA60BFF34F8FC046FDE7C0460010000028 +:103ED0000040004102A5FFFF00ED00E00400FA05EC +:103EE0008601010701010107060100000000000032 +:103EF0004A544147494345206D6B49490000000041 +:103F000000C20100FF0813040165736172454D563C +:103F10004E20676F72504D564E00000040420F0019 +:103F2000FFFFFFFF40420F00FFFFFFFF00C2010045 +:103F3000000008000904000001020200000524003E +:103F400010010424020605240600010524010101D4 +:103F50000705810310001009040100020A00000097 +:103F60000705020240000007058302400000000030 +:103F7000FFFFFFFF000000008300000002000000C0 +:103F80008200000008010020000000000000000086 +:103F90000000000000000000000000000000000021 +:103FA0000000000000000000000000000000000011 +:103FB0000000000000000000000000000000000001 +:103FC00000000000000000000000000000000000F1 +:103FD00000000000000000000000000000000000E1 +:103FE0000000000000000000B5100000291C0000C7 +:103FF00061240000513400008D100000000000001A +:0400000300001CA934 +:00000001FF diff --git a/firmwares/MuxTO/MuxTO.ino b/firmwares/MuxTO/MuxTO.ino new file mode 100644 index 00000000..85603071 --- /dev/null +++ b/firmwares/MuxTO/MuxTO.ino @@ -0,0 +1,228 @@ +/* + j2updi.cpp + + Created: 11-11-2017 22:29:58 + Author : JMR_2 + Ported to generic Arduino framework by the Arduino Team - 2019 +*/ + +/* + Compile with + fqbn=arduino:samd:muxto:float=default,config=enabled,clock=internal_usb,timer=timer_732Hz,bootloader=4kb,serial=two_uart,usb=cdc + to obtain the binary for Serial-to-USB converter + UPDI programmer on the Arduino Nano Every (MuxTO for brevity) + + Since the "sketch" is (almost) pure Arduino it can be ported easily to other architectures (on chips with two serial ports) + The bitbanged UPDI layer is being reworked to make it compatible with chips with just one UART (eg. atmega 32u4) +*/ + +// Includes +#include "sys.h" +#include "lock.h" +#include "updi_io.h" +#include "JICE_io.h" +#include "JTAG2.h" +#include "UPDI_hi_lvl.h" + +volatile bool updi_mode = false; +unsigned long baudrate = 115200; +unsigned long updi_mode_start = 0; +unsigned long updi_mode_end = 0; +uint8_t stopbits = 1; +uint8_t paritytype = 0; +uint8_t numbits = 8; +int8_t dtr = -1; +int8_t rts = -1; +uint16_t serial_mode = SERIAL_8N1; +bool serialNeedReconfiguration = false; + +char support_buffer[64]; + +struct lock q; + +void setup() { + /* Initialize MCU */ + pinMode(LED_BUILTIN, OUTPUT); + + /* Initialize serial links */ + JICE_io::init(); + UPDI_io::init(); + Serial1.begin(baudrate, serial_mode); + lock_init(&q); + JTAG2::sign_on(); +} + +//#define DEBUG; + +//long blink_timer = 0; +//long blink_delay = 1000; + +void loop() { + +#ifdef DEBUG + if (millis() - blink_timer > blink_delay) { + SYS::toggleLED(); + blink_timer = millis(); + } +#endif + + if (updi_mode == false) { + + //blink_delay = 1000; + + if (int c = Serial1.available()) { + lock(&q); + if (c > Serial.availableForWrite()) { + c = Serial.availableForWrite(); + } + unlock(&q); + Serial1.readBytes(support_buffer, c); + Serial.write(support_buffer, c); + } + + if (int c = Serial.available()) { + lock(&q); + if (c > Serial1.availableForWrite()) { + c = Serial1.availableForWrite(); + } + unlock(&q); + Serial.readBytes(support_buffer, c); + Serial1.write(support_buffer, c); + } + + if (Serial.stopbits() != stopbits) { + serial_mode &= ~HARDSER_STOP_BIT_MASK; + stopbits = Serial.stopbits(); + serialNeedReconfiguration = true; + switch (stopbits) { + case 1: + serial_mode |= HARDSER_STOP_BIT_1; + break; + case 2: + serial_mode |= HARDSER_STOP_BIT_2; + break; + } + } + if (Serial.paritytype() != paritytype) { + serial_mode &= ~HARDSER_PARITY_MASK; + paritytype = Serial.paritytype(); + serialNeedReconfiguration = true; + switch (paritytype) { + case 0: + serial_mode |= HARDSER_PARITY_NONE; + break; + case 1: + serial_mode |= HARDSER_PARITY_EVEN; + break; + case 2: + serial_mode |= HARDSER_PARITY_ODD; + break; + } + } + if (Serial.numbits() != numbits) { + serial_mode &= ~HARDSER_DATA_MASK; + numbits = Serial.numbits(); + serialNeedReconfiguration = true; + switch (numbits) { + case 5: + serial_mode |= HARDSER_DATA_5; + break; + case 6: + serial_mode |= HARDSER_DATA_6; + break; + case 7: + serial_mode |= HARDSER_DATA_7; + break; + case 8: + serial_mode |= HARDSER_DATA_8; + break; + } + } + + if (baudrate == 1200 && Serial.dtr() == 0 && (millis() - updi_mode_end > 200)) { + // don't reenter here if you just finished flashing + updi_mode = true; + updi_mode_start = millis(); + updi_mode_end = 0; + } + + if (Serial.baud() != baudrate || serialNeedReconfiguration || Serial.dtr() != dtr) { + dtr = Serial.dtr(); + if (Serial.dtr() == 1) { + baudrate = Serial.baud(); + Serial1.end(); + if (baudrate != 1200) { + Serial1.begin(baudrate, serial_mode); + serialNeedReconfiguration = false; + // Request reset + UPDI::stcs(UPDI::reg::ASI_Reset_Request, UPDI::RESET_ON); + // Release reset (System remains in reset state until released) + UPDI::stcs(UPDI::reg::ASI_Reset_Request, UPDI::RESET_OFF); + } + } + } + return; + } + + if (updi_mode == true) { + + // updi_mode cannot last more than 1 minute; in that case, break forcibly + if ((updi_mode_end != 0 && (millis() - updi_mode_end) > 500) || ((millis() - updi_mode_start) > 60000)) { + updi_mode = false; + baudrate = -1; + return; + } + + //blink_delay = 100; + + // Receive command + if (!JTAG2::receive()) { + return; + } + // Process command + switch (JTAG2::packet.body[0]) { + case JTAG2::CMND_GET_SIGN_ON: + JTAG2::sign_on(); + break; + case JTAG2::CMND_GET_PARAMETER: + JTAG2::get_parameter(); + break; + case JTAG2::CMND_SET_PARAMETER: + JTAG2::set_parameter(); + break; + case JTAG2::CMND_RESET: + case JTAG2::CMND_ENTER_PROGMODE: + JTAG2::enter_progmode(); + break; + case JTAG2::CMND_SIGN_OFF: + // Restore default baud rate before exiting + JTAG2::PARAM_BAUD_RATE_VAL = JTAG2::baud_19200; + case JTAG2::CMND_LEAVE_PROGMODE: + JTAG2::leave_progmode(); + updi_mode_end = millis(); + break; + case JTAG2::CMND_GET_SYNC: + case JTAG2::CMND_GO: + JTAG2::set_status(JTAG2::RSP_OK); + break; + case JTAG2::CMND_SET_DEVICE_DESCRIPTOR: + JTAG2::set_device_descriptor(); + break; + case JTAG2::CMND_READ_MEMORY: + JTAG2::read_mem(); + break; + case JTAG2::CMND_WRITE_MEMORY: + JTAG2::write_mem(); + break; + case JTAG2::CMND_XMEGA_ERASE: + JTAG2::erase(); + break; + default: + JTAG2::set_status(JTAG2::RSP_FAILED); + break; + } + // send response + JTAG2::answer(); + // some commands need to be executed after sending the answer + JTAG2::delay_exec(); + } +} diff --git a/firmwares/MuxTO/NVM.h b/firmwares/MuxTO/NVM.h new file mode 100644 index 00000000..f2af4ead --- /dev/null +++ b/firmwares/MuxTO/NVM.h @@ -0,0 +1,75 @@ +/* + NVM.h + + Created: 15-12-2017 10:59:53 + Author: JMR_2 +*/ + + +#ifndef NVM_H_ +#define NVM_H_ + +#include +#include "UPDI_lo_lvl.h" + +namespace NVM { +// *** Base Addresses *** +enum base { + NVM_base = 0x1000, /* Base address of the NVM controller */ + Sig_base = 0x1100, /* Base address of the signature */ + Fuse_base = 0x1280, /* Base address of the fuses */ + User_base = 0x1300, /* Base address of the User Row EEPROM */ + EEPROM_base = 0x1400 /* Base address of the main EEPROM */ +}; + +// *** NVM Registers (offsets from NVN_base are enum default values) *** +enum reg { + CTRLA, + CTRLB, + STATUS, + INTCTRL, + INTFLAGS, + Reg_5, + DATA_lo, + DATA_hi, + ADDR_lo, + ADDR_hi +}; + +// *** NVM Commands (write to CTRLA to execute) *** +enum cmnd { + NOP, /* Does nothing */ + WP, /* Write page buffer to memory */ + ER, /* Erase page */ + ERWP, /* Erase and write page */ + PBC, /* Page buffer clear */ + CHER, /* Chip erase: erase Flash and EEPROM */ + EEER, /* EEPROM Erase */ + WFU /* Write fuse */ +}; + +// *** NVM Functions *** +template +void command (uint8_t cmd) { + uint16_t temp; + /* preserve UPDI pointer if requested */ + if (preserve_ptr) temp = UPDI::ldptr_w(); + /* Execute NVM command */ + UPDI::sts_b(NVM_base + CTRLA, cmd); + /* restore UPDI pointer if requested */ + if (preserve_ptr) UPDI::stptr_w(temp); +} + +template +void wait () { + uint16_t temp; + /* preserve UPDI pointer if requested */ + if (preserve_ptr) temp = UPDI::ldptr_w(); + /* Wait while NVM is busy from previous operations */ + while (UPDI::lds_b(NVM::NVM_base + NVM::STATUS) & 0x03); + /* restore UPDI pointer if requested */ + if (preserve_ptr) UPDI::stptr_w(temp); +} +} + +#endif /* NVM_H_ */ diff --git a/firmwares/MuxTO/UPDI_hi_lvl.cpp b/firmwares/MuxTO/UPDI_hi_lvl.cpp new file mode 100644 index 00000000..6f2c2042 --- /dev/null +++ b/firmwares/MuxTO/UPDI_hi_lvl.cpp @@ -0,0 +1,20 @@ +/* + UPDI_hi_lvl.cpp + + Created: 15-02-2018 23:08:39 + Author: JMR_2 +*/ + +#include "UPDI_hi_lvl.h" + +void UPDI::CPU_reset() { + // Request reset + UPDI::stcs(UPDI::reg::ASI_Reset_Request, UPDI::RESET_ON); + // Release reset (System remains in reset state until released) + UPDI::stcs(UPDI::reg::ASI_Reset_Request, UPDI::RESET_OFF); + + // Wait for the reset process to end. + // Either NVMPROG, UROWPROG or BOOTDONE bit will be set in the ASI_SYS_STATUS UPDI register. + // This indicates reset is complete. + while ( UPDI::CPU_mode<0x0E>() == 0 ); +} diff --git a/firmwares/MuxTO/UPDI_hi_lvl.h b/firmwares/MuxTO/UPDI_hi_lvl.h new file mode 100644 index 00000000..55bdf5b7 --- /dev/null +++ b/firmwares/MuxTO/UPDI_hi_lvl.h @@ -0,0 +1,30 @@ +/* + UPDI_hi_lvl.h + + Created: 15-02-2018 23:12:54 + Author: JMR_2 +*/ + + +#ifndef UPDI_HI_LVL_H_ +#define UPDI_HI_LVL_H_ + +#include "UPDI_lo_lvl.h" + +namespace UPDI { +// Constant Expressions +constexpr uint8_t RESET_ON = 0x59; +constexpr uint8_t RESET_OFF = 0x00; + +// Function prototypes +void CPU_reset(); + +// returns the current CPU mode, optionally a mask can be applied to ignore "don't care" status bits +template +uint8_t CPU_mode() { + uint8_t mode = UPDI::lcds(UPDI::reg::ASI_System_Status); + return mode & mask; +} +} + +#endif /* UPDI_HI_LVL_H_ */ diff --git a/firmwares/MuxTO/UPDI_lo_lvl.cpp b/firmwares/MuxTO/UPDI_lo_lvl.cpp new file mode 100644 index 00000000..6c66f7ab --- /dev/null +++ b/firmwares/MuxTO/UPDI_lo_lvl.cpp @@ -0,0 +1,221 @@ +/* + UPDI_cmd.cpp + + Created: 23-11-2017 22:48:36 + Author: JMR_2 +*/ + +// Includes +#include "UPDI_lo_lvl.h" + +// Special optimization options +// Unused r/w I/O registers residing in the space addressable by in/out instructions +// can be used as temporary registers to save a few bytes/cycles. +// Warning: MCU specific!!! +//#define TEMP0 EEARL +//#define TEMP1 GPIOR0 +//#define TEMP2 GPIOR1 + +// Keys +uint8_t UPDI::Chip_Erase[8] {0x65, 0x73, 0x61, 0x72, 0x45, 0x4D, 0x56, 0x4E}; +uint8_t UPDI::NVM_Prog[8] {0x20, 0x67, 0x6F, 0x72, 0x50, 0x4D, 0x56, 0x4E}; +uint8_t UPDI::UserRow_Write[8] {0x65, 0x74, 0x26, 0x73, 0x55, 0x4D, 0x56, 0x4E}; + +// Functions +void UPDI::rep(uint8_t repeats) { +# ifdef TEMP0 + TEMP0 = repeats; +# endif + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0xA0); +# ifdef TEMP0 + UPDI_io::put(TEMP0); +# else + UPDI_io::put(repeats); +# endif +} + +void UPDI::stcs(reg r, uint8_t data) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0xC0 + r); + UPDI_io::put(data); +} + +uint8_t UPDI::lcds(reg r) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x80 + r); + return UPDI_io::get(); +} + +void UPDI::read_sib(uint8_t (& buffer)[16]) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0xE5); + for (uint8_t i = 0; i < 16; i++) { + buffer[i] = UPDI_io::get(); + } +} + +uint8_t UPDI::lds_b(uint16_t address) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x04); + UPDI_io::put(address & 0xFF); + UPDI_io::put(address >> 8); + return UPDI_io::get(); +} + +uint16_t UPDI::lds_w(uint16_t address) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x05); + UPDI_io::put(address & 0xFF); + UPDI_io::put(address >> 8); + return UPDI_io::get() | (UPDI_io::get() << 8); +} + +void UPDI::sts_b(uint16_t address, uint8_t data) { +# ifdef TEMP0 + TEMP0 = data; +# endif +# ifdef TEMP1 + TEMP1 = address & 0xFF; +# endif +# ifdef TEMP2 + TEMP2 = address >> 8; +# endif + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x44); +# ifdef TEMP1 + UPDI_io::put(TEMP1); +# else + UPDI_io::put(address & 0xFF); +# endif +# ifdef TEMP2 + UPDI_io::put(TEMP2); +# else + UPDI_io::put(address >> 8); +# endif + UPDI_io::get(); +# ifdef TEMP0 + UPDI_io::put(TEMP0); +# else + UPDI_io::put(data); +# endif + UPDI_io::get(); +} + +void UPDI::sts_w(uint16_t address, uint16_t data) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x45); + UPDI_io::put(address & 0xFF); + UPDI_io::put(address >> 8); + UPDI_io::get(); + UPDI_io::put(data & 0xFF); + UPDI_io::put(data >> 8); + UPDI_io::get(); +} + +uint8_t UPDI::ldptr_b() { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x28); + return UPDI_io::get(); +} + +uint16_t UPDI::ldptr_w() { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x29); +# ifdef TEMP0 + TEMP0 = UPDI_io::get(); + return (UPDI_io::get() << 8) | TEMP0; +# else + return UPDI_io::get() | (UPDI_io::get() << 8); +# endif +} + +uint8_t UPDI::ld_b() { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x20); + return UPDI_io::get(); +} + +uint16_t UPDI::ld_w() { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x21); + return UPDI_io::get() | (UPDI_io::get() << 8); +} + +uint8_t UPDI::ldinc_b() { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x24); + return UPDI_io::get(); +} + +uint16_t UPDI::ldinc_w() { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x25); + return UPDI_io::get() | (UPDI_io::get() << 8); +} + +void UPDI::stptr_b(uint8_t address) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x68); + UPDI_io::put(address); + UPDI_io::get(); +} + +void UPDI::stptr_w(uint16_t address) { +# ifdef TEMP0 + TEMP0 = address & 0xFF; +# endif +# ifdef TEMP1 + TEMP1 = address >> 8; +# endif + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x69); +# ifdef TEMP0 + UPDI_io::put(TEMP0); +# else + UPDI_io::put(address & 0xFF); +# endif +# ifdef TEMP1 + UPDI_io::put(TEMP1); +# else + UPDI_io::put(address >> 8); +# endif + UPDI_io::get(); +} + +void UPDI::st_b(uint8_t data) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x60); + UPDI_io::put(data); + UPDI_io::get(); +} + +void UPDI::st_w(uint16_t data) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x61); + UPDI_io::put(data & 0xFF); + UPDI_io::put(data >> 8); + UPDI_io::get(); +} + +void UPDI::stinc_b(uint8_t data) { +# ifdef TEMP0 + TEMP0 = data; +# endif + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x64); +# ifdef TEMP0 + UPDI_io::put(TEMP0); +# else + UPDI_io::put(data); +# endif + UPDI_io::get(); +} + +void UPDI::stinc_w(uint16_t data) { + UPDI_io::put(UPDI::SYNCH); + UPDI_io::put(0x65); + UPDI_io::put(data & 0xFF); + UPDI_io::put(data >> 8); + UPDI_io::get(); +} diff --git a/firmwares/MuxTO/UPDI_lo_lvl.h b/firmwares/MuxTO/UPDI_lo_lvl.h new file mode 100644 index 00000000..7915062a --- /dev/null +++ b/firmwares/MuxTO/UPDI_lo_lvl.h @@ -0,0 +1,80 @@ +/* + UPDI_cmd.h + + Created: 23-11-2017 22:46:11 + Author: JMR_2 +*/ + + +#ifndef UPDI_LO_LVL_H_ +#define UPDI_LO_LVL_H_ + +#include +#include "sys.h" +#include "updi_io.h" + +namespace UPDI { +// UPDI registers +enum reg { + Status_A, Status_B, Control_A, Control_B, + Reg_4, Reg_5, Reg_6, ASI_Key_Status, + ASI_Reset_Request, ASI_Control_A, ASI_System_Control_A, ASI_System_Status, + ASI_CRC_Status, Reg_13, Reg_14, Reg_15 +}; + + +// Constant Expressions +constexpr uint8_t SYNCH = 0x55; +constexpr uint8_t ACK = 0x40; + +// Activation Keys +extern uint8_t Chip_Erase[8]; +extern uint8_t NVM_Prog[8]; +extern uint8_t UserRow_Write[8]; + + +// Function prototypes +void rep(uint8_t); + +void stcs(reg, uint8_t); +uint8_t lcds(reg); + +void read_sib(uint8_t (&)[16]); + +uint8_t lds_b(uint16_t); +uint16_t lds_w(uint16_t); + +void sts_b(uint16_t address, uint8_t data); /* Store data at address */ +void sts_w(uint16_t, uint16_t); + +uint8_t ldptr_b(); +uint16_t ldptr_w(); +uint8_t ld_b(); +uint16_t ld_w(); +uint8_t ldinc_b(); +uint16_t ldinc_w(); + +void stptr_b(uint8_t); +void stptr_w(uint16_t); +void st_b(uint8_t); +void st_w(uint16_t); +void stinc_b(uint8_t); +void stinc_w(uint16_t); + +template +inline void write_key(T (& k)[8]) __attribute__(( optimize("no-tree-loop-optimize") )); + +// Function Templates +template +void write_key(T (& k)[8]) { + UPDI_io::put(SYNCH); + UPDI_io::put(0xE0); + T* key_ptr = k; + for (uint8_t i = 8; i != 0; i--) { + UPDI_io::put(*key_ptr); + key_ptr++; + } +} +} + +#endif /* UPDI_LO_LVL_H_ */ diff --git a/firmwares/MuxTO/crc16.cpp b/firmwares/MuxTO/crc16.cpp new file mode 100644 index 00000000..e0766b86 --- /dev/null +++ b/firmwares/MuxTO/crc16.cpp @@ -0,0 +1,61 @@ +/* + crc16.cpp + + Created: 16-01-2018 23:06:40 + Author: JMR_2 +*/ + +#include "crc16.h" +#include "sys.h" +#include "JICE_io.h" + +namespace { +static const uint16_t crc_table[256] = +{ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +} + +uint16_t CRC::next(uint8_t newchar, uint16_t previous) { + union { + uint16_t word; + struct { + uint8_t low; + uint8_t high; + } byte; + } crc; + crc.word = previous; + crc.word = crc_table[crc.byte.low ^ newchar]; + crc.byte.low ^= (previous >> 8); + return crc.word; +} diff --git a/firmwares/MuxTO/crc16.h b/firmwares/MuxTO/crc16.h new file mode 100644 index 00000000..8942dd47 --- /dev/null +++ b/firmwares/MuxTO/crc16.h @@ -0,0 +1,18 @@ +/* + crc16.h + + Created: 16-01-2018 23:07:05 + Author: JMR_2 +*/ + + +#ifndef CRC16_H_ +#define CRC16_H_ + +#include + +namespace CRC { +uint16_t next (uint8_t newchar, uint16_t previous = 0xFFFF); // 'previous' defaults to CRC seed value, 0xFFFF +} + +#endif /* CRC16_H_ */ diff --git a/firmwares/MuxTO/lock.h b/firmwares/MuxTO/lock.h new file mode 100644 index 00000000..16c5cb36 --- /dev/null +++ b/firmwares/MuxTO/lock.h @@ -0,0 +1,38 @@ +#ifndef _ARCH_LOCK_H_ +#define _ARCH_LOCK_H_ + +struct lock { + uint32_t primask; +}; + +#define LOCK_INIT (struct lock) {} + +static inline void lock_init(struct lock *lock) +{ +} + +// source: +// http://embeddedfreak.wordpress.com/2009/08/14/cortex-m3-global-interruptexception-control/ +// +// confirm this is correct by printing primask before after + +// note arm architecture v7m rm... setting PRIMASK raises priority to 0 + +static inline void lock(struct lock *lock) +{ + uint32_t tmp; + asm volatile ( + "mrs %0, PRIMASK\n\t" + "cpsid i\n\t" + : "=r" (tmp) ); + lock->primask = tmp; +} + +static inline void unlock(struct lock *lock) +{ + asm volatile ( + "msr PRIMASK, %0\n\t" + : : "r" (lock->primask) ); +} + +#endif diff --git a/firmwares/MuxTO/sys.cpp b/firmwares/MuxTO/sys.cpp new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/firmwares/MuxTO/sys.cpp @@ -0,0 +1 @@ + diff --git a/firmwares/MuxTO/sys.h b/firmwares/MuxTO/sys.h new file mode 100644 index 00000000..f9db76f5 --- /dev/null +++ b/firmwares/MuxTO/sys.h @@ -0,0 +1,42 @@ +/* + sys.h + + Created: 02-10-2018 13:07:18 + Author: JMR_2 +*/ + +#ifndef SYS_H_ +#define SYS_H_ + +#define FLASH const + +template +class flash { + private: + const T data; + + public: + // normal constructor + constexpr flash (T _data) : data(_data) {} + // default constructor + constexpr flash () : data(0) {} + + operator T() const { + switch (sizeof(T)) { + case 1: return pgm_read_byte(&data); + case 2: return pgm_read_word(&data); + case 4: return pgm_read_dword(&data); + } + } +}; + +#ifndef F_CPU +#define F_CPU 16000000U +#endif + +constexpr unsigned int baud(unsigned long b) { + return F_CPU / (b * 8.0) - 0.5; +} + + +#endif /* SYS_H_ */ diff --git a/firmwares/MuxTO/updi_io.cpp b/firmwares/MuxTO/updi_io.cpp new file mode 100644 index 00000000..582bd488 --- /dev/null +++ b/firmwares/MuxTO/updi_io.cpp @@ -0,0 +1,68 @@ +/* + updi_io.cpp + + Created: 18-11-2017 10:36:54 + Author: JMR_2 +*/ + +// Includes +#include +#include +#include "updi_io.h" + +// Functions +/* Sends regular characters through the UPDI link */ +uint8_t UPDI_io::put(char c) { + Serial2.write(c); + Serial2.flush(); + //delayMicroseconds(10); + long start = millis(); + while (!Serial2.available() && millis() - start < 20) {} + char d = Serial2.read(); + if (c != d) { + // Serial.println("echo failed! " + String(d, HEX)); + } + return c; +} + +/* Sends special sequences through the UPDI link */ +uint8_t UPDI_io::put(ctrl c) +{ + Serial2.begin(300, SERIAL_8N1); + + switch (c) { + case double_break: + Serial2.write((uint8_t)0x00); + Serial2.flush(); + Serial2.write((uint8_t)0x00); + Serial2.flush(); + break; + case single_break: + Serial2.write((uint8_t)0x00); + Serial2.flush(); + break; + default: + break; + } + delay(15); + while (Serial2.available()) { + Serial2.read(); + } + Serial2.begin(230400, SERIAL_8E2); + return 0; +} + +uint8_t UPDI_io::get() { + uint8_t c; + while (!Serial2.available()) {} + c = Serial2.read(); + //delayMicroseconds(5); + //Serial.println("get! " + String(c, HEX)); + return c; +} + +void UPDI_io::init(void) +{ + Serial2.begin(230400, SERIAL_8E2); + //Serial.begin(115200); +} diff --git a/firmwares/MuxTO/updi_io.h b/firmwares/MuxTO/updi_io.h new file mode 100644 index 00000000..5272d04d --- /dev/null +++ b/firmwares/MuxTO/updi_io.h @@ -0,0 +1,23 @@ +/* + updi_io.h + + Created: 18-11-2017 10:38:31 + Author: JMR_2 +*/ + + +#ifndef UPDI_IO_H_ +#define UPDI_IO_H_ + +namespace UPDI_io { +// Enums +enum ctrl {single_break, double_break, enable}; + +// Function prototypes +uint8_t put(char) __attribute__((optimize("no-tree-loop-optimize"))); +uint8_t put(ctrl); +uint8_t get() __attribute__((optimize("no-tree-loop-optimize"))); +void init(void); +} + +#endif /* UPDI_IO_H_ */ diff --git a/firmwares/MuxTO/updi_io_soft.cpp b/firmwares/MuxTO/updi_io_soft.cpp new file mode 100644 index 00000000..d8ebfe70 --- /dev/null +++ b/firmwares/MuxTO/updi_io_soft.cpp @@ -0,0 +1,250 @@ +/* + updi_io_soft.cpp + + Created: 11-08-2018 22:08:14 + Author: Cristian Balint +*/ + +#ifdef __AVR_ATmega16__ + +// Includes +#include +#include + +#include "sys.h" +#include "updi_io.h" + +// Defines +#ifndef F_CPU +# define F_CPU 16000000U +#endif +#ifndef UPDI_BAUD +# define UPDI_BAUD 225000U // (max 225000 min approx. F_CPU/100) +#endif + +// Cycle timing +#define TXDELAY (uint8_t)(((F_CPU/UPDI_BAUD) - 9) / 3) +#define RXDELAY (uint8_t)(((F_CPU/UPDI_BAUD) - 9) / 3) +#define RXHALFD (uint8_t) (RXDELAY / 2) + +// Check +#if ( (((F_CPU/UPDI_BAUD) - 9) / 3) > 254 ) +# error Low baud rates are not supported - use higher UPDI_BAUD +#endif + +// Functions +/* Sends regular characters through the UPDI link */ +uint8_t UPDI_io::get() { + + // rx input + DDR(UPDI_PORT) &= ~(1 << UPDI_PIN); + // no pullup + PORT(UPDI_PORT) &= ~(1 << UPDI_PIN); + + uint8_t c; + + __asm volatile + ( + " ldi %0, 0 \n\t" // init + " ldi r20, 8 \n\t" // 8 bits + " ldi r19, 3 \n\t" // 1 parity + 2 stop bits + + // wait for start edge + "WaitStart: \n\t" + " sbic %[uart_port], %[uart_pin] \n\t" + " rjmp WaitStart \n\t" + + // skew into middle of edge + " ldi r18, %[rxhalfd] \n\t" // 0.5 bit cycle delay + "HBitDelay: \n\t" + " dec r18 \n\t" + " brne HBitDelay \n\t" + + // 8 bits + "RxBLoop: \n\t" + " ldi r18, %[rxdelay] \n\t" // 1 bit cycle delay + "RxBDelay: \n\t" + " dec r18 \n\t" + " brne RxBDelay \n\t" + " in r21, %[uart_port] \n\t" // get current bit from serial link + " bst r21, %[uart_pin] \n\t" // use T flag + " bld r22, 0\n\t" // to move current data bit + " lsr r22 \n\t" // into carry + " ror %0 \n\t" // accumulate serial data bits into result + " dec r20 \n\t" + " brne RxBLoop \n\t" + " nop \n\t" + + // 1 parity + 2 stop bits + "RxSLoop: \n\t" + " ldi r18, %[rxdelay] \n\t" // 1 bit cycle delay + "RxSDelay: \n\t" + " dec r18 \n\t" + " brne RxSDelay \n\t" + " in r21, %[uart_port] \n\t" // get current bit from serial link + " bst r21, %[uart_pin] \n\t" // use T flag + " bld r22, 0\n\t" // to move current data bit + " lsr r22 \n\t" // into carry + " nop \n\t" // accumulate serial data bits into result + " dec r19 \n\t" + " brne RxSLoop \n\t" + " nop \n\t" + + : "=r" (c) + : [uart_port] "i" (_SFR_IO_ADDR(PIN(UPDI_PORT))), + [uart_pin] "i" (UPDI_PIN), + [rxdelay] "i" (RXDELAY), + [rxhalfd] "i" (RXHALFD) + : "r0", "r18", "r19", "r20", "r21", "r22" + ); + + // re-enable pull up + PORT(UPDI_PORT) |= (1 << UPDI_PIN); + + return c; +} + +uint8_t UPDI_io::put(char c) { + + // tx enable + DDR(UPDI_PORT) |= (1 << UPDI_PIN); + + __asm volatile + ( + " in r0, %[uart_port] \n\t" // port state + " ldi r26, 2 \n\t" // 2 bit stop + " ldi r27, 8 \n\t" // 8 bit parity + " ldi r28, %[txdelay] \n\t" // delay counter + " ldi r30, 8 \n\t" // 8 bit loop + + // pre delay + // 2 bit time + " mov r29, r28 \n\t" + "TxDelay: \n\t" + " nop \n\t" + " dec r29 \n\t" + " brne TxDelay \n\t" + + // start bit + " mov r29, r28 \n\t" + "TxDelayS: \n\t" + " dec r29 \n\t" + " brne TxDelayS \n\t" + " bclr 6 \n\t" + " bld r0, %[uart_pin] \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " out %[uart_port], r0 \n\t" + " nop \n\t" + " nop \n\t" + + // 8 bits + "TxLoop: \n\t" + " mov r29, r28 \n\t" // load delay counter + "TxDelayB: \n\t" // delay (3 cycle * delayCount) - 1 + " dec r29 \n\t" + " brne TxDelayB \n\t" + " bst %[ch], 0 \n\t" // load bit in T + " bld r0, %[uart_pin] \n\t" // store T bit in r0 + " ror %[ch] \n\t" // shift right into carry + " sbci r27, 0 \n\t" // subtract carry (accumulate parity) + " dec r30 \n\t" // decrement bits counter + " out %[uart_port], r0 \n\t" // send bit out + " brne TxLoop \n\t" // loop for each bit + " nop \n\t" + + // parity bit + " mov r29, r28 \n\t" + "TxDelayP: \n\t" + " dec r29 \n\t" + " brne TxDelayP \n\t" + " bst r27, 0 \n\t" // extract accumulated parity + " bld r0, %[uart_pin] \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " out %[uart_port], r0 \n\t" // send bit out to serial link + " nop \n\t" + " nop \n\t" + + // stop bits + "StopLoop: \n\t" + " mov r29, r28 \n\t" + "TxDelayStop: \n\t" + " dec r29 \n\t" + " brne TxDelayStop \n\t" + " bset 6 \n\t" + " bld r0, %[uart_pin] \n\t" + " nop \n\t" + " nop \n\t" + " dec r26 \n\t" + " out %[uart_port], r0 \n\t" // send bit out to serial link + " brne StopLoop \n\t" // loop for each bit + " nop \n\t" + + : + : [uart_port] "i" (_SFR_IO_ADDR(PORT(UPDI_PORT))), + [uart_pin] "i" (UPDI_PIN), + [txdelay] "i" (TXDELAY), + [ch] "r" (c) + : "r0", "r26", "r27", "r28", "r29", "r30" + ); + + // Ready for RX input + DDR(UPDI_PORT) &= ~(1 << UPDI_PIN); + + return c; +} + +static inline void send_break() { + + // tx enable + DDR(UPDI_PORT) |= (1 << UPDI_PIN); + + // + // 13 cycles = 24.60ms + // + + // low 12 cycle + PORT(UPDI_PORT) &= ~(1 << UPDI_PIN); + _delay_us(2048 * 11); + + // high 1 cycle + PORT(UPDI_PORT) |= (1 << UPDI_PIN); + _delay_us(2048); + + // RX enable + DDR(UPDI_PORT) &= ~(1 << UPDI_PIN); + + return; +} + +/* Sends special sequences through the UPDI link */ +uint8_t UPDI_io::put(ctrl c) { + + switch (c) { + + case double_break: + send_break(); + send_break(); + break; + + case single_break: + send_break(); + break; + + case enable: + + default: + break; + } + + return 0; +} + +void UPDI_io::init(void) { + +} + +#endif //__AVR_ATmega16__ diff --git a/libraries/HID/keywords.txt b/libraries/HID/keywords.txt deleted file mode 100644 index 32a9ba5f..00000000 --- a/libraries/HID/keywords.txt +++ /dev/null @@ -1,21 +0,0 @@ -####################################### -# Syntax Coloring Map HID -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -HID KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### -begin KEYWORD2 -SendReport KEYWORD2 -AppendDescriptor KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### -HID_TX LITERAL1 \ No newline at end of file diff --git a/libraries/HID/library.properties b/libraries/HID/library.properties deleted file mode 100644 index 499286d4..00000000 --- a/libraries/HID/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=HID -version=1.0 -author=Arduino -maintainer=Arduino -sentence=Module for PluggableUSB infrastructure. Exposes an API for devices like Keyboards, Mice and Gamepads. -paragraph= -category=Communication -url=http://www.arduino.cc/en/Reference/HID -architectures=megaavr diff --git a/libraries/HID/src/HID.cpp b/libraries/HID/src/HID.cpp deleted file mode 100644 index 21ede269..00000000 --- a/libraries/HID/src/HID.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, 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 "HID.h" - -#if defined(USBCON) - -HID_& HID() -{ - static HID_ obj; - return obj; -} - -int HID_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(descriptorSize), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int HID_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - int total = 0; - HIDSubDescriptor* node; - for (node = rootNode; node; node = node->next) { - int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); - if (res == -1) - return -1; - total += res; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return total; -} - -uint8_t HID_::getShortName(char *name) -{ - name[0] = 'H'; - name[1] = 'I'; - name[2] = 'D'; - name[3] = 'A' + (descriptorSize & 0x0F); - name[4] = 'A' + ((descriptorSize >> 4) & 0x0F); - return 5; -} - -void HID_::AppendDescriptor(HIDSubDescriptor *node) -{ - if (!rootNode) { - rootNode = node; - } else { - HIDSubDescriptor *current = rootNode; - while (current->next) { - current = current->next; - } - current->next = node; - } - descriptorSize += node->length; -} - -int HID_::SendReport(uint8_t id, const void* data, int len) -{ - auto ret = USB_Send(pluggedEndpoint, &id, 1); - if (ret < 0) return ret; - auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); - if (ret2 < 0) return ret2; - return ret + ret2; -} - -bool HID_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - if (request == HID_GET_IDLE) { - // TODO: Send8(idle); - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - // The USB Host tells us if we are in boot or report mode. - // This only works with a real boot compatible device. - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - //uint8_t reportID = setup.wValueL; - //uint16_t length = setup.wLength; - //uint8_t data[length]; - // Make sure to not read more data than USB_EP_SIZE. - // You can read multiple times through a loop. - // The first byte (may!) contain the reportID on a multreport. - //USB_RecvControl(data, length); - } - } - - return false; -} - -HID_::HID_(void) : PluggableUSBModule(1, 1, epType), - rootNode(NULL), descriptorSize(0), - protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int HID_::begin(void) -{ - return 0; -} - -#endif /* if defined(USBCON) */ diff --git a/libraries/HID/src/HID.h b/libraries/HID/src/HID.h deleted file mode 100644 index ad2b06b1..00000000 --- a/libraries/HID/src/HID.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, 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. - */ - -#ifndef HID_h -#define HID_h - -#include -#include -#include "api/PluggableUSB.h" - -#if defined(USBCON) - -#define _USING_HID - -// HID 'Driver' -// ------------ -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - -// HID subclass HID1.11 Page 8 4.2 Subclass -#define HID_SUBCLASS_NONE 0 -#define HID_SUBCLASS_BOOT_INTERFACE 1 - -// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols -#define HID_PROTOCOL_NONE 0 -#define HID_PROTOCOL_KEYBOARD 1 -#define HID_PROTOCOL_MOUSE 2 - -// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request -// "protocol" variable is used for this purpose. -#define HID_BOOT_PROTOCOL 0 -#define HID_REPORT_PROTOCOL 1 - -// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request -#define HID_REPORT_TYPE_INPUT 1 -#define HID_REPORT_TYPE_OUTPUT 2 -#define HID_REPORT_TYPE_FEATURE 3 - -typedef struct -{ - uint8_t len; // 9 - uint8_t dtype; // 0x21 - uint8_t addr; - uint8_t versionL; // 0x101 - uint8_t versionH; // 0x101 - uint8_t country; - uint8_t desctype; // 0x22 report - uint8_t descLenL; - uint8_t descLenH; -} HIDDescDescriptor; - -typedef struct -{ - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; -} HIDDescriptor; - -class HIDSubDescriptor { -public: - HIDSubDescriptor *next = NULL; - HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } - - const void* data; - const uint16_t length; -}; - -class HID_ : public PluggableUSBModule -{ -public: - HID_(void); - int begin(void); - int SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDSubDescriptor* node); - -protected: - // Implementation of the PluggableUSBModule - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - uint8_t getShortName(char* name); - -private: - unsigned int epType[1]; - - HIDSubDescriptor* rootNode; - uint16_t descriptorSize; - - uint8_t protocol; - uint8_t idle; -}; - -// Replacement for global singleton. -// This function prevents static-initialization-order-fiasco -// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use -HID_& HID(); - -#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } - -#else - -#error "No Native USB support available on this board" - -#endif // USBCON - -#endif // HID_h diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 48a8a74c..d2c94f1c 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -24,8 +24,6 @@ #define SPI_IMODE_EXTINT 1 #define SPI_IMODE_GLOBAL 2 -const SPISettings DEFAULT_SPI_SETTINGS = SPISettings(); - SPIClass::SPIClass(uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, uint8_t uc_pinSS, uint8_t uc_mux) { initialized = false; @@ -66,7 +64,7 @@ void SPIClass::init() initialized = true; } -void SPIClass::config(SPISettings settings) +void SPIClass::config(SPISettingsMegaAVR settings) { SPI0.CTRLA = settings.ctrla; SPI0.CTRLB = settings.ctrlb; @@ -173,7 +171,7 @@ void SPIClass::reattachMaskedInterrupts() { } } -void SPIClass::beginTransaction(SPISettings settings) +void SPIClass::beginTransaction(SPISettingsMegaAVR settings) { if (interruptMode != SPI_IMODE_NONE) { diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 18262c9d..53e15839 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -21,6 +21,7 @@ #define _SPI_H_INCLUDED #include +#include #ifndef USE_MALLOC_FOR_IRQ_MAP #define USE_MALLOC_FOR_IRQ_MAP 0 @@ -31,7 +32,7 @@ // - endTransaction() // - usingInterrupt() // - SPISetting(clock, bitOrder, dataMode) -#define SPI_HAS_TRANSACTION 1 +// #define SPI_HAS_TRANSACTION 1 // SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method #define SPI_HAS_NOTUSINGINTERRUPT 1 @@ -52,9 +53,9 @@ #define EXTERNAL_NUM_INTERRUPTS NUM_TOTAL_PINS #endif -class SPISettings { +class SPISettingsMegaAVR : public arduino::SPISettings { public: - SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { + SPISettingsMegaAVR(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { if (__builtin_constant_p(clock)) { init_AlwaysInline(clock, bitOrder, dataMode); } else { @@ -63,7 +64,9 @@ class SPISettings { } // Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first. - SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } + SPISettingsMegaAVR() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } + + SPISettingsMegaAVR(SPISettings& x) { SPISettingsMegaAVR(x.getClockFreq(), x.getBitOrder(), x.getDataMode()); } private: void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { @@ -142,12 +145,12 @@ class SPISettings { /* member variables containing the desired SPI settings */ uint8_t ctrla; uint8_t ctrlb; - friend class SPIClass; + friend class SPIClassMegaAVR; }; -class SPIClass { +class SPIClassMegaAVR : public arduino::HardwareSPI { public: - SPIClass(uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, uint8_t uc_pinSS, uint8_t uc_mux); + SPIClassMegaAVR(uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, uint8_t uc_pinSS, uint8_t uc_mux); byte transfer(uint8_t data); uint16_t transfer16(uint16_t data); @@ -156,7 +159,10 @@ class SPIClass { // Transaction Functions void usingInterrupt(int interruptNumber); void notUsingInterrupt(int interruptNumber); - void beginTransaction(SPISettings settings); + void beginTransaction(SPISettingsMegaAVR settings); + void beginTransaction(SPISettings settings) { + beginTransaction(SPISettingsMegaAVR(settings)); + } void endTransaction(void); void begin(); @@ -169,13 +175,16 @@ class SPIClass { private: void init(); - void config(SPISettings settings); + void config(SPISettingsMegaAVR settings); + void config(SPISettings settings) { + config(SPISettingsMegaAVR(settings)); + } // These undocumented functions should not be used. SPI.transfer() // polls the hardware flag which is automatically cleared as the // AVR responds to SPI's interrupt - inline static void attachInterrupt() { SPI0.INTCTRL |= (SPI_IE_bm); } - inline static void detachInterrupt() { SPI0.INTCTRL &= ~(SPI_IE_bm); } + inline void attachInterrupt() { SPI0.INTCTRL |= (SPI_IE_bm); } + inline void detachInterrupt() { SPI0.INTCTRL &= ~(SPI_IE_bm); } void detachMaskedInterrupts(); void reattachMaskedInterrupts(); @@ -199,6 +208,7 @@ class SPIClass { #endif }; +#define SPIClass SPIClassMegaAVR #if SPI_INTERFACES_COUNT > 0 extern SPIClass SPI; diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index b1a37c4a..edcf7607 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -103,7 +103,7 @@ class SoftwareSerial : public Stream virtual int read(); virtual int available(); virtual void flush(); - operator bool() { return true; } + explicit operator bool() { return true; } using Print::write; diff --git a/libraries/Wire/keywords.txt b/libraries/Wire/keywords.txt index 5e3d2b1c..04b8301a 100644 --- a/libraries/Wire/keywords.txt +++ b/libraries/Wire/keywords.txt @@ -6,6 +6,8 @@ # Datatypes (KEYWORD1) ####################################### +Wire KEYWORD2 + ####################################### # Methods and Functions (KEYWORD2) ####################################### @@ -18,12 +20,6 @@ requestFrom KEYWORD2 onReceive KEYWORD2 onRequest KEYWORD2 -####################################### -# Instances (KEYWORD2) -####################################### - -Wire KEYWORD2 - ####################################### # Constants (LITERAL1) ####################################### diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index febee50c..cdec85cf 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -95,7 +95,7 @@ void TwoWire::setClock(uint32_t clock) TWI_MasterSetBaud(clock); } -uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool sendStop) { +size_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool sendStop) { if(quantity > BUFFER_LENGTH){ quantity = BUFFER_LENGTH; } @@ -109,17 +109,17 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool sendStop) { return bytes_read; } -uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity) +size_t TwoWire::requestFrom(uint8_t address, size_t quantity) { return requestFrom(address, quantity, true); } -uint8_t TwoWire::requestFrom(int address, int quantity) +size_t TwoWire::requestFrom(int address, int quantity) { return requestFrom((uint8_t)address, (size_t)quantity, true); } -uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) +size_t TwoWire::requestFrom(int address, int quantity, int sendStop) { return requestFrom((uint8_t)address, (size_t)quantity, (bool)sendStop); } diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index 7a1375bd..3871e350 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -23,6 +23,7 @@ #define TwoWire_h #include +#include #define BUFFER_LENGTH 128 @@ -57,10 +58,10 @@ class TwoWire : public HardwareI2C void beginTransmission(int); uint8_t endTransmission(void); uint8_t endTransmission(bool); - uint8_t requestFrom(uint8_t, size_t); - uint8_t requestFrom(uint8_t, size_t, bool); - uint8_t requestFrom(int, int); - uint8_t requestFrom(int, int, int); + size_t requestFrom(uint8_t, size_t); + size_t requestFrom(uint8_t, size_t, bool); + size_t requestFrom(int, int); + size_t requestFrom(int, int, int); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *, size_t); virtual int available(void); diff --git a/libraries/Wire/src/utility/twi.c b/libraries/Wire/src/utility/twi.c index a313ac07..5e34609a 100644 --- a/libraries/Wire/src/utility/twi.c +++ b/libraries/Wire/src/utility/twi.c @@ -201,7 +201,7 @@ void TWI_MasterSetBaud(uint32_t frequency){ t_rise = 1000; } - uint32_t baud = ((F_CPU_CORRECTED/frequency) - (((F_CPU_CORRECTED*t_rise)/1000)/1000)/1000 - 10)/2; + uint32_t baud = (F_CPU_CORRECTED / frequency - F_CPU_CORRECTED / 1000 / 1000 * t_rise / 1000 - 10) / 2; TWI0.MBAUD = (uint8_t)baud; } @@ -270,8 +270,11 @@ uint8_t TWI_MasterRead(uint8_t slave_address, * \param bytesToWrite Number of bytes to write. * \param bytesToRead Number of bytes to read. * - * \retval true If transaction could be started. - * \retval false If transaction could not be started. + * \retval 0:success + * \retval 1:data too long to fit in transmit buffer + * \retval 2:received NACK on transmit of address + * \retval 3:received NACK on transmit of data + * \retval 4:other error */ uint8_t TWI_MasterWriteRead(uint8_t slave_address, uint8_t *write_data, @@ -335,8 +338,21 @@ uint8_t TWI_MasterWriteRead(uint8_t slave_address, // return bytes really read ret = master_bytesRead; } else { - // return 0 if success, >0 otherwise - ret = (master_result == TWIM_RESULT_OK ? 0 : 1); + // return 0 if success, >0 otherwise (follow classic AVR conventions) + switch (master_result) { + case TWIM_RESULT_OK: + ret = 0; + break; + case TWIM_RESULT_BUFFER_OVERFLOW: + ret = 1; + break; + case TWIM_RESULT_NACK_RECEIVED: + ret = 3; + break; + default: + ret = 4; + break; + } } return ret; diff --git a/platform.txt b/platform.txt index 4a611e44..50992217 100644 --- a/platform.txt +++ b/platform.txt @@ -3,10 +3,10 @@ # ------------------------------ # # For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification +# https://arduino.github.io/arduino-cli/latest/platform-specification/ name=Arduino megaAVR Boards -version=1.8.1 +version=1.8.8 # AVR compile variables # --------------------- @@ -34,6 +34,7 @@ compiler.elf2hex.flags=-O ihex -R .eeprom compiler.elf2hex.bin.flags=-O binary -R .eeprom compiler.elf2hex.cmd=avr-objcopy compiler.ldflags= +compiler.libraries.ldflags= compiler.size.cmd=avr-size # This can be overridden in boards.txt @@ -66,7 +67,7 @@ archive_file_path={build.path}/{archive_file} recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} {compiler.libraries.ldflags} "{build.path}/{archive_file}" "-L{build.path}" -lm "-Wl,-Map,{build.path}/{build.project_name}.map" ## Create output files (.eep and .hex) recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" @@ -79,7 +80,7 @@ recipe.output.save_file={build.project_name}.{build.variant}.hex ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* +recipe.size.regex=^(?:\.text|\.data|\.rodata|\.bootloader)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* @@ -90,15 +91,19 @@ recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} preproc.macros.flags=-w -x c++ -E -CC recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.macros.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} "-I{build.core.path}/api/deprecated" {includes} "{source_file}" -o "{preprocessed_file_path}" +# Required discoveries and monitors +# --------------------------------- +pluggable_discovery.required.0=builtin:serial-discovery +pluggable_discovery.required.1=builtin:mdns-discovery +pluggable_monitor.required.serial=builtin:serial-monitor + # AVR Uploader/Programmers tools # ------------------------------ -tools.avrdude.path={runtime.tools.avrdude-6.3.0-arduino16.path} +tools.avrdude.path={runtime.tools.avrdude-6.3.0-arduino17.path} tools.avrdude.cmd.path={path}/bin/avrdude tools.avrdude.config.path={path}/etc/avrdude.conf -tools.avrdude.network_cmd={runtime.tools.arduinoOTA-1.3.0.path}/bin/arduinoOTA - tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q # tools.avrdude.upload.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value @@ -123,8 +128,17 @@ tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verb tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu} +# The following rule is deprecated by pluggable discovery. +# We keep it to avoid breaking compatibility with the Arduino Java IDE. +tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -d -v +# ArduinoOTA +tools.arduino_ota.cmd={runtime.tools.arduinoOTA-1.3.0.path}/bin/arduinoOTA +tools.arduino_ota.upload.field.password=Password +tools.arduino_ota.upload.field.password.secret=true +tools.arduino_ota.upload.pattern="{tools.arduino_ota.cmd}" -address {upload.port.address} -port 65280 -username arduino -password "{upload.field.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -d -v + # USB Default Flags # Default blank usb manufacturer will be filled in at compile time # - from numeric vendor ID, set to Unknown otherwise diff --git a/post_install.sh b/post_install.sh new file mode 100644 index 00000000..9a944e8a --- /dev/null +++ b/post_install.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +megaAVR_rules () { + echo "" + echo "# Arduino Mega AVR boards bootloader mode udev rules" + echo "" +cat < /etc/udev/rules.d/60-arduino-megaAVR.rules + +# reload udev rules +echo "Reload rules..." +udevadm control --reload-rules +udevadm trigger + diff --git a/programmers.txt b/programmers.txt index d9e83344..70af3a0a 100644 --- a/programmers.txt +++ b/programmers.txt @@ -3,4 +3,5 @@ medbg.communication=usb medbg.protocol=xplainedmini_updi medbg.program.protocol=xplainedmini_updi medbg.program.tool=avrdude -medbg.program.extra_params=-Pusb \ No newline at end of file +medbg.program.tool.default=avrdude +medbg.program.extra_params=-Pusb diff --git a/scripts/create_dfu_udev_rule b/scripts/create_dfu_udev_rule deleted file mode 100755 index 89d2a8a3..00000000 --- a/scripts/create_dfu_udev_rule +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# - -if [ "$(id -u)" != "0" ]; then - echo "This script must be run as root" - exit -fi - -NAME=99-arduino-uno-wifi-rev2.rules - -echo >/etc/udev/rules.d/$NAME -echo \# Arduino UNO WiFi Rev2 mEDBG CMSIS-DAP >>/etc/udev/rules.d/$NAME -echo SUBSYSTEM==\"tty\", ENV{ID_REVISION}==\"03eb\", ENV{ID_MODEL_ID}==\"2145\", MODE=\"0666\", ENV{ID_MM_DEVICE_IGNORE}=\"1\", ENV{ID_MM_CANDIDATE}=\"0\" >>/etc/udev/rules.d/$NAME -echo SUBSYSTEM==\"usb\", ATTR{idVendor}==\"03eb\", ATTR{idProduct}==\"2145\", MODE=\"0666\", ENV{ID_MM_DEVICE_IGNORE}=\"1\" >>/etc/udev/rules.d/$NAME - -udevadm control --reload-rules -udevadm trigger diff --git a/variants/nona4809/pins_arduino.h b/variants/nona4809/pins_arduino.h index a84ae9ba..589dc2ae 100644 --- a/variants/nona4809/pins_arduino.h +++ b/variants/nona4809/pins_arduino.h @@ -51,8 +51,8 @@ static const uint8_t MOSI = PIN_SPI_MOSI; static const uint8_t MISO = PIN_SPI_MISO; static const uint8_t SCK = PIN_SPI_SCK; -#define PIN_WIRE_SDA (20) -#define PIN_WIRE_SCL (21) +#define PIN_WIRE_SDA (22) +#define PIN_WIRE_SCL (23) static const uint8_t SDA = PIN_WIRE_SDA; static const uint8_t SCL = PIN_WIRE_SCL; @@ -76,8 +76,8 @@ static const uint8_t SCL = PIN_WIRE_SCL; #define HWSERIAL0_DRE_VECTOR_NUM (USART3_DRE_vect_num) #define HWSERIAL0_RXC_VECTOR (USART3_RXC_vect) #define HWSERIAL0_MUX (PORTMUX_USART3_ALT1_gc) -#define PIN_WIRE_HWSERIAL0_RX (26) -#define PIN_WIRE_HWSERIAL0_TX (27) +#define PIN_WIRE_HWSERIAL0_RX (24) +#define PIN_WIRE_HWSERIAL0_TX (25) #define HWSERIAL2_MUX (PORTMUX_USART0_NONE_gc) #define HWSERIAL3_MUX (PORTMUX_USART2_NONE_gc) @@ -89,14 +89,14 @@ static const uint8_t SCL = PIN_WIRE_SCL; #define LED_BUILTIN (13) -#define PIN_A0 (0) // AIN3 -#define PIN_A1 (1) // AIN2 -#define PIN_A2 (2) // AIN1 -#define PIN_A3 (3) // AIN0 -#define PIN_A4 (4) // PF2 / AIN12 -#define PIN_A5 (5) // PF3 / AIN13 -#define PIN_A6 (6) // AIN5 -#define PIN_A7 (7) // AIN4 +#define PIN_A0 (14) // AIN3 +#define PIN_A1 (15) // AIN2 +#define PIN_A2 (16) // AIN1 +#define PIN_A3 (17) // AIN0 +#define PIN_A4 (18) // PF2 / AIN12 +#define PIN_A5 (19) // PF3 / AIN13 +#define PIN_A6 (20) // AIN5 +#define PIN_A7 (21) // AIN4 static const uint8_t A0 = PIN_A0; static const uint8_t A1 = PIN_A1; @@ -142,7 +142,7 @@ static const uint8_t A7 = PIN_A7; // -const uint8_t PROGMEM digital_pin_to_port[] = { +const uint8_t digital_pin_to_port[] = { PC, // 0 PC5/USART1_Rx PC, // 1 PC4/USART1_Tx PA, // 2 PA0 @@ -157,37 +157,22 @@ const uint8_t PROGMEM digital_pin_to_port[] = { PE, // 11 PE0 PE, // 12 PE1 PE, // 13 PE2 - PD, // 14 PD0/AI0 - PD, // 15 PD1AI1 - PD, // 16 PD2/AI2 - PD, // 17 PD3/AI3 - PD, // 18 PD4/AI4 - PD, // 19 PD5/AI5 - PA, // 20 PA2/TWI_SDA - PA, // 21 PA3/TWI_SCL - PC, // 22 PC3 - PA, // 23 PA5/NINA TX - PA, // 24 PA4/NINA RX - PD, // 25 PD6/LED_BUILTIN - PB, // 26 PB5/USART3_Rx - PB, // 27 PB4/USART3_Tx - PA, // 28 PA6/NINA GPIO0 - PA, // 29 PA7/NINA RST - PB, // 30 PB3/IMU CS - PC, // 31 PC7/IMU INT - PC, // 32 PC0/MOSI - PC, // 33 PC1/MISO - PC, // 34 PC2/SCK - PF, // 35 PF2/NINA CS - PF, // 36 PF3/NINA ACK - PF, // 37 PF0 TOSC 1 - PF, // 38 PF1 TOSC 2 - PD, // 39 PD7 VREF - PF // 40 PF6 RESET + PD, // 14 PD3/AI3 + PD, // 15 PD2/AI2 + PD, // 16 PD1/AI1 + PD, // 17 PD0/AI0 + PF, // 18 PF2/AI12 + PF, // 19 PF3/AI13 + PD, // 20 PD4/AI4 + PD, // 21 PD5/AI5 + PA, // 22 PA2/TWI_SDA + PA, // 23 PA3/TWI_SCL + PB, // 24 PB5/USART3_Rx + PB, // 25 PB4/USART3_Tx }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_position[] = { +const uint8_t digital_pin_to_bit_position[] = { PIN5_bp, // 0 PC5/USART1_Rx PIN4_bp, // 1 PC4/USART1_Tx PIN0_bp, // 2 PA0 @@ -202,37 +187,22 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { PIN0_bp, // 11 PE0 PIN1_bp, // 12 PE1 PIN2_bp, // 13 PE2 - PIN0_bp, // 14 PD0/AI0 - PIN1_bp, // 15 PD1AI1 - PIN2_bp, // 16 PD2/AI2 - PIN3_bp, // 17 PD3/AI3 - PIN4_bp, // 18 PD4/AI4 - PIN5_bp, // 19 PD5/AI5 - PIN2_bp, // 20 PA2/TWI_SDA - PIN3_bp, // 21 PA3/TWI_SCL - PIN3_bp, // 22 PC3 - PIN5_bp, // 23 PA5/NINA TX - PIN4_bp, // 24 PA4/NINA RX - PIN6_bp, // 25 PD6/LED_BUILTIN - PIN5_bp, // 26 PB5/USART3_Rx - PIN4_bp, // 27 PB4/USART3_Tx - PIN6_bp, // 28 PA6/NINA GPIO0 - PIN7_bp, // 29 PA7/NINA RST - PIN3_bp, // 30 PB3/IMU CS - PIN7_bp, // 31 PC7/IMU INT - PIN0_bp, // 32 PC0/MOSI - PIN1_bp, // 33 PC1/MISO - PIN2_bp, // 34 PC2/SCK - PIN2_bp, // 35 PF2/NINA CS - PIN3_bp, // 36 PF3/NINA ACK - PIN0_bp, // 37 PF0 TOSC 1 - PIN1_bp, // 38 PF1 TOSC 2 - PIN7_bp, // 39 PD7 VREF - PIN6_bp // 40 PF6 RESET + PIN3_bp, // 14 PD3/AI3 + PIN2_bp, // 15 PD2/AI2 + PIN1_bp, // 16 PD1/AI1 + PIN0_bp, // 17 PD0/AI0 + PIN2_bp, // 18 PF2/AI12 + PIN3_bp, // 19 PF3/AI13 + PIN4_bp, // 20 PD4/AI4 + PIN5_bp, // 21 PD5/AI5 + PIN2_bp, // 22 PA2/TWI_SDA + PIN3_bp, // 23 PA3/TWI_SCL + PIN5_bp, // 24 PB5/USART3_Rx + PIN4_bp, // 25 PB4/USART3_Tx }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_mask[] = { +const uint8_t digital_pin_to_bit_mask[] = { PIN5_bm, // 0 PC5/USART1_Rx PIN4_bm, // 1 PC4/USART1_Tx PIN0_bm, // 2 PA0 @@ -247,36 +217,21 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN0_bm, // 11 PE0 PIN1_bm, // 12 PE1 PIN2_bm, // 13 PE2 - PIN0_bm, // 14 PD0/AI0 - PIN1_bm, // 15 PD1AI1 - PIN2_bm, // 16 PD2/AI2 - PIN3_bm, // 17 PD3/AI3 - PIN4_bm, // 18 PD4/AI4 - PIN5_bm, // 19 PD5/AI5 - PIN2_bm, // 20 PA2/TWI_SDA - PIN3_bm, // 21 PA3/TWI_SCL - PIN3_bm, // 22 PC3 - PIN5_bm, // 23 PA5/NINA TX - PIN4_bm, // 24 PA4/NINA RX - PIN6_bm, // 25 PD6/LED_BUILTIN - PIN5_bm, // 26 PB5/USART3_Rx - PIN4_bm, // 27 PB4/USART3_Tx - PIN6_bm, // 28 PA6/NINA GPIO0 - PIN7_bm, // 29 PA7/NINA RST - PIN3_bm, // 30 PB3/IMU CS - PIN7_bm, // 31 PC7/IMU INT - PIN0_bm, // 32 PC0/MOSI - PIN1_bm, // 33 PC1/MISO - PIN2_bm, // 34 PC2/SCK - PIN2_bm, // 35 PF2/NINA CS - PIN3_bm, // 36 PF3/NINA ACK - PIN0_bm, // 37 PF0 TOSC 1 - PIN1_bm, // 38 PF1 TOSC 2 - PIN7_bm, // 39 PD7 VREF - PIN6_bm // 40 PF6 RESET + PIN3_bm, // 14 PD3/AI3 + PIN2_bm, // 15 PD2/AI2 + PIN1_bm, // 16 PD1/AI1 + PIN0_bm, // 17 PD0/AI0 + PIN2_bm, // 18 PF2/AI12 + PIN3_bm, // 19 PF3/AI13 + PIN4_bm, // 20 PD4/AI4 + PIN5_bm, // 21 PD5/AI5 + PIN2_bm, // 22 PA2/TWI_SDA + PIN3_bm, // 23 PA3/TWI_SCL + PIN5_bm, // 24 PB5/USART3_Rx + PIN4_bm, // 25 PB4/USART3_Tx }; -const uint8_t PROGMEM digital_pin_to_timer[] = { +const uint8_t digital_pin_to_timer[] = { NOT_ON_TIMER, // 0 PC5/USART1_Rx NOT_ON_TIMER, // 1 PC4/USART1_Tx NOT_ON_TIMER, // 2 PA0 @@ -291,50 +246,34 @@ const uint8_t PROGMEM digital_pin_to_timer[] = { NOT_ON_TIMER, // 11 PE0 NOT_ON_TIMER, // 12 PE1 NOT_ON_TIMER, // 13 PE2 - NOT_ON_TIMER, // 14 PD0/AI0 - NOT_ON_TIMER, // 15 PD1AI1 - NOT_ON_TIMER, // 16 PD2/AI2 - NOT_ON_TIMER, // 17 PD3/AI3 - NOT_ON_TIMER, // 18 PD4/AI4 - NOT_ON_TIMER, // 19 PD5/AI5 - NOT_ON_TIMER, // 20 PA2/TWI_SDA - NOT_ON_TIMER, // 21 PA3/TWI_SCL - NOT_ON_TIMER, // 22 PC3 - NOT_ON_TIMER, // 23 PA5/NINA TX - NOT_ON_TIMER, // 24 PA4/NINA RX - NOT_ON_TIMER, // 25 PD6/LED_BUILTIN - NOT_ON_TIMER, // 26 PB5/USART3_Rx - NOT_ON_TIMER, // 27 PB4/USART3_Tx - NOT_ON_TIMER, // 28 PA6/NINA GPIO0 - NOT_ON_TIMER, // 29 PA7/NINA RST - NOT_ON_TIMER, // 30 PB3/IMU CS - NOT_ON_TIMER, // 31 PC7/IMU INT - NOT_ON_TIMER, // 32 PC0/MOSI - NOT_ON_TIMER, // 33 PC1/MISO - NOT_ON_TIMER, // 34 PC2/SCK - NOT_ON_TIMER, // 35 PF2/NINA CS - NOT_ON_TIMER, // 36 PF3/NINA ACK - NOT_ON_TIMER, // 37 PF0 TOSC 1 - NOT_ON_TIMER, // 38 PF1 TOSC 2 - NOT_ON_TIMER, // 39 PD7 VREF - NOT_ON_TIMER // 40 PF6 RESET + NOT_ON_TIMER, // 14 PD3/AI3 + NOT_ON_TIMER, // 15 PD2/AI2 + NOT_ON_TIMER, // 16 PD1/AI1 + NOT_ON_TIMER, // 17 PD0/AI0 + NOT_ON_TIMER, // 18 PF2/AI12 + NOT_ON_TIMER, // 19 PF3/AI13 + NOT_ON_TIMER, // 20 PD4/AI4 + NOT_ON_TIMER, // 21 PD5/AI5 + NOT_ON_TIMER, // 22 PA2/TWI_SDA + NOT_ON_TIMER, // 23 PA3/TWI_SCL + NOT_ON_TIMER, // 24 PB5/USART3_Rx + NOT_ON_TIMER, // 25 PB4/USART3_Tx }; -const uint8_t PROGMEM analog_pin_to_channel[] = { +const uint8_t analog_pin_to_channel[] = { 3, 2, 1, 0, 12, 13, - 5, - 4 + 4, + 5 }; #endif -extern const uint8_t analog_pin_to_channel[]; -#define digitalPinToAnalogInput(p) ((p < NUM_ANALOG_INPUTS) ? pgm_read_byte(analog_pin_to_channel + p) : NOT_A_PIN ) +#define digitalPinToAnalogInput(p) ((p < ANALOG_INPUT_OFFSET) ? analog_pin_to_channel[p] : analog_pin_to_channel[p - ANALOG_INPUT_OFFSET] ) // These serial port names are intended to allow libraries and architecture-neutral // sketches to automatically default to the correct port name for a particular type diff --git a/variants/uno2018/pins_arduino.h b/variants/uno2018/pins_arduino.h index 71dd6edd..3b7e3aae 100644 --- a/variants/uno2018/pins_arduino.h +++ b/variants/uno2018/pins_arduino.h @@ -163,7 +163,7 @@ static const uint8_t A5 = PIN_A5; // -const uint8_t PROGMEM digital_pin_to_port[] = { +const uint8_t digital_pin_to_port[] = { PC, // 0 PC5/USART1_Rx PC, // 1 PC4/USART1_Tx PA, // 2 PA0 @@ -208,7 +208,7 @@ const uint8_t PROGMEM digital_pin_to_port[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_position[] = { +const uint8_t digital_pin_to_bit_position[] = { PIN5_bp, // 0 PC5/USART1_Rx PIN4_bp, // 1 PC4/USART1_Tx PIN0_bp, // 2 PA0 @@ -253,7 +253,7 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_mask[] = { +const uint8_t digital_pin_to_bit_mask[] = { PIN5_bm, // 0 PC5/USART1_Rx PIN4_bm, // 1 PC4/USART1_Tx PIN0_bm, // 2 PA0 @@ -297,7 +297,7 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN6_bm // 40 PF6 RESET }; -const uint8_t PROGMEM digital_pin_to_timer[] = { +const uint8_t digital_pin_to_timer[] = { NOT_ON_TIMER, // 0 PC5/USART1_Rx NOT_ON_TIMER, // 1 PC4/USART1_Tx NOT_ON_TIMER, // 2 PA0