Skip to content

Commit

Permalink
Partly fix one example. Fix linter errors in a new reference document
Browse files Browse the repository at this point in the history
  • Loading branch information
SpenceKonde committed Jan 30, 2023
1 parent c063ef8 commit b899565
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 98 deletions.
28 changes: 14 additions & 14 deletions megaavr/extras/Ref_dirty_tricks.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# dirty_tricks.h - a package of macros that act as a forceful shove to the optimizer.
# dirty_tricks.h - a package of macros that act as a forceful shove to the optimizer
These are intended primarily for internal use.
**For experienced users with at least basic AVR assembly knowledge only**

Expand Down Expand Up @@ -63,12 +63,12 @@ In lower case (but less compatible. Not dirty)
These are the dirty tricks that we warned you about.

### High and Low math
* `_addLow(16_bit_t a, variable uint8_t b)`
* `_subLow(16_bit_t a, variable uint8_t b)`
* `_addHigh(16_bit_t a, variable uint8_t b)`
* `_subHigh(16_bit_t a, variable uint8_t b)`
* `_addLowConst(16_bit_t a, constant uint8_t b)`
* `_subLowConst(16_bit_t a, constant uint8_t b)`
* ` _addLow(16_bit_t a, variable uint8_t b)`
* ` _subLow(16_bit_t a, variable uint8_t b)`
* ` _addHigh(16_bit_t a, variable uint8_t b)`
* ` _subHigh(16_bit_t a, variable uint8_t b)`
* ` _addLowConst(16_bit_t a, constant uint8_t b)`
* ` _subLowConst(16_bit_t a, constant uint8_t b)`
* `_addHighConst(16_bit_t a, constant uint8_t b)`
* `_subHighConst(16_bit_t a, constant uint8_t b)`

Expand Down Expand Up @@ -97,12 +97,12 @@ This instead comes out to 6 clocks and 6 words.
### dirty tricks which can often but not always be replicated with clever use of C type unions
These pertain to setting the high or low bit to a constant value, setting it to a value already in a variable
* `_setHigh(16_bit_t a, variable uint8_t b)`
* `_setHighConst(16_bit_t a, constant uint8_t b)`
* `_clrHigh(16_bit_t a)`
* `_setLow(16_bit_t a, variable uint8_t b)`
* `_setLowConst(16_bit_t a, constant uint8_t b)`
* `_clrLow(16_bit_t a)`
* ` _setHigh(16_bit_t a, variable uint8_t b)`
* ` _setHighConst(16_bit_t a, constant uint8_t b)`
* ` _clrHigh(16_bit_t a)`
* ` _setLow(16_bit_t a, variable uint8_t b)`
* ` _setLowConst(16_bit_t a, constant uint8_t b)`
* ` _clrLow(16_bit_t a)`
This sets the high or low byte (as requested) to a specified variable or constant. The change is made in place, and the other byte is unchanged.
Most useful when working with pointers. "set" and "setconst" set the specified byte to a non-zero value, "clr" version sets the specified byte to 0.
Expand Down Expand Up @@ -130,7 +130,7 @@ pADC->CTRLB = 0x55;
### Building pointers from bytes
These two macros give you a pointer (in either Z or Y, or in X, Y or Z).
* `_makeFastPtr_d(uint8_t * newptt, const uint8_t highbyte, uint8_t lowbyte)` // Z or Y - the displacement capable ones
* `_makeFastPtr(uint8_t * newptt, const uint8_t highbyte, uint8_t lowbyte)` // any pointer register pair. Can almost always be done with a union.
* ` _makeFastPtr(uint8_t * newptt, const uint8_t highbyte, uint8_t lowbyte)` // any pointer register pair. Can almost always be done with a union.

