Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages   Examples  

pgmspace.h

00001 /* Copyright (c) 2002, Marek Michalkiewicz
00002    All rights reserved.
00003 
00004    Redistribution and use in source and binary forms, with or without
00005    modification, are permitted provided that the following conditions are met:
00006 
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
00011      the documentation and/or other materials provided with the
00012      distribution.
00013    * Neither the name of the copyright holders nor the names of
00014      contributors may be used to endorse or promote products derived
00015      from this software without specific prior written permission.
00016 
00017   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027   POSSIBILITY OF SUCH DAMAGE. */
00028 
00029 /*
00030    pgmspace.h
00031 
00032    Contributors:
00033      Created by Marek Michalkiewicz <marekm@linux.org.pl>
00034  */
00035 
00053 #ifndef __PGMSPACE_H_
00054 #define __PGMSPACE_H_ 1
00055 
00056 #define __need_size_t
00057 #include <stddef.h>
00058 
00059 #ifndef __ATTR_CONST__
00060 #define __ATTR_CONST__ __attribute__((__const__))
00061 #endif
00062 
00063 #ifndef __ATTR_PROGMEM__
00064 #define __ATTR_PROGMEM__ __attribute__((__progmem__))
00065 #endif
00066 
00067 #ifndef __ATTR_PURE__
00068 #define __ATTR_PURE__ __attribute__((__pure__))
00069 #endif
00070 
00071 #define PROGMEM __ATTR_PROGMEM__
00072 
00073 #ifdef __cplusplus
00074 extern "C" {
00075 #endif
00076 
00077 typedef void prog_void PROGMEM;
00078 typedef char prog_char PROGMEM;
00079 typedef unsigned char prog_uchar PROGMEM;
00080 typedef int prog_int PROGMEM;
00081 typedef long prog_long PROGMEM;
00082 typedef long long prog_long_long PROGMEM;
00083 
00089 #define PSTR(s) ({static char __c[] PROGMEM = (s); __c;})
00090 
00091 #define __LPM_enhanced__(addr) ({               \
00092         unsigned short __addr16 = (unsigned short)(addr); \
00093         unsigned char __result;                 \
00094         __asm__ (                               \
00095                 "lpm %0, Z"                     \
00096                 : "=r" (__result)               \
00097                 : "z" (__addr16)                \
00098         );                                      \
00099         __result;                               \
00100  })
00101 
00102 #define __LPM_classic__(addr) ({                \
00103         unsigned short __addr16 = (unsigned short)(addr); \
00104         unsigned char __result;                 \
00105         __asm__ (                               \
00106                 "lpm" "\n\t"                    \
00107                 "mov %0, r0"                    \
00108                 : "=r" (__result)               \
00109                 : "z" (__addr16)                \
00110                 : "r0"                          \
00111         );                                      \
00112         __result;                               \
00113  })
00114 
00115 /* Only for devices with more than 64K of program memory.
00116    RAMPZ must be defined (see iom103.h).  */
00117 
00118 #define __ELPM_enhanced__(addr) ({              \
00119         unsigned long __addr32 = (unsigned long)(addr); \
00120         unsigned char __result;                 \
00121         __asm__ (                               \
00122                 "out %2, %C1" "\n\t"            \
00123                 "movw r30, %1" "\n\t"           \
00124                 "elpm %0, Z"                    \
00125                 : "=r" (__result)               \
00126                 : "r" (__addr32),               \
00127                   "I" (_SFR_IO_ADDR(RAMPZ))     \
00128                 : "r30", "r31"                  \
00129         );                                      \
00130         __result;                               \
00131  })
00132 
00133 #define __ELPM_classic__(addr) ({               \
00134         unsigned long __addr32 = (unsigned long)(addr); \
00135         unsigned char __result;                 \
00136         __asm__ (                               \
00137                 "out %2, %C1" "\n\t"            \
00138                 "mov r31, %B1" "\n\t"           \
00139                 "mov r30, %A1" "\n\t"           \
00140                 "elpm" "\n\t"                   \
00141                 "mov %0, r0"                    \
00142                 : "=r" (__result)               \
00143                 : "r" (__addr32),               \
00144                   "I" (_SFR_IO_ADDR(RAMPZ))     \
00145                 : "r0", "r30", "r31"            \
00146         );                                      \
00147         __result;                               \
00148  })
00149 
00150 #if defined (__AVR_ENHANCED__)
00151 #define  __LPM(addr)  __LPM_enhanced__(addr)
00152 #define __ELPM(addr) __ELPM_enhanced__(addr)
00153 #else
00154 #define  __LPM(addr)  __LPM_classic__(addr)
00155 #define __ELPM(addr) __ELPM_classic__(addr)
00156 #endif
00157 
00158 
00159 static inline unsigned char __lpm_inline(unsigned short __addr) __ATTR_CONST__;
00160 static inline unsigned char __lpm_inline(unsigned short __addr)
00161 {
00162         return __LPM(__addr);
00163 }
00164 
00165 #ifdef RAMPZ  /* >64K program memory (ATmega103) */
00166 
00177 static inline unsigned char __elpm_inline(unsigned long __addr) __ATTR_CONST__;
00178 static inline unsigned char __elpm_inline(unsigned long __addr)
00179 {
00180         return __ELPM(__addr);
00181 }
00182 #endif
00183 
00184 #if 0
00185 #define PRG_RDB(addr) __lpm_inline((unsigned short)(addr))
00186 #else
00187 #define PRG_RDB(addr) __LPM((unsigned short)(addr))
00188 #endif
00189 
00196 #ifndef PGM_P
00197 #define PGM_P const prog_char *
00198 #endif
00199 
00205 #ifndef PGM_VOID_P
00206 #define PGM_VOID_P const prog_void *
00207 #endif
00208 
00209 extern void *memcpy_P(void *, PGM_VOID_P, size_t);
00210 extern char *strcat_P(char *, PGM_P);
00211 extern int strcmp_P(const char *, PGM_P) __ATTR_PURE__;
00212 extern char *strcpy_P(char *, PGM_P);
00213 extern int strcasecmp_P(const char *, PGM_P) __ATTR_PURE__;
00214 extern size_t strlen_P(PGM_P) __ATTR_CONST__; /* program memory can't change */
00215 extern int strncmp_P(const char *, PGM_P, size_t) __ATTR_PURE__;
00216 extern int strncasecmp_P(const char *, PGM_P, size_t) __ATTR_PURE__;
00217 extern char *strncpy_P(char *, PGM_P, size_t);
00218 
00219 #if 0  /* not implemented yet */
00220 extern char *strncat(char *, PGM_P, size_t);
00221 extern int printf_P(PGM_P, ...);
00222 extern int puts_P(PGM_P);
00223 extern int scanf_P(PGM_P, ...);
00224 extern int sprintf_P(char *, PGM_P, ...);
00225 extern int sscanf_P(const char *, PGM_P, ...);
00226 extern PGM_P strerror_P(int);
00227 #endif
00228 
00229 #ifdef __cplusplus
00230 }
00231 #endif
00232 
00233 #endif /* __PGMSPACE_H_ */
00234 

Generated on Thu Jan 30 22:30:51 2003 for EduNet by doxygen1.2.18