MHVLib  20111227
An efficiency oriented runtime library for AVR microcontrollers
A:/eclipse/mhvlib/MHV_io.h
Go to the documentation of this file.
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_ */