These take three arguments: A local variable that must be a pointer, a constant value that is to be the high byte and a 8-bit variable which is to be the low byte.
They provide NO GUARANTEE that the compiler won't waste even more time shuffling them out of the register you forced them into, but the compiler is rarely that boneheaded. It does dumb stuff, yes, but if you've forced variables into certain registers, it's unlikely to move them unless it has to, in which case the compilers first attempt may not have been as bad as you thought.
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,42 @@
// *INDENT-OFF* this code is unreadable of you follow astyle's conventions!
#if __AVR_ARCH__ >=100
/* FOR MODERN AVRs:
*
* tinyAVR must use PB0, PB1 or PB2 (PB2 is by default a serial pin though.
* In order for these to be good tuning sources you should have an external clock chip on them, or have a watch crystal connected to them and use RTC tuning mode, and use the adjusted RTC-tuning version of the tuning sketch as well
* In order for these to be good tuning sources you must have an external clock chip on them, or have a watch crystal connected to them and use RTC tuning mode.
* Same goes for AVR DA and megaAVR 0-series.
*
* AVR DB-series and DD-series parts can use a simple crystal.
* AVR DB-series and DD-series parts can use a simple MHz crystal.
*
* Your tuning will never be better than the thing you're ruimning it from, so don't use something
* running on an internal oscillator!
* Your tuning will never be better than the thing you're tuning it from, so don't use something
* running on an internal oscillator - just grab any pro mini clone which you can see the HC/49 16 mhz crystal on (the tiny ones are often much less accurate
* ceramic resonators that are barely better than the modern internal oscillator. )
*/
#ifndef TUNE_OUTPUT_PIN // If not defined in parts.h, need to pick default pin
#ifndef TUNE_WITH_RTC // First the non-RTC version
#if !defined(MEGATINYCORE)
#elif !defined(_AVR_PINCOUNT > 14)
// Except under tight constraints of 14-pin non-tinies, we can always count on their being a PA2.
#define TUNE_OUTPUT_PIN PIN_PA2
#elif !(defined(__AVR_DU__)) /*AVR DD-series has no PC0, PA2-7, and the only pins nubered 2 or lower in any port
* are thus PA0, PA1, and PC1 and PC2. The pins on PORTA are needed for the crystal if this is to be used
* and you actually want to tune to within an accuracy measured in (tens of) "ppm" instead of (several) "%" on datasheet specs.
* (since any error in th tuning is reflected in the USART baud rate error and all timing accuracy).
* You can use PIN_PC2 just as well.
*/
#define TUNE_OUTPUT_PIN PIN_PC1
#if (_AVR_PINCOUNT > 14)
// Except under tight constraints of 14-pin non-tinies, we can always count on their being a PA2.
#define TUNE_OUTPUT_PIN PIN_PA2
#elif defined(PIN_PC2) /*AVR DD-series has no PC0, PA2-7, and the only pins nubered 2 or lower in any port
* are thus PA0, PA1, and PC1 and PC2. The pins on PORTA are needed for the crystal if this is to be used
* and you actually want to tune to within an accuracy measured in (tens of) "ppm" instead of (several) "%" on datasheet specs.
* So we're using either PC1 or PC2!
*/
#define TUNE_OUTPUT_PIN PIN_PC2
/* This must be a pin that exists, and which is numbered 0-2 in the port; we will use TCA0 to
* generate it and set PORTMUX.TCAROUTEA appropriately.
* This sketch uses TCA0 to generate the tuning signal, and hence you can't use it for millis
* Well - you can, and it will still tune parts perfectly well, but only because we don't rely on
* millis in any way shape or form to get our timing (if we did it'[d be totally fucked_/
*
* This sketch does not support using the CCL to redirect these orphaned output channels to usable pins,
* and this is in fact practically trivial to do without even using the libraries. Se my 8-channel
* "millis, never heard of her..." for the 2-series, I demonstrate this in order to force both of those
* fancy 16-bit TCB's to be reduces to generating a single 8-pit PWM output redirected via the CCL.
* The timers involved, in an interview after the testing, described the work as humuiliating, and
* and de-humanizing [desiliconizing?]. They had objected at the time, they claimed, but said that
* I had brandished a grill starter (the spark ones - to a semiconductor, this is like pointing a gun at them yasee)
* and ordered them to work as 8 bit timers, with my loyal logic blocks putting a friendly facade over the operation.
* These accusations are totally false, as are their claims that I wasn't even paying for that derading work.
* They're supposed to receive a nominal portion of the package rate that I pay for the chips.
* They're all under contract through Microchip, so if they're not happy with the working conditions, they need to
* talk to Microchip. So don't blame me for peripheral abuse. "but you make us work at 40 MMz instead of 24!
* "Shot up, you're a piece of silicon, your opinion doesn't count, now start counting unprescaled clock cycles
* or I'll teach you about peizoelectricity got that?" *clickclick*
* "Anyway, you're not even supposed to be involved in this sketch, go back to 8WayPWM2Series.ino!"
* *y-yes, right away... right away Sir*.
* ... On chip peripherals. Give em an inch and they take a mile.
* and this is in fact practically trivial to do without even using the libraries.
*/
#elif defined(__AVR_DU__) //previous case caught all except DU14
#else /* tinyAVR */
#define TUNE_OUTPUT_PIN PIN_PB0 /* pins B1 and B2 also work. No other pins are supported. */
#endif
#else

