diff --git a/README.md b/README.md index 5d26df64..ba8b0582 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # DxCore - Arduino support for the AVR DA, DB-series and DD-series -## 1.5.7 - EA "support" in beta form is now available. +## 1.5.7 - EA "support" in beta form is now available This is a very generous definition of the word - The first version where it is believed to be fully working will be numbered 1.6.0, and within a few patch versions of that, it likely will be. There are lots of issues impacting this currently and I'm not going to even start listing them here, but make issues if you don't see em. @@ -12,7 +12,7 @@ Expect particular issues with: * Flash.h is not supposed to work on it - it needs a different library, and to write when optiboot is not in use will require a novel implementation, while writing via optiboot will require optiboot to work, which will not be easy - that the first EA's are impacted by excruciatingly severe silicon bugs that make writing to nvm more complicated makes this significantly more challenging -### Optiboot for EA does not look encouraging. +### Optiboot for EA does not look encouraging Before the errata, I was pretty sure that it would be part definitions and a few lines of logic change in optiboot_x. oh ho ho no. No such luck, cause we can't do a bloody erase+write, the optiboot protocol doesn't know where a given page is going to be written (hence where to erase) to until the first bytes of the blob of data that was sent to it is hurtling towards it, and see the quoted section of the datasheet below. I am praying for an early die rev. > The resulting data will be a binary AND operation between the new and the previous content of the page buffer. The page buffer will automatically be erased (all bits set) **after**: diff --git a/megaavr/cores/dxcore/Arduino.h b/megaavr/cores/dxcore/Arduino.h index af2f1b28..29e31cc1 100644 --- a/megaavr/cores/dxcore/Arduino.h +++ b/megaavr/cores/dxcore/Arduino.h @@ -882,7 +882,7 @@ void pinConfigure(const uint8_t digital_pin, const pin_configure_t mode, const M _pinconfigure(digital_pin, pin_config); } -/* If you understand the preceeding code, studies show you are more likely than the average developer to +/* If you understand the preceding code, studies show you are more likely than the average developer to * know C++, with a statistically significant relationship between how well you know the language and your likelihood of * understanding that code. I got distracted after the first + and have yet to comprehend the above implementation. * But it lets you separate arguments with commas instead of pipes, which is far more tasteful and graceful diff --git a/megaavr/cores/dxcore/wiring.c b/megaavr/cores/dxcore/wiring.c index bd175269..4be953d2 100644 --- a/megaavr/cores/dxcore/wiring.c +++ b/megaavr/cores/dxcore/wiring.c @@ -1812,8 +1812,8 @@ void nudge_millis(__attribute__((unused)) uint16_t nudgesize) { */ /* Some speeds not otherwise possible can be generated with the internal oscillator by prescaling * This is done for 5 and 10 because those were common speeds to run 0 and 1-series parts at. - * The logic for setting clock to the other stupid frequencies that can be generated this way - * or for generating millis, micros, or delayMicroseconds() at those speeds is belived to be implented + * The logic for setting clock to the other stupid frequencies that can be generated this way + * or for generating millis, micros, or delayMicroseconds() at those speeds is believed to be implemented * but has not been tested. * If it fails to work at speeds evenly divisible by 1000000 and less than 8 MHz, that can be reported * as a bug, though it will not be a priority one. We have no plans to support speeds with non-integer diff --git a/megaavr/extras/DA28.md b/megaavr/extras/DA28.md index bca9ec47..8274eef0 100644 --- a/megaavr/extras/DA28.md +++ b/megaavr/extras/DA28.md @@ -125,7 +125,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input (but never an output). The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. The Dx-ADC is better than a no-frills classic +Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. The Dx-ADC is better than a no-frills classic ADC - for one thing it gained two bits - but the differential mode is a little disappointing: It cannot be used if a voltage exceeds VRef: you get junk results even though the difference doesn't exceed VREF. This of course kills one of the popular uses of ADC differential mode = high side current sensing, where you'relooking at a voltage very close to Vdd, maybe you've turned up the gain and you'd use the lowest ref you had? Not if you're on a Dx-series you're not. No opamps here either to condition signals. diff --git a/megaavr/extras/DA32.md b/megaavr/extras/DA32.md index 4b5686a6..e0a7d5b2 100644 --- a/megaavr/extras/DA32.md +++ b/megaavr/extras/DA32.md @@ -139,7 +139,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input (but never an output). The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. +Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. ## Official Documentation When all else fails, read the real documentation. They keep moving the .pdf files around, so now I just link to the prduct page, from whence the datasheet, errata, and "technical briefs". diff --git a/megaavr/extras/DA48.md b/megaavr/extras/DA48.md index 88918f56..3dc05ba5 100644 --- a/megaavr/extras/DA48.md +++ b/megaavr/extras/DA48.md @@ -134,7 +134,7 @@ PORTMUX.TCAROUTEA = (PORTMUX.TCAROUTEA & PORTMUX_TCA1_gm) | PORTMUX_TCA0_PORTD_g These are NOT PORTMUX-aware. Only the **bold** pin can be used without modifying or creating a new variant file. -The type B timers are much better utility timers than PWM timers. TCB2 is the default millis timer and cannot be used for PWM in that mode. This configuration is recommended. See the [Timer Reference](REF_Timers.md) for more information +The type B timers are much better utility timers than PWM timers. TCB2 is the default millis timer and cannot be used for PWM in that mode. This configuration is recommended. See the [Timer Reference](Ref_Timers.md) for more information #### TCD0 mux options | TCD0 | WOA | WOB | WOC | WOD | @@ -152,7 +152,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input (but never an output). The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. +Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. ## Official Documentation When all else fails, read the real documentation. They keep moving the .pdf files around, so now I just link to the prduct page, from whence the datasheet, errata, and "technical briefs". diff --git a/megaavr/extras/DA64.md b/megaavr/extras/DA64.md index e7cbbc9e..b03bbcae 100644 --- a/megaavr/extras/DA64.md +++ b/megaavr/extras/DA64.md @@ -140,7 +140,7 @@ PORTMUX.TCAROUTEA = (PORTMUX.TCAROUTEA & PORTMUX_TCA1_gm) | PORTMUX_TCA0_PORTD_g These are NOT PORTMUX-aware. Only the **bold** pin can be used without modifying or creating a new variant file. TCAs take priority over TCBs, so without changing the TCA0 mapping, TCB2/TCB3 are not used. -The type B timers are much better utility timers than PWM timers. TCB2 is the default millis timer and cannot be used for PWM in that mode. This configuration is recommended. See the [Timer Reference](REF_Timers.md) for more information +The type B timers are much better utility timers than PWM timers. TCB2 is the default millis timer and cannot be used for PWM in that mode. This configuration is recommended. See the [Timer Reference](Ref_Timers.md) for more information #### TCD0 mux options | TCD0 | WOA | WOB | WOC | WOD | @@ -159,7 +159,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input (but never an output). The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. +Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. ## Official Documentation When all else fails, read the real documentation. They keep moving the .pdf files around, so now I just link to the prduct page, from whence the datasheet, errata, and "technical briefs". diff --git a/megaavr/extras/DB28.md b/megaavr/extras/DB28.md index 3e27af3b..ca5adf36 100644 --- a/megaavr/extras/DB28.md +++ b/megaavr/extras/DB28.md @@ -125,7 +125,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input (but never an output). The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. +Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. ## Official Documentation When all else fails, read the real documentation. They keep moving the .pdf files around, so now I just link to the prduct page, from whence the datasheet, errata, and "technical briefs". diff --git a/megaavr/extras/DB32.md b/megaavr/extras/DB32.md index bc9fde53..c1c2b39e 100644 --- a/megaavr/extras/DB32.md +++ b/megaavr/extras/DB32.md @@ -119,7 +119,7 @@ Note that this differs from both the hardware default, as well as what would be These are NOT PORTMUX-aware. Only the **bold** pin can be used without modifying or creating a new variant file. -The type B timers are much better utility timers than PWM timers. TCB2 is the default millis timer and cannot be used for PWM in that mode. This configuration is recommended. See the [Timer Reference](REF_Timers.md) for more information +The type B timers are much better utility timers than PWM timers. TCB2 is the default millis timer and cannot be used for PWM in that mode. This configuration is recommended. See the [Timer Reference](Ref_Timers.md) for more information #### TCD0 mux options @@ -137,7 +137,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input (but never an output). The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. +Only pins on PORTD can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. On parts with more pins, PORTE can also be used for negative inputs. ## Official Documentation When all else fails, read the real documentation. They keep moving the .pdf files around, so now I just link to the prduct page, from whence the datasheet, errata, and "technical briefs". diff --git a/megaavr/extras/DB48.md b/megaavr/extras/DB48.md index 88b792a2..9627d6c5 100644 --- a/megaavr/extras/DB48.md +++ b/megaavr/extras/DB48.md @@ -165,7 +165,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input (but never an output). The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. +Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. ## Official Documentation When all else fails, read the real documentation. They keep moving the .pdf files around, so now I just link to the prduct page, from whence the datasheet, errata, and "technical briefs". diff --git a/megaavr/extras/DB64.md b/megaavr/extras/DB64.md index 1eb55cfa..d3391a16 100644 --- a/megaavr/extras/DB64.md +++ b/megaavr/extras/DB64.md @@ -175,7 +175,7 @@ Following precedent set by MegaCoreX, we declare that pin 7 - `PIN_PA7` shall be Reset (PF6) can be set to work as an input *(but never an output)*. The UPDI pin cannot be configured as an I/O pin. ### ADC pins in differential mode -Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](REF_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. +Only pins on PORTD and PORTE can be used as the negative side of a differential analog reading (`analogReadDiff()`, see [Analog Reference](Ref_Analog.md)). Pins on PORTF can be used as positive or single ended ADC inputs only. ## Official Documentation When all else fails, read the real documentation. They keep moving the .pdf files around, so now I just link to the prduct page, from whence the datasheet, errata, and "technical briefs". diff --git a/megaavr/extras/Ref_Analog.md b/megaavr/extras/Ref_Analog.md index e1fae30c..31d6ae85 100644 --- a/megaavr/extras/Ref_Analog.md +++ b/megaavr/extras/Ref_Analog.md @@ -45,7 +45,7 @@ In some cases the voltage determines the maximum ADC clock speed. Call analogRef #### Limits of external refeences External reference voltage should be between 1.8v and Vdd if CLK_ADC is higher than 500kHz (by default, it is), however if you slow the ADC clock down, external references as low as 1.0V (they gave 1.024V as the lower limit. It is unclear if the slower clock speed must also be used for the internal 1.024V reference. -This is not all bad news though on the 2-series and Ex, instead of having to slow down for some reference voltages, we get higher max CLK_ADC with external references! +This is not all bad news though on the 2-series and Ex, instead of having to slow down for some reference voltages, we get higher max CLK_ADC with external references! @@ -81,7 +81,7 @@ If anyone reading this has performed any testing of this, I would appreciate it To compensate for the faster ADC clock, we extend the sampling period so it ends up with a similar sampling period to classic AVRs, while still being significantly faster by virtue of the much shorter conversion time. But you can shorten that further (or extend it) using analogSampleDuration(). With minimum sample duration, external voltage reference in burst or freerun mode and maximum ADC clock, 450k sps may be possible at full resolution. You're unlikely to want that ofc, but that's a separate matter, just don't configure it like that if you don't want it. The fact remains that it is definitely the faster ADC. - + ## ADC Function Reference This core includes the following ADC-related functions. Out of the box, analogRead() is intended to be directly compatible with the standard Arduino implementation. Additional functions are provided to use the advanced functionality of these parts and further tune the ADC to your application. Several functions are unique to the cores I maintain. The functions here not marked if they are simple implementations that duplicate the stock one. They are marked (semi-standard) if it is something that is standard on some arduino cores but not official AVR cores and/or which works differently here), or (one of more of mTC, DxC, and ATC - these are the three cores I maintain, megaTinyCore, DxCore and ATTinyCore). @@ -368,7 +368,7 @@ ADC_CH(channel number) - converts channel numbers to analog channel ide Try not to use these unless you're getting really deep into library development and direct interaction with the ADC; we provide all the constants you will need. listed above. ## A word of warning to capacitive touch sensing applications -Libraries exist that use trickery and the ADC to measure capacitance, hence detect touch/proximity. Most of these libraries (since Atmel always locked up QTouch) relied on the leftover charge in the ADC S&H cap. The magnitude of this source of error is much larger on classic AVRs. It is considered undesirable (this is why when changing ADC channels in the past, you were advised to throw out the first couple of readings!) and with each generation, this has been reduced. There are still ways to do this effectively on the 2series, but require very different approaches. Thankfully for parts that do have a PTC, great strides are being made. the tiny1-series has an active developer working on it, while Microchip itself will release a library based on qtouch for the DA. +Libraries exist that use trickery and the ADC to measure capacitance, hence detect touch/proximity. Most of these libraries (since Atmel always locked up QTouch) relied on the leftover charge in the ADC S&H cap. The magnitude of this source of error is much larger on classic AVRs. It is considered undesirable (this is why when changing ADC channels in the past, you were advised to throw out the first couple of readings!) and with each generation, this has been reduced. There are still ways to do this effectively on the 2series, but require very different approaches. Thankfully for parts that do have a PTC, great strides are being made. the tiny1-series has an active developer working on it, while Microchip itself will release a library based on qtouch for the DA. ## Microchip Documentation Has been much expanded and I'm very happy to see this sort of document produced before the EA release. Wondering about the numbering? Well, TB stands for Technical Brief, which is different in some way from an Application Note (AN), and obviously a whitepaper or "Datasheet" (DS) is something else altogether. Even when they're about the same length and contain similar types of content. S diff --git a/megaavr/extras/Ref_Defines.md b/megaavr/extras/Ref_Defines.md index f2eb02eb..aaca8a81 100644 --- a/megaavr/extras/Ref_Defines.md +++ b/megaavr/extras/Ref_Defines.md @@ -241,11 +241,11 @@ There are a number of macros for determining what (if any) features the core sup * `CORE_HAS_OPENDRAIN = 1` - If defined as 1, indicates that `openDrain()` and (assuming `CORE_HAS_FASTIO` is >= 1) `openDrainFast()` are available. If undefined or 0, these are not available. * `CORE_HAS_PINCONFIG = 1` - If defined as Indicates that `pinConfigure()` is available. If not defined or defined as 0, it is not available. * `CORE_HAS_TIMER_TAKEOVER = 1` - if defined as 1, `takeOverTCxn()` functions are available to let user code take full control of TCA0, TCA1 and/or TCD0. -* `CORE_HAS_TIMER_RESUME = 1`- if defined as 1, the corresponding `resumeTCxn()` functions, which reinitialize them and return them to their normal core-integrated functions, are available. -* `ADC_NATIVE_RESOLUTION = `10 or 12`- This is the maximum resolution, in bits, of the ADC without using oversampling. -* `ADC_NATIVE_RESOLUTION_LOW = `8 or 10` - The ADC has a resolution setting that chooses between ADC_NATIVE_RESOLUTION, and a lower resolution. +* `CORE_HAS_TIMER_RESUME = 1` - if defined as 1, the corresponding `resumeTCxn()` functions, which reinitialize them and return them to their normal core-integrated functions, are available. +* `ADC_NATIVE_RESOLUTION = 10 or 12` - This is the maximum resolution, in bits, of the ADC without using oversampling. +* `ADC_NATIVE_RESOLUTION_LOW = 8 or 10` - The ADC has a resolution setting that chooses between ADC_NATIVE_RESOLUTION, and a lower resolution. * `ADC_DIFFERENTIAL = 1` - This is defined as 1 if the part has a basic differential ADC (no gain, and Vanalog_in constrained to between Gnd and VRef), and 2 if it has a full-featured one. It does not indicate whether said differential capability is exposed by the core. If it's defined as -1, it has differential capability in the way that classic AVRs do. See also `CORE_HAS_ANALOG_DIFF` -* `SUPPORT_LONG_TONES = 1` - On some modern AVR cores, an intermediate value in the tone duration calculation can overflow (which is timed by counting times the pin is flipped) leading to a maximum duration of 4.294 million millisecond. This is worst at high frequencies, and can manifest at durations as short as 65 seconds worst case. Working around this, however, costs some flash, and some cores may make the choice to not address it (megaTinyCore only supports long tones on parts with more than 8k of flash). If `SUPPORT_LONG_TONES` is defined as 1, as long as (duration * frequency)/500 < 4.294 billion, the duration will not be truncated. If it is defined as 0, the bug was known to the core maintainer and they chose not to fully correct it (eg, to save flash) but took the obvious step to reduce the impact, it will be truncated if (duration * frequency) exceeds 4.294 billion. If `SUPPORT_LONG_TONES` is not defined at all, the bug may be present in its original form, in which case the duration will be truncated if (duration * frequency) exceeds 2.14 billion. +* `SUPPORT_LONG_TONES = 1` - On some modern AVR cores, an intermediate value in the tone duration calculation can overflow (which is timed by counting times the pin is flipped) leading to a maximum duration of 4.294 million millisecond. This is worst at high frequencies, and can manifest at durations as short as 65 seconds worst case. Working around this, however, costs some flash, and some cores may make the choice to not address it (megaTinyCore only supports long tones on parts with more than 8k of flash). If `SUPPORT_LONG_TONES` is defined as 1, as long as (duration * frequency)/500 < 4.294 billion, the duration will not be truncated. If it is defined as 0, the bug was known to the core maintainer and they chose not to fully correct it (eg, to save flash) but took the obvious step to reduce the impact, it will be truncated if (duration * frequency) exceeds 4.294 billion. If `SUPPORT_LONG_TONES` is not defined at all, the bug may be present in its original form, in which case the duration will be truncated if (duration * frequency) exceeds 2.14 billion. * `CORE_HAS_ANALOG_ENH` - If defined as 1, `analogReadEnh()` (enhanced analogRead) is available. Otherwise, it is not. * `CORE_HAS_ANALOG_DIFF` - If defined as 1, `analogReadDiff()` (differential enhanced analogRead) is available. Otherwise, it is not. It has same features as enhanced, except that it takes a differential measurement. If this is -128, (128 unsigned), it is a classic AVR, not a modern one with a differential ADC, and the core's analogRead implementation accepts the constants listed in the core documentation to make an analogRead * `CORE_HAS_ENH_SERIAL` - if defined as 1 the core has the new implementation of Serial. See [the serial reference](Ref_Serial.md) diff --git a/megaavr/extras/Ref_Microchip.md b/megaavr/extras/Ref_Microchip.md index f1be54d8..fe857003 100644 --- a/megaavr/extras/Ref_Microchip.md +++ b/megaavr/extras/Ref_Microchip.md @@ -51,7 +51,7 @@ In fact, because of the great consistency between modern AVRs this has proven to If working with assembly you should make a rigorous study of the insruction set reference. One of the great strengths of AVR is the simplicity of the instruction set. You should know all the mneumonics, what arguments they take and what constraints apply - and this does not take a terribly great deal of effort, as there are not that many instructions. This is the Bible of the AVR architecture. Much like any other tome of the sort, it is packed with insight and wisdom from the creators, and describe in detail considerations you must observe, and some parts are not readily applicable to the present day`*`, and reading it is a long slog through obtuse verbiage and grammar. Unlike other more famous scriptures, you won't suffer eternal damnation for not reading this - but if you're writing assembly without it you may not be able to tell the difference. Even those who merely write C should try to make time for a cursory study of this, because this is what the compiler is turning your C into, and you can sometimes make choices that lead to the compiler being able to make better code. ### So uh, where are the datasheets? -I gave up trying to keep track of them all. The part-specific docs here now link to the Micochip product page. +I gave up trying to keep track of them all. The part-specific docs here now link to the Micochip product page. * [AVR128DA28, AVR64DA28, AVR32DA28](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DA28.md) * [AVR128DA32, AVR64DA32, AVR32DA32](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DA32.md) * [AVR128DA48, AVR64DA48, AVR32DA48](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DA48.md) @@ -61,7 +61,6 @@ I gave up trying to keep track of them all. The part-specific docs here now link * [AVR128DB48, AVR64DB48, AVR32DB48](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DB48.md) * [AVR128DB64 and AVR64DB64](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DB64.md) * [AVR64DD14, AVR32DD14, AVR16DD14](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DD14.md) -* [AVR64DD20, AVR32DD20, AVR16DD20](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DD20.md +* [AVR64DD20, AVR32DD20, AVR16DD20](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DD20.md) * [AVR64DD28, AVR32DD28, AVR16DD28](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DD28.md) * [AVR64DD32, AVR32DD32, AVR16DD32](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/DD32.md) - diff --git a/megaavr/extras/Ref_Optiboot.md b/megaavr/extras/Ref_Optiboot.md index fd59b605..cf8ab131 100644 --- a/megaavr/extras/Ref_Optiboot.md +++ b/megaavr/extras/Ref_Optiboot.md @@ -149,13 +149,13 @@ All ports and mux options subject to pin availability, as always: ## Bootloader size There is a critical difference between the classic AVRs and the modern ones, and this one I think is one of the few places they may have made a questionable design decision (Obviously, their implementation left something to be desired in many areas, as described in the silicon errata, but that's not what we're talking about here). On classic AVRs, the bootloader section was at the very end of the flash. When it was enabled, the chip would jump to there on reset instead of starting at 0x0000, the bootloader would do it's thing, and then get to the application code by jumping to 0x0000. That way, there was no need to know whether it was a bootloader or non-bootloader configuration at compile time. Now, the bootloader is at the start of the flash, and jumps to the end of it's section. Hence, the compiler needs to know to offset everything by 512 bytes (or more for other theoretical bootloaders), and now you cannot use optiboot to upload a binary compiled for non-optiboot mode, nor the other way around. You cannot translate a hex file compiled for optiboot to non-optiboot or vise-versa. ## Writing to the flash from the app -On Dx-series, this can always be done, with or without optiboot, and without optiboot, you can specify anything from only a tiny bit of flash at the end as writable, or let the entire flash be written. The key to this is that AVR-DA only requires the single instruction that writes to the flash to execute from the proper section, so the entry point you call need only be 2 istructions! If a data section is specified, you should try to not end up with application code in there, as certain operation cannot be executed from APPDATA. -On Ex-series, it requires optiboot as it will work like tinyAVR, and will always be able to always write anywhere in the flash. More detail will be provided when we have optiboot working on EA. +On Dx-series, this can always be done, with or without optiboot, and without optiboot, you can specify anything from only a tiny bit of flash at the end as writable, or let the entire flash be written. The key to this is that AVR-DA only requires the single instruction that writes to the flash to execute from the proper section, so the entry point you call need only be 2 istructions! If a data section is specified, you should try to not end up with application code in there, as certain operation cannot be executed from APPDATA. +On Ex-series, it requires optiboot as it will work like tinyAVR, and will always be able to always write anywhere in the flash. More detail will be provided when we have optiboot working on EA. On Dx-series, This library achieves this magic through one of three pathways, depending on conditions: -1. If Optiboot is present, there will be the 2-word entry point at the end of the bootloader section, just before the serial number. -2. Optiboot is not present, writes everywhere permitted - The entry point is placed within the first page of flash, that page is marked as bootloader (even though it's application), and we switch the vector select bit to use the correct vectors (in the fake bootloader section) instead of the wrong addresses in the "app section" -3. Optiboot is not present, writes restricted - the write can be executed from anywhere in APPCODE or BOOTCODE. We still have to do the fake 1 page bootloader (otherwise all flash is treated as bootcode, hence none can be written) but it has no bootloader function and we put no entrypoint there, and just write normally. This only works as long as the application code has not overflowed into APPDATA, a situataion which must be avoided. +1. If Optiboot is present, there will be the 2-word entry point at the end of the bootloader section, just before the serial number. +2. Optiboot is not present, writes everywhere permitted - The entry point is placed within the first page of flash, that page is marked as bootloader (even though it's application), and we switch the vector select bit to use the correct vectors (in the fake bootloader section) instead of the wrong addresses in the "app section" +3. Optiboot is not present, writes restricted - the write can be executed from anywhere in APPCODE or BOOTCODE. We still have to do the fake 1 page bootloader (otherwise all flash is treated as bootcode, hence none can be written) but it has no bootloader function and we put no entrypoint there, and just write normally. This only works as long as the application code has not overflowed into APPDATA, a situataion which must be avoided. The library used by megaTinyCore is completely and totally different from this one, despite the same name and similar function. (among other things, it's *much* easier to do on a Dx, because only the actual instruction that writes to the flash needs to be run from the boot section, whereas for tinyAVR, both writes to NVMCTRL and the page buffer do), @@ -166,13 +166,13 @@ One's first thought on hearing about the binaries being different might be wheth There are also a couple of differences between what is generated for bootloader and non-bootloader boards. With a bootloader, we don't need to put in a guard function for handling of empty reset cause (see the [reset guide](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/Ref_Reset.md), since Optiboot handles that. Writing to flash also has very different requirements depending on the presence or absence of a bootloader, and in the latter case, how much flash you want to be able to write. With Optiboot it is simple: The SPM instruction must be located in the boot section, that's the first page of flash. We put that in the two words immediately before the version number. Because only the actual spm instruction needs to run from bootloader section - you can stage everything else from the app - all that is needed is an a SPM Z+ (write word to flash and increment Z pointer) and RET (return). So in this case, you set up r0 and r1 with inline assembly, and then instead of calling SPM yourself (since you're in the application section), you can just call that address - it will be in the bootloader section, so it will be allowed to write to the application, and then it will immediately return. (The bootloader can be built without that feature - but that's not secure enough for a product where untrusted code could be involved, since if you can read from the bootloader section, you can find the SPM or an ST instruction with a clear path to a return after it, and call that instead. But don't worry - there's a bit you can set in the NVMCTRL registers that turns off the ability to read from or execute anything from the boot section; it can only be set from the bootloader, and only cleared by a total reset. So a bootloader that set that bit before jumping to the app could never be used to write to flash from the app - all it would see is NOOP instructions there if it tried). Making it work without a bootloader is trickier because the you still have to define a boot section (otherwise it treasts all of the flash as boot flash, which you can't write except over UPDI) - but you don't have a bootloader, you only have an app. If you're content to do it "the right way" and have part of the flash marked as "app data section" and the rest as "app code" this is as simple as setting the first page to be bootloader, and in early initialization, setting int interrupt vectors to be located in the bootloader section, which is what we do for "allow flash write from app" restricted to certain addresses. However, you can't write to EEPROM from appdata either, and if your code overflows into the app data section, depending on where the compiler happened to put it, you might end up failing to write to EEPROM. For unrestricted writes, we have to make something that looks like the case with the bootloader. We use the exact same structure, but it takes some trickery to make sure it goes into the correct section, since priority goes to several difficult to control sections before the .initn sections, so those won't work. ## Be sure you are using the latest bootloader version -Within approximately every minor version, we have had a substantial improvement to the bootloaded. For tinyAVR, very little fat is left to trim. On Dx - if we actually honored the chip erase command (-e from avrdude) and did that at the start of any write, we could then just take data and store it directly to the flash as it came in. We could even double the baud and not miss anything! On Ex - well, that'll be an adventure +Within approximately every minor version, we have had a substantial improvement to the bootloaded. For tinyAVR, very little fat is left to trim. On Dx - if we actually honored the chip erase command (-e from avrdude) and did that at the start of any write, we could then just take data and store it directly to the flash as it came in. We could even double the baud and not miss anything! On Ex - well, that'll be an adventure There are also a couple of small differences between what is generated for bootloader and non-bootloader boards. With a bootloader, we don't need to put in a guard function for handling of empty reset cause (see the [reset guide](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/Ref_Reset.md), since Optiboot handles that. DD support has been added ## Future Devices -* Optiboot_dx is expected to be the base for any future word-at-a-time NVMCTRL based AVR. This only such devices announced are the DA, DB, and DD and of course the long awaited DU. +* Optiboot_dx is expected to be the base for any future word-at-a-time NVMCTRL based AVR. This only such devices announced are the DA, DB, and DD and of course the long awaited DU. * Optiboot_x (for megaTinyCore and MegaCoreX) is likely to be the basis of page-buffer-using NVMCTRL AVRs. -* The EA-series is page-based (unfortunately) Not only that, but it's got poor flash endurance and you can't execute any instructions during the write half of a page erasewrite, so you are basically going to be doing tinyAVR algorithm plus added complications to account for this mess. \ No newline at end of file +* The EA-series is page-based (unfortunately) Not only that, but it's got poor flash endurance and you can't execute any instructions during the write half of a page erasewrite, so you are basically going to be doing tinyAVR algorithm plus added complications to account for this mess. diff --git a/megaavr/extras/Ref_Reset.md b/megaavr/extras/Ref_Reset.md index 680c3055..cec11741 100644 --- a/megaavr/extras/Ref_Reset.md +++ b/megaavr/extras/Ref_Reset.md @@ -67,7 +67,7 @@ The reset sources are listed below. Note that for brevity and familiarity to tho | 1 | 0 | 1 | Reset occurred because ramp from below VPOR to VBOR was slow. BOD was enabled, but the weak power supply was still supplying less than VBOR. This situation should be unusual. | 1 | 1 | X | The reset pin voltage significantly more slowly than VDD, possibly due to loading and insufficient pullup strength on the reset pin (You should immediately suspect that there is an issue with autoreset if you are using that - Perhaps a different (larger) value capacitor was used? Could the pullup be disconnected?). This has the visible consequence that the bootloader runs on startup. Even when a sketch is present and the reset button was never pressed. While ideally it should not occur, it is also not indicative of the sort of "drop everything and find this bug" situation, whereas a starting with no flags set indicates a critical failure occurring, and ought never be tolerated, but rather investigated promptly. -### The power of two software resets +## The power of two software resets The fact that there are now two ways of resetting from software changes things. There is an obvious way that both features can be used (an application uses the WDT to detect that it has gotten hung up somewhere and reset itself, and issues a software reset when some set of conditions is met or per user command). This is likely the most common use of them outside of Arduino. But there is also a second way that these can be used, and this is how we use it by default - Use SWRF as a "reset and run bootloader" while you can trigger resets without SWRF by the standard method of setting the WDT for minimum time and then going into forever loop which will trigger the reset. It is not recommended to set windowed mode and continualy send WDRs. You're doing something strange. When someone else reads it, or you read it later, you will likely have to come back and read either this document or the datasheet to understand how continually WDRs which normally would prevent the WDT from resetting, but for windowed mode. That would be okay - an ugly hack if it would reult in elimiating the 8 ms wait - but it just replaces it with a slightly slower one - WDRs, like everything related to the WDT, have a 2-3 WDT clock sync delay. The WDT clock is around 1 kHz derived from the internal 32 kHz ULP. Once you write the settings to the WDT register, it will take 2-3ms. Then the timer starts up. Now you can execute WDR, and it's no longer a no-op. The first WDR goes in - but you can't queue up a second WDR - WDR will again be a no-op unil, 2-3 ms later, the first WDR finishes syncing; it will reach the WDT and reset the timer - only after this first WDR is the window used, and only after that WDR is synced will a WDR instruction do start syncing a WDR. 2-3 ms later, it will finally slam into the closed window. Now a total of 3 sync periods have happened, for a total of 6-9 ms If we had not done this and simply used the shortest timeout, we would reset in 10-11 ms (2-3 ms sync before it turns on, minimum setting of 8 WDT ticks as WDT period. We could save as little as 1ms or as much as 6ms. diff --git a/megaavr/extras/Ref_Timers.md b/megaavr/extras/Ref_Timers.md index 0bae6a54..2f95797e 100644 --- a/megaavr/extras/Ref_Timers.md +++ b/megaavr/extras/Ref_Timers.md @@ -261,7 +261,7 @@ The frequency of PWM output using the settings supplied by the core is shown in This shows what the core will configure the TCA and TCD timers for at initialization. On the type A timers, only the prescaler can be changed "safely". If you need more control than that, see the included examples for demonstrations of taking over TCA and reconfiguring it to provide (for example) 16-bit PWM on three pins instead of 8-bit PWM on six pins. -On the type D timer, ALL situations with an external clock source (crystal or clock), we just say "screw this!" to the thorny problem of deciding how to generate a good PWM frequency from whackjob eternal clocks, and use the internal oscillator at 8 MHz, with a /32 prescale on the counter and /1 on the synchronizer, because we know that gives the target frequency, and don't have to play games with top or nothing. Because Timer D is uncooperative and combative, we have taken pains to make it easier to adjust. This is detailed in the [TCD Reference](REF_TCD.md) - but to give a brief summary, without doing takeOverTCD0() and taking full responsibility for that timer in all of it's hostile glory you can do the following without breaking analogWrite(): +On the type D timer, ALL situations with an external clock source (crystal or clock), we just say "screw this!" to the thorny problem of deciding how to generate a good PWM frequency from whackjob eternal clocks, and use the internal oscillator at 8 MHz, with a /32 prescale on the counter and /1 on the synchronizer, because we know that gives the target frequency, and don't have to play games with top or nothing. Because Timer D is uncooperative and combative, we have taken pains to make it easier to adjust. This is detailed in the [TCD Reference](Ref_TCD.md) - but to give a brief summary, without doing takeOverTCD0() and taking full responsibility for that timer in all of it's hostile glory you can do the following without breaking analogWrite(): * Change TOP to 254, 509, 1019, 2039, or 4079 (the last options are only available at F_CPU > 32 MHz - not for a fundamental reason, just tradeoff of time and space vs features, and consideration of the conditions under which those features would be most useful (high clock speeds) - in order to act as an ersatz prescaler. * This can be done without stopping the timer. It is accomplished by setting `TCD0.CMPBCLR` to one of those values. * No values other than the 5 listed above are supported. No design consideration was given to this case while implementing analogWrite(), other than to declare it unsupported. Our tests to detect which option is selected are optimized for execution speed, and assume that only those 5 valid values will be there (so we only need to look at one byte). @@ -275,7 +275,7 @@ On the type D timer, ALL situations with an external clock source (crystal or cl On the table below, I repeat, all external clock configurations get the same TCD configuration. This is shown explicitly for clock speeds that can only be achieved with an external clock, but the table will otherwise assume the internal oscillator is used as the system clock; if an external clock or crystal is used to achieve the same speed, refer to the External line for the TCD only. -Some frequencies shown are not supported by the core, but may be specified by a variant or boards.txt and while not guaranteed to work, are belived to work. 2 should definitely work, 6 and 3 very likely work, and 14 and 7 likely work. +Some frequencies shown are not supported by the core, but may be specified by a variant or boards.txt and while not guaranteed to work, are believed to work. 2 should definitely work, 6 and 3 very likely work, and 14 and 7 likely work. | CLK_PER | Prescale A | fPWM | Prescale D | TOP D | fPWM (D) | Notes | |-----------|------------|---------|-------------|-------|-----------|--------------------------------------------------| diff --git a/megaavr/extras/tinyNeoPixel.md b/megaavr/extras/tinyNeoPixel.md index 782074c1..c00e3e0a 100644 --- a/megaavr/extras/tinyNeoPixel.md +++ b/megaavr/extras/tinyNeoPixel.md @@ -282,7 +282,7 @@ Real pingpong balls are insanely flammable - unbelivably so. for reasons I've ne These are, as far as I know, a fairly recent innovation. These use thinner wires and MUCH smaller leds (looks like a single LED, with wires soldered directly onto it, covered in a blob of diffusing plastic. They come in strings of (typically) 50, 100, and 200. Some of the 50's can be daisy-chained (and include wires to inject power). The longer strings generally can't, and most have an integral USB power connector and controller (which generates impressively ugly patterns). It can be desoldered where it meets the LEDs, though I'd recommend cutting the wire, or desoldering it at the USB end, as their wire looks more attractive that the wire most of us have kicking around, and the LED wire itself is is a bit tricky to work with. These strings use lower current SK6805 LEDs, which allows the existence of 100 and 200 LED strings with such thin wire and with USB power (though in the case of 200-LED strings, if you start playing with them, you'll realize that the the controller is limiting the brightness in software to stay within a power budget and keep the ones at the end from going off-color; close investigation will also reveal that most strings of 200 have a joint in the middle. When repurposing these, this should be desoldered unless power can be injected from both ends. Note also that there are (or at least were) two kinds of these; in both cases, the wire looks fragile, but through totally different mechanisms. The currently dominant version has solid (not stranded) wire. On the one hand, this holds its shape very well and can easily be bent into a desired shape. On the downside, this bending action makes it more likely to break via fatigue, and the wires are also more visible. In the past, I have received a few sets made with a very different wire - incredibly flexible; I think there were other fibers woven in with the copper for improved flexibility (like "Litz wire"); it looked great, but it was eager to knot itself if you did anything suboptimal to it (like putting it onto a reel without spinning the reel on it's axis - if the reel does not rotate on it's axis during rolling and unrolling each wrap introduces a 360 degree twist!). #### Fairy Light controllers -The fairy lights appear to use an LED that has slightly different timing from the standard ones - or at least, one that *tolerates* slightly different timing than the standard. (Some of them have a 32.768kHz crystal in them. This can be replaced with a 40 kHz crystal and that is good enough to make most LEDs work.) So if you were thinking you could chop off the controller, and wire it up to an Arduino, you can. But if you were expecting to use that controller to debug any other kind of addressable LEDs? Nope - they seem to work with only a minority of LEDs, making them of practically zero use as a debugging aid. The ones with a 32k crystal on them work if it's swapped for a 40k one. +The fairy lights appear to use an LED that has slightly different timing from the standard ones - or at least, one that *tolerates* slightly different timing than the standard. (Some of them have a 32.768kHz crystal in them. This can be replaced with a 40 kHz crystal and that is good enough to make most LEDs work.) So if you were thinking you could chop off the controller, and wire it up to an Arduino, you can. But if you were expecting to use that controller to debug any other kind of addressable LEDs? Nope - they seem to work with only a minority of LEDs, making them of practically zero use as a debugging aid. The ones with a 32k crystal on them work if it's swapped for a 40k one. ### Notable LEDs that are NOT compatible * Anything that is not addressable, such as standard (single color or RGB) LED strip. As far as I have seen, every listing for a WS2812 compatible device has either WS2811, WS2812, or SK6812, and usually all three, in the title of the listing on marketplace sites like EBay, AliExpress, and Amazon. diff --git a/megaavr/libraries/Flash/src/Flash.h b/megaavr/libraries/Flash/src/Flash.h index 25049a74..035c8698 100644 --- a/megaavr/libraries/Flash/src/Flash.h +++ b/megaavr/libraries/Flash/src/Flash.h @@ -1,7 +1,6 @@ #ifndef FLASH_H #include #define FLASH_H -#if !defined() //*INDENT-OFF* /* Flash.h for DxCore 1.5.0 * A library to easily write to the flash of an AVR Dx-series part from within an Arduino sketch diff --git a/megaavr/libraries/Wire/src/twi_pins.c b/megaavr/libraries/Wire/src/twi_pins.c index 358bb666..f0628816 100644 --- a/megaavr/libraries/Wire/src/twi_pins.c +++ b/megaavr/libraries/Wire/src/twi_pins.c @@ -269,7 +269,7 @@ bool TWI0_swap(uint8_t state) { #if defined(PORTMUX_TWI0_bm) if (state == 1) { // Use pin swap - PORTMUX.CTRLB |= PORTMUX_TWI0_bm; + PORTMUX.CTRLB |= PORTMUX_TWI0_bm; return true; } else if (state == 0) { // Use default configuration @@ -550,7 +550,7 @@ uint8_t TWI0_checkPinLevel(void) { #if defined(TWI1) void TWI1_ClearPins() { #if defined(PIN_WIRE1_SDA_PINSWAP_2) || defined(TWI1_DUALCTRL) - uint8_t portmux = PORTMUX.TWIROUTEA & PORTMUX_TWI1_gm; + uint8_t portmux = PORTMUX.TWIROUTEA & PORTMUX_TWI1_gm; #endif #if defined(PIN_WIRE1_SDA_PINSWAP_2) if (portmux == PORTMUX_TWI1_ALT2_gc) { // make sure we don't get errata'ed @@ -581,7 +581,7 @@ bool TWI1_Pins(uint8_t sda_pin, uint8_t scl_pin) { #if (defined(PIN_WIRE1_SDA_PINSWAP_1) || defined(PIN_WIRE1_SDA_PINSWAP_2)) // Danger: 'portmux' in this context means all the other settings in portmux, since we're replacing the PORTMUX setting for TWI1, and will bitwise-or with the _gc constants. // Elsewhere, 'portmux' refers to the setting for this peripheral only, and we compare it to PORTMUX_TWI1_xxx_gc - uint8_t portmux = PORTMUX.TWIROUTEA & ~PORTMUX_TWI1_gm; + uint8_t portmux = PORTMUX.TWIROUTEA & ~PORTMUX_TWI1_gm; #if defined(PIN_WIRE1_SDA_PINSWAP_2) if (sda_pin == PIN_WIRE1_SDA_PINSWAP_2 && scl_pin == PIN_WIRE1_SCL_PINSWAP_2) { // Use pin swap @@ -627,7 +627,7 @@ bool TWI1_Pins(uint8_t sda_pin, uint8_t scl_pin) { bool TWI1_swap(uint8_t state) { // Danger: 'portmux' in this context means all the other settings in portmux, since we're replacing the PORTMUX setting for TWI1, and will bitwise-or with the _gc constants. // Elsewhere, 'portmux' refers to the setting for this peripheral only, and we compare it to PORTMUX_TWI1_xxx_gc - uint8_t portmux = PORTMUX.TWIROUTEA & (~PORTMUX_TWI1_gm); + uint8_t portmux = PORTMUX.TWIROUTEA & (~PORTMUX_TWI1_gm); #if defined(PIN_WIRE1_SDA_PINSWAP_2) if (state == 2) { // Use pin swap @@ -665,7 +665,7 @@ bool TWI1_swap(uint8_t state) { void TWI1_usePullups() { #if defined(PIN_WIRE1_SDA_PINSWAP_2) || defined(TWI1_DUALCTRL) - uint8_t portmux = PORTMUX.TWIROUTEA & PORTMUX_TWI1_gm; + uint8_t portmux = PORTMUX.TWIROUTEA & PORTMUX_TWI1_gm; #endif PORT_t *port; #if defined(PORTB) //All parts with a TWI1 have a PORTF diff --git a/megaavr/libraries/tinyNeoPixel_Static/examples/buttoncycler/buttoncycler.ino b/megaavr/libraries/tinyNeoPixel_Static/examples/buttoncycler/buttoncycler.ino index 66bc384d..71e18411 100644 --- a/megaavr/libraries/tinyNeoPixel_Static/examples/buttoncycler/buttoncycler.ino +++ b/megaavr/libraries/tinyNeoPixel_Static/examples/buttoncycler/buttoncycler.ino @@ -12,10 +12,10 @@ #if _AVR_PINCOUNT == 14 // need to use a different pins on DD14 #define BUTTON_PIN PIN_PD5 // Digital IO pin connected to the button. This will be -// driven with a pull-up resistor so the switch should -// pull the pin to ground momentarily. On a high -> low -// transition the button press logic will execute. - #define PIXEL_PIN PIN_PD4 + // driven with a pull-up resistor so the switch should + // pull the pin to ground momentarily. On a high -> low + // transition the button press logic will execute. + #define PIXEL_PIN PIN_PD4 #else #define BUTTON_PIN PIN_PA2 #define PIXEL_PIN PIN_PA3 // Digital IO pin connected to the NeoPixels diff --git a/megaavr/tools/VersionHistory.md b/megaavr/tools/VersionHistory.md index a6a3588f..b536b691 100644 --- a/megaavr/tools/VersionHistory.md +++ b/megaavr/tools/VersionHistory.md @@ -11,11 +11,11 @@ Add LOCKEDUSERROW action to write to the userrow of a locked chip. Fix unlock() so that when run interactively, it will check if the chip is locked and prompt the user if they try to unlock an unlocked chip unless a "yes I'm really sure" flag is passed. 6/2/2023 -## 1.3.0.2 (DxC only, stopgap) - fix die ref and serial reported by SerialUPDI. +## 1.3.0.2 (DxC only, stopgap) - fix die ref and serial reported by SerialUPDI It was observed that totally bogus values were output for the system die revision (not that we get die revs), and for the device serial number. This was fixed for the general case in application.py, but it is done independently in nvmserialupdi.py, but there, I don't know how to find out if we're on a Dx or not. But since this version is distributed only with DxCore, and the megaTinyCore version is separate (though otherwise identical), and since they don't work on parts meant for use with the other as installed by the IDE (even if you leave programmer selected after changing boards, it will fail because it's using the wrong platform.txt for the boards.txt and have unresolved substitution patterns), so it's unlikely that this specific version will ever be used to upload to tinyAVRs. Thus, this hacky fix of assuming it's a Dx-or-later is viable. 5/9/2023 -## 1.3.0.1 - changed wording of errors with easy fixes to suggest the fix. +## 1.3.0.1 - changed wording of errors with easy fixes to suggest the fix 8/18/2022 ## 1.3.0