hmmm, i tried the fast write on an RET6, but got no blinking LED
BB_PERIPHERAL(GPIOA_ODR, 5), // D13
i printed out the bitband address
42210614
GPIOA_BASE->BSRR = 1<<5; this variation works
hmmm, i tried the fast write on an RET6, but got no blinking LED
BB_PERIPHERAL(GPIOA_ODR, 5), // D13
i printed out the bitband address
42210614
GPIOA_BASE->BSRR = 1<<5; this variation works
a hand calculation of the bit band address gives 0x42210194 and that blinks the LED.
now why doesn't the BB_PERIPHERAL macro give me that ... ?
the problem with the macro is #define GPIOA_ODR ((uint32_t*) GPIOA_BASE+ODR)
GPIOA_BASE is an int32 pointer, so the ODR value of 0x0C is the number of words to add to the address, so ODR should be "3" to get C added to the BASE ... not sure how you wish to "fix" that ...
you don't need to include GPIOn_BASE macros, they are picked up by the compiler
here is a first cut at pulseIn() (just took cycle counts from teensy version), i adjusted IDR to be a word offset, not a byte offset. tested with maple ide v0.0.12
// pulsein, fast digital read and count cycles
// http://forums.leaflabs.com/topic.php?id=737
// attach pin 3 to pin 24 for test
typedef unsigned int uint32_t;
#define IDR (0x08>>2) // word offset of output register within port
// Address of output data register for each GPIO peripheral
#define GPIOA_IDR ((uint32_t*) GPIOA_BASE+IDR)
#define GPIOB_IDR ((uint32_t*) GPIOB_BASE+IDR)
#define GPIOC_IDR ((uint32_t*) GPIOC_BASE+IDR)
#define GPIOD_IDR ((uint32_t*) GPIOD_BASE+IDR)
#define GPIOE_IDR ((uint32_t*) GPIOE_BASE+IDR)
// Formula converts peripheral address to bit band peripheral address
// See ARMs Cortex™-M3 Technical Reference Manual fpr details
// Must all be calculated at compile time
#define BB_PERIPHERAL(peripheral_address, bit) ((volatile uint32_t*)(0x42000000 \
+ ((uint32_t)peripheral_address - 0x40000000) * 32 + bit * 4))
// RET6 http://leaflabs.com/docs/hardware/maple-ret6.html
// to map Maple mini pins back to STM32F103CB
// Each entry is the bit-band address of one GPIO output pin
volatile uint32_t* const bb_port_IDR_bit_address[] = {
BB_PERIPHERAL(GPIOA_IDR, 3), // D0
BB_PERIPHERAL(GPIOA_IDR, 2), // D1
BB_PERIPHERAL(GPIOA_IDR, 0), // D2
BB_PERIPHERAL(GPIOA_IDR, 1), // D3
BB_PERIPHERAL(GPIOB_IDR, 5), // D4
// ... etc
};
#define fast_digitalRead(pin) (*bb_port_IDR_bit_address[pin])
#define PULSEIN_CYCLES_PER_LOOP 21
#define PULSEIN_CYCLES_LATENCY 11
#define C2US 72
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse. */
unsigned int pulseIn(unsigned char pin, unsigned char state, unsigned int timeout)
{
unsigned int width = 0; // keep initialization out of time critical area
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes 16 clock cycles per iteration.
unsigned int numloops = 0;
unsigned int maxloops = timeout*C2US / PULSEIN_CYCLES_PER_LOOP;
// unsigned int maxloops = microsecondsToClockCycles(timeout) / 16;
// wait for any previous pulse to end
while (fast_digitalRead(pin) == state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to start
while (fast_digitalRead(pin) != state)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to stop
while (fast_digitalRead(pin) == state) {
if (numloops++ == maxloops)
return 0;
width++;
}
// convert the reading to microseconds. The loop has been determined
// to be 20 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
//return clockCyclesToMicroseconds(width * 21 + 16);
return ((width * PULSEIN_CYCLES_PER_LOOP + PULSEIN_CYCLES_LATENCY)/C2US);
}
HardwareTimer timer(4); // ch 4 is D24
void setup() {
// Set up the built-in LED pin as an output:
pinMode(13, OUTPUT);
pinMode(3, INPUT);
SerialUSB.begin();
pinMode(24,PWM);
timer.setPrescaleFactor(72);
timer.setOverflow(30);
timer.setMode(4, TIMER_PWM);
timer.setCompare(4,30);
}
void loop() {
int val = fast_digitalRead(3);
digitalWrite(13, val);
SerialUSB.println(val);
val = pulseIn(3,HIGH,500000);
SerialUSB.println(val);
delay(3000); // Wait
}
manitou - sorry about that. The only part that cares about the value being a (volatile uint32_t*)
is BB_PERIPHERAL
Everything else could be simple integers, i.e. uint32_t
, and don't need to be pointers. I'll try to fix that, and repost.
AFAICT pulseIn
will lose accuracy when other interrupts happen; the value of width
will be too small.
A more robust approach would be to use the value of micros() which uses the hardware systick timer, which won't drift with interrupts.
The code in wirish_time.h shows how micros works. Or you could get at the systick timer in your code (though it'll look similar to micros). AFAIK the systick timer is counting at 72MHz (which is likely more precision than is needed).
NB: There was a bug in the Maple IDE wirish_time.h micros(); it should read:
// corrected:
do {
ms = millis();
cycle_cnt = systick_get_count();
} while (ms != millis());
and not
// bug:
do {
cycle_cnt = systick_get_count();
ms = millis();
} while (ms != millis());
This looks a bit better on my Mac, but still not checked on Maple (sorry folks it's a bit long):
// base address of each GPIO peripheral port
#define GPIOA_BASE ((uint32_t) 0x40010800)
#define GPIOB_BASE ((uint32_t) 0x40010C00)
#define GPIOC_BASE ((uint32_t) 0x40011000)
#define GPIOD_BASE ((uint32_t) 0x40011400)
#define GPIOE_BASE ((uint32_t) 0x40011800)
#define GPIOF_BASE ((uint32_t) 0x40011C00)
#define GPIOG_BASE ((uint32_t) 0x40012000)
// GPIO Register byte offsets
#define ODR (0x0C) // *BYTE* address offset of output register within port
#define IDR (0x08) // *BYTE* address offset of input register within port
// Formula converts peripheral address to bit band peripheral address
// See ARMs Cortex™-M3 Technical Reference Manual fpr details
// Must all be calculatable at compile time
#define BB_PERIPHERAL(peripheral_address, bit) ((volatile uint32_t*)(0x42000000 \
+ ((((const uint32_t)(peripheral_address)) - 0x40000000)*32) \
+ ((const uint32_t)(bit)*4)))
// uses http://leaflabs.com/docs/hardware/maple-mini.html#gpio-port-pin-map
// to map Maple mini pins back to STM32F103CB
// Each entry is the bit-band address of one GPIO output pin
volatile uint32_t* const bb_port_ODR_bit_address[] = {
BB_PERIPHERAL(GPIOB_BASE+ODR, 11), // D0
BB_PERIPHERAL(GPIOB_BASE+ODR, 10), // D1
BB_PERIPHERAL(GPIOB_BASE+ODR, 2), // D2
BB_PERIPHERAL(GPIOB_BASE+ODR, 0), // D3
BB_PERIPHERAL(GPIOA_BASE+ODR, 7), // D4
BB_PERIPHERAL(GPIOA_BASE+ODR, 6), // D5
BB_PERIPHERAL(GPIOA_BASE+ODR, 5), // D6
BB_PERIPHERAL(GPIOA_BASE+ODR, 4), // D7
BB_PERIPHERAL(GPIOA_BASE+ODR, 3), // D8
BB_PERIPHERAL(GPIOA_BASE+ODR, 2), // D9
BB_PERIPHERAL(GPIOA_BASE+ODR, 1), // D10
BB_PERIPHERAL(GPIOA_BASE+ODR, 0), // D11
BB_PERIPHERAL(GPIOC_BASE+ODR, 15), // D12
BB_PERIPHERAL(GPIOC_BASE+ODR, 14), // D13
BB_PERIPHERAL(GPIOC_BASE+ODR, 13), // D14
// etc ...
};
// Each entry is the bit-band address of one GPIO input pin
volatile uint32_t* const bb_port_IDR_bit_address[] = {
BB_PERIPHERAL(GPIOB_BASE+IDR, 11), // D0
BB_PERIPHERAL(GPIOB_BASE+IDR, 10), // D1
BB_PERIPHERAL(GPIOB_BASE+IDR, 2), // D2
BB_PERIPHERAL(GPIOB_BASE+IDR, 0), // D3
BB_PERIPHERAL(GPIOA_BASE+IDR, 7), // D4
BB_PERIPHERAL(GPIOA_BASE+IDR, 6), // D5
BB_PERIPHERAL(GPIOA_BASE+IDR, 5), // D6
BB_PERIPHERAL(GPIOA_BASE+IDR, 4), // D7
BB_PERIPHERAL(GPIOA_BASE+IDR, 3), // D8
BB_PERIPHERAL(GPIOA_BASE+IDR, 2), // D9
BB_PERIPHERAL(GPIOA_BASE+IDR, 1), // D10
BB_PERIPHERAL(GPIOA_BASE+IDR, 0), // D11
BB_PERIPHERAL(GPIOC_BASE+IDR, 15), // D12
BB_PERIPHERAL(GPIOC_BASE+IDR, 14), // D13
BB_PERIPHERAL(GPIOC_BASE+IDR, 13), // D14
// etc ...
};
#define fast_digitalWrite(pin, value) (*bb_port_ODR_bit_address[pin] = value)
#define fast_digitalRead(pin) (*bb_port_IDR_bit_address[pin])
void setup() {
// Set up the built-in LED pin as an output:
pinMode(13, OUTPUT);
pinMode(9, INPUT);
}
void loop() {
int val = fast_digitalRead(9);
fast_digitalWrite(13, HIGH);
delay(1000); // Wait for 1 second (1000 milliseconds)
fast_digitalWrite(13, LOW);
delay(1000); // Wait for 1 second (1000 milliseconds)
}
I tried using the typedef struct gpio_reg_map
declaration in gpio.h, but got a 'not constant' error when multiplying by 32, even though the pointer (e.g. &GPIOB_BASE->ODR
) was cast to uint32_t
digitalWriteFaster is here!
I re-packaged this code into a permanent header file for our libraries "digitalWriteFaster.h".
I've been using this library for a couple of weeks and I have to say that this code you guys wrote is so much better than digitalWrite and digitalRead that I think it should just be part of the standard distribution.
Thanks again to member 'manitou' and moderator 'gbulmer'.
/******************************************************************************
* digitalWriteFaster.h
*
* An ultra-fast hardware specific replacement for both
* digitalWrite and digitalRead.
*
* Works for Maple, Maple-Mini, Maple Native, and Maple Ret6.
*
* To use, create a folder named 'digitalWriteFaster' inside your 'libraries' folder.
* Create a text file named 'digitalWriteFaster.h' and cut&paste this code.
*
* Use 'digitalWriteFaster' and 'digitalReadFaster' in the original manner.
*
* Based on code written by moderator 'gbulmer' and member 'manitou'.
* Re-packaged by member tlgosser 4/24/2013.
* http://forums.leaflabs.com/topic.php?id=737
*
*****************************************************************************/
typedef unsigned int uint32_t;
#define ODR (0x0C>>2) // offset of output register within port
#define IDR (0x08>>2) // offset of input register within port
// Address of output data register for each GPIO peripheral
#define GPIOA_ODR ((uint32_t*) GPIOA_BASE+ODR)
#define GPIOB_ODR ((uint32_t*) GPIOB_BASE+ODR)
#define GPIOC_ODR ((uint32_t*) GPIOC_BASE+ODR)
#define GPIOD_ODR ((uint32_t*) GPIOD_BASE+ODR)
#define GPIOE_ODR ((uint32_t*) GPIOE_BASE+ODR)
#define GPIOF_ODR ((uint32_t*) GPIOF_BASE+ODR)
#define GPIOG_ODR ((uint32_t*) GPIOG_BASE+ODR)
#define GPIOA_IDR ((uint32_t*) GPIOA_BASE+IDR)
#define GPIOB_IDR ((uint32_t*) GPIOB_BASE+IDR)
#define GPIOC_IDR ((uint32_t*) GPIOC_BASE+IDR)
#define GPIOD_IDR ((uint32_t*) GPIOD_BASE+IDR)
#define GPIOE_IDR ((uint32_t*) GPIOE_BASE+IDR)
#define GPIOF_IDR ((uint32_t*) GPIOF_BASE+IDR)
#define GPIOG_IDR ((uint32_t*) GPIOG_BASE+IDR)
// Formula converts peripheral address to bit band peripheral address
// See ARMs Cortex™-M3 Technical Reference Manual for details
// Must all be calculated at compile time
#define BB_PERIPHERAL(peripheral_address, bit) ((volatile uint32_t*) (0x42000000 \
+ ((uint32_t)peripheral_address - 0x40000000) * 32 + bit * 4))
#ifdef BOARD_maple_mini
// uses http://leaflabs.com/docs/hardware/maple-mini.html#gpio-port-pin-map
// to map Maple mini pins back to STM32F103CB
// Each entry is the bit-band address of one GPIO output pin
volatile uint32_t* const bb_port_ODR_bit_address[] = {
BB_PERIPHERAL(GPIOB_ODR, 11), // D0
BB_PERIPHERAL(GPIOB_ODR, 10), // D1
BB_PERIPHERAL(GPIOB_ODR, 2), // D2
BB_PERIPHERAL(GPIOB_ODR, 0), // D3
BB_PERIPHERAL(GPIOA_ODR, 7), // D4
BB_PERIPHERAL(GPIOA_ODR, 6), // D5
BB_PERIPHERAL(GPIOA_ODR, 5), // D6
BB_PERIPHERAL(GPIOA_ODR, 4), // D7
BB_PERIPHERAL(GPIOA_ODR, 3), // D8
BB_PERIPHERAL(GPIOA_ODR, 2), // D9
BB_PERIPHERAL(GPIOA_ODR, 1), // D10
BB_PERIPHERAL(GPIOA_ODR, 0), // D11
BB_PERIPHERAL(GPIOC_ODR, 15), // D12
BB_PERIPHERAL(GPIOC_ODR, 14), // D13
BB_PERIPHERAL(GPIOC_ODR, 13), // D14
BB_PERIPHERAL(GPIOB_ODR, 7), //D15
BB_PERIPHERAL(GPIOB_ODR, 6), //D16
BB_PERIPHERAL(GPIOB_ODR, 5), //D17
BB_PERIPHERAL(GPIOB_ODR, 4), //D18
BB_PERIPHERAL(GPIOB_ODR, 3), //D19
BB_PERIPHERAL(GPIOA_ODR, 15), //D20
BB_PERIPHERAL(GPIOA_ODR, 14), //D21
BB_PERIPHERAL(GPIOA_ODR, 13), //D22
BB_PERIPHERAL(GPIOA_ODR, 12), //D23
BB_PERIPHERAL(GPIOA_ODR, 11), //D24
BB_PERIPHERAL(GPIOA_ODR, 10), //D25
BB_PERIPHERAL(GPIOA_ODR, 9), //D26
BB_PERIPHERAL(GPIOA_ODR, 8), //D27
BB_PERIPHERAL(GPIOB_ODR, 15), //D28
BB_PERIPHERAL(GPIOB_ODR, 14), //D29
BB_PERIPHERAL(GPIOB_ODR, 13), //D30
BB_PERIPHERAL(GPIOB_ODR, 12) //D31
};
// Each entry is the bit-band address of one GPIO input pin
volatile uint32_t* const bb_port_IDR_bit_address[] = {
BB_PERIPHERAL(GPIOB_IDR, 11), // D0
BB_PERIPHERAL(GPIOB_IDR, 10), // D1
BB_PERIPHERAL(GPIOB_IDR, 2), // D2
BB_PERIPHERAL(GPIOB_IDR, 0), // D3
BB_PERIPHERAL(GPIOA_IDR, 7), // D4
BB_PERIPHERAL(GPIOA_IDR, 6), // D5
BB_PERIPHERAL(GPIOA_IDR, 5), // D6
BB_PERIPHERAL(GPIOA_IDR, 4), // D7
BB_PERIPHERAL(GPIOA_IDR, 3), // D8
BB_PERIPHERAL(GPIOA_IDR, 2), // D9
BB_PERIPHERAL(GPIOA_IDR, 1), // D10
BB_PERIPHERAL(GPIOA_IDR, 0), // D11
BB_PERIPHERAL(GPIOC_IDR, 15), // D12
BB_PERIPHERAL(GPIOC_IDR, 14), // D13
BB_PERIPHERAL(GPIOC_IDR, 13), // D14
BB_PERIPHERAL(GPIOB_IDR, 7), // D15
BB_PERIPHERAL(GPIOB_IDR, 6), // D16
BB_PERIPHERAL(GPIOB_IDR, 5), // D17
BB_PERIPHERAL(GPIOB_IDR, 4), // D18
BB_PERIPHERAL(GPIOB_IDR, 3), // D19
BB_PERIPHERAL(GPIOA_IDR, 15), // D20
BB_PERIPHERAL(GPIOA_IDR, 14), // D21
BB_PERIPHERAL(GPIOA_IDR, 13), // D22
BB_PERIPHERAL(GPIOA_IDR, 12), // D23
BB_PERIPHERAL(GPIOA_IDR, 11), // D24
BB_PERIPHERAL(GPIOA_IDR, 10), // D25
BB_PERIPHERAL(GPIOA_IDR, 9), // D26
BB_PERIPHERAL(GPIOA_IDR, 8), // D27
BB_PERIPHERAL(GPIOB_IDR, 15), // D28
BB_PERIPHERAL(GPIOB_IDR, 14), // D29
BB_PERIPHERAL(GPIOB_IDR, 13), // D30
BB_PERIPHERAL(GPIOB_IDR, 12) // D31
};
#elif defined BOARD_maple_native
// uses http://leaflabs.com/docs/hardware/maple-native-beta.html#gpio-port-pin-map
volatile uint32_t* const bb_port_ODR_bit_address[] = {
BB_PERIPHERAL(GPIOB_ODR, 10), // D0
BB_PERIPHERAL(GPIOB_ODR, 11), // D1
BB_PERIPHERAL(GPIOB_ODR, 12), // D2
BB_PERIPHERAL(GPIOB_ODR, 13), // D3
BB_PERIPHERAL(GPIOB_ODR, 14), // D4
BB_PERIPHERAL(-1, -1), // D5
BB_PERIPHERAL(-1, -1), // D6 button pin
BB_PERIPHERAL(GPIOC_ODR, 0), // D7
BB_PERIPHERAL(GPIOC_ODR, 1), // D8
BB_PERIPHERAL(GPIOC_ODR, 2), // D9
BB_PERIPHERAL(GPIOC_ODR, 3), // D10
BB_PERIPHERAL(GPIOC_ODR, 4), // D11
BB_PERIPHERAL(GPIOC_ODR, 5), // D12
BB_PERIPHERAL(GPIOC_ODR, 6), // D13
BB_PERIPHERAL(GPIOC_ODR, 7), // D14
BB_PERIPHERAL(GPIOC_ODR, 8), // D15
BB_PERIPHERAL(GPIOC_ODR, 9), // D16
BB_PERIPHERAL(GPIOC_ODR, 10), // D17
BB_PERIPHERAL(GPIOC_ODR, 11), // D18
BB_PERIPHERAL(GPIOC_ODR, 12), // D19
BB_PERIPHERAL(GPIOC_ODR, 13), // D20
BB_PERIPHERAL(GPIOC_ODR, 14), // D21
BB_PERIPHERAL(-1, -1), // D22
BB_PERIPHERAL(GPIOA_ODR, 8), // D23
BB_PERIPHERAL(GPIOA_ODR, 9), // D24
BB_PERIPHERAL(GPIOA_ODR, 10), // D25
BB_PERIPHERAL(GPIOB_ODR, 9), // D26
BB_PERIPHERAL(GPIOD_ODR, 2), // D27
BB_PERIPHERAL(GPIOD_ODR, 3), // D28
BB_PERIPHERAL(GPIOD_ODR, 6), // D29
BB_PERIPHERAL(GPIOG_ODR, 11), // D30
BB_PERIPHERAL(GPIOG_ODR, 12), // D31
BB_PERIPHERAL(GPIOG_ODR, 13), // D32
BB_PERIPHERAL(GPIOG_ODR, 14) // D33
BB_PERIPHERAL(GPIOG_ODR, 8), // D34
BB_PERIPHERAL(GPIOG_ODR, 7), // D35
BB_PERIPHERAL(GPIOG_ODR, 6), // D36
BB_PERIPHERAL(GPIOB_ODR, 5), // D37
BB_PERIPHERAL(GPIOB_ODR, 6), // D38
BB_PERIPHERAL(GPIOB_ODR, 7), // D39
BB_PERIPHERAL(GPIOF_ODR, 11), // D40
BB_PERIPHERAL(GPIOF_ODR, 6), // D41
BB_PERIPHERAL(GPIOF_ODR, 7), // D42
BB_PERIPHERAL(GPIOF_ODR, 8), // D43
BB_PERIPHERAL(GPIOF_ODR, 9), // D44
BB_PERIPHERAL(GPIOF_ODR, 10), // D45
BB_PERIPHERAL(GPIOB_ODR, 1), // D46
BB_PERIPHERAL(GPIOB_ODR, 0), // D47
BB_PERIPHERAL(GPIOA_ODR, 0), // D48
BB_PERIPHERAL(GPIOA_ODR, 1), // D49
BB_PERIPHERAL(GPIOA_ODR, 2), // D50
BB_PERIPHERAL(GPIOA_ODR, 3), // D51
BB_PERIPHERAL(GPIOA_ODR, 4), // D52
BB_PERIPHERAL(GPIOA_ODR, 5), // D53
BB_PERIPHERAL(GPIOA_ODR, 6), // D54
BB_PERIPHERAL(GPIOA_ODR, 7), // D55
BB_PERIPHERAL(GPIOF_ODR, 0), // D56
BB_PERIPHERAL(GPIOD_ODR, 11), // D57
BB_PERIPHERAL(GPIOD_ODR, 14), // D58
BB_PERIPHERAL(GPIOF_ODR, 1), // D59
BB_PERIPHERAL(GPIOD_ODR, 12), // D60
BB_PERIPHERAL(-1, -1), // D61
BB_PERIPHERAL(GPIOF_ODR, 2), // D62
BB_PERIPHERAL(GPIOD_ODR, 13), // D63
BB_PERIPHERAL(GPIOD_ODR, 0), // D64
BB_PERIPHERAL(GPIOF_ODR, 3), // D65
BB_PERIPHERAL(GPIOE_ODR, 3), // D66
BB_PERIPHERAL(GPIOD_ODR, 1), // D67
BB_PERIPHERAL(GPIOF_ODR, 4), // D68
BB_PERIPHERAL(GPIOE_ODR, 4), // D69
BB_PERIPHERAL(GPIOE_ODR, 7), // D70
BB_PERIPHERAL(GPIOF_ODR, 5), // D71
BB_PERIPHERAL(GPIOE_ODR, 5), // D72
BB_PERIPHERAL(GPIOE_ODR, 8), // D73
BB_PERIPHERAL(GPIOF_ODR, 12), // D74
BB_PERIPHERAL(GPIOE_ODR, 6), // D75
BB_PERIPHERAL(GPIOE_ODR, 9), // D76
BB_PERIPHERAL(GPIOF_ODR, 13), // D77
BB_PERIPHERAL(GPIOE_ODR, 10), // D78
BB_PERIPHERAL(GPIOF_ODR, 14), // D79
BB_PERIPHERAL(GPIOG_ODR, 9), // D80
BB_PERIPHERAL(GPIOE_ODR, 11), // D81
BB_PERIPHERAL(-1, -1), // D82
BB_PERIPHERAL(GPIOG_ODR, 10), // D83
BB_PERIPHERAL(GPIOE_ODR, 12), // D84
BB_PERIPHERAL(GPIOG_ODR, 0), // D85
BB_PERIPHERAL(GPIOD_ODR, 5), // D86
BB_PERIPHERAL(GPIOE_ODR, 13), // D87
BB_PERIPHERAL(GPIOG_ODR, 1), // D88
BB_PERIPHERAL(GPIOD_ODR, 4), // D89
BB_PERIPHERAL(GPIOE_ODR, 14), // D90
BB_PERIPHERAL(GPIOG_ODR, 2), // D91
BB_PERIPHERAL(GPIOE_ODR, 1), // D92
BB_PERIPHERAL(-1, -1), // D93
BB_PERIPHERAL(GPIOG_ODR, 3), // D94
BB_PERIPHERAL(GPIOE_ODR, 0), // D95
BB_PERIPHERAL(GPIOD_ODR, 8), // D96
BB_PERIPHERAL(GPIOG_ODR, 4), // D97
BB_PERIPHERAL(GPIOD_ODR, 9), // D98
BB_PERIPHERAL(GPIOG_ODR, 5), // D99
BB_PERIPHERAL(GPIOD_ODR, 10), // D100
BB_PERIPHERAL(GPIOA_ODR, 13), // D101
BB_PERIPHERAL(GPIOA_ODR, 14), // D102
BB_PERIPHERAL(-1, -1), // D103
BB_PERIPHERAL(GPIOB_ODR, 3), // D104
BB_PERIPHERAL(GPIOB_ODR, 4) // D105
};
// Each entry is the bit-band address of one GPIO input pin
volatile uint32_t* const bb_port_IDR_bit_address[] = {
BB_PERIPHERAL(GPIOB_IDR, 10), // D0
BB_PERIPHERAL(GPIOB_IDR, 11), // D1
BB_PERIPHERAL(GPIOB_IDR, 12), // D2
BB_PERIPHERAL(GPIOB_IDR, 13), // D3
BB_PERIPHERAL(GPIOB_IDR, 14), // D4
BB_PERIPHERAL(-1, -1), // D5
BB_PERIPHERAL(-1, -1), // D6 button pin
BB_PERIPHERAL(GPIOC_IDR, 0), // D7
BB_PERIPHERAL(GPIOC_IDR, 1), // D8
BB_PERIPHERAL(GPIOC_IDR, 2), // D9
BB_PERIPHERAL(GPIOC_IDR, 3), // D10
BB_PERIPHERAL(GPIOC_IDR, 4), // D11
BB_PERIPHERAL(GPIOC_IDR, 5), // D12
BB_PERIPHERAL(GPIOC_IDR, 6), // D13
BB_PERIPHERAL(GPIOC_IDR, 7), // D14
BB_PERIPHERAL(GPIOC_IDR, 8), // D15
BB_PERIPHERAL(GPIOC_IDR, 9), // D16
BB_PERIPHERAL(GPIOC_IDR, 10), // D17
BB_PERIPHERAL(GPIOC_IDR, 11), // D18
BB_PERIPHERAL(GPIOC_IDR, 12), // D19
BB_PERIPHERAL(GPIOC_IDR, 13), // D20
BB_PERIPHERAL(GPIOC_IDR, 14), // D21
BB_PERIPHERAL(-1, -1), // D22
BB_PERIPHERAL(GPIOA_IDR, 8), // D23
BB_PERIPHERAL(GPIOA_IDR, 9), // D24
BB_PERIPHERAL(GPIOA_IDR, 10), // D25
BB_PERIPHERAL(GPIOB_IDR, 9), // D26
BB_PERIPHERAL(GPIOD_IDR, 2), // D27
BB_PERIPHERAL(GPIOD_IDR, 3), // D28
BB_PERIPHERAL(GPIOD_IDR, 6), // D29
BB_PERIPHERAL(GPIOG_IDR, 11), // D30
BB_PERIPHERAL(GPIOG_IDR, 12), // D31
BB_PERIPHERAL(GPIOG_IDR, 13), // D32
BB_PERIPHERAL(GPIOG_IDR, 14) // D33
BB_PERIPHERAL(GPIOG_IDR, 8), // D34
BB_PERIPHERAL(GPIOG_IDR, 7), // D35
BB_PERIPHERAL(GPIOG_IDR, 6), // D36
BB_PERIPHERAL(GPIOB_IDR, 5), // D37
BB_PERIPHERAL(GPIOB_IDR, 6), // D38
BB_PERIPHERAL(GPIOB_IDR, 7), // D39
BB_PERIPHERAL(GPIOF_IDR, 11), // D40
BB_PERIPHERAL(GPIOF_IDR, 6), // D41
BB_PERIPHERAL(GPIOF_IDR, 7), // D42
BB_PERIPHERAL(GPIOF_IDR, 8), // D43
BB_PERIPHERAL(GPIOF_IDR, 9), // D44
BB_PERIPHERAL(GPIOF_IDR, 10), // D45
BB_PERIPHERAL(GPIOB_IDR, 1), // D46
BB_PERIPHERAL(GPIOB_IDR, 0), // D47
BB_PERIPHERAL(GPIOA_IDR, 0), // D48
BB_PERIPHERAL(GPIOA_IDR, 1), // D49
BB_PERIPHERAL(GPIOA_IDR, 2), // D50
BB_PERIPHERAL(GPIOA_IDR, 3), // D51
BB_PERIPHERAL(GPIOA_IDR, 4), // D52
BB_PERIPHERAL(GPIOA_IDR, 5), // D53
BB_PERIPHERAL(GPIOA_IDR, 6), // D54
BB_PERIPHERAL(GPIOA_IDR, 7), // D55
BB_PERIPHERAL(GPIOF_IDR, 0), // D56
BB_PERIPHERAL(GPIOD_IDR, 11), // D57
BB_PERIPHERAL(GPIOD_IDR, 14), // D58
BB_PERIPHERAL(GPIOF_IDR, 1), // D59
BB_PERIPHERAL(GPIOD_IDR, 12), // D60
BB_PERIPHERAL(-1, -1), // D61
BB_PERIPHERAL(GPIOF_IDR, 2), // D62
BB_PERIPHERAL(GPIOD_IDR, 13), // D63
BB_PERIPHERAL(GPIOD_IDR, 0), // D64
BB_PERIPHERAL(GPIOF_IDR, 3), // D65
BB_PERIPHERAL(GPIOE_IDR, 3), // D66
BB_PERIPHERAL(GPIOD_IDR, 1), // D67
BB_PERIPHERAL(GPIOF_IDR, 4), // D68
BB_PERIPHERAL(GPIOE_IDR, 4), // D69
BB_PERIPHERAL(GPIOE_IDR, 7), // D70
BB_PERIPHERAL(GPIOF_IDR, 5), // D71
BB_PERIPHERAL(GPIOE_IDR, 5), // D72
BB_PERIPHERAL(GPIOE_IDR, 8), // D73
BB_PERIPHERAL(GPIOF_IDR, 12), // D74
BB_PERIPHERAL(GPIOE_IDR, 6), // D75
BB_PERIPHERAL(GPIOE_IDR, 9), // D76
BB_PERIPHERAL(GPIOF_IDR, 13), // D77
BB_PERIPHERAL(GPIOE_IDR, 10), // D78
BB_PERIPHERAL(GPIOF_IDR, 14), // D79
BB_PERIPHERAL(GPIOG_IDR, 9), // D80
BB_PERIPHERAL(GPIOE_IDR, 11), // D81
BB_PERIPHERAL(-1, -1), // D82
BB_PERIPHERAL(GPIOG_IDR, 10), // D83
BB_PERIPHERAL(GPIOE_IDR, 12), // D84
BB_PERIPHERAL(GPIOG_IDR, 0), // D85
BB_PERIPHERAL(GPIOD_IDR, 5), // D86
BB_PERIPHERAL(GPIOE_IDR, 13), // D87
BB_PERIPHERAL(GPIOG_IDR, 1), // D88
BB_PERIPHERAL(GPIOD_IDR, 4), // D89
BB_PERIPHERAL(GPIOE_IDR, 14), // D90
BB_PERIPHERAL(GPIOG_IDR, 2), // D91
BB_PERIPHERAL(GPIOE_IDR, 1), // D92
BB_PERIPHERAL(-1, -1), // D93
BB_PERIPHERAL(GPIOG_IDR, 3), // D94
BB_PERIPHERAL(GPIOE_IDR, 0), // D95
BB_PERIPHERAL(GPIOD_IDR, 8), // D96
BB_PERIPHERAL(GPIOG_IDR, 4), // D97
BB_PERIPHERAL(GPIOD_IDR, 9), // D98
BB_PERIPHERAL(GPIOG_IDR, 5), // D99
BB_PERIPHERAL(GPIOD_IDR, 10), // D100
BB_PERIPHERAL(GPIOA_IDR, 13), // D101
BB_PERIPHERAL(GPIOA_IDR, 14), // D102
BB_PERIPHERAL(-1, -1), // D103
BB_PERIPHERAL(GPIOB_IDR, 3), // D104
BB_PERIPHERAL(GPIOB_IDR, 4) // D105
};
#elif defined (BOARD_maple_RET6) || defined(BOARD_maple)
// uses http://leaflabs.com/docs/hardware/maple.html#gpio-port-pin-map
volatile uint32_t* const bb_port_ODR_bit_address[] = {
BB_PERIPHERAL(GPIOA_ODR, 3), // D0
BB_PERIPHERAL(GPIOA_ODR, 2), // D1
BB_PERIPHERAL(GPIOA_ODR, 0), // D2
BB_PERIPHERAL(GPIOA_ODR, 1), // D3
BB_PERIPHERAL(GPIOB_ODR, 5), // D4
BB_PERIPHERAL(GPIOB_ODR, 6), // D5
BB_PERIPHERAL(GPIOA_ODR, 8), // D6
BB_PERIPHERAL(GPIOA_ODR, 9), // D7
BB_PERIPHERAL(GPIOA_ODR, 10), // D8
BB_PERIPHERAL(GPIOB_ODR, 7), // D9
BB_PERIPHERAL(GPIOA_ODR, 4), // D10
BB_PERIPHERAL(GPIOA_ODR, 7), // D11
BB_PERIPHERAL(GPIOA_ODR, 6), // D12
BB_PERIPHERAL(GPIOA_ODR, 5), // D13
BB_PERIPHERAL(GPIOB_ODR, 8), // D14
BB_PERIPHERAL(GPIOC_ODR, 0), // D15
BB_PERIPHERAL(GPIOC_ODR, 1), // D16
BB_PERIPHERAL(GPIOC_ODR, 2), // D17
BB_PERIPHERAL(GPIOC_ODR, 3), // D18
BB_PERIPHERAL(GPIOC_ODR, 4), // D19
BB_PERIPHERAL(GPIOC_ODR, 5), // D20
BB_PERIPHERAL(GPIOC_ODR, 13), // D21
BB_PERIPHERAL(GPIOC_ODR, 14), // D22
BB_PERIPHERAL(GPIOC_ODR, 15), // D23
BB_PERIPHERAL(GPIOB_ODR, 9), // D24
BB_PERIPHERAL(GPIOD_ODR, 2), // D25 - changed by gbulmer 2014/6/16
BB_PERIPHERAL(GPIOC_ODR, 10), // D26
BB_PERIPHERAL(GPIOB_ODR, 0), // D27
BB_PERIPHERAL(GPIOB_ODR, 1), // D28
BB_PERIPHERAL(GPIOB_ODR, 10), // D29
BB_PERIPHERAL(GPIOB_ODR, 11), // D30
BB_PERIPHERAL(GPIOB_ODR, 12), // D31
BB_PERIPHERAL(GPIOB_ODR, 13), // D32
BB_PERIPHERAL(GPIOB_ODR, 14), // D33
BB_PERIPHERAL(GPIOB_ODR, 15), // D34
BB_PERIPHERAL(GPIOC_ODR, 6), // D35
BB_PERIPHERAL(GPIOC_ODR, 7), // D36
BB_PERIPHERAL(GPIOC_ODR, 8), // D37
BB_PERIPHERAL(GPIOC_ODR, 9), // D38
BB_PERIPHERAL(GPIOA_ODR, 13), // D39
BB_PERIPHERAL(GPIOA_ODR, 14), // D40
BB_PERIPHERAL(GPIOA_ODR, 15), // D41
BB_PERIPHERAL(GPIOB_ODR, 3), // D42
BB_PERIPHERAL(GPIOB_ODR, 4) // D43
};
volatile uint32_t* const bb_port_IDR_bit_address[] = {
BB_PERIPHERAL(GPIOA_IDR, 3), // D0
BB_PERIPHERAL(GPIOA_IDR, 2), // D1
BB_PERIPHERAL(GPIOA_IDR, 0), // D2
BB_PERIPHERAL(GPIOA_IDR, 1), // D3
BB_PERIPHERAL(GPIOB_IDR, 5), // D4
BB_PERIPHERAL(GPIOB_IDR, 6), // D5
BB_PERIPHERAL(GPIOA_IDR, 8), // D6
BB_PERIPHERAL(GPIOA_IDR, 9), // D7
BB_PERIPHERAL(GPIOA_IDR, 10), // D8
BB_PERIPHERAL(GPIOB_IDR, 7), // D9
BB_PERIPHERAL(GPIOA_IDR, 4), // D10
BB_PERIPHERAL(GPIOA_IDR, 7), // D11
BB_PERIPHERAL(GPIOA_IDR, 6), // D12
BB_PERIPHERAL(GPIOA_IDR, 5), // D13
BB_PERIPHERAL(GPIOB_IDR, 8), // D14
BB_PERIPHERAL(GPIOC_IDR, 0), // D15
BB_PERIPHERAL(GPIOC_IDR, 1), // D16
BB_PERIPHERAL(GPIOC_IDR, 2), // D17
BB_PERIPHERAL(GPIOC_IDR, 3), // D18
BB_PERIPHERAL(GPIOC_IDR, 4), // D19
BB_PERIPHERAL(GPIOC_IDR, 5), // D20
BB_PERIPHERAL(GPIOC_IDR, 13), // D21
BB_PERIPHERAL(GPIOC_IDR, 14), // D22
BB_PERIPHERAL(GPIOC_IDR, 15), // D23
BB_PERIPHERAL(GPIOB_IDR, 9), // D24
BB_PERIPHERAL(GPIOD_IDR, 2), // D25 - changed by gbulmer 2014/6/16
BB_PERIPHERAL(GPIOC_IDR, 10), // D26
BB_PERIPHERAL(GPIOB_IDR, 0), // D27
BB_PERIPHERAL(GPIOB_IDR, 1), // D28
BB_PERIPHERAL(GPIOB_IDR, 10), // D29
BB_PERIPHERAL(GPIOB_IDR, 11), // D30
BB_PERIPHERAL(GPIOB_IDR, 12), // D31
BB_PERIPHERAL(GPIOB_IDR, 13), // D32
BB_PERIPHERAL(GPIOB_IDR, 14), // D33
BB_PERIPHERAL(GPIOB_IDR, 15), // D34
BB_PERIPHERAL(GPIOC_IDR, 6), // D35
BB_PERIPHERAL(GPIOC_IDR, 7), // D36
BB_PERIPHERAL(GPIOC_IDR, 8), // D37
BB_PERIPHERAL(GPIOC_IDR, 9), // D38
BB_PERIPHERAL(GPIOA_IDR, 13), // D39
BB_PERIPHERAL(GPIOA_IDR, 14), // D40
BB_PERIPHERAL(GPIOA_IDR, 15), // D41
BB_PERIPHERAL(GPIOB_IDR, 3), // D42
BB_PERIPHERAL(GPIOB_IDR, 4) // D43
};
#else
#error "digitalWriteFaster only works on the Maple, Maple-Mini, Native, and Ret6."
#endif
#define digitalWriteFaster(pin, value) (*bb_port_ODR_bit_address[pin] = value)
#define digitalReadFaster(pin) (*bb_port_IDR_bit_address[pin])
// Edit: There may be some entries for Maple Native which are uninitialised
// They contain BB_PERIPHERAL(-1, -1),
instead of the correct value.
// Please check the appropriate Maple Native pin table. gbulmer
/* digitalWriteFaster example as per gbulmer's code above */
#include <gpio.h>
#include <digitalWriteFaster.h>
void setup() {
// Set up the built-in LED pin as an output:
pinMode(13, OUTPUT);
pinMode(9, INPUT);
}
void loop() {
int val = digitalReadFaster(9);
digitalWriteFaster(13, HIGH);
delay(250);
digitalWriteFaster(13, LOW);
delay(250);
}
And you will probably have to restart your editor for the library to show up.
this looks very interesting.
i tried to integrate it in to my project which also receives dmx data.
digitalWriteFaster works fine before running my dmx setup routine. could it be that some of my dmx pins are being effect by the digitalWriteFaster.h library?
i am using pin 25 to receive dmx data
-------------dmx code-----------------
enum
{
DMX_IDLE,
DMX_BREAK,
DMX_START,
DMX_RUN
};
// We need to read the data register in order to avoid overrun errors,
// but we don't do anything with the value. This attribute silences an
// unused variable warning from GCC.
#define __unused __attribute__((unused))
volatile unsigned char dmx_state;
// this is the start address for the dmx frame
//const unsigned int dmx_start_addr = 0;
unsigned int dmx_start_addr = 0;
// this is the current address of the dmx frame
volatile unsigned int dmx_addr;
//// this is used to keep track of the channels
volatile unsigned int chan_cnt;
extern "C" {
void __irq_usart1(void) {
unsigned char status = USART1_BASE->SR;
data = USART1_BASE->DR;
switch (dmx_state)
{
case DMX_IDLE:
if (status & 1<<USART_SR_FE_BIT)
{
dmx_addr = 0;
dmx_state = DMX_BREAK;
update = 1;
//delayMicroseconds(8);
}
break;
case DMX_BREAK:
if (data == 0)
{
dmx_state = DMX_START;
}
else
{
dmx_state = DMX_IDLE;
}
break;
case DMX_START:
dmx_addr++;
if (dmx_addr == dmx_start_addr)
{
chan_cnt = 0;
dmx_data[chan_cnt++] = data; //constrain(data,0,maxDMXvalue); //data;
dmx_state = DMX_RUN;
}
break;
case DMX_RUN:
//for (int wasteTime =0; wasteTime <2; wasteTime++) {}
dmx_data[chan_cnt++] = data; //constrain(data,0,maxDMXvalue); //data;
if (chan_cnt >= DMX_NUM_CHANNELS)
{
// printTestStage = 2;
dmx_state = DMX_IDLE;
}
break;
default:
dmx_state = DMX_IDLE;
break;
}
}
}
void setup_dmx(){
update = 0;
// set default DMX state
dmx_state = DMX_IDLE;
dmx_start_addr = myGroupID * 16 + 1;
Serial1.begin(250000);
// Set USART1 to 2 stop bits
USART1_BASE->CR2 = 2;
}
---------------------and this is my dimming code------------------------
void setup_dimming(){
for(int i=0; i<DMX_NUM_CHANNELS; i++){
pinMode(ledPin[i],OUTPUT_OPEN_DRAIN);
// dimValue[i] = counterLimit/DMX_NUM_CHANNELS * i;
}
Timer3.setPrescaleFactor(1);
Timer3.setOverflow(255); //2000); //500); //1079);
Timer3.attachCompare1Interrupt(timer3_dimming_handler);
}
void timer3_dimming_handler(void) {
for(int i=0; i<DMX_NUM_CHANNELS; i++){
if(dmx_data[i] > counter){
dimStates[i] = true;
}
else{
dimStates[i] = false;
}
digitalWriteFaster(ledPin[i],dimStates[i]);
//if(LED_PORTref_ARRAY[i] == 0) gpio_write_bit(GPIOA, LED_BIT_ARRAY[i],dimStates[i]);
//if(LED_PORTref_ARRAY[i] == 1) gpio_write_bit(GPIOB, LED_BIT_ARRAY[i],dimStates[i]);
//digitalWrite(ledPin[i],dimStates[i]);
}
counter++;
if(counter > counterLimit) counter = 0;
}
now it works. i had some other problem that were not apparent when using gpio_write_bit and only showed up when using digitalwrite. works great this library.
thanks.
I'm looking at this on my phone so it's difficult to read.
Is the dmx dimming data already 'curved' or are you generating
linear gradients here ++?
The maple is fast enough to run the arduino spline library effectively
if you want to interpolate splines on board.
https://github.com/kerinin/arduino-splines
I think you only have to replace Arduino.h with WProgram.h
thanks for the reply.
i figured out my problem. i was trying to access an array element that did not exist.
about the dimming. i am just doing it linear, but your idea of some sort of curve is interesting. i did notice that the leds dim more noticeably in the lower numbers.
but i am also concerned that the dimming of my 16 leds takes up too much time and in turn messes up the dmx receiving. i have 16 channels per maple mini and a chain of 30 boards.
all works well at this point though.
Of course. That is why you are participating in the port registers forum. That's a lot of LEDs. Are you making a monitor?
With LEDs it's all about the refresh rate in your eyeballs somehow.
Btw how did you change your icon? I don't mean to sound insecure but my icon was assigned to me randomly and I assumed it would be simple to change.
You must log in to post.