#if (defined(MEGATINYCORE) || !defined(DD_14_PINS))
#define TUNE_OUTPUT_PIN PIN_PA2
#else
Expand All @@ -66,7 +50,7 @@
#ifndef TUNE_WITH_RTC
#if !((((defined(PIN_PA0) && TUNE_OUTPUT_PIN == PIN_PA0) || (defined(PIN_PA1) && TUNE_OUTPUT_PIN == PIN_PA1) || (defined(PIN_PA2) && TUNE_OUTPUT_PIN == PIN_PA2) || \
(defined(PIN_PC0) && TUNE_OUTPUT_PIN == PIN_PC0) || (defined(PIN_PC1) && TUNE_OUTPUT_PIN == PIN_PC1) || (defined(PIN_PC2) && TUNE_OUTPUT_PIN == PIN_PC2) || \
(defined(PIN_PD1) && TUNE_OUTPUT_PIN == PIN_PD1) || (defined(PIN_PD2) && TUNE_OUTPUT_PIN == PIN_PD2) || ((defined(PIN_PD0) && TUNE_OUTPUT_PIN == PIN_PD0) && PIN_PD0 != NOT_A_PIN) || \
(defined(PIN_PD1) && TUNE_OUTPUT_PIN == PIN_PD1) || (defined(PIN_PD2) && TUNE_OUTPUT_PIN == PIN_PD2) || (defined(PIN_PD0) && TUNE_OUTPUT_PIN == PIN_PD0) || \
(defined(PIN_PE0) && TUNE_OUTPUT_PIN == PIN_PE0) || (defined(PIN_PE1) && TUNE_OUTPUT_PIN == PIN_PE1) || (defined(PIN_PE2) && TUNE_OUTPUT_PIN == PIN_PE2) || \
(defined(PIN_PF0) && TUNE_OUTPUT_PIN == PIN_PF0) || (defined(PIN_PF1) && TUNE_OUTPUT_PIN == PIN_PF1) || (defined(PIN_PF2) && TUNE_OUTPUT_PIN == PIN_PF2) || \
(defined(PIN_PG0) && TUNE_OUTPUT_PIN == PIN_PG0) || (defined(PIN_PG1) && TUNE_OUTPUT_PIN == PIN_PG1) || (defined(PIN_PG2) && TUNE_OUTPUT_PIN == PIN_PG2)) || \
Expand Down Expand Up @@ -94,11 +78,9 @@
/* FOR CLASSIC AVRs:
* Uncomment which comopare channel you wish to enable (sorry not done by pins here...
* default will come out pin 9 on a 328p or 328pb... Hell you can even use an MHET Micronucleus t88.
* Anything with a 16-bit timer and a crystal or external clock (though for weird options you may have
* you will have to add the pins to parts.h
* Anything with a 16-bit timer and a crystal or external clock
*/
#if TIMER1_TYPICAL == 87) {
if (!PIN_IS_VALID_TIMER1(pin) {return;)
#if TIMER1_TYPICAL == 87) {
CONFIGURE_PWM();
#define ENABLEOC1A 0
#define ENABLEOC1B 1
Expand Down Expand Up @@ -127,11 +109,8 @@ void setup() {
PORTMUX.TCAROUTEA = port;

#endif

pinMode(TUNE_OUTPUT_PIN,OUTPUT);
TCA0.SPLIT.CTRLA = 0; // disable TCA0 and set divider to 1
TCA0.SPLIT.CTRLESET = TCA_SPLIT_CMD_RESET_gc|0x03; // set CMD to RESET, and enable on both pins.
TCA0.SPLIT.CTRLD = 0; // Split mode now off, CMPn = 0, CNT = 0, PER = 255
takeOverTCA0();
pinMode(TUNE_OUTPUT_PIN, OUTPUT);
TCA0.SINGLE.CTRLB = (TCA_SINGLE_CMP1EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc); // Single slope PWM mode, PWM on WO0
#if (F_CPU > 32000000) // Some lunatic has is using a chip that's way overlcocked as timing reference!
TCA0.SINGLE.PER = (F_CPU/1000) - 1; //
Expand Down Expand Up @@ -172,7 +151,7 @@ void setup() {
}
TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm; // enable the timer with no prescaling
#endif
pinMode(LED_BUILTIN,OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
}
#else // this is for tuning another chip from a watch crystal on this chip.
// Self-tuning with watch crystal may also be supported in the future,
Expand All @@ -189,7 +168,7 @@ void setup() {
void invalidPin() {
while(1) {
_delay_ms(100);
digitalWrite(LED_BUILTIN,CHANGE);
digitalWrite(LED_BUILTIN, CHANGE);
}
}
#else
Expand Down
Loading

0 comments on commit b899565

Please sign in to comment.