From 4ddeb7129cf286ccad8eead70108da18032385cc Mon Sep 17 00:00:00 2001 From: Dan Sheppard Date: Mon, 8 Apr 2024 19:29:29 +0100 Subject: [PATCH] Spelling corrections suggested by codespell CI and manually verified. --- README.md | 2 +- avr/bootloaders/optiboot/source/optiboot.c | 2 +- avr/cores/tiny/HardwareSerial.h | 2 +- avr/cores/tiny/TinySoftwareSerial.cpp | 2 +- avr/extras/ATtiny_x41.md | 2 +- avr/extras/ATtiny_x7.md | 4 ++-- avr/extras/Ref_ChangePWMFreq.md | 4 ++-- avr/extras/Ref_Optiboot.md | 2 +- avr/extras/Ref_Programming.md | 2 +- avr/extras/Ref_TinySoftSerial.md | 2 +- avr/extras/tinyNeoPixel.md | 4 ++-- avr/libraries/Wire/Readme.md | 2 +- avr/libraries/Wire/src/SoftI2CMaster.h | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 6c6182c1..b41d9731 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Typically 8x slower than expected - see below entry. The option should really be named "Set fuses and install bootloader (if any)" rather than "burn bootloader", which makes it sound irreversible (it's not), and by not mentioning the fuses, many users think that it isn't needed if a bootloader is being used. But it is, because this is the only time fuses are set; this is the same behavior as all other classic AVR cores, because it is possible to soft-brick the parts if the fuses are misconfigured, and so writing the . #### VUSB is not supported for USB functionality within the sketch -It has been persuasively argued to me that it is not possible to get these parts to meet USB timing contstraints in an interrupt driven context without compromising on everything else. On the classical digispark, their core bent over backwards and got only mediocre results. The libraries floating around are stale, having rarely received updates, often dating back to the days of avr-gcc 4.8.x, and only ever worked on the digispark core - and even there they didn't work particularly well. USB timing constraints are very constraining. If anyone cared to put in the considerable amount of effort it would involve to port micronucleus and package the VUSB libraries, the pieces to make this viable *are actually present on the tinyAVR 0/1/2-series* (the key feature being the lvl 1 priority interrupt option though the improvements to instruction set timing don't hurt). But I don't know that anyone is showing much interest in taking that on. +It has been persuasively argued to me that it is not possible to get these parts to meet USB timing constraints in an interrupt driven context without compromising on everything else. On the classical digispark, their core bent over backwards and got only mediocre results. The libraries floating around are stale, having rarely received updates, often dating back to the days of avr-gcc 4.8.x, and only ever worked on the digispark core - and even there they didn't work particularly well. USB timing constraints are very constraining. If anyone cared to put in the considerable amount of effort it would involve to port micronucleus and package the VUSB libraries, the pieces to make this viable *are actually present on the tinyAVR 0/1/2-series* (the key feature being the lvl 1 priority interrupt option though the improvements to instruction set timing don't hurt). But I don't know that anyone is showing much interest in taking that on. To make matters worse, much of the functionality you want on Windows (namely, low speed CDC for a serial port) requires drivers that don't exist in a fully working form. Unfortunately, even if you found a solution to meet the USB constraint and made the drivers work, that's still not enough because you need to bend over backwards to install them if they haven't been blessed with a digital signaure from Microsoft, so it is difficult to get a solution you could share with the world diff --git a/avr/bootloaders/optiboot/source/optiboot.c b/avr/bootloaders/optiboot/source/optiboot.c index 717716a5..70a6b73b 100644 --- a/avr/bootloaders/optiboot/source/optiboot.c +++ b/avr/bootloaders/optiboot/source/optiboot.c @@ -212,7 +212,7 @@ /* There are already enough unholy things done to this*/ /* version that it shouldn't compile for any ATmega */ /* so why imply that it would? */ -/* Adust most indentation to match all of my cores */ +/* Adjust most indentation to match all of my cores */ /* 58.0 Pull in RS485 support by Vladimir Dronnikov */ /* ( github.com/dvv ) as used in */ /* github.com/SodaqMoja/optiboot */ diff --git a/avr/cores/tiny/HardwareSerial.h b/avr/cores/tiny/HardwareSerial.h index e7a8be69..dcc8ee3b 100644 --- a/avr/cores/tiny/HardwareSerial.h +++ b/avr/cores/tiny/HardwareSerial.h @@ -73,7 +73,7 @@ #endif /* WARNING * BUFFER SIZES MUST BE POWERS OF TWO - The compiler misses some of the - * optimization possible with the % opperator. only a small portion of it, but as there's no compelling reason NOT + * optimization possible with the % operator. only a small portion of it, but as there's no compelling reason NOT * to use a power of two size, and there are some extrenely flash-constrained parts that have a USART (I'm thinking of the 2313 in particular * I couldn't justify not explicitly optimizing the % SERIAL_BUFFER_SIZE to a & (SERIAL_BUFFER_SIZE -1)) */ diff --git a/avr/cores/tiny/TinySoftwareSerial.cpp b/avr/cores/tiny/TinySoftwareSerial.cpp index 2415c712..f43e6203 100644 --- a/avr/cores/tiny/TinySoftwareSerial.cpp +++ b/avr/cores/tiny/TinySoftwareSerial.cpp @@ -259,7 +259,7 @@ size_t TinySoftwareSerial::write(uint8_t ch) { // // We can't use r0 for this, because uartDelay uses r0 as it's delay counter. "cli" "\n\t" // disable interrupts if they're not disabled already. "ldi r20, 10" "\n\t" // - "in r19, %[uartPort]" "\n\t" // load the curret value of the TX PORT register. + "in r19, %[uartPort]" "\n\t" // load the current value of the TX PORT register. "or r19, %[txmask]" "\n\t" // there's our pattern for a 1. one hopes that this line is unnecessary since serial is IDLE HIGH. "mov r18,r19" "\n\t" // copy it to the zero bit... "eor r18, %[txmask]" "\n\t" // xor with the txmask, which has all but 1 bit set, a bit which we know is set in the destination register. 4 instructions to prepare the 0 and 1 bit patterns. diff --git a/avr/extras/ATtiny_x41.md b/avr/extras/ATtiny_x41.md index b3d104ec..ba8d2b9b 100644 --- a/avr/extras/ATtiny_x41.md +++ b/avr/extras/ATtiny_x41.md @@ -35,7 +35,7 @@ The ATtiny x41-family is a more advanced version of the ATtiny x4-family. It is Any of these parts can be programmed by use of any ISP programmer. 4k and 8k parts can be programmed over the software serial port using Optiboot, and 8k parts can be programmed via Micronucleus. Be sure to read the section of the main readme on the ISP programmers and IDE versions. 1.8.13 is recommended for best results. ### Optiboot Bootloader -This core includes an Optiboot bootloader for the ATtiny841/441, operating on the hardware UART0 (Serial) port at 115200 baud for 12 MHz or higher, or 57600 when running at lower speeds. The bootloader uses 640b of space, leaving 3456 or 7552b available for user code. In order to work on these parts, which do not have hardware bootloader support (hence no BOOTRST functionality), "Virtual Boot" is used. This works around this limitation by rewriting the vector table of the sketch as it's uploaded - the reset vector gets pointed at the start of the bootloader, while the EE_RDY vector gets pointed to the start of the application (versions of the core prior to 1.2.0 used WDT vector, so WDT cannot be used as an interrupt - we recommend burning bootloader with the new version if this is an issue). A version of the bootloader that operates on Serial1 is included as well (choose the desired UART when burning the booloader). +This core includes an Optiboot bootloader for the ATtiny841/441, operating on the hardware UART0 (Serial) port at 115200 baud for 12 MHz or higher, or 57600 when running at lower speeds. The bootloader uses 640b of space, leaving 3456 or 7552b available for user code. In order to work on these parts, which do not have hardware bootloader support (hence no BOOTRST functionality), "Virtual Boot" is used. This works around this limitation by rewriting the vector table of the sketch as it's uploaded - the reset vector gets pointed at the start of the bootloader, while the EE_RDY vector gets pointed to the start of the application (versions of the core prior to 1.2.0 used WDT vector, so WDT cannot be used as an interrupt - we recommend burning bootloader with the new version if this is an issue). A version of the bootloader that operates on Serial1 is included as well (choose the desired UART when burning the bootloader). ### Micronucleus VUSB Bootloader This core includes a Micronucleus bootloader that supports the ATtiny841, allowing sketches to be uploaded directly over USB. The board definition runs at 8 MHz via the internal oscillator. For low power applications, it can be prescaled as listed in the table, or cranked up to 16 MHz for the adventurous. See the document on [Micronucleus usage](Ref_Micronucleus.md) for more information. In order to achieve the 12 MHz clock during USB operation, the OSCCAL is drastically increased to 12MHz while the bootloader is running, but is set back down before running the sketch. diff --git a/avr/extras/ATtiny_x7.md b/avr/extras/ATtiny_x7.md index 832b7cba..f8b4deb1 100644 --- a/avr/extras/ATtiny_x7.md +++ b/avr/extras/ATtiny_x7.md @@ -80,7 +80,7 @@ TC0 is always run in Fast PWM mode: We use TC0 for millis, and phase correct mod |>16 MHz | x/128/256=30 * x Hz | x/64/512= 30 * x Hz | Phase correct TC1 | | 20 MHz | 20/128/255= 610 Hz | 20/64/512= 610 Hz | Phase correct TC1 | -Where the /32 or /128 prescaler, not available on most parts, is used, it sigificantly improves the output frequency in the most desirable range for typical applications - unfortunately timer0 has only a single output (it's not the standard TC0 - it has much in common the the ATmega TC2 async, potentially externally-clocked timer. +Where the /32 or /128 prescaler, not available on most parts, is used, it significantly improves the output frequency in the most desirable range for typical applications - unfortunately timer0 has only a single output (it's not the standard TC0 - it has much in common the the ATmega TC2 async, potentially externally-clocked timer. Where speeds above or below a certain speed are specified, it's implied that the other end of the range is the next marked value. So >16 in that table is for 16-20 MHz clocks. The formula is given as a constant times x where x is expressed as MHz (the division above gets the time in megahertz - in the interest of readability I did not include the MHz to Hz conversion - I'm sure you all know how to multiply by a million) @@ -183,7 +183,7 @@ I (Spence Konde / Dr. Azzy) sell ATtiny167 boards through my Tindie store - your The 87 and 167 are available in three package variations. Additionally, the 167 only can be had in a fourth package. * SOIC-20 (wide) - bigger than the side of a house, but easy to hand solder * TSSOP-20 - Slightly more demanding to solder. While it is hard to imagine being able to read this text and miss a bridge between adjacent pins on a SOIC-20, the same cannot be said for a SSOP-20 - depending on your eyesight, you may need magnification or more attention to lighting in order to spot bridges visually -* VQFN32 - with 12 unused pins - Atmel seemed to REALLY like this package - a lot of 20-pin tinyAVR parts got this as their QFN instead of a proper QFN20-type. It's an annoying package, though - it's very fine pitch, large for a QFN (5mm x 5mm), and the unused pins don't appear to have been arranged with consideration of the layout. They're in the same order as the pins up and down the two sides of the SOIC/SSOP parts (probably a technical constraint I've never seen a chip with what was believed to have the same die, *not* have the same pin order, so I think bond wires have to make straight lines that don't cross each other from the die to the pin), but the decisons for where those dummy pins would go appears to have been based only on their convenience. +* VQFN32 - with 12 unused pins - Atmel seemed to REALLY like this package - a lot of 20-pin tinyAVR parts got this as their QFN instead of a proper QFN20-type. It's an annoying package, though - it's very fine pitch, large for a QFN (5mm x 5mm), and the unused pins don't appear to have been arranged with consideration of the layout. They're in the same order as the pins up and down the two sides of the SOIC/SSOP parts (probably a technical constraint I've never seen a chip with what was believed to have the same die, *not* have the same pin order, so I think bond wires have to make straight lines that don't cross each other from the die to the pin), but the decisions for where those dummy pins would go appears to have been based only on their convenience. ## Interrupt Vectors This table lists all of the interrupt vectors available on the ATtiny x7-family, as well as the name you refer to them as when using the `ISR()` macro. Be aware that a non-existent vector is just a "warning" not an "error" (for example, if you misspell a vector name) - however, when that interrupt is triggered, the device will (at best) immediately reset (and not clearly - I refer to this as a "dirty reset") The catastrophic nature of the failure often makes debugging challenging. diff --git a/avr/extras/Ref_ChangePWMFreq.md b/avr/extras/Ref_ChangePWMFreq.md index 6769f98f..735842b1 100644 --- a/avr/extras/Ref_ChangePWMFreq.md +++ b/avr/extras/Ref_ChangePWMFreq.md @@ -24,7 +24,7 @@ In a timer counter unit, when we're talking about PWM, we're talking about the s * When full control of the timer is taken the additional functionality might include (briefly - these features are beyond the scope of this document): * Periodic interrupts with CTC (Clear Timer on Compare match) * Arbitrary TOP values, sometimes without the loss of an output, other times only at the cost of an output channel. - * 16-bit timers which have an input capture feature (I belive all of the classic AVR "standard" timer1s plus higher timers that are a copy of the standard timer1) have a PWM mode where you set the ICR register to the TOP value without losing either of the output compares. + * 16-bit timers which have an input capture feature (I believe all of the classic AVR "standard" timer1s plus higher timers that are a copy of the standard timer1) have a PWM mode where you set the ICR register to the TOP value without losing either of the output compares. * On 8-bit timers, typically the only option is to set it so output compare channel A sets top, losing a channel. * Higher resolution on Timer1, except: * On the 43 - it's 8-bit there, copy of timer0. @@ -85,7 +85,7 @@ The high speed timers have a few bits of odd behavior to them, the most relevant When either of these timers used to generate PWM, which is what they're made for, OCR1C is TOP (though this defaults to 255), while OCR1A, B, and D if present are the output channels. -For the Tiny x5, you again have two swiches available that impact the frequency. The Tx61 does as well, but also lets you choose one of the whopping 4 WGMs available; all of these can be done without losing analogWrite(). Either way, the prescaler is 4 bits now (0 = stopped, otherwise, the prescaler is 2^(n-1)) +For the Tiny x5, you again have two switches available that impact the frequency. The Tx61 does as well, but also lets you choose one of the whopping 4 WGMs available; all of these can be done without losing analogWrite(). Either way, the prescaler is 4 bits now (0 = stopped, otherwise, the prescaler is 2^(n-1)) The bits are located in TCCR1 on the tiny85: ```c diff --git a/avr/extras/Ref_Optiboot.md b/avr/extras/Ref_Optiboot.md index 430acafc..008bb822 100644 --- a/avr/extras/Ref_Optiboot.md +++ b/avr/extras/Ref_Optiboot.md @@ -53,7 +53,7 @@ This is much harder without the `BOOTRST` fuse. The bootloader still gets locate Optiboot erases pages when using virtual boot the same way as it does when it has the insurance of a hardware bootloader (ie, the simplest way possible): Whenever it is fed the first byte of a page, it first erases that page, and then proceeds with programming. That all is fine as long as you have a BOOTRST fuse to guarantee that you can get back to the bootloader. A failure of some sort at this state would simply require reuploading the sketch. But with virtual boot, if it has erased the first page, but not rewritten it, it neither knows how to run the bootloader or start the application. It is bricked until it can be reprogrammed with an ISP programmer. Bitter experience has shown that this does happen in the field, particularly when running on batteries (where a "brownout", where weak batteries drop below the minimum voltage required (by BOD or physics) from the current of the erase process), from a mishandled programming attempt (where an attempt is started, abandoned with the port being closed, and retried) on a board with autoreset, or from other unknown adverse events. Murphy's law dictates that the greater the cost and inconvenience of trudging out there to reprogram the device, the higher the chance of it failing like this. -**There is a well known and extensively tested (Micronucleus uses it) solution**: The moment that the booloader is told to write anything, you erase every page of flash outside the bootloader section, starting with the end and finishing with the first page (the one with the reset vector, which if you recall is pointed to the bootloader), and the application vector must be placed not in the vector table at the start of the flash, but rather as the last word of the application section. Thus, if an erase is incomplete, the application will be hosed, but the bootloader will still run, unless the erase completed, in which case there is nothing but empty flash between the reset vector and the bootloader. Empty flash holds all 1's. `0xFFFF`, despite being an invalid opcode, is interpreted as a "skip [next instruction] if bit 7 in 31 is set" (sbrs r31, 7) (opcode 0xFFF7) - so depending on the value of r31, it will skid along the empty flash executing and skipping alternating words, or executing every word. Since the only instructions running are `sbrs r31,7` sbrs will either skip every other instruction, or not, as there's no way for r31's value to change until it reaches non-empty flash. Since the bootloader must be an integer number of pages in size, and pages are always even numbers of words in size (typical page sizes are 32b to 128b), it will never miss the first instruction of the bootloader. Thus the case of a complete erase with no write will reach the bootloader. And if a failure occurs after writing the first page of flash, but before finishing the last, the bootloader will jump to the last location in the application section to try to start the app. That will be empty flash, from whence it will proceed to the bootloader and the upload could be reattempted. +**There is a well known and extensively tested (Micronucleus uses it) solution**: The moment that the bootloader is told to write anything, you erase every page of flash outside the bootloader section, starting with the end and finishing with the first page (the one with the reset vector, which if you recall is pointed to the bootloader), and the application vector must be placed not in the vector table at the start of the flash, but rather as the last word of the application section. Thus, if an erase is incomplete, the application will be hosed, but the bootloader will still run, unless the erase completed, in which case there is nothing but empty flash between the reset vector and the bootloader. Empty flash holds all 1's. `0xFFFF`, despite being an invalid opcode, is interpreted as a "skip [next instruction] if bit 7 in 31 is set" (sbrs r31, 7) (opcode 0xFFF7) - so depending on the value of r31, it will skid along the empty flash executing and skipping alternating words, or executing every word. Since the only instructions running are `sbrs r31,7` sbrs will either skip every other instruction, or not, as there's no way for r31's value to change until it reaches non-empty flash. Since the bootloader must be an integer number of pages in size, and pages are always even numbers of words in size (typical page sizes are 32b to 128b), it will never miss the first instruction of the bootloader. Thus the case of a complete erase with no write will reach the bootloader. And if a failure occurs after writing the first page of flash, but before finishing the last, the bootloader will jump to the last location in the application section to try to start the app. That will be empty flash, from whence it will proceed to the bootloader and the upload could be reattempted. Optiboot needs to be adapted to do that. I wasn't able to see a clear route towards doing that when I last looked into that adaptation. diff --git a/avr/extras/Ref_Programming.md b/avr/extras/Ref_Programming.md index fecf0b52..3a7a7c28 100644 --- a/avr/extras/Ref_Programming.md +++ b/avr/extras/Ref_Programming.md @@ -16,7 +16,7 @@ Ensure that you have connected all necessary external components (see [Wiring Gu * SCK of programmer (pin 13 on Uno/Nano/ProMini) to SCK of target * MISO of programmer (pin 12 on Uno/Nano/ProMini) to MISO of target * MOSI of programmer (pin 11 on Uno/Nano/ProMini) to MOSI of target -* Pin 10 (pin 10 on Uno/Nano/ProMini, or pin "RST" pin on the ISP connector of a dedicated programer) to RST of target +* Pin 10 (pin 10 on Uno/Nano/ProMini, or pin "RST" pin on the ISP connector of a dedicated programmer) to RST of target You must have a supported programmer: * AVR ISP diff --git a/avr/extras/Ref_TinySoftSerial.md b/avr/extras/Ref_TinySoftSerial.md index 6531df0c..9ef7fd1f 100644 --- a/avr/extras/Ref_TinySoftSerial.md +++ b/avr/extras/Ref_TinySoftSerial.md @@ -5,7 +5,7 @@ Working with the tinyAVR parts without any sort of serial port is quite challeng ## TinySoftSerial and baud rates -The builtin software serial implementation has a rather limited range between maximum and minimum possible baud rates - the "delay" loop used for timing also has a lower bound on the baud rate that it can generate, because it uses a byte to count down it's iterations. There is no means of error reporting of the normal sort - however you can test if begin() has been called succeessfully with if (Serial) - this will return false if Serial has not yet been given a valid baud rate. If the port has not yet been "begun", all transmission attempts will fail immediately, with write returning 0. +The builtin software serial implementation has a rather limited range between maximum and minimum possible baud rates - the "delay" loop used for timing also has a lower bound on the baud rate that it can generate, because it uses a byte to count down it's iterations. There is no means of error reporting of the normal sort - however you can test if begin() has been called successfully with if (Serial) - this will return false if Serial has not yet been given a valid baud rate. If the port has not yet been "begun", all transmission attempts will fail immediately, with write returning 0. Clock Speed | Minimum Baud | Maximum plausible Baud -------------|--------------|--------------------------- diff --git a/avr/extras/tinyNeoPixel.md b/avr/extras/tinyNeoPixel.md index 1dbf7114..667a337b 100644 --- a/avr/extras/tinyNeoPixel.md +++ b/avr/extras/tinyNeoPixel.md @@ -287,7 +287,7 @@ In addition to following all the usual safety guidelines, pay particular attenti * PVC wire is almost universally afflicted with this. It is rare to purchase PVC wire from chinese suppliersand get what was advertised; I have found in the wild that the wire is typically 4 AWG thinner, but it may be as little as 1 AWG undersized to as much as 8. This does not apply western wire makers who subcontract manufacture to China - they weren't born yesterday, and are keenly aware of this trick, and keep their manufacturing partners in line. I try to avoid PVC insulated wire from China entirely. * This is particularly troublesome when you were planning to crimp on connectors, as the insulation thickness no longer matches what the crimper and terminals expect. You can think "Okay, I need 24 AWG wire, so I'll order 20 AWG wire" to maximize your chance of getting 24 AWG wire". But to conceal their fraud, they made the insulation as thick as it would be on to 20 AWG wire: Your terminals won't fit over it! * You know those "christmas light" style WS2811 strings? You know how you need to inject power stupidly often? The wire says 20 AWG on the side, so you really shouldn't need to inject power that often... So is it really 20 AWG? I counted 19 wires, measured each strand as 0.08mm, so it's 19/0.08, or in AWG... around 27 AWG. *No wonder we have to feed power in every 50 LEDs!* That wire is the second least honestly spec'ed wire I have encountered, being beaten by less than 1 AWG by a particularly horrible batch of prewired JST-SM connectors (the ones I mentioned above where red wire was cooked black) - * FEP (Flourinated ethylene-propylene, a copolymer of perflouroethylene and perflouropropylene) is a much tougher, stronger, more heat resistant material used as insulation. It is considerably harder to manufacture, but can be made thinner while having superior mechanical properties. Like PVC, however, it can still be removed with thermal wire strippers, and is not terribly hard to remove with hand strippers either. It is, unsurprisingly, more expensive. What **is** surprising is that it doesn't seem to have the undersizing problem that PVC insulated wire does. I don't know if this is just because it's harder to make and that keeps the riff-raff out of the market, or if they consider people who would buy FEP wire to be more likely to notice their bogus wire, or what the full reason is, but I've never had PVC-insulated wire arrive from China that wasn't at least 1 AWG undersized, while no FEP insulated wire has been undersized by even 1 AWG. The thinner insulation ensures that crimp connnectors will fit over the wire, even when you're pushing the upper limits of the size of wire that can fit a given type of terminal. This wire is often mis-sold as PTFE (teflon) insulated wire. Luckily they are lying about this: you don't want *actual* PTFE insulated wire. That stuff is tough as nails. It laughs at a normal thermal wire stripper, and is very challenging to strip with hand strippers as well. Stripping it easily needs a *fancy* thermal-wirestripper (and my chemical background struggles to come up with potential compounds which might make up odd-smelling fumes which wouldn't be noxious). Thankfully, little if any of the "PTFE" wire you would get buying from China is PTFE - it's all FEP. + * FEP (Flourinated ethylene-propylene, a copolymer of perflouroethylene and perflouropropylene) is a much tougher, stronger, more heat resistant material used as insulation. It is considerably harder to manufacture, but can be made thinner while having superior mechanical properties. Like PVC, however, it can still be removed with thermal wire strippers, and is not terribly hard to remove with hand strippers either. It is, unsurprisingly, more expensive. What **is** surprising is that it doesn't seem to have the undersizing problem that PVC insulated wire does. I don't know if this is just because it's harder to make and that keeps the riff-raff out of the market, or if they consider people who would buy FEP wire to be more likely to notice their bogus wire, or what the full reason is, but I've never had PVC-insulated wire arrive from China that wasn't at least 1 AWG undersized, while no FEP insulated wire has been undersized by even 1 AWG. The thinner insulation ensures that crimp connectors will fit over the wire, even when you're pushing the upper limits of the size of wire that can fit a given type of terminal. This wire is often mis-sold as PTFE (teflon) insulated wire. Luckily they are lying about this: you don't want *actual* PTFE insulated wire. That stuff is tough as nails. It laughs at a normal thermal wire stripper, and is very challenging to strip with hand strippers as well. Stripping it easily needs a *fancy* thermal-wirestripper (and my chemical background struggles to come up with potential compounds which might make up odd-smelling fumes which wouldn't be noxious). Thankfully, little if any of the "PTFE" wire you would get buying from China is PTFE - it's all FEP. * Always pull-test a few samples from a batch of prewired connectors (most commercial dupont line fails the pull test, and even some JST-SM prewired connector fails. Hopefully if you crimp your own, you're already pull testing them). * When using pre-wired connectors, use a pin extractor to pull out a male and female pin from a given batch and compare them to a pin on the "same" connectors you already have. Proceed only with great caution and testing if you discover that the existing connectors and the ones you just got do not look identical - some terminals are made in several versions with different mating force or for different wire gauges. These both matter, but are generally designed to be compatible. On the other hand there are horror stories of incompatible male and female pins from different suppliers that would fail over time when used together, or male pins that were ever so slightly too large and would damage female terminals from other manufacturers - both could result in a poor (high resistance) connection which might get hot without causing visible symptoms until you start a fire, or notice that the wires have been discolored from heat.. * Make sure that any power supply you use will turn itself off in the event of overcurrent, instead of changing to constant current mode. Folding back to constant current mode is great for a benchtop supply in your workshop, but in the field, all it does is waste power while generating a bunch of heat wherever the fault is, until either someone notices, something burns out, or it starts a fire. @@ -318,4 +318,4 @@ If Adafruit has added new methods to their library, please report via an issue i ## License Unlike the core itself (as noted within the library files), tinyNeoPixel is licensed under LGPL 3, not LGPL 2.1, since the Adafruit library was always LGPL 3. -`*` - C++ predates the invention of names like "properties" and "methods" (as well as countless programming concepts that we take for granted on more modern lanuages, if you haven't noticed). Strictly speaking, they are called "member variables" and "member functions" - however when you call them those names, nobody without exposure to C++ outside Arduino who didn't learn programming 25+ years ago will have any idea what you're talking about. +`*` - C++ predates the invention of names like "properties" and "methods" (as well as countless programming concepts that we take for granted on more modern languages, if you haven't noticed). Strictly speaking, they are called "member variables" and "member functions" - however when you call them those names, nobody without exposure to C++ outside Arduino who didn't learn programming 25+ years ago will have any idea what you're talking about. diff --git a/avr/libraries/Wire/Readme.md b/avr/libraries/Wire/Readme.md index d90112e2..58a3504b 100644 --- a/avr/libraries/Wire/Readme.md +++ b/avr/libraries/Wire/Readme.md @@ -51,7 +51,7 @@ When the master *writes* to the slave: 3. Slave ACKs 4. Master clocks out 8 databytes 5. Slave stores in buffer and ACKs -6. repeat 4-5 until master is done sending or slave's buffer is full causeing it to NACK. +6. repeat 4-5 until master is done sending or slave's buffer is full causing it to NACK. 7. Master generates a stop condition. 8. Slave's onReceive handler is called, being passed the number of bytes received. diff --git a/avr/libraries/Wire/src/SoftI2CMaster.h b/avr/libraries/Wire/src/SoftI2CMaster.h index ccd7875e..30eb4cbe 100644 --- a/avr/libraries/Wire/src/SoftI2CMaster.h +++ b/avr/libraries/Wire/src/SoftI2CMaster.h @@ -435,7 +435,7 @@ bool i2c_write(uint8_t value) { " nop \n\t " " sbi %[SCLDDR],%[SCLPIN] ; force SCL low so SCL = H is short\n\t" " ret \n\t" - " ; + 4 = 17C + 2X for acknowldge bit" + " ; + 4 = 17C + 2X for acknowledge bit" :: [SCLDDR] "I" (SCL_DDR), [SCLPIN] "I" (SCL_PIN), [SCLIN] "I" (SCL_IN), [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN), [SDAIN] "I" (SDA_IN));