|
MHVLib
20111227
An efficiency oriented runtime library for AVR microcontrollers
|
00001 /* 00002 * Copyright (c) 2011, Make, Hack, Void Inc 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the Make, Hack, Void nor the 00013 * names of its contributors may be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY 00020 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 00029 #ifdef MHVLIB_NEED_PURE_VIRTUAL 00030 #ifndef MHVLIB_PURE_VIRTUAL_DECLARED 00031 #ifndef MHVLIB_CORE 00032 #define MHVLIB_PURE_VIRTUAL_DECLARED 00033 #include <avr/interrupt.h> 00034 extern "C" void __cxa_pure_virtual() { 00035 cli(); 00036 for (;;); 00037 } 00038 #endif 00039 #endif 00040 #endif 00041 00042 00043 #ifndef MHV_IO_H_ 00044 #define MHV_IO_H_ 00045 00046 #include <avr/io.h> 00047 #include <inttypes.h> 00048 #include <stddef.h> 00049 #include <util/atomic.h> 00050 00051 // Some useful attributes 00052 00053 // A function that does not return 00054 #define NORETURN __attribute__ ((noreturn)) 00055 00056 // Code here is unreachable 00057 #define UNREACHABLE __builtin_unreachable(); 00058 00059 // A function that has no effect other than its return value 00060 #define PURE __attribute__ ((pure)) 00061 00062 #if defined(__AVR_ATtiny2313__) 00063 #include <MHV_io_ATtiny2313.h> 00064 #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) 00065 #include <MHV_io_ATtiny85.h> 00066 #elif defined(__AVR_ATmega1280__) 00067 #include <MHV_io_ATmega1280.h> 00068 #include <MHV_io_ArduinoMega.h> 00069 #elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48A__) || defined(__AVR_ATmega88__) || \ 00070 defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168__) || \ 00071 defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328__) || \ 00072 defined(__AVR_ATmega328P__) 00073 #include <MHV_io_ATmega168.h> 00074 #include <MHV_io_ArduinoDiecimilla.h> 00075 #endif 00076 00077 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 00078 00079 struct mhv_pin { 00080 volatile uint8_t *dir; 00081 volatile uint8_t *input; 00082 volatile uint8_t *output; 00083 // Contains a mask of the pin 00084 uint8_t bit; 00085 int8_t pcInt; 00086 }; 00087 typedef struct mhv_pin MHV_PIN; 00088 00094 #define MHV_MAKE_PIN(_mhv_port, _mhv_bit) \ 00095 _MHV_MAKE_PIN(_mhv_port, _mhv_bit) 00096 00097 #define _MHV_MAKE_PIN(_mhv_port, _mhv_bit) \ 00098 MHV_PIN_ ## _mhv_port ## _mhv_bit 00099 00104 #define MHV_DECLARE_PIN(_mhvPrefix) \ 00105 volatile uint8_t *_mhvPrefix ## Dir, volatile uint8_t *_mhvPrefix ## Out, \ 00106 volatile uint8_t *_mhvPrefix ## In, uint8_t _mhvPrefix ## Pin, \ 00107 int8_t _mhvPrefix ## PinchangeInterrupt 00108 00113 #define MHV_PIN_PARMS(_mhvPrefix) \ 00114 _mhvPrefix ## Dir, _mhvPrefix ## Out, _mhvPrefix ## In, _mhvPrefix ## Pin, _mhvPrefix ## PinchangeInterrupt 00115 00120 #define mhv_pin(mhvParms) \ 00121 _mhv_pin(mhvParms) 00122 00123 #define _mhv_pin(mhvDir,mhvOutput,mhvInput,mhvBit,mhvPCInt) \ 00124 {mhvDir, mhvOutput, mhvInput, _BV(mhvBit), mhvPCInt} 00125 00130 inline void mhv_pinOn(MHV_PIN *pin) { 00131 *(pin->output) |= pin->bit; 00132 } 00133 00138 inline void mhv_pinOnAtomic(MHV_PIN *pin) { 00139 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00140 mhv_pinOn(pin); 00141 } 00142 } 00143 00144 00149 inline void mhv_pinOn(MHV_DECLARE_PIN(pin)) { 00150 *pinOut |= _BV(pinPin); 00151 } 00152 00157 inline void mhv_pinOnAtomic(MHV_DECLARE_PIN(pin)) { 00158 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00159 mhv_pinOn(MHV_PIN_PARMS(pin)); 00160 } 00161 } 00162 00163 00168 inline void mhv_pinOff(MHV_PIN *pin) { 00169 *(pin->output) &= ~(pin->bit); 00170 } 00171 00176 inline void mhv_pinOffAtomic(MHV_PIN *pin) { 00177 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00178 mhv_pinOff(pin); 00179 } 00180 } 00181 00182 00187 inline void mhv_pinOff(MHV_DECLARE_PIN(pin)) { 00188 *pinOut &= ~_BV(pinPin); 00189 } 00190 00195 inline void mhv_pinOffAtomic(MHV_DECLARE_PIN(pin)) { 00196 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00197 mhv_pinOff(MHV_PIN_PARMS(pin)); 00198 } 00199 } 00200 00201 00207 inline void mhv_pinSet(MHV_DECLARE_PIN(pin), bool state) { 00208 if (state) { 00209 mhv_pinOn(pinDir, pinOut, pinIn, pinPin, pinPinchangeInterrupt); 00210 } else { 00211 mhv_pinOff(pinDir, pinOut, pinIn, pinPin, pinPinchangeInterrupt); 00212 } 00213 } 00214 00221 inline void mhv_pinSetAtomic(MHV_DECLARE_PIN(pin), bool state) { 00222 if (state) { 00223 mhv_pinOnAtomic(pinDir, pinOut, pinIn, pinPin, pinPinchangeInterrupt); 00224 } else { 00225 mhv_pinOffAtomic(pinDir, pinOut, pinIn, pinPin, pinPinchangeInterrupt); 00226 } 00227 } 00228 00229 00234 inline void mhv_setOutput(MHV_PIN *pin) { 00235 *(pin->dir) |= pin->bit; 00236 } 00237 00242 inline void mhv_setOutputAtomic(MHV_PIN *pin) { 00243 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00244 mhv_setOutput(pin); 00245 } 00246 } 00247 00248 00253 inline void mhv_setOutput(MHV_DECLARE_PIN(pin)) { 00254 *pinDir |= _BV(pinPin); 00255 } 00256 00261 inline void mhv_setOutputAtomic(MHV_DECLARE_PIN(pin)) { 00262 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00263 mhv_setOutput(MHV_PIN_PARMS(pin)); 00264 } 00265 } 00266 00271 inline void mhv_setInput(MHV_PIN *pin) { 00272 *(pin->dir) &= ~(pin->bit); 00273 *(pin->output) &= ~(pin->bit); 00274 } 00275 00280 inline void mhv_setInputAtomic(MHV_PIN *pin) { 00281 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00282 mhv_setInput(pin); 00283 } 00284 } 00285 00290 inline void mhv_setInput(MHV_DECLARE_PIN(pin)) { 00291 *pinDir &= ~_BV(pinPin); 00292 *pinOut &= ~_BV(pinPin); 00293 } 00294 00299 inline void mhv_setInputAtomic(MHV_DECLARE_PIN(pin)) { 00300 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00301 mhv_setInput(MHV_PIN_PARMS(pin)); 00302 } 00303 } 00304 00305 00310 inline void mhv_setInputPullup(MHV_PIN *pin) { 00311 *(pin->dir) &= ~(pin->bit); 00312 *(pin->output) |= pin->bit; 00313 } 00314 00319 inline void mhv_setInputPullupAtomic(MHV_PIN *pin) { 00320 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00321 mhv_setInputPullup(pin); 00322 } 00323 } 00324 00325 00330 inline void mhv_setInputPullup(MHV_DECLARE_PIN(pin)) { 00331 *pinDir &= ~_BV(pinPin); 00332 *pinOut |= _BV(pinPin); 00333 } 00334 00339 inline void mhv_setInputPullupAtomic(MHV_DECLARE_PIN(pin)) { 00340 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00341 mhv_setInputPullup(MHV_PIN_PARMS(pin)); 00342 } 00343 } 00344 00345 00350 inline void mhv_pinToggle(MHV_PIN *pin) { 00351 *(pin->input) |= pin->bit; 00352 } 00353 00358 inline void mhv_pinToggleAtomic(MHV_PIN *pin) { 00359 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00360 *(pin->input) |= pin->bit; 00361 } 00362 } 00363 00364 00369 inline void mhv_pinToggle(MHV_DECLARE_PIN(pin)) { 00370 *pinIn |= _BV(pinPin); 00371 } 00372 00377 inline void mhv_pinToggleAtomic(MHV_DECLARE_PIN(pin)) { 00378 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00379 *pinIn |= _BV(pinPin); 00380 } 00381 } 00382 00383 00388 inline bool mhv_pinRead(MHV_PIN *pin) { 00389 return *(pin->input) & pin->bit; 00390 } 00391 00392 00397 inline bool mhv_pinRead(MHV_DECLARE_PIN(pin)) { 00398 return *pinIn & _BV(pinPin); 00399 } 00400 00401 00407 #define MHV_BYTESIZEOF(_mhvItem) (uint8_t)(sizeof(_mhvItem)) 00408 00415 inline void mhv_memClear(void *bufIn, uint8_t len, uint8_t count) { 00416 char *buf = (char *)bufIn; 00417 00418 for (uint8_t i = 0; i < count; i++) { 00419 for (uint8_t j = 0; j < len; j++, buf++) { 00420 *buf = 0; 00421 } 00422 } 00423 } 00424 00430 inline void mhv_memClear(void *bufIn, uint8_t len) { 00431 char *buf = (char *)bufIn; 00432 00433 for (uint8_t i = 0; i < len; i++, buf++) { 00434 *buf = 0; 00435 } 00436 } 00437 00438 00445 inline void mhv_memClear(void *bufIn, uint8_t len, uint16_t count) { 00446 char *buf = (char *)bufIn; 00447 00448 for (uint8_t i = 0; i < count; i++) { 00449 for (uint8_t j = 0; j < len; j++, buf++) { 00450 *buf = 0; 00451 } 00452 } 00453 } 00454 00460 inline void mhv_memClear(void *bufIn, uint16_t len) { 00461 char *buf = (char *)bufIn; 00462 00463 for (uint8_t i = 0; i < len; i++, buf++) { 00464 *buf = 0; 00465 } 00466 } 00467 00468 00476 inline void mhv_memcpy(void *bufOut, void *bufIn, uint8_t len, uint8_t count) { 00477 char *src = (char *)bufIn; 00478 char *dst = (char *)bufOut; 00479 00480 for (uint8_t i = 0; i < count; i++) { 00481 for (uint8_t j = 0; j < len; j++, src++, dst++) { 00482 *dst = *src; 00483 } 00484 } 00485 } 00486 00493 inline void mhv_memcpy(void *bufOut, void *bufIn, uint8_t len) { 00494 char *src = (char *)bufIn; 00495 char *dst = (char *)bufOut; 00496 00497 for (uint8_t i = 0; i < len; i++, src++, dst++) { 00498 *dst = *src; 00499 } 00500 } 00501 00502 00510 inline void mhv_memcpy(void *bufOut, void *bufIn, uint8_t len, uint16_t count) { 00511 char *src = (char *)bufIn; 00512 char *dst = (char *)bufOut; 00513 00514 for (uint8_t i = 0; i < count; i++) { 00515 for (uint8_t j = 0; j < len; j++, src++, dst++) { 00516 *dst = *src; 00517 } 00518 } 00519 } 00520 00527 inline void mhv_memcpy(void *bufOut, void *bufIn, uint16_t len) { 00528 char *src = (char *)bufIn; 00529 char *dst = (char *)bufOut; 00530 00531 for (uint8_t i = 0; i < len; i++, src++, dst++) { 00532 *dst = *src; 00533 } 00534 } 00535 00543 inline void mhv_memcpyTailFirst(void *bufOut, void *bufIn, uint8_t len, uint8_t count) { 00544 size_t offset = (size_t)len * count; 00545 char *src = (char *)bufIn + offset; 00546 char *dst = (char *)bufOut + offset; 00547 00548 for (uint8_t i = 0; i < count; i++) { 00549 for (uint8_t j = 0; j < len; j++, --src, --dst) { 00550 *dst = *src; 00551 } 00552 } 00553 } 00554 00561 inline void mhv_memcpyTailFirst(void *bufOut, void *bufIn, uint8_t len) { 00562 char *src = (char *)bufIn + len; 00563 char *dst = (char *)bufOut + len; 00564 00565 for (uint8_t i = 0; i < len; i++, --src, --dst) { 00566 *dst = *src; 00567 } 00568 } 00569 00570 00578 inline void mhv_memcpyTailFirst(void *bufOut, void *bufIn, uint8_t len, uint16_t count) { 00579 size_t offset = (size_t)len * count; 00580 char *src = (char *)bufIn + offset; 00581 char *dst = (char *)bufOut + offset; 00582 00583 for (uint8_t i = 0; i < count; i++) { 00584 for (uint8_t j = 0; j < len; j++, --src, --dst) { 00585 *dst = *src; 00586 } 00587 } 00588 } 00589 00596 inline void mhv_memcpyTailFirst(void *bufOut, void *bufIn, uint16_t len) { 00597 char *src = (char *)bufIn + len; 00598 char *dst = (char *)bufOut + len; 00599 00600 for (uint8_t i = 0; i < len; i++, --src, --dst) { 00601 *dst = *src; 00602 } 00603 } 00604 00605 00606 00607 /* We have to shadow all the macros below as the precedence of macro expansion means that 00608 * the multi-parmeter macros will only see a single argument if one of our MHV_PIN macros 00609 * is used 00610 */ 00611 00612 /* See http://gcc.gnu.org/onlinedocs/gcc-3.3.6/cpp/Swallowing-the-Semicolon.html 00613 * to understand why we have do...while(0) on our macros 00614 */ 00615 00620 #define mhv_out(mhvParms) \ 00621 _mhv_out(mhvParms) 00622 00623 #define _mhv_out(mhvDir,mhvOutput,mhvInput,mhvBit,mhvPCInt) \ 00624 mhvOutput 00625 00630 #define mhv_in(mhvParms) \ 00631 _mhv_in(mhvParms) 00632 00633 #define _mhv_in(mhvDir,mhvOutput,mhvInput,mhvBit,mhvPCInt) \ 00634 mhvInput 00635 00640 #define mhv_bit(mhvParms) \ 00641 _mhv_bit(mhvParms) 00642 00643 #define _mhv_bit(mhvDir,mhvOutput,mhvInput,mhvBit,mhvPCInt) \ 00644 mhvBit 00645 00650 #define mhv_dir(mhvParms) \ 00651 _mhv_dir(mhvParms) 00652 00653 #define _mhv_dir(mhvDir,mhvOutput,mhvInput,mhvBit,mhvPCInt) \ 00654 mhvDir 00655 00660 #define mhv_pcint(mhvParms) \ 00661 _mhv_pcint(mhvParms) 00662 00663 #define _mhv_PCInt(mhvDir,mhvOutput,mhvInput,mhvBit,mhvPCInt) \ 00664 mhvPCInt 00665 00666 00672 #define mhv_declareExternalInterrupt(mhvInterruptParms,mhvFunction) \ 00673 _mhv_declareExternalInterrupt(mhvInterruptParms, mhvFunction) 00674 00675 #define _mhv_declareExternalInterrupt(mhvInterruptHandler,mhvModeRegister,mhvModeBitshift,mhvFunction) \ 00676 ISR(mhvInterruptHandler) mhvFunction 00677 00681 enum mhv_interruptMode { 00682 MHV_INTERRUPT_LOW, 00683 MHV_INTERRUPT_CHANGE, 00684 MHV_INTERRUPT_FALLING, 00685 MHV_INTERRUPT_RISING 00686 }; 00687 typedef enum mhv_interruptMode MHV_INTERRUPTMODE; 00688 00689 00695 #define mhv_enableExternalInterrupt(mhvInterruptParms,mhvInterruptMode) \ 00696 do { \ 00697 _mhv_enableExternalInterrupt(mhvInterruptParms,mhvInterruptMode); \ 00698 } while (0) 00699 00700 #define _mhv_enableExternalInterrupt(mhvInterruptHandler,mhvModeRegister,mhvModeBitshift,mhvInterruptMode) \ 00701 *mhvModeRegister = (*mhvModeRegister & ~(0x03 << mhvModeBitshift)) | (mhvInterruptMode << mhvModeBitshift) 00702 00703 #endif /* MHV_IO_H_ */