diff --git a/megaavr/extras/Ref_dirty_tricks.md b/megaavr/extras/Ref_dirty_tricks.md index ddab5fdb..3ad180e9 100644 --- a/megaavr/extras/Ref_dirty_tricks.md +++ b/megaavr/extras/Ref_dirty_tricks.md @@ -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** @@ -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)` @@ -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. @@ -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. diff --git a/megaavr/libraries/megaTinyCore/examples/TuningSource/TuningSource.ino b/megaavr/libraries/megaTinyCore/examples/TuningSource/TuningSource.ino index 4878fb1d..99fddb98 100644 --- a/megaavr/libraries/megaTinyCore/examples/TuningSource/TuningSource.ino +++ b/megaavr/libraries/megaTinyCore/examples/TuningSource/TuningSource.ino @@ -4,28 +4,29 @@ // *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 @@ -33,29 +34,12 @@ * 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 @@ -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)) || \ @@ -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 @@ -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; // @@ -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, @@ -189,7 +168,7 @@ void setup() { void invalidPin() { while(1) { _delay_ms(100); - digitalWrite(LED_BUILTIN,CHANGE); + digitalWrite(LED_BUILTIN, CHANGE); } } #else diff --git a/megaavr/libraries/megaTinyCore/examples/TuningSource/parts.h b/megaavr/libraries/megaTinyCore/examples/TuningSource/parts.h index b1966967..eb5fe31f 100644 --- a/megaavr/libraries/megaTinyCore/examples/TuningSource/parts.h +++ b/megaavr/libraries/megaTinyCore/examples/TuningSource/parts.h @@ -1,27 +1,61 @@ #ifndef PARTS_H_ -// *INDENT-OFF* The indentation that it demands =is stupid and wrong. +// *INDENT-OFF* The indentation that it demands is stupid and wrong. #define PARTS_H_ - #include #if (defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) || defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || \ defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164PA__) || \ defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega324PB__) || defined(__AVR_ATmega644A__) || \ defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)) #define __AVR_ATmega_Mighty__ + #ifndef TIMER0_TYPICAL + #define TIMER0_TYPICAL (1) + /* Yes, timer0 is 8-bit timer with or without PWM */ + #define PIN_TIMER_OC0A (PIN_PD5) + #define PIN_TIMER_OC0B (PIN_PD6) + #define PIN_TIMER_T0 (PIN_PD4) + + #define TIMER1_TYPICAL (1) + /* Yes, timer1 is 16-bit PWM timer */ + #define PIN_TIMER_ICP1 (PIN_PB0) + #define PIN_TIMER_OC1A (9) + #define PIN_TIMER_OC1B (10) + #define PIN_TIMER_T1 (PIN_PD5) + + #define TIMER2_TYPICAL (1) + /* Yes, timer2 is 8-bit async timer */ + #define PIN_TIMER_OC2A (PIN_PD3) + #define PIN_TIMER_OC2B (PIN_PB3) + #endif #elif (defined(__AVR_ATmega641__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) || \ defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) #define __AVR_ATmega_Mega__ + #ifndef TIMER0_TYPICAL + #define TIMER0_TYPICAL (1) + /* Yes, timer0 is 8-bit timer with or without PWM */ + #define PIN_TIMER_OC0A (PIN_PD5) + #define PIN_TIMER_OC0B (PIN_PD6) + #define PIN_TIMER_T0 (PIN_PD4) + + #define TIMER1_TYPICAL (1) + /* Yes, timer1 is 16-bit PWM timer */ + #define PIN_TIMER_ICP1 (PIN_PB0) + #define PIN_TIMER_OC1A (9) + #define PIN_TIMER_OC1B (10) + #define PIN_TIMER_T1 (PIN_PD5) + + #define TIMER2_TYPICAL (1) + /* Yes, timer2 is 8-bit async timer */ + #define PIN_TIMER_OC2A (PIN_PD3) + #define PIN_TIMER_OC2B (PIN_PB3) + #endif #elif (defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__)) #define TINY_X7_TIMER - #if !(defined(TIMER0_TYPICAL)) - #undef TIMER1_TYPICAL - #endif #undef TIMER1_TYPICAL #undef TIMER0_TYPICAL - #define TIMER0_TYPICAL (0) - #define TIMER1_TYPICAL (87) - #define PIN_TIMER_OC0A (PIN_PA2) - #define PIN_IS_VALID_TIMER1(pin) (pin == PIN_PB1) + #define TIMER0_TYPICAL (0) + #define TIMER1_TYPICAL (87) + #define PIN_TIMER_OC0A (PIN_PA2) + #define PIN_TIMER_OC1B (PIN_PB1) #define CONFIGURE_PWM() (TCCR1D = 0x1 << OC1BU;) #elif (defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || \ @@ -52,43 +86,35 @@ #define CONFIG_OK #endif // we can handle the others without mess like what is seen below. - - /* - #elif (defined(__AVR_ATmega808__) ||defined(__AVR_ATmega1608__) ||defined(__AVR_ATmega3208__) ||defined(__AVR_ATmega4808__) || \ - defined(__AVR_ATmega809__) ||defined(__AVR_ATmega1609__) ||defined(__AVR_ATmega3209__) ||defined(__AVR_ATmega4809__)) - + #elif (defined(__AVR_ATmega808__) || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega4808__) || \ + defined(__AVR_ATmega809__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega3209__) || defined(__AVR_ATmega4809__) ) #define __AVR_ATmega_Zero__ - #else - #if !(defined(MEGATINYCORE) || defined(DXCORE) || defined(ATTINYCORE)) + #if (defined(MEGATINYCORE) || defined(DXCORE) || defined(ATTINYCORE)) // Well then what the heck is it? - #if (defined(__AVR_ATtiny3217__) || defined(__AVR_ATtiny1617__) || defined(__AVR_ATtiny1604__) || defined(__AVR_ATtiny1607__) || \ - defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny1606__) || defined(__AVR_ATtiny1614__)) - + #if (defined(__AVR_ATtiny3217__) || defined(__AVR_ATtiny1617__) || defined(__AVR_ATtiny1604__) || defined(__AVR_ATtiny1607__) || \ + defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny1606__) || defined(__AVR_ATtiny1614__) || \ + defined(__AVR_ATtiny817__) || defined(__AVR_ATtiny807__) || defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny806__) || \ + defined(__AVR_ATtiny814__) || defined(__AVR_ATtiny804__) || defined(__AVR_ATtiny417__) || defined(__AVR_ATtiny807__) || \ + defined(__AVR_ATtiny416__) || defined(__AVR_ATtiny406__) || defined(__AVR_ATtiny414__) || defined(__AVR_ATtiny404__) || \ + defined(__AVR_ATtiny214__) || defined(__AVR_ATtiny204__) || defined(__AVR_ATtiny412__) || defined(__AVR_ATtiny402__) || \ + defined(__AVR_ATtiny212__) || defined(__AVR_ATtiny202__) ) #define __AVR_ATtiny_Zero_One__ - - #elif (defined(__AVR_ATtiny3227__) || defined(__AVR_ATtiny1627__) || defined(__AVR_ATtiny3224__) || defined(__AVR_ATtiny1624__) || \ - defined(__AVR_ATtiny3226__) || defined(__AVR_ATtiny1626__) || defined(__AVR_ATtiny827__) || defined(__AVR_ATtiny826__) || defined(__AVR_ATtiny827__)) - + #elif (defined(__AVR_ATtiny3227__) || defined(__AVR_ATtiny1627__) || defined(__AVR_ATtiny3224__) || defined(__AVR_ATtiny1624__) || \ + defined(__AVR_ATtiny3226__) || defined(__AVR_ATtiny1626__) || defined(__AVR_ATtiny827__) || defined(__AVR_ATtiny826__) || \ + defined(__AVR_ATtiny827__) ) #define __AVR_ATtiny_Two__ - - - #elif (defined(__AVR_AVR128DA28__) ||defined(__AVR_AVR128DA32__) ||defined(__AVR_AVR128DA48__) ||defined(__AVR_AVR128DA64__) || \ - defined(__AVR_AVR64DA28__) ||defined(__AVR_AVR64DA32__) ||defined(__AVR_AVR64DA48__) ||defined(__AVR_AVR64DA64__) || \ - defined(__AVR_AVR32DA28__) ||defined(__AVR_AV324DA32__) ||defined(__AVR_AVR32DA48__) ) - + #elif (defined(__AVR_AVR128DA28__) || defined(__AVR_AVR128DA32__) || defined(__AVR_AVR128DA48__) || defined(__AVR_AVR128DA64__) || \ + defined(__AVR_AVR64DA28__) || defined(__AVR_AVR64DA32__) || defined(__AVR_AVR64DA48__) || defined(__AVR_AVR64DA64__) || \ + defined(__AVR_AVR32DA28__) || defined(__AVR_AV324DA32__) || defined(__AVR_AVR32DA48__) ) #define __AVR_DA__ - - #elif (defined(__AVR_AVR128DB28__) ||defined(__AVR_AVR128DB32__) ||defined(__AVR_AVR128DB48__) ||defined(__AVR_AVR128DB64__) || \ - defined(__AVR_AVR64DB28__) ||defined(__AVR_AVR64DB32__) ||defined(__AVR_AVR64DB48__) ||defined(__AVR_AVR64DB64__) || \ - defined(__AVR_AVR32DB28__) ||defined(__AVR_AV324DB32__) ||defined(__AVR_AVR32DB48__) ) - + #elif (defined(__AVR_AVR128DB28__) || defined(__AVR_AVR128DB32__) || defined(__AVR_AVR128DB48__) || defined(__AVR_AVR128DB64__) || \ + defined(__AVR_AVR64DB28__) || defined(__AVR_AVR64DB32__) || defined(__AVR_AVR64DB48__) || defined(__AVR_AVR64DB64__) || \ + defined(__AVR_AVR32DB28__) || defined(__AVR_AV324DB32__) || defined(__AVR_AVR32DB48__) ) #define __AVR_DB__ - - #elif (defined(__AVR_AVR16DD28__) ||defined(__AVR_AVR16DD32__) ||defined(__AVR_AVR16DD20__) ||defined(__AVR_AVR16DD14__) || \ - defined(__AVR_AVR64DD28__) ||defined(__AVR_AVR6DDA32__) ||defined(__AVR_AVR64DD20__) ||defined(__AVR_AVR64DD14__) || \ - defined(__AVR_AVR32DD28__) ||defined(__AVR_AV32DDA32__) ||defined(__AVR_AVR32DD20__) ||defined(__AVR_AVR64DD14__)) - + #elif (defined(__AVR_AVR16DD28__) || defined(__AVR_AVR16DD32__) || defined(__AVR_AVR16DD20__) || defined(__AVR_AVR16DD14__) || \ + defined(__AVR_AVR64DD28__) || defined(__AVR_AVR6DDA32__) || defined(__AVR_AVR64DD20__) || defined(__AVR_AVR64DD14__) || \ + defined(__AVR_AVR32DD28__) || defined(__AVR_AV32DDA32__) || defined(__AVR_AVR32DD20__) || defined(__AVR_AVR64DD14__) ) #define __AVR_DD__ #else error "Unknown or unsupported part" @@ -102,5 +128,4 @@ #ifndef CONFIG_OK #error "Part unknown, or known but unsupported." #endif -*/ #endif