|
@@ -3,14 +3,125 @@
|
|
|
|
|
|
#include <endian.h>
|
|
|
#include <stdint.h>
|
|
|
+#include <mutex>
|
|
|
+
|
|
|
+
|
|
|
+template <typename T> class FakeIO
|
|
|
+{
|
|
|
+public:
|
|
|
+ FakeIO()
|
|
|
+ : m_read_hook(NULL)
|
|
|
+ , m_read_hook_running(false)
|
|
|
+ , m_write_hook(NULL)
|
|
|
+ , m_write_hook_running(false)
|
|
|
+ {
|
|
|
+ }
|
|
|
+ virtual ~FakeIO()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ FakeIO & operator=(const T &other)
|
|
|
+ {
|
|
|
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
|
|
|
+
|
|
|
+ T prev_value = m_reg;
|
|
|
+ m_reg = other;
|
|
|
+ call_write_hook(prev_value);
|
|
|
+
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FakeIO & operator|=(const T &other)
|
|
|
+ {
|
|
|
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
|
|
|
+
|
|
|
+ T prev_value = m_reg;
|
|
|
+ m_reg |= other;
|
|
|
+ call_write_hook(prev_value);
|
|
|
+
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FakeIO & operator&=(const T &other)
|
|
|
+ {
|
|
|
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
|
|
|
+
|
|
|
+ T prev_value = m_reg;
|
|
|
+ m_reg &= other;
|
|
|
+ call_write_hook(prev_value);
|
|
|
+
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ operator T()
|
|
|
+ {
|
|
|
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
|
|
|
+
|
|
|
+ call_read_hook();
|
|
|
+ return m_reg;
|
|
|
+ }
|
|
|
+
|
|
|
+ volatile uint8_t * low_byte()
|
|
|
+ {
|
|
|
+#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
+ return reinterpret_cast<volatile uint8_t *>(&m_reg) + 0;
|
|
|
+#else
|
|
|
+ return reinterpret_cast<volatile uint8_t *>(&m_reg) + 1;
|
|
|
+#endif
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
-#define _SFR_ADDR(x) (&(x))
|
|
|
-#define _MMIO_BYTE(x) (*(uint8_t *)(x))
|
|
|
-typedef volatile uint8_t * sfr_addr_t;
|
|
|
-#define sfr_addr_t sfr_addr_t
|
|
|
-
|
|
|
-extern volatile uint8_t MCUCSR;
|
|
|
+ volatile uint8_t * high_byte()
|
|
|
+ {
|
|
|
+#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
+ return reinterpret_cast<volatile uint8_t *>(&m_reg) + 1;
|
|
|
+#else
|
|
|
+ return reinterpret_cast<volatile uint8_t *>(&m_reg) + 0;
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
+ void set_read_hook(void (*read_hook)(FakeIO<T> &io))
|
|
|
+ {
|
|
|
+ m_read_hook = read_hook;
|
|
|
+ }
|
|
|
+ void set_write_hook(void (*write_hook)(FakeIO<T> &io, T prev_value))
|
|
|
+ {
|
|
|
+ m_write_hook = write_hook;
|
|
|
+ }
|
|
|
+
|
|
|
+protected:
|
|
|
+ void call_read_hook()
|
|
|
+ {
|
|
|
+ if (m_read_hook && !m_read_hook_running) {
|
|
|
+ m_read_hook_running = true;
|
|
|
+ m_read_hook(*this);
|
|
|
+ m_read_hook_running = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void call_write_hook(T prev_value)
|
|
|
+ {
|
|
|
+ if (m_write_hook && !m_write_hook_running) {
|
|
|
+ m_write_hook_running = true;
|
|
|
+ m_write_hook(*this, prev_value);
|
|
|
+ m_write_hook_running = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+protected:
|
|
|
+ std::recursive_mutex m_mutex;
|
|
|
+ volatile T m_reg;
|
|
|
+ void (*m_read_hook)(FakeIO<T> &io);
|
|
|
+ bool m_read_hook_running;
|
|
|
+ void (*m_write_hook)(FakeIO<T> &io, T prev_value);
|
|
|
+ bool m_write_hook_running;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+#define _SFR_ADDR(x) (static_cast<void *>(&(x)))
|
|
|
+#define _MMIO_BYTE(x) (*(static_cast<FakeIO<uint8_t> *>(x)))
|
|
|
+typedef void * sfr_addr_t;
|
|
|
+#define sfr_addr_t sfr_addr_t
|
|
|
+
|
|
|
+extern FakeIO<uint8_t> MCUCSR;
|
|
|
#define MCUCSR MCUCSR
|
|
|
#define MCUSR MCUCSR
|
|
|
|
|
@@ -22,7 +133,7 @@ extern volatile uint8_t MCUCSR;
|
|
|
#define PB5 5
|
|
|
#define PB6 6
|
|
|
#define PB7 7
|
|
|
-extern volatile uint8_t PORTB;
|
|
|
+extern FakeIO<uint8_t> PORTB;
|
|
|
#define PORTB PORTB
|
|
|
#define PC0 0
|
|
|
#define PC1 1
|
|
@@ -32,7 +143,7 @@ extern volatile uint8_t PORTB;
|
|
|
#define PC5 5
|
|
|
#define PC6 6
|
|
|
#define PC7 7
|
|
|
-extern volatile uint8_t PORTC;
|
|
|
+extern FakeIO<uint8_t> PORTC;
|
|
|
#define PORTC PORTC
|
|
|
#define PD0 0
|
|
|
#define PD1 1
|
|
@@ -42,7 +153,7 @@ extern volatile uint8_t PORTC;
|
|
|
#define PD5 5
|
|
|
#define PD6 6
|
|
|
#define PD7 7
|
|
|
-extern volatile uint8_t PORTD;
|
|
|
+extern FakeIO<uint8_t> PORTD;
|
|
|
#define PORTD PORTD
|
|
|
#define DDB0 0
|
|
|
#define DDB1 1
|
|
@@ -52,7 +163,7 @@ extern volatile uint8_t PORTD;
|
|
|
#define DDB5 5
|
|
|
#define DDB6 6
|
|
|
#define DDB7 7
|
|
|
-extern volatile uint8_t DDRB;
|
|
|
+extern FakeIO<uint8_t> DDRB;
|
|
|
#define DDRB DDRB
|
|
|
#define DDC0 0
|
|
|
#define DDC1 1
|
|
@@ -62,7 +173,7 @@ extern volatile uint8_t DDRB;
|
|
|
#define DDC5 5
|
|
|
#define DDC6 6
|
|
|
#define DDC7 7
|
|
|
-extern volatile uint8_t DDRC;
|
|
|
+extern FakeIO<uint8_t> DDRC;
|
|
|
#define DDRC DDRC
|
|
|
#define DDD0 0
|
|
|
#define DDD1 1
|
|
@@ -72,7 +183,7 @@ extern volatile uint8_t DDRC;
|
|
|
#define DDD5 5
|
|
|
#define DDD6 6
|
|
|
#define DDD7 7
|
|
|
-extern volatile uint8_t DDRD;
|
|
|
+extern FakeIO<uint8_t> DDRD;
|
|
|
#define DDRD DDRD
|
|
|
#define PINB0 0
|
|
|
#define PINB1 1
|
|
@@ -82,7 +193,7 @@ extern volatile uint8_t DDRD;
|
|
|
#define PINB5 5
|
|
|
#define PINB6 6
|
|
|
#define PINB7 7
|
|
|
-extern volatile uint8_t PINB;
|
|
|
+extern FakeIO<uint8_t> PINB;
|
|
|
#define PINB PINB
|
|
|
#define PINC0 0
|
|
|
#define PINC1 1
|
|
@@ -92,7 +203,7 @@ extern volatile uint8_t PINB;
|
|
|
#define PINC5 5
|
|
|
#define PINC6 6
|
|
|
#define PINC7 7
|
|
|
-extern volatile uint8_t PINC;
|
|
|
+extern FakeIO<uint8_t> PINC;
|
|
|
#define PINC PINC
|
|
|
#define PIND0 0
|
|
|
#define PIND1 1
|
|
@@ -102,33 +213,33 @@ extern volatile uint8_t PINC;
|
|
|
#define PIND5 5
|
|
|
#define PIND6 6
|
|
|
#define PIND7 7
|
|
|
-extern volatile uint8_t PIND;
|
|
|
+extern FakeIO<uint8_t> PIND;
|
|
|
#define PIND PIND
|
|
|
|
|
|
#define OCIE0B 2
|
|
|
#define OCIE0A 1
|
|
|
#define TOIE0 0
|
|
|
-extern volatile uint8_t TIMSK0;
|
|
|
+extern FakeIO<uint8_t> TIMSK0;
|
|
|
#define TIMSK0 TIMSK0
|
|
|
|
|
|
#define OCF0B 2
|
|
|
#define OCF0A 1
|
|
|
#define TOV0 0
|
|
|
-extern volatile uint8_t TIFR0;
|
|
|
+extern FakeIO<uint8_t> TIFR0;
|
|
|
#define TIFR0 TIFR0
|
|
|
|
|
|
#define ICIE1 5
|
|
|
#define OCIE1B 2
|
|
|
#define OCIE1A 1
|
|
|
#define TOIE1 0
|
|
|
-extern volatile uint8_t TIMSK1;
|
|
|
+extern FakeIO<uint8_t> TIMSK1;
|
|
|
#define TIMSK1 TIMSK1
|
|
|
|
|
|
#define ICF1 5
|
|
|
#define OCF1B 2
|
|
|
#define OCF1A 1
|
|
|
#define TOV1 0
|
|
|
-extern volatile uint8_t TIFR1;
|
|
|
+extern FakeIO<uint8_t> TIFR1;
|
|
|
#define TIFR1 TIFR1
|
|
|
|
|
|
#define SREG_C 0
|
|
@@ -139,7 +250,7 @@ extern volatile uint8_t TIFR1;
|
|
|
#define SREG_H 5
|
|
|
#define SREG_T 6
|
|
|
#define SREG_I 7
|
|
|
-extern volatile uint8_t SREG;
|
|
|
+extern FakeIO<uint8_t> SREG;
|
|
|
#define SREG SREG
|
|
|
|
|
|
#define COM0A1 7
|
|
@@ -171,40 +282,40 @@ extern volatile uint8_t SREG;
|
|
|
#define FOC1A 7
|
|
|
#define FOC1B 6
|
|
|
|
|
|
-extern volatile uint8_t OCR0A;
|
|
|
+extern FakeIO<uint8_t> OCR0A;
|
|
|
#define OCR0A OCR0A
|
|
|
|
|
|
-extern volatile uint8_t OCR0B;
|
|
|
+extern FakeIO<uint8_t> OCR0B;
|
|
|
#define OCR0B OCR0B
|
|
|
|
|
|
-extern volatile uint8_t TCNT0;
|
|
|
+extern FakeIO<uint8_t> TCNT0;
|
|
|
#define TCNT0 TCNT0
|
|
|
|
|
|
-extern volatile uint8_t TCCR0A;
|
|
|
+extern FakeIO<uint8_t> TCCR0A;
|
|
|
#define TCCR0A TCCR0A
|
|
|
|
|
|
-extern volatile uint8_t TCCR0B;
|
|
|
+extern FakeIO<uint8_t> TCCR0B;
|
|
|
#define TCCR0B TCCR0B
|
|
|
|
|
|
-extern volatile uint16_t OCR1A;
|
|
|
+extern FakeIO<uint16_t> OCR1A;
|
|
|
#define OCR1A OCR1A
|
|
|
|
|
|
-extern volatile uint16_t OCR1B;
|
|
|
+extern FakeIO<uint16_t> OCR1B;
|
|
|
#define OCR1B OCR1B
|
|
|
|
|
|
-extern volatile uint16_t ICR1;
|
|
|
+extern FakeIO<uint16_t> ICR1;
|
|
|
#define ICR1 ICR1
|
|
|
|
|
|
-extern volatile uint8_t TCNT1;
|
|
|
+extern FakeIO<uint8_t> TCNT1;
|
|
|
#define TCNT1 TCNT1
|
|
|
|
|
|
-extern volatile uint8_t TCCR1A;
|
|
|
+extern FakeIO<uint8_t> TCCR1A;
|
|
|
#define TCCR1A TCCR1A
|
|
|
|
|
|
-extern volatile uint8_t TCCR1B;
|
|
|
+extern FakeIO<uint8_t> TCCR1B;
|
|
|
#define TCCR1B TCCR1B
|
|
|
|
|
|
-extern volatile uint8_t TCCR1C;
|
|
|
+extern FakeIO<uint8_t> TCCR1C;
|
|
|
#define TCCR1C TCCR1C
|
|
|
|
|
|
|
|
@@ -214,35 +325,25 @@ extern volatile uint8_t TCCR1C;
|
|
|
#define EEMPE 2
|
|
|
#define EEPE 1
|
|
|
#define EERE 0
|
|
|
-extern volatile uint8_t EECR;
|
|
|
+extern FakeIO<uint8_t> EECR;
|
|
|
#define EECR EECR
|
|
|
|
|
|
-extern volatile uint8_t EEDR;
|
|
|
+extern FakeIO<uint8_t> EEDR;
|
|
|
#define EEDR EEDR
|
|
|
|
|
|
-extern volatile uint16_t EEAR;
|
|
|
+typedef uintptr_t ee_addr_t;
|
|
|
+#define ee_addr_t ee_addr_t
|
|
|
+extern FakeIO<ee_addr_t> EEAR;
|
|
|
#define EEAR EEAR
|
|
|
-#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
-# define EEARL (*(((uint8_t *)&EEAR) + 0))
|
|
|
-# define EEARH (*(((uint8_t *)&EEAR) + 1))
|
|
|
-#else
|
|
|
-# define ADCL (*(((uint8_t *)&EEAR) + 1))
|
|
|
-# define ADCH (*(((uint8_t *)&EEAR) + 0))
|
|
|
-#endif
|
|
|
|
|
|
#define E2END 0x3FF
|
|
|
|
|
|
|
|
|
-extern volatile uint16_t ADC;
|
|
|
+extern FakeIO<uint16_t> ADC;
|
|
|
#define ADC ADC
|
|
|
#define ADCW ADC
|
|
|
-#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
-# define ADCL (*(((uint8_t *)&ADC) + 0))
|
|
|
-# define ADCH (*(((uint8_t *)&ADC) + 1))
|
|
|
-#else
|
|
|
-# define ADCL (*(((uint8_t *)&ADC) + 1))
|
|
|
-# define ADCH (*(((uint8_t *)&ADC) + 0))
|
|
|
-#endif
|
|
|
+#define ADCL (*(ADC.low_byte()))
|
|
|
+#define ADCH (*(ADC.high_byte()))
|
|
|
|
|
|
#define ADEN 7
|
|
|
#define ADSC 6
|
|
@@ -252,14 +353,14 @@ extern volatile uint16_t ADC;
|
|
|
#define ADPS2 2
|
|
|
#define ADPS1 1
|
|
|
#define ADPS0 0
|
|
|
-extern volatile uint8_t ADCSRA;
|
|
|
+extern FakeIO<uint8_t> ADCSRA;
|
|
|
#define ADCSRA ADCSRA
|
|
|
|
|
|
#define ACME 6
|
|
|
#define ADTS2 2
|
|
|
#define ADTS1 1
|
|
|
#define ADTS0 0
|
|
|
-extern volatile uint8_t ADCSRB;
|
|
|
+extern FakeIO<uint8_t> ADCSRB;
|
|
|
#define ADCSRB ADCSRB
|
|
|
|
|
|
#define REFS1 7
|
|
@@ -269,7 +370,7 @@ extern volatile uint8_t ADCSRB;
|
|
|
#define MUX2 2
|
|
|
#define MUX1 1
|
|
|
#define MUX0 0
|
|
|
-extern volatile uint8_t ADMUX;
|
|
|
+extern FakeIO<uint8_t> ADMUX;
|
|
|
#define ADMUX ADMUX
|
|
|
|
|
|
#define ADC5D 5
|
|
@@ -278,13 +379,57 @@ extern volatile uint8_t ADMUX;
|
|
|
#define ADC2D 2
|
|
|
#define ADC1D 1
|
|
|
#define ADC0D 0
|
|
|
-extern volatile uint8_t DIDR0;
|
|
|
+extern FakeIO<uint8_t> DIDR0;
|
|
|
#define DIDR0 DIDR0
|
|
|
|
|
|
#define AIN1D 1
|
|
|
#define AIN0D 0
|
|
|
-extern volatile uint8_t DIDR1;
|
|
|
+extern FakeIO<uint8_t> DIDR1;
|
|
|
#define DIDR1 DIDR1
|
|
|
|
|
|
|
|
|
+#define RXC0 7
|
|
|
+#define TXC0 6
|
|
|
+#define UDRE0 5
|
|
|
+#define FE0 4
|
|
|
+#define DOR0 3
|
|
|
+#define UPE0 2
|
|
|
+#define U2X0 1
|
|
|
+#define MPCM0 0
|
|
|
+extern FakeIO<uint8_t> UCSR0A;
|
|
|
+#define UCSR0A UCSR0A
|
|
|
+
|
|
|
+#define RXCIE0 7
|
|
|
+#define TXCIE0 6
|
|
|
+#define UDRIE0 5
|
|
|
+#define RXEN0 4
|
|
|
+#define TXEN0 3
|
|
|
+#define UCSZ02 2
|
|
|
+#define RXB80 1
|
|
|
+#define TXB80 0
|
|
|
+extern FakeIO<uint8_t> UCSR0B;
|
|
|
+#define UCSR0B UCSR0B
|
|
|
+
|
|
|
+#define UMSEL01 7
|
|
|
+#define UMSEL00 6
|
|
|
+#define UPM01 5
|
|
|
+#define UPM00 4
|
|
|
+#define USBS0 3
|
|
|
+#define UCSZ01 2
|
|
|
+#define UDORD0 2
|
|
|
+#define UCSZ00 1
|
|
|
+#define UCPHA0 1
|
|
|
+#define UCPOL0 0
|
|
|
+extern FakeIO<uint8_t> UCSR0C;
|
|
|
+#define UCSR0C UCSR0C
|
|
|
+
|
|
|
+extern FakeIO<uint16_t> UBRR0;
|
|
|
+#define UBRR0 UBRR0
|
|
|
+#define UBRR0L (*(UBRR0.low_byte()))
|
|
|
+#define UBRR0H (*(UBRR0.high_byte()))
|
|
|
+
|
|
|
+extern FakeIO<uint8_t> UDR0;
|
|
|
+#define UDR0 UDR0
|
|
|
+
|
|
|
+
|
|
|
#endif /* FAKE_IO_H_ */
|