Just like the Knightrider 2 this is another port of one of my experiments to the Arduino Due. This time I port the lighthouses experiment. The challenge with this experiment is not the pin mappings but the timer. For the original lighthouses experiment I used the MsTimer2 library. See the crucial piece of code below.
#include <MsTimer2.h> // ... void setup() { MsTimer2::set(1, blink); MsTimer2::start(); }
Unfortunately this does not compile for the Due. Searching the internet I found out that ARM Cortex processors provide a “systicks” timer which typically runs at 100 Hz. As it turns out Atmel decided to implement it differently such that it runs at 1 kHz. Lucky me. This is exactly what I need. So the next question was how to register for the systicks.
A short call of “grep sysTick -i -r .” revealed the relevant source lines.
./hardware/arduino/sam/cores/arduino/cortex_handlers.c:extern int sysTickHook(void); ./hardware/arduino/sam/cores/arduino/cortex_handlers.c: if (sysTickHook()) ./hardware/arduino/sam/cores/arduino/hooks.c:int sysTickHook(void) __attribute__ ((weak, alias("__false")));
Looking into the files it becomes clear that sysTickHook is implemented by Arduino as a weak symbol. That is: if I define this symbol it will overwrite the default. However my first attempt below did not work.
// sysTicks will be triggered once per 1 ms int sysTickHook(void) { blink(); return 0; }
Some more searching turned out that CMSIS low level system API is compiled in C instead of C++. So the compiler must be explicitly told that this is a C symbol.
extern "C" { // sysTicks will be triggered once per 1 ms int sysTickHook(void) { blink(); return 0; } }
And hurray it works. The full solution now looks as exhibited below.
// // www.blinkenlight.net // // Copyright 2015 Udo Klein // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see http://www.gnu.org/licenses/ uint8_t ledpin(const int8_t led) { return led<14? led: led+(54-14); } uint8_t setOutput(uint8_t led) { pinMode(ledpin(led), OUTPUT); return 0; } template <uint8_t led, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4, uint32_t d5, uint32_t d6, uint32_t d7, uint32_t d8> void light_my_fire() { static uint32_t phase = setOutput(led); phase = phase < d1+d2+d3+d4+d5+d6+d7+d8-1? phase+1: 0; digitalWrite(ledpin(led), phase < d1 ? HIGH: phase < d1+d2 ? LOW: phase < d1+d2+d3 ? HIGH: phase < d1+d2+d3+d4 ? LOW: phase < d1+d2+d3+d4+d5 ? HIGH: phase < d1+d2+d3+d4+d5+d6 ? LOW: phase < d1+d2+d3+d4+d5+d6+d7? HIGH: LOW); } extern "C" { // sysTicks will be triggered once per 1 ms int sysTickHook(void) { blink(); return 0; } } void blink() { light_my_fire<0, 200, 2800, 200, 2800, 200, 5800, 0, 0>(); // Norderney light_my_fire<1, 3000, 3000, 3000, 3000, 0, 8500, 0, 0>(); // Pilsum light_my_fire<2, 700, 2300, 700, 2300, 700, 2300, 700, 5300>(); // Campen light_my_fire<3, 6000, 6000, 0, 0, 0, 0, 0, 0>(); // Schillig light_my_fire<4, 6000, 3000, 0, 0, 0, 0, 0, 0>(); // Voslap light_my_fire<5, 6000, 1000, 0, 0, 0, 0, 0, 0>(); // Tossens light_my_fire<6, 1000, 1000, 0, 0, 0, 0, 0, 0>(); // test1 light_my_fire<7, 500, 500, 0, 0, 0, 0, 0, 0>(); // test2 } void setup() {} void loop() {}
Thank you very much for sharing your code. I’m looking to implement something very similar, but get the following error when compiling your example. Any ideas what might be going wrong here?
Lighthouse:48: error: previous declaration of ‘int sysTickHook()’ with ‘C++’ linkage
int sysTickHook(void) {
^
Lighthouse:48: error: conflicts with new declaration with ‘C’ linkage
int sysTickHook(void) {
^
exit status 1
previous declaration of ‘int sysTickHook()’ with ‘C++’ linkage
Thanks in advance!
Do you compile my code or do you compile a modified version of my code?
Which gcc compiler version are you using? (Compile in verbose mode, find the path to the compiler your Arduino IDE uses and execute “gcc -v” from a terminal window).
Thanks for getting back so quickly. The code is unchanged from yours. I’m inculding some links to the input / output in the hope that this helps clear things up!
Input (code same as yours): https://www.dropbox.com/s/7lvc3rrxr0puyvs/Lighthouse.ino?dl=0
Complete output during compile: https://www.dropbox.com/s/dpiufc3ss8rpkl1/lighthouse-compile.txt?dl=0
GCC version output: https://www.dropbox.com/s/d5ddrsiyub7v4ld/gcc-version.txt?dl=0
Thanks again!