Basic question about #defines #547
Replies: 1 comment
-
Everything ending in _gc, _gm, _gp _bm and _bp, and all those ALLCAPS objects representing peripherals are all supplied by Microchip as part of the ATpacks, where they are found in the IO header for your device. Search is recommended in those files. The AVR128DB64's io header file almost half a megabyte of nothing but plain text, mostly in the form of #defines and typedefs for the structs that represent peripherals and typedefs for the enums for multi-bit fields. https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/ioheaders/README.md _gc is a Group Code (the value of the relevant bits in a multi-bit field corresponding to the option described by the name). Bits that are not relevant to this option are returned as 0's. //Let SOMESETTING be the name of a feature with multiple configuration options
//Let SOMEOPTION be the name of the desired configuration of SOMESETTING, (option number 5, 0b101)
//Let SOMEREG be a register, wherein bits 2, 3, and 4 are part of SOMESETTING
//Let SOMEBIT be a single-bit field in the same register, bit 7.
//SOMESETTING_gp = 2
//SOMESETTING_gm = 0b00011100;
//SOMEOPTION_gc = 0b00010100; // as noted, this is the 5th option, 0b101. 5 << SOMESETTING_gp
//SOMEBIT_bp = 7;
//SOMEBIT_bm = 0b10000000 = 1<<SOMEBIT_bp; //Note that the math is optimized away, since all operands are constant
//Update value w/out trashing other stuff set in SOMEREG, which gives an idea of what the point of these annoyingly verbose
SOMEREG &= ~(SOMESETTING_gm); // clear the bits
SOMEREG |= SOMEOPTION_gc; //set the appropriate bits
SOMEREG |= SOMEBIT_bm; // set the bit
SOMEREG&=~SOMEBIT_bm; //clear the bit by ANDing with the bitwise inverted bitmask. The invert is optimized away.
/* Note that the above is actually an antipattern - it's surprisingly inefficient, because registers are defined as volatile (The same I/O headers have the declaration in there - it uses the macros at the start of the file, and the part where they're specifying the memory map is around line 3500 and they run for about 1100 lines. But yeah, what I wrote above is a good conceptual demo, but is not a recommended practice. (For example, don't make a macro out of it with a name that implies that it's fast or small or that you'd be likely to reuse willynilly. It's a silly way to waste flash, but if you're using a macro to make it real easy to do that ideom, it can be easy to start throwing it around, The bloat can end up getting out of hand easily. */
//The right way to do that is to copy the register to a temp variable, change that, and write that back (also lets you make several changes to the value in some register before you actually apply the changes by writing it back to the register and apply them all at once, which is often the preferred behavior in that case.
// The right way to do that is this - which despite looking longer, is 5 clocks faster and 8 bytes smaller.
uint8_t temp = SOMEREG;
temp &= ~(SOMESETTING_gm);
temp |= SOMEOPTION_gc; //set the appropriate bits
SOMEREG = temp; But I digress. Link above goes to a page with online-viewable copies of those headers, because you otherwise.... I don't know how else you could work with these things, honestly. They're way too long, ALLCAP_AND_UNDERSCORE with strange abbreviations in the names, and they occasionally make breaking changes to the name conventions...... |
Beta Was this translation helpful? Give feedback.
-
Where do I find them? For example where is the file in which RTC_PERIOD_CYC32768_gc is defined? Is there a comprehensive list somewhere?
Beta Was this translation helpful? Give feedback.
All reactions