/*!
* \file
* <!--
- * Copyright 2004, 2005 Develer S.r.l. (http://www.develer.com/)
- * Copyright 2004 Giovanni Bajo
+ * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
* This file is part of DevLib - See README.devlib for information.
* -->
*
#ifndef MWARE_PGM_H
#define MWARE_PGM_H
-#include <cpu_detect.h>
+#include <cfg/cpu_detect.h>
+#include <cfg/compiler.h> /* For intXX_t */
+#include <cfg/cpu.h> /* For CPU_HARVARD */
#if CPU_AVR
); \
__result; \
})
- #else
+ #if 0 // 128/103
+ #define pgm_read_uint16_t(addr) \
+ ({ \
+ uint32_t __addr32 = (uint32_t)(addr); \
+ uint16_t __result; \
+ __asm__ \
+ ( \
+ "out %2, %C1" "\n\t" \
+ "movw r30, %1" "\n\t" \
+ "elpm %A0, Z+" "\n\t" \
+ "elpm %B0, Z" "\n\t" \
+ : "=r" (__result) \
+ : "r" (__addr32), \
+ "I" (_SFR_IO_ADDR(RAMPZ)) \
+ : "r30", "r31" \
+ ); \
+ __result; \
+ })
+ #endif
+
+ #define pgm_read_uint16_t(addr) \
+ ({ \
+ uint16_t __addr16 = (uint16_t)(addr); \
+ uint16_t __result; \
+ __asm__ \
+ ( \
+ "lpm %A0, Z+" "\n\t" \
+ "lpm %B0, Z" "\n\t" \
+ : "=r" (__result), "=z" (__addr16) \
+ : "1" (__addr16) \
+ ); \
+ __result; \
+ })
+
+
+ #else /* !__AVR_ENHANCED__ */
+
#define pgm_read_char(addr) \
({ \
uint16_t __addr16 = (uint16_t)(addr); \
); \
__result; \
})
+ #if 0 // 128/103
+ #define pgm_read_uint16_t(addr) \
+ ({ \
+ uint32_t __addr32 = (uint32_t)(addr); \
+ uint16_t __result; \
+ __asm__ \
+ ( \
+ "out %2, %C1" "\n\t" \
+ "mov r31, %B1" "\n\t" \
+ "mov r30, %A1" "\n\t" \
+ "elpm" "\n\t" \
+ "mov %A0, r0" "\n\t" \
+ "in r0, %2" "\n\t" \
+ "adiw r30, 1" "\n\t" \
+ "adc r0, __zero_reg__" "\n\t" \
+ "out %2, r0" "\n\t" \
+ "elpm" "\n\t" \
+ "mov %B0, r0" "\n\t" \
+ : "=r" (__result) \
+ : "r" (__addr32), \
+ "I" (_SFR_IO_ADDR(RAMPZ)) \
+ : "r0", "r30", "r31" \
+ ); \
+ __result; \
+ })
+ #endif
+ #define pgm_read_uint16_t(addr) \
+ ({ \
+ uint16_t __addr16 = (uint16_t)(addr); \
+ uint16_t __result; \
+ __asm__ \
+ ( \
+ "lpm" "\n\t" \
+ "mov %A0, r0" "\n\t" \
+ "adiw r30, 1" "\n\t" \
+ "lpm" "\n\t" \
+ "mov %B0, r0" "\n\t" \
+ : "=r" (__result), "=z" (__addr16) \
+ : "1" (__addr16) \
+ : "r0" \
+ ); \
+ __result; \
+ })
+
+ #endif /* !__AVR_ENHANCED__ */
+
+ #if SIZEOF_INT == 2
+ #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr))
+ #else
+ #error Missing support for CPU word size != 16bit
#endif
+ #ifndef PROGMEM
#define PROGMEM __attribute__((__progmem__))
- #define PSTR(s) ({static const char __c[] PROGMEM = (s); __c;})
+ #endif
+ #ifndef PSTR
+ #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; })
+ #endif
#elif CPU_HARVARD
#error Missing CPU support
#endif
#ifndef PROGMEM
-#define PROGMEM /* nothing */
+#define PROGMEM /* nothing */
#endif
/*!
/*\}*/
/*!
- * \def PGM_READ_CHAR
- * \def PGM_FUNC
- * \def PGM_ATTR
+ * \name PGM support macros.
*
* These macros enable dual compilation of code for both program
* and data memory.
* // To be used when invoking inside other PGM_FUNC functions:
* PGM_FUNC(lcd_puts)(some_string);
* \endcode
+ *
+ * \{
*/
#ifdef _PROGMEM
#define PGM_READ_CHAR(s) pgm_read_char(s)
#define PGM_FUNC(x) x ## _P
+ #define PGM_STR(x) PSTR(x)
#define PGM_ATTR PROGMEM
#else
#define PGM_READ_CHAR(s) (*(s))
#define PGM_FUNC(x) x
+ #define PGM_STR(x) x
#define PGM_ATTR /* nothing */
#endif
+/* \} */
#endif /* MWARE_PGM_H */