diff --git a/ContributionGuidelines.md b/ContributionGuidelines.md index 7e3ebb51..9698dc72 100644 --- a/ContributionGuidelines.md +++ b/ContributionGuidelines.md @@ -11,7 +11,7 @@ They are discussions. I dont check them as often, because I don't expect to see ### Before creating an issue or discussion topic Check the existing [issues](https://github.com/SpenceKonde/DxCore/issues), and recent [discussions](https://github.com/SpenceKonde/DxCore/discussions) and recently closed issues [closed issues](https://github.com/SpenceKonde/DxCore/issues?q=is%3Aissue+is%3Aclosed) -1. If there is a disusssion, read it and see if it applies to you. If it does, either it will solve your problem or you will have additional information that shows that the issue is a defect in the core - if so it is recommended to post that information as a comment in that discussion thread **IFF** there is a large amount of additional and necessary context in the discussion, such that I should be converting the discusssion to an issue. Otherwise reference the discusssion and open a new issue. +1. If there is a disusssion, read it and see if it applies to you. If it does, either it will solve your problem or you will have additional information that shows that the issue is a defect in the core - if so it is recommended to post that information as a comment in that discussion thread **IFF** there is a large amount of additional and necessary context in the discussion, such that I should be converting the discussion to an issue. Otherwise reference the discussion and open a new issue. 2. If there is an existing issue that appears to be the exact same issue, read it and if it really is the same issue, comment there instead of making a new issue - HOWEVER is is *more* important to avoid posting a report of a DIFFERENT issue in an existing issue, as there is no function that lets me split them into separate issues. So this raises the risk that the original problem wiioll; get fixed and the issue closed without your issue being looked at. So don't hijack issues like that. It is not critical to avoid creating a new issue, since I can always close your issue as a duplicate. If lots of people are tripping over an issue it is helpful to know that it is a problem for more people and 3. If such an issue was **recently** closed, read it to be sure it really is same. Have you updated to a version that I claimed fixed that issue, or if it wasn't a defect in the core, does whatever fixed it for them work for you? If not, reopen the issue. **Note that issues are closed when they are fixed in github, not when a released version including the fix is available** - so you may need to update to the github version of the core in order to test a change. 4. If you don't find such an issue, or it was closed months ago, create a new issue. Reference the old one by number (the number sign followed by the issue number will automatically create a link). diff --git a/README.md b/README.md index dde2b46b..8ded849b 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ This corrects many of the bugs present in 2.6.x ### IDE Versions 2.0.x and some 2.1 do not work correctly. This is a bug in the Arduino client. -IDE versions between 1.8.13 and 2.x developed significant novel defects. IDE versions 1.8.2 and earlier , however, possess crippling unfixed defects. I belive that they finally have a working version of the IDE out, and I belive that latest is able to install my core correctly. +IDE versions between 1.8.13 and 2.x developed significant novel defects. IDE versions 1.8.2 and earlier , however, possess crippling unfixed defects. I believe that they finally have a working version of the IDE out, and I believe that latest is able to install my core correctly. Prior to megaTinyCore 2.6.0, manual installation of megaTinyCore would cause V1.8.14 of the IDE to crash due to [this bug](https://github.com/arduino/Arduino/issues/11813) when you install the core manually in your arduino folder. Users of 1.8.14 and later must use version 2.6.0 of megaTinyCore. diff --git a/megaavr/bootloaders/optiboot_x/optiboot_x.c b/megaavr/bootloaders/optiboot_x/optiboot_x.c index affaf8a7..28b109c2 100644 --- a/megaavr/bootloaders/optiboot_x/optiboot_x.c +++ b/megaavr/bootloaders/optiboot_x/optiboot_x.c @@ -65,7 +65,7 @@ /* Set bootloader baud rate. */ /* */ /* LED_START_FLASHES: */ -/* Number of LED flashes on bootup. */ +/* Number of LED flashes on boot-up. */ /* */ /* LED_DATA_FLASH: */ /* Flash LED when transferring data. For boards without */ diff --git a/megaavr/cores/megatinycore/WInterrupts.c b/megaavr/cores/megatinycore/WInterrupts.c index 7e84952a..1c7d2c9b 100644 --- a/megaavr/cores/megatinycore/WInterrupts.c +++ b/megaavr/cores/megatinycore/WInterrupts.c @@ -252,7 +252,7 @@ "icall" "\n\t" // call their function, which is allowed to shit on any upper registers other than 28, 29, 16, and 17. "rjmp AIntLoop" "\n\t" // Restart loop after. "AIntEnd:" "\n\t" // sooner or later r17 will be 0 and we'll branch here. - // with EARLYCLEAR variant, we don't need to do anythin other than cleaning up working registers - flags already cleared. + // with EARLYCLEAR variant, we don't need to do anything other than cleaning up working registers - flags already cleared. "pop r31" "\n\t" // clean up a million registers "pop r30" "\n\t" "pop r29" "\n\t" diff --git a/megaavr/cores/megatinycore/core_devices.h b/megaavr/cores/megatinycore/core_devices.h index 27c2fd1c..fcd8c93c 100644 --- a/megaavr/cores/megatinycore/core_devices.h +++ b/megaavr/cores/megatinycore/core_devices.h @@ -805,7 +805,7 @@ int8_t _setPrescale(int8_t prescale) { * On the modern AVRs, address 0x0000 is VPORTA.OUT, so the first thing you'd trash if you wrote * to a null pointer is the PORTA configuration. BUT had they put the GPIOR's first - like xmega * then writing the null pointer would have first trashed a byte or bytes that most applications - * don't even use - but which would also naturally be a perfect probe of whether the bizzare bug + * don't even use - but which would also naturally be a perfect probe of whether the bizarre bug * you're trying to sort out is caused by following a null pointer somewhere or by something else. * Not that that's a super-common bug. 99 times out of 10 those sorts of "everything is totally * confused" bugs happen when you return from a function that has overflowed the bounds of a diff --git a/megaavr/extras/Arduino-cli.md b/megaavr/extras/Arduino-cli.md index fcbaba14..574eacd4 100644 --- a/megaavr/extras/Arduino-cli.md +++ b/megaavr/extras/Arduino-cli.md @@ -50,7 +50,7 @@ arduino-cli core upgrade arduino-cli core update-index ``` -__Note:__ Sometimes in environments like Github Actions, arduino-cli is not able to find the megaTinyCore with the above comamnd. +__Note:__ Sometimes in environments like Github Actions, arduino-cli is not able to find the megaTinyCore with the above command. The reason could be many folds. In runners like Github Actions, if the arduino-cli is not able to fetch the JSON file automatically, we can manually download the necessary JSON file and place it in the expected directory before running the core search or install command. example: diff --git a/megaavr/extras/Ref_Defines.md b/megaavr/extras/Ref_Defines.md index 321ab034..668875bd 100644 --- a/megaavr/extras/Ref_Defines.md +++ b/megaavr/extras/Ref_Defines.md @@ -284,7 +284,7 @@ There are a number of macros for determining what (if any) features the core sup ## Hardware feature detection * `ADC_MAX_OVERSAMPLED_RESOLUTION` = 13 (tinyAVR0/1), 15 (Dx-series) or 17 (tinyAVR 2 or Ex-series) - If either `CORE_HAS_ANALOG_ENH` or `CORE_HAS_ANALOG_DIFF` is 1, this will be defined as the maximum resolution obtainable automatically via oversampling and decimation using those functions. -* `ADC_MAXIMUM_GAIN` is 0 (DA, DD, DU, tinyAVR0/1), -1 (DB), or 16 (EA, EB, tinyAVR 2) - Some parts' ADC is blessed with a Programmable Gain Amplifier (PGA) amplifier, often used for differential readings (though modern AVRs can use it for single-ended readings, if they have it - not that it's terribly useful). The Dx-series are not among them, though the EA will have it. If this is defined as a positive number, it is the maximum gain available (16 on the EA). If this is defined as 0 that means there is no way to amplify an analog signal we might want to measure (if this is a problem you need external opamps). If this is defined as -1 (or 255 if stuffed into a uint8), there are one or more `OPAMP` peripherals available which could be directed towards the same purpose, though more deliberation and part specific work would be needed; they may be more flexible in some ways, but they are very rigid in others (for example, in that there is only one pin option for them. If it is defined as -128 (128 in a uint8) there is a gain stage on the differential ADC, but it is specified along with the pair of pins, not with separate configuration options. This also means that it's *NOT* a modern AVR! This is generally what is done on all classic AVRs with a differential ADC) so the available gain options depend on which pins are being measured, and there is a different procedure to use it, as detailed in the core documentation (ex, ATTinyCore 2.0.0 and later). If it is undefined, there is definitley no support exposed through the core, and it may not be a feature of the hardware at all. +* `ADC_MAXIMUM_GAIN` is 0 (DA, DD, DU, tinyAVR0/1), -1 (DB), or 16 (EA, EB, tinyAVR 2) - Some parts' ADC is blessed with a Programmable Gain Amplifier (PGA) amplifier, often used for differential readings (though modern AVRs can use it for single-ended readings, if they have it - not that it's terribly useful). The Dx-series are not among them, though the EA will have it. If this is defined as a positive number, it is the maximum gain available (16 on the EA). If this is defined as 0 that means there is no way to amplify an analog signal we might want to measure (if this is a problem you need external opamps). If this is defined as -1 (or 255 if stuffed into a uint8), there are one or more `OPAMP` peripherals available which could be directed towards the same purpose, though more deliberation and part specific work would be needed; they may be more flexible in some ways, but they are very rigid in others (for example, in that there is only one pin option for them. If it is defined as -128 (128 in a uint8) there is a gain stage on the differential ADC, but it is specified along with the pair of pins, not with separate configuration options. This also means that it's *NOT* a modern AVR! This is generally what is done on all classic AVRs with a differential ADC) so the available gain options depend on which pins are being measured, and there is a different procedure to use it, as detailed in the core documentation (ex, ATTinyCore 2.0.0 and later). If it is undefined, there is definitely no support exposed through the core, and it may not be a feature of the hardware at all. * `_AVR_PORT_INLVL` is 1 if the INLVL bit is present. If undefined or 0, that feature is not available. ## Hardware pin determination diff --git a/megaavr/extras/Ref_Digital.md b/megaavr/extras/Ref_Digital.md index 429e65f1..c5a6841b 100644 --- a/megaavr/extras/Ref_Digital.md +++ b/megaavr/extras/Ref_Digital.md @@ -199,7 +199,7 @@ These are the maximum voltage guaranteed to qualify as LOW and the minimum guara * With Vdd = 1.8 V (the minimum), below about half the operating voltage, it's going to read low, while it may need to be very close to the power rail to read `HIGH`. * With Vdd = 5.0 V (maximum typically used intentionally) anything over about 1/3rd if the supply voltage is guaranteed to be `HIGH`, and you need to get down to 1/6th of the supply voltage for a guaranteed `LOW`. * The actual lower threshold is likely to be higher, and the upper threshold lower. For example, on DA-series SMBus pins, those voltages are 1.09 V and 1.24 V over most of the operating voltage range. This leave you with very little hysteresis, if that happens to be problematic. - * If interacting with an output that for whatever reason struggles to pull the pin as close to ground as an ideal output should, or if you're counting on the transition being somewhere near the middle of the range, definitley don't use this option. + * If interacting with an output that for whatever reason struggles to pull the pin as close to ground as an ideal output should, or if you're counting on the transition being somewhere near the middle of the range, definitely don't use this option. Particularly in the context of these MVIO-equipped parts, however, the TTL input level option has an obvious major advatage: It makes communication with parts that run at lower voltages easier, and reduces competition for the limited number of MVIO pins. If we allow the low part to control it push-pull (aka totam-pole and other names), and treat it as an `INPUT`, we will always read what they intend. The fact that you can switch a pin between input and output, while pulling it up externally was noted above, and the voltage it was pulled up to could be the lower operating vboltage. That can be done on any AVR. But with INLVL, this scheme is viable for a bidirectional line: the The line between devices could either be pulled up to the lowest operating voltage externally, with the DB or DD series part manipulating the pin as an open drain output (see above). One need not stop with just two devices - multiple DB/DD-series parts with `INVLV = TTL` set could communicate with multiple devices operating at the low voltage, as long as none of them ever drove it `HIGH` (though, if it was low, they would not know which device was doing that. The designer would have to make sure this approach made sense in that regard, and that everything was smart enough to not hold onto the line or anything. diff --git a/megaavr/extras/Ref_Reset.md b/megaavr/extras/Ref_Reset.md index a9847b1e..6b608df3 100644 --- a/megaavr/extras/Ref_Reset.md +++ b/megaavr/extras/Ref_Reset.md @@ -79,7 +79,7 @@ The reset sources are listed below. Note that for brevity and familiarity to tho ### 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 eliminating 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. +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 result in eliminating 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. No matter what, triggering a reset with the WDT hence takes far longer than other methods., but at 11 ms, still a very short period of tme by human standards. diff --git a/megaavr/extras/Ref_Robust.md b/megaavr/extras/Ref_Robust.md index 76ce5adb..1b6aa7cd 100644 --- a/megaavr/extras/Ref_Robust.md +++ b/megaavr/extras/Ref_Robust.md @@ -103,4 +103,4 @@ If it doesn't work, you need to either solve the technical problem, or clearly d In warm conditions, are any heatsinks you're using sufficient? How close does the temperature get to the ratings? ### Shake, poke, drop -Everything gets abused. Make sure your physical assembly is sufficiently robust. Shake it while it's running and make sure it doesn't reset (unless that's what it's designed to do, or is too heavy to shake). Poke and prod it while it's running (assuming it doesn't have dangerous voltages exposed, which it really ought not to have!). Hold it by it's wires, Yank out it's cable (Micro USB connectors should be the kind with the through holes, which prevent a yank from pulling the connector off the PCB, unless you have a case around it to keep the force from being handled mainly by the connector. The crap connectors that many developemnt boards have used are so bad they've given MicroUSB a bad rep in some circles - including for a time Arduino circles due to the connector on early Arduino Micros. Pick them up and drop them from as high a height as is plausible. Your customers may use the products while frazzled and hurried, at awkward physical angles, and while intoxicated - sometimes all of the above. If your product is unavoidably fragile, warn people (but don't cry wolf if it's not). +Everything gets abused. Make sure your physical assembly is sufficiently robust. Shake it while it's running and make sure it doesn't reset (unless that's what it's designed to do, or is too heavy to shake). Poke and prod it while it's running (assuming it doesn't have dangerous voltages exposed, which it really ought not to have!). Hold it by it's wires, Yank out it's cable (Micro USB connectors should be the kind with the through holes, which prevent a yank from pulling the connector off the PCB, unless you have a case around it to keep the force from being handled mainly by the connector. The crap connectors that many development boards have used are so bad they've given MicroUSB a bad rep in some circles - including for a time Arduino circles due to the connector on early Arduino Micros. Pick them up and drop them from as high a height as is plausible. Your customers may use the products while frazzled and hurried, at awkward physical angles, and while intoxicated - sometimes all of the above. If your product is unavoidably fragile, warn people (but don't cry wolf if it's not). diff --git a/megaavr/extras/Ref_Timers.md b/megaavr/extras/Ref_Timers.md index a234e6d5..54e1d24c 100644 --- a/megaavr/extras/Ref_Timers.md +++ b/megaavr/extras/Ref_Timers.md @@ -13,7 +13,7 @@ This document is divided into two sections. The first one simply describes the a * [Input Capture on Event](Ref_Timers.md#input-capture-on-event) * [Input Capture Frequency Measurement](Ref_Timers.md#input-capture-frequency-measurement) * [Input Capture Pulse Width Measurement](Ref_Timers.md#input-capture-pulse-width-measurement) - * [Input Capture Frequecy And Pulse Width Measurement](Ref_Timers.md#input-capture-frequecy-and-pulse-width-measurement) + * [Input Capture Frequency And Pulse Width Measurement](Ref_Timers.md#input-capture-frequecy-and-pulse-width-measurement) * [Single-shot](Ref_Timers.md#single-shot) * [Timeout Check](Ref_Timers.md#timeout-check) * [8-bit PWM mode](Ref_Timers.md#8-bit-pwm-mode) @@ -106,7 +106,7 @@ This applies to the tinyAVR 0/1/2-series, megaAVR 0-series, and AVR DA, DB and D ### TCA0 - Type A 16-bit Timer with 3/6 PWM channels This timer is the crown jewel of the modern AVR devices, as far as timers go. It can be operated in two very different modes. The default mode on startup is "Normal" or `SINGLE` mode - it acts as a single 16-bit timer with 3 output compare channels. It can count in either direction, and can also be used as an event counter (ie, effectively "clocked" off the event), is capable of counting up or down, generating PWM in single and dual slope modes, and has 7-output prescaler. In terms of PWM generation, a TCA in SINGLE mode is on the same level as the classic avr 16-bit Timer1 (though most classic AVRs only had 2 outputs per timer - there the third output was a rare feature reserved for top-end parts like the 2560). The newly added features aren't ones that are particularly relevant for most Arduino users. TCA0 can generate events or interrupts on compare match for each channel (independently), as well as on an overflow. -The Type A timer can be also be set to split mode to get six 8-bit PWM channels (this is how it is configured by default by megaTinyCore and DxCore - since `analogWrite()` is only 8-bit, we might as well double the number of channels we get right? In split mode the high and low bytes of the timer count `TCA0.SINGLE.CNT` register become `TCA.SPLIT.LCNT` and `TCA.SPLIT.LCNT`; likewise the period and compare registers *in SINGLE mode, these are 16-bit registers; accessing them uses the temporary register. In SPLIT mode, they are 8-bit registers!* (Unlike the TCB in PWM mode, this works correctly on all parts). The frequency of the clock from which the signals generated by the two halves of the timer are derived is always the same - they share the prescaler - but the period, and hence the frequecy of the output, is not. For example, if we have a 1 MHz clock (16 MHz prescaled by 16), and set LPER to 249 (250 clocks) and HPER to 199 (200 clocks) the low-half period, covering WO 0-2 will generate PWM at 4kHz, and the high half will generate PWM at 5 kHz on WO3-5. +The Type A timer can be also be set to split mode to get six 8-bit PWM channels (this is how it is configured by default by megaTinyCore and DxCore - since `analogWrite()` is only 8-bit, we might as well double the number of channels we get right? In split mode the high and low bytes of the timer count `TCA0.SINGLE.CNT` register become `TCA.SPLIT.LCNT` and `TCA.SPLIT.LCNT`; likewise the period and compare registers *in SINGLE mode, these are 16-bit registers; accessing them uses the temporary register. In SPLIT mode, they are 8-bit registers!* (Unlike the TCB in PWM mode, this works correctly on all parts). The frequency of the clock from which the signals generated by the two halves of the timer are derived is always the same - they share the prescaler - but the period, and hence the frequency of the output, is not. For example, if we have a 1 MHz clock (16 MHz prescaled by 16), and set LPER to 249 (250 clocks) and HPER to 199 (200 clocks) the low-half period, covering WO 0-2 will generate PWM at 4kHz, and the high half will generate PWM at 5 kHz on WO3-5. Event functionality is not supported in SPLIT mode. @@ -150,7 +150,7 @@ As above, but at the specified edge, the timer count is automatically reset (aft #### Input Capture Pulse Width Measurement One edge restarts the timer. The other edge copies the value and fires the interrupt, thus making it perfect for timing the length of pulses. -#### Input Capture Frequecy And Pulse Width Measurement +#### Input Capture Frequency And Pulse Width Measurement This one is the weird one. Does not work with prescaled clocks on some tinyAVRs (see silicon errata listings). On one edge, it starts the timer. On the other edge, it copies the count to CCMP *and continues to count* until the next edge. Only then will the interrupt fire (if enabled). Whether via polling or interrupt, when you see that this has happened, you need copy the count value someplace safely, then the CCMP value. As soon as CCMP has been read, when it next sees the "start count" edge, it will reset the timer and start counting. Thus, while great for measuring PWM of varying frequency and duty cycle where the duty cycle does not change drastically from cycle to cycle, it is not useful if you need to record every cycle (for that, you're forced to use Input Capture on Event mode, and have your interrupt very quickly switch the edge to which it is sensitive). #### Single-shot diff --git a/megaavr/extras/Ref_Tuning.md b/megaavr/extras/Ref_Tuning.md index 44fa5613..7fe660d0 100644 --- a/megaavr/extras/Ref_Tuning.md +++ b/megaavr/extras/Ref_Tuning.md @@ -233,7 +233,7 @@ Setting: A classroom full of programmers and anthropomorphized peripherals are a *My name's Clock, and - unlike a certain instructor - I value yer Time, and I specialize in keeping it Real... I've got just what you need, right here....* -The idea here is simple: Run RTC from internal 32kHz oscillator. This is inaccurate (if you have a crystal, it's not, rich kid), but pretty stable stable. Pipe it to the event system via ASYNCCH3 for 1-series or any odd channel for the 2-series (0-series parts and their owners are S. O. L. here - as usual for those low budget parts. I hope we don't have any of those here today, we dun like your kind round these parts, you hear me? The 0-series is strictly inferior and can't selftune! So if you're a 0-series, get out of here, I'm not talking to your kind. *several sadfaced 0-series parts slink out of the classroom with tears in their eyess* Because, ya see here one of the many ways ways the 0-series `EVSYS` is gimped is that, lacking async channels 2 and 3 while having the exactly same list of peripherals for the channels they do have... they don't got no PIT output channels. So they can't use the divided PIT signals as event generators. It's a little hard to imagine who'd save 7 cents tops at that kinda cost isn't it? What I never got was way there was always so many of em around, takin our precious die space! +The idea here is simple: Run RTC from internal 32kHz oscillator. This is inaccurate (if you have a crystal, it's not, rich kid), but pretty stable stable. Pipe it to the event system via ASYNCCH3 for 1-series or any odd channel for the 2-series (0-series parts and their owners are S. O. L. here - as usual for those low budget parts. I hope we don't have any of those here today, we dun like your kind round these parts, you hear me? The 0-series is strictly inferior and can't selftune! So if you're a 0-series, get out of here, I'm not talking to your kind. *several sadfaced 0-series parts slink out of the classroom with tears in their eyess* Because, ya see here one of the many ways ways the 0-series `EVSYS` is gimped is that, lacking async channels 2 and 3 while having the exactly same list of peripherals for the channels they do have... they don't got no PIT output channels. So they can't use the divided PIT signals as event generators. It's a little hard to imagine who'd save 7 cents tops at that kinda cost isn't it? What I never got was way there was always so many of em around, taking our precious die space! Anyway, so let's turn on the RTC and turn on the PIT! PIT/64 should be around 512 Hz diff --git a/megaavr/extras/Ref_dirty_tricks.md b/megaavr/extras/Ref_dirty_tricks.md index 1ba205ee..01e7baf1 100644 --- a/megaavr/extras/Ref_dirty_tricks.md +++ b/megaavr/extras/Ref_dirty_tricks.md @@ -10,7 +10,7 @@ There are a few of us who work on the core (me, and 1, maybe two others) who kno The ramifications of C type promotion and integer literals defaulting to 16-bit signed ints come together to cause math to be done with larger datatypes than you intend, and frequently it is nearly impossible to talk it out of this. -There is no C syntax that is consistently optimized intelligently for << 8 operations and larger shifts, and frequntly, the optimization choices made with -Os result in not *no* consideration being given to performance. +There is no C syntax that is consistently optimized intelligently for << 8 operations and larger shifts, and frequently, the optimization choices made with -Os result in not *no* consideration being given to performance. So this is a combination of simply pathological code where the n'th instruction negates the n-1-th instruction, poor renditions of the C type promotion rules that make things really inefficient, and -Os is too willing to pick incredibly slow implementations diff --git a/megaavr/libraries/Logic/Tricks_and_Tips.md b/megaavr/libraries/Logic/Tricks_and_Tips.md index 1e293574..1d3a2ddc 100644 --- a/megaavr/libraries/Logic/Tricks_and_Tips.md +++ b/megaavr/libraries/Logic/Tricks_and_Tips.md @@ -104,7 +104,7 @@ Sync/Filter: Off Yes, we could have done the third one with another CCL lut too - but why when there's a trick to do it without wasting a second LUT? Maybe we need the other LUTs. ### Modulated PWM -Like classic AVRs had on larger pincount devices. One PWM frequency should be significantly higher than the other if you're trying to modulate it, rather than measure the beat frequency or something, and they definitley should be at different frequencies, otherwise see the previous pattern. +Like classic AVRs had on larger pincount devices. One PWM frequency should be significantly higher than the other if you're trying to modulate it, rather than measure the beat frequency or something, and they definitely should be at different frequencies, otherwise see the previous pattern. INSEL: * X: Timer PWM channel. diff --git a/megaavr/libraries/megaTinyCore/keywords.txt b/megaavr/libraries/megaTinyCore/keywords.txt index 1e20b7ef..0a197d47 100644 --- a/megaavr/libraries/megaTinyCore/keywords.txt +++ b/megaavr/libraries/megaTinyCore/keywords.txt @@ -2418,7 +2418,7 @@ NVMCTRL_EE_vect LITERAL1 _VECTOR_SIZE LITERAL1 _VECTORS_SIZE LITERAL1 -# MEMORY PERAMETERS +# MEMORY PARAMETERS DATAMEM_START LITERAL1 DATAMEM_SIZE LITERAL1 DATAMEM_END LITERAL1 diff --git a/megaavr/libraries/tinyNeoPixel/tinyNeoPixel.cpp b/megaavr/libraries/tinyNeoPixel/tinyNeoPixel.cpp index 1fba1f42..91b90e31 100644 --- a/megaavr/libraries/tinyNeoPixel/tinyNeoPixel.cpp +++ b/megaavr/libraries/tinyNeoPixel/tinyNeoPixel.cpp @@ -186,7 +186,7 @@ void tinyNeoPixel::show(uint16_t leds) { // // Finally, some of the constraints were incorrect, and this only ever // worked because classes are kryptonite to the optimizer. - // * [ptr] was decleared read only. No, it is not. The register is + // * [ptr] was declared read only. No, it is not. The register is // register contaains the address being pointed to. We read with // postincrement, so this is read-write. // * Conversely, [port], another pointer, is never written. The thing that diff --git a/megaavr/libraries/tinyNeoPixel_Static/tinyNeoPixel_Static.cpp b/megaavr/libraries/tinyNeoPixel_Static/tinyNeoPixel_Static.cpp index 98e87edf..7e511bdf 100644 --- a/megaavr/libraries/tinyNeoPixel_Static/tinyNeoPixel_Static.cpp +++ b/megaavr/libraries/tinyNeoPixel_Static/tinyNeoPixel_Static.cpp @@ -142,7 +142,7 @@ void tinyNeoPixel::show(uint16_t leds) { // // Finally, some of the constraints were incorrect, and this only ever // worked because classes are kryptonite to the optimizer. - // * [ptr] was decleared read only. No, it is not. The register is + // * [ptr] was declared read only. No, it is not. The register is // register contaains the address being pointed to. We read with // postincrement, so this is read-write. // * Conversely, [port], another pointer, is never written. The thing that