/*
 * ul_other.h
 *
 *  Created on: Sep 27, 2011
 *      Author: qwer1
 */

#ifndef UL_OTHER_H_
#define UL_OTHER_H_

#include <stdint.h>

#ifndef offsetof
    #define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
#ifndef countof
	#define countof(arg) (sizeof(arg) / sizeof(arg[0]))
#endif

#define BIT(b) (1 << b)

//attributes
#define WEAK        __attribute__ ((weak))
#define NAKED       __attribute__ ((naked))
#define INTERRUPT   __attribute__ ((__interrupt__))
#define USED        __attribute__ ((used))
#define NORETURN    __attribute__ ((noreturn))
#define NOINIT      __attribute__ ((section (".noinit")))

//architecture-specific inlines
#ifdef __AVR
	#define wdr()   asm volatile("wdr")
	#define nop()   asm volatile("nop")
	#define sleep() asm volatile("sleep")
#endif

#ifdef __i8051
	#define cli()  EI = 0
	#define sei()  EI = 1
#endif

#ifdef __STM8
	#define cli()  _asm("sim")
	#define sei()  _asm("rim")
	#define nop()  _asm("nop")
	#define wdr()  { IWDG_KR = 0xAA; }
#endif

#ifdef __ARM_ARCH_7M__
	#define cli() asm volatile ( "CPSID i \n" )
	#define sei() asm volatile ( "CPSIE i \n" )
#endif

//short named types
#define U8   uint8_t
#define S8   int8_t
#define U16  uint16_t
#define S16  int16_t
#define U32  uint32_t
#define S32  int32_t
#define U64  uint64_t
#define S64  int64_t
#define F32  float
#define F64  double
#define F128 __float128

//bit mask
#define B(b) (1 << b)
#define BIT(b) (1 << b)

//Increment/decrement, Add/Subtract with range rollover/limit
#define INC_ROLL(a, min, max) { if ((a) >= (max)) (a) = (min); else (a)++; }
#define INC_LIMIT(a, max) { if ((a) < (max)) (a)++; }
#define ADD_LIMIT(a, b, max)  { (a) += (b); if ((a) > (max)) (a) = (max); }
#define DEC_ROLL(a, min, max) { if ((a) <= (min)) (a) = (max); else (a)--; }
#define SUB_LIMIT(a, b, min) { (a) -= (b); if ((a) < (min)) (a) = (min); }


#ifdef __ARM_ARCH_7M__
	//ARM Cortex BitBand access macros
	#define BITBAND_SRAM_REF   0x20000000
	#define BITBAND_SRAM_BASE  0x22000000
	// Convert SRAM address
	#define BITBAND_SRAM(addr, bit) ((volatile U8 *)((BITBAND_SRAM_BASE + ((U32)(addr)-BITBAND_SRAM_REF)*32 + (bit*4))))
	#define BITM( addr, bit ) (BITBAND_SRAM(addr,bit))

	#define BITBAND_PERI_REF   0x40000000
	#define BITBAND_PERI_BASE  0x42000000
	// Convert PERIPHERAL address
	#define BITBAND_PERI(addr, bit) ((volatile U8 *)((BITBAND_PERI_BASE + ((U32)(addr)-BITBAND_PERI_REF)*32 + (bit*4))))
	#define BITP( addr, bit ) (BITBAND_PERI(addr,bit))
#endif

#endif /* OTHER_H_ */
