High speed serial and port control for logic analysis
#ifndef TESTPOINTS_H
#define TESTPOINTS_H
#include "gpio.h"
class TpHw
{
public:
//===================================================================================
// TOG, CLR, SET macros provide a means to quickly clear, set or toggle a pin.
// Each macro compiles into a single machine instruction when optimized.
// usage is:
// TOG(AVR32_PIN10);
//===================================================================================
#define TOG(pin) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
gpio_pin->ovrt = 1 << (pin & 0x1F); }
#define CLR(pin) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
gpio_pin->ovrc = 1 << (pin & 0x1F); }
#define SET(pin) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
gpio_pin->ovrs = 1 << (pin & 0x1F); }
//===================================================================================
// TAG provides a means to insert static real time serial data to be displayed on a
// logic analyzer. The TAG macro should be optimized for a baud rate that matches
// the instruction cycle time of the compiler. Each letter compiles into 10
// machine instructions when optimized. Use 8 data bits, no parity and one stop bit.
// usage is:
// TAG(AVR32_PIN10, 'H', 'E', 'L', 'L', 'O');
//===================================================================================
// this macro builds the bit
#define BT(pin, letter, bit) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
if (letter & bit) \
gpio_pin->ovrs = 1 << (pin & 0x1F); \
else \
gpio_pin->ovrc = 1 << (pin & 0x1F); }
// this macro builds the letter
#define LETTER(pin, letter) { \
BT(pin, letter, 0x00); \
BT(pin, letter, 0x01); \
BT(pin, letter, 0x02); \
BT(pin, letter, 0x04); \
BT(pin, letter, 0x08); \
BT(pin, letter, 0x10); \
BT(pin, letter, 0x20); \
BT(pin, letter, 0x40); \
BT(pin, letter, 0x80); \
BT(pin, 0xff, 0xff); }
// these build the tag
#define LETTER1(pin, letter) LETTER(pin, letter)
#define LETTER2(pin, letter, ...) LETTER1(pin, letter) LETTER1(pin, __VA_ARGS__)
#define LETTER3(pin, letter, ...) LETTER1(pin, letter) LETTER2(pin, __VA_ARGS__)
#define LETTER4(pin, letter, ...) LETTER1(pin, letter) LETTER3(pin, __VA_ARGS__)
#define LETTER5(pin, letter, ...) LETTER1(pin, letter) LETTER4(pin, __VA_ARGS__)
#define LETTER6(pin, letter, ...) LETTER1(pin, letter) LETTER5(pin, __VA_ARGS__)
#define LETTER7(pin, letter, ...) LETTER1(pin, letter) LETTER6(pin, __VA_ARGS__)
#define LETTER8(pin, letter, ...) LETTER1(pin, letter) LETTER7(pin, __VA_ARGS__)
// these calculate the number of arguments passed
#define ARGS_N(x1, x2, x3, x4, x5, x6, x7, x8, N, ...) N
#define RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define NARG_N(...) ARGS_N(__VA_ARGS__)
#define NARG(...) NARG_N(__VA_ARGS__, RSEQ_N())
// these build the macro to start with (T1 - T8) base on number of arguments
#define PASTE(a, b) a ## b
#define XPASTE(a, b) PASTE(a, b)
#define T_(pin, M_, ...) M_(pin, __VA_ARGS__)
#define TAG(pin, ...) T_(pin, XPASTE(LETTER, NARG(__VA_ARGS__)), __VA_ARGS__)
//=====================================================================================
// textOut provides a means to insert dynamic real time serial data to be displayed
// on a logic analyzer. The code below should be optimized for a baud rate that matches
// the instruction cycle time of the compiler by stuffing no ops where appropriate
// to balance the bit output. Use 8 data bits, no parity and one stop bit. This
// gives a character that should take 55 cycles and doesn't take any time to set up.
// usage is:
// TpHw::textOut(AVR32_PIN_PA22, "HELLO");
//=====================================================================================
static void serialOut(uint32_t pin, uint8_t value)
{
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5];
volatile uint32_t out = 1 << (pin & 0x1F);
// start bit
gpio_pin->ovrc = out;
asm("nop");
// bit 0
if (value & (1 << 0))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 1
if (value & (1 << 1))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 2
if (value & (1 << 2))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 3
if (value & (1 << 3))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 4
if (value & (1 << 4))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 5
if (value & (1 << 5))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 6
if (value & (1 << 6))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 7
if (value & (1 << 7))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// stop bit
asm("nop");
asm("nop");
asm("nop");
gpio_pin->ovrs = out;
}
static void textOut(uint32_t pin, char *text)
{
while (*text != 0)
{
serialOut(pin, *text++);
}
}
};
#endif
High speed serial and port control for logic analysis
#ifndef TESTPOINTS_H
#define TESTPOINTS_H
#include "gpio.h"
class TpHw
{
public:
//===================================================================================
// TOG, CLR, SET macros provide a means to quickly clear, set or toggle a pin.
// Each macro compiles into a single machine instruction when optimized.
// usage is:
// TOG(AVR32_PIN10);
//===================================================================================
#define TOG(pin) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
gpio_pin->ovrt = 1 << (pin & 0x1F); }
#define CLR(pin) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
gpio_pin->ovrc = 1 << (pin & 0x1F); }
#define SET(pin) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
gpio_pin->ovrs = 1 << (pin & 0x1F); }
//===================================================================================
// TAG provides a means to insert static real time serial data to be displayed on a
// logic analyzer. The TAG macro should be optimized for a baud rate that matches
// the instruction cycle time of the compiler. Each letter compiles into 10
// machine instructions when optimized. Use 8 data bits, no parity and one stop bit.
// usage is:
// TAG(AVR32_PIN10, 'H', 'E', 'L', 'L', 'O');
//===================================================================================
// this macro builds the bit
#define BT(pin, letter, bit) { \
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5]; \
if (letter & bit) \
gpio_pin->ovrs = 1 << (pin & 0x1F); \
else \
gpio_pin->ovrc = 1 << (pin & 0x1F); }
// this macro builds the letter
#define LETTER(pin, letter) { \
BT(pin, letter, 0x00); \
BT(pin, letter, 0x01); \
BT(pin, letter, 0x02); \
BT(pin, letter, 0x04); \
BT(pin, letter, 0x08); \
BT(pin, letter, 0x10); \
BT(pin, letter, 0x20); \
BT(pin, letter, 0x40); \
BT(pin, letter, 0x80); \
BT(pin, 0xff, 0xff); }
// these build the tag
#define LETTER1(pin, letter) LETTER(pin, letter)
#define LETTER2(pin, letter, ...) LETTER1(pin, letter) LETTER1(pin, __VA_ARGS__)
#define LETTER3(pin, letter, ...) LETTER1(pin, letter) LETTER2(pin, __VA_ARGS__)
#define LETTER4(pin, letter, ...) LETTER1(pin, letter) LETTER3(pin, __VA_ARGS__)
#define LETTER5(pin, letter, ...) LETTER1(pin, letter) LETTER4(pin, __VA_ARGS__)
#define LETTER6(pin, letter, ...) LETTER1(pin, letter) LETTER5(pin, __VA_ARGS__)
#define LETTER7(pin, letter, ...) LETTER1(pin, letter) LETTER6(pin, __VA_ARGS__)
#define LETTER8(pin, letter, ...) LETTER1(pin, letter) LETTER7(pin, __VA_ARGS__)
// these calculate the number of arguments passed
#define ARGS_N(x1, x2, x3, x4, x5, x6, x7, x8, N, ...) N
#define RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define NARG_N(...) ARGS_N(__VA_ARGS__)
#define NARG(...) NARG_N(__VA_ARGS__, RSEQ_N())
// these build the macro to start with (T1 - T8) base on number of arguments
#define PASTE(a, b) a ## b
#define XPASTE(a, b) PASTE(a, b)
#define T_(pin, M_, ...) M_(pin, __VA_ARGS__)
#define TAG(pin, ...) T_(pin, XPASTE(LETTER, NARG(__VA_ARGS__)), __VA_ARGS__)
//=====================================================================================
// textOut provides a means to insert dynamic real time serial data to be displayed
// on a logic analyzer. The code below should be optimized for a baud rate that matches
// the instruction cycle time of the compiler by stuffing no ops where appropriate
// to balance the bit output. Use 8 data bits, no parity and one stop bit. This
// gives a character that should take 55 cycles and doesn't take any time to set up.
// usage is:
// TpHw::textOut(AVR32_PIN_PA22, "HELLO");
//=====================================================================================
static void serialOut(uint32_t pin, uint8_t value)
{
volatile avr32_gpio_port_t *gpio_pin = &AVR32_GPIO.port[pin >> 5];
volatile uint32_t out = 1 << (pin & 0x1F);
// start bit
gpio_pin->ovrc = out;
asm("nop");
// bit 0
if (value & (1 << 0))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 1
if (value & (1 << 1))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 2
if (value & (1 << 2))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 3
if (value & (1 << 3))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 4
if (value & (1 << 4))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 5
if (value & (1 << 5))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 6
if (value & (1 << 6))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// bit 7
if (value & (1 << 7))
{
gpio_pin->ovrs = out;
}
else
{
gpio_pin->ovrc = out;
asm("nop");
}
// stop bit
asm("nop");
asm("nop");
asm("nop");
gpio_pin->ovrs = out;
}
static void textOut(uint32_t pin, char *text)
{
while (*text != 0)
{
serialOut(pin, *text++);
}
}
};
#endif