Commit | Line | Data |
---|---|---|
df27a6a3 | 1 | /* |
cd011f58 AW |
2 | This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). |
3 | Smoothie 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. | |
4 | Smoothie 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. | |
df27a6a3 | 5 | You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. |
cd011f58 AW |
6 | */ |
7 | ||
ded56b35 AW |
8 | #include "libs/nuts_bolts.h" |
9 | #include "libs/Module.h" | |
10 | #include "libs/Kernel.h" | |
11 | #include "SlowTicker.h" | |
cb2e6bc6 | 12 | #include "StepTicker.h" |
d9ebc974 | 13 | #include "libs/Hook.h" |
3c4f2dd8 | 14 | #include "modules/robot/Conveyor.h" |
61134a65 | 15 | #include "Gcode.h" |
ded56b35 | 16 | |
65fe0408 | 17 | #include <mri.h> |
ded56b35 | 18 | |
93694d6b AW |
19 | // This module uses a Timer to periodically call hooks |
20 | // Modules register with a function ( callback ) and a frequency, and we then call that function at the given frequency. | |
21 | ||
ded56b35 AW |
22 | SlowTicker* global_slow_ticker; |
23 | ||
24 | SlowTicker::SlowTicker(){ | |
25 | global_slow_ticker = this; | |
93694d6b | 26 | |
62675f96 | 27 | // ISP button FIXME: WHy is this here? |
65fe0408 | 28 | ispbtn.from_string("2.10")->as_input()->pull_up(); |
ab2a4410 | 29 | |
62675f96 | 30 | LPC_SC->PCONP |= (1 << 22); // Power Ticker ON |
62675f96 | 31 | LPC_TIM2->MCR = 3; // Match on MR0, reset on MR0 |
b772a11c JM |
32 | // do not enable interrupt until setup is complete |
33 | LPC_TIM2->TCR = 0; // Disable interrupt | |
34 | ||
35 | max_frequency = 5; // initial max frequency is set to 5Hz | |
36 | set_frequency(max_frequency); | |
37 | flag_1s_flag = 0; | |
38 | } | |
39 | ||
40 | void SlowTicker::start() | |
41 | { | |
62675f96 JM |
42 | LPC_TIM2->TCR = 1; // Enable interrupt |
43 | NVIC_EnableIRQ(TIMER2_IRQn); // Enable interrupt handler | |
ded56b35 AW |
44 | } |
45 | ||
0854d371 | 46 | void SlowTicker::on_module_loaded(){ |
4df07f88 MM |
47 | register_for_event(ON_IDLE); |
48 | } | |
49 | ||
93694d6b | 50 | // Set the base frequency we use for all sub-frequencies |
ded56b35 | 51 | void SlowTicker::set_frequency( int frequency ){ |
1fcb3a2a | 52 | this->interval = (SystemCoreClock >> 2) / frequency; // SystemCoreClock/4 = Timer increments in a second |
50b9ac30 | 53 | LPC_TIM2->MR0 = this->interval; |
7dd8133c AW |
54 | LPC_TIM2->TCR = 3; // Reset |
55 | LPC_TIM2->TCR = 1; // Reset | |
574d9897 | 56 | flag_1s_count= SystemCoreClock>>2; |
ded56b35 AW |
57 | } |
58 | ||
93694d6b | 59 | // The actual interrupt being called by the timer, this is where work is done |
0854d371 | 60 | void SlowTicker::tick(){ |
eaeca34b | 61 | |
b9ad75de | 62 | // Call all hooks that need to be called |
ac971358 | 63 | for (Hook* hook : this->hooks){ |
50b9ac30 MM |
64 | hook->countdown -= this->interval; |
65 | if (hook->countdown < 0) | |
66 | { | |
67 | hook->countdown += hook->interval; | |
d9ebc974 | 68 | hook->call(); |
df27a6a3 | 69 | } |
ded56b35 | 70 | } |
2f7d3dba | 71 | |
b9ad75de | 72 | // deduct tick time from second counter |
ab2a4410 | 73 | flag_1s_count -= this->interval; |
eaeca34b | 74 | // if a whole second has elapsed, |
ab2a4410 MM |
75 | if (flag_1s_count < 0) |
76 | { | |
eaeca34b | 77 | // add a second to our counter |
ab2a4410 | 78 | flag_1s_count += SystemCoreClock >> 2; |
eaeca34b | 79 | // and set a flag for idle event to pick up |
ab2a4410 MM |
80 | flag_1s_flag++; |
81 | } | |
82 | ||
d337942a MM |
83 | // Enter MRI mode if the ISP button is pressed |
84 | // TODO: This should have it's own module | |
65fe0408 MM |
85 | if (ispbtn.get() == 0) |
86 | __debugbreak(); | |
4df07f88 | 87 | |
ded56b35 AW |
88 | } |
89 | ||
ab2a4410 | 90 | bool SlowTicker::flag_1s(){ |
eaeca34b MM |
91 | // atomic flag check routine |
92 | // first disable interrupts | |
ab2a4410 | 93 | __disable_irq(); |
eaeca34b | 94 | // then check for a flag |
ab2a4410 MM |
95 | if (flag_1s_flag) |
96 | { | |
eaeca34b | 97 | // if we have a flag, decrement the counter |
ab2a4410 | 98 | flag_1s_flag--; |
eaeca34b | 99 | // re-enable interrupts |
ab2a4410 | 100 | __enable_irq(); |
eaeca34b | 101 | // and tell caller that we consumed a flag |
ab2a4410 MM |
102 | return true; |
103 | } | |
eaeca34b | 104 | // if no flag, re-enable interrupts and return false |
ab2a4410 MM |
105 | __enable_irq(); |
106 | return false; | |
107 | } | |
108 | ||
82d1ceb3 JM |
109 | #include "gpio.h" |
110 | extern GPIO leds[]; | |
4df07f88 MM |
111 | void SlowTicker::on_idle(void*) |
112 | { | |
82d1ceb3 | 113 | static uint16_t ledcnt= 0; |
73706276 | 114 | if(THEKERNEL->is_using_leds()) { |
21320fc6 JM |
115 | // flash led 3 to show we are alive |
116 | leds[2]= (ledcnt++ & 0x1000) ? 1 : 0; | |
117 | } | |
82d1ceb3 | 118 | |
eaeca34b | 119 | // if interrupt has set the 1 second flag |
4df07f88 | 120 | if (flag_1s()) |
eaeca34b | 121 | // fire the on_second_tick event |
347854ff | 122 | THEKERNEL->call_event(ON_SECOND_TICK); |
4df07f88 MM |
123 | } |
124 | ||
ded56b35 | 125 | extern "C" void TIMER2_IRQHandler (void){ |
7dd8133c | 126 | if((LPC_TIM2->IR >> 0) & 1){ // If interrupt register set for MR0 |
df27a6a3 | 127 | LPC_TIM2->IR |= 1 << 0; // Reset it |
ded56b35 | 128 | } |
df27a6a3 | 129 | global_slow_ticker->tick(); |
ded56b35 AW |
130 | } |
131 |