Merge pull request #139 from logxen/edge
[clinton/Smoothieware.git] / src / libs / SlowTicker.cpp
CommitLineData
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
8using namespace std;
9#include <vector>
ded56b35
AW
10#include "libs/nuts_bolts.h"
11#include "libs/Module.h"
12#include "libs/Kernel.h"
13#include "SlowTicker.h"
d9ebc974 14#include "libs/Hook.h"
ded56b35 15
65fe0408 16#include <mri.h>
ded56b35
AW
17
18SlowTicker* global_slow_ticker;
19
20SlowTicker::SlowTicker(){
1fcb3a2a 21 max_frequency = 0;
ded56b35 22 global_slow_ticker = this;
7dd8133c 23 LPC_SC->PCONP |= (1 << 22); // Power Ticker ON
d9ebc974 24 LPC_TIM2->MR0 = 10000; // Initial dummy value for Match Register
7dd8133c
AW
25 LPC_TIM2->MCR = 3; // Match on MR0, reset on MR0
26 LPC_TIM2->TCR = 1; // Enable interrupt
27 NVIC_EnableIRQ(TIMER2_IRQn); // Enable interrupt handler
65fe0408
MM
28
29 ispbtn.from_string("2.10")->as_input()->pull_up();
ab2a4410
MM
30
31 flag_1s_flag = 0;
32 flag_1s_count = SystemCoreClock;
1fcb3a2a
MM
33
34 g4_ticks = 0;
35 g4_pause = false;
ded56b35
AW
36}
37
4df07f88
MM
38void SlowTicker::on_module_loaded()
39{
40 register_for_event(ON_IDLE);
1fcb3a2a 41 register_for_event(ON_GCODE_EXECUTE);
4df07f88
MM
42}
43
ded56b35 44void SlowTicker::set_frequency( int frequency ){
1fcb3a2a 45 this->interval = (SystemCoreClock >> 2) / frequency; // SystemCoreClock/4 = Timer increments in a second
50b9ac30 46 LPC_TIM2->MR0 = this->interval;
7dd8133c
AW
47 LPC_TIM2->TCR = 3; // Reset
48 LPC_TIM2->TCR = 1; // Reset
ded56b35
AW
49}
50
ab2a4410
MM
51void SlowTicker::tick()
52{
4df07f88
MM
53 _isr_context = true;
54
2f7d3dba
AW
55 LPC_GPIO1->FIODIR |= 1<<20;
56 LPC_GPIO1->FIOSET = 1<<20;
57
1fcb3a2a 58 for (uint32_t i=0; i<this->hooks.size(); i++){
d9ebc974 59 Hook* hook = this->hooks.at(i);
50b9ac30
MM
60 hook->countdown -= this->interval;
61 if (hook->countdown < 0)
62 {
63 hook->countdown += hook->interval;
d9ebc974 64 hook->call();
df27a6a3 65 }
ded56b35 66 }
2f7d3dba 67
ab2a4410
MM
68 flag_1s_count -= this->interval;
69 if (flag_1s_count < 0)
70 {
71 flag_1s_count += SystemCoreClock >> 2;
72 flag_1s_flag++;
73 }
74
1fcb3a2a
MM
75 if (g4_ticks > 0)
76 {
77 if (g4_ticks > interval)
78 g4_ticks -= interval;
79 else
80 g4_ticks = 0;
81 }
82
2f7d3dba
AW
83 LPC_GPIO1->FIOCLR = 1<<20;
84
65fe0408
MM
85 if (ispbtn.get() == 0)
86 __debugbreak();
4df07f88
MM
87
88 _isr_context = false;
ded56b35
AW
89}
90
ab2a4410
MM
91bool SlowTicker::flag_1s(){
92 __disable_irq();
93 if (flag_1s_flag)
94 {
95 flag_1s_flag--;
96 __enable_irq();
97 return true;
98 }
99 __enable_irq();
100 return false;
101}
102
4df07f88
MM
103void SlowTicker::on_idle(void*)
104{
105 if (flag_1s())
106 kernel->call_event(ON_SECOND_TICK);
1fcb3a2a
MM
107
108 // if G4 has finished, release our pause
109 if (g4_pause && (g4_ticks == 0))
110 {
111 g4_pause = false;
112 kernel->pauser->release();
113 }
114}
115
116void SlowTicker::on_gcode_execute(void* argument)
117{
118 Gcode* gcode = static_cast<Gcode*>(argument);
119
120 if (gcode->has_g)
121 {
122 if (gcode->g == 4)
123 {
124 if (gcode->has_letter('P'))
125 {
126 // G4 Pnn should pause for nn milliseconds
127 // at 120MHz core clock, the longest possible delay is (2^32 / (120MHz / 4)) = 143 seconds
128 if (g4_pause)
129 {
130 g4_ticks += gcode->get_int('P') * ((SystemCoreClock >> 2) / 1000UL);
131 }
132 else
133 {
134 g4_ticks = gcode->get_int('P') * ((SystemCoreClock >> 2) / 1000UL);
135 g4_pause = true;
136 kernel->pauser->take();
137 }
138 }
139 }
140 }
4df07f88
MM
141}
142
ded56b35 143extern "C" void TIMER2_IRQHandler (void){
7dd8133c 144 if((LPC_TIM2->IR >> 0) & 1){ // If interrupt register set for MR0
df27a6a3 145 LPC_TIM2->IR |= 1 << 0; // Reset it
ded56b35 146 }
df27a6a3 147 global_slow_ticker->tick();
ded56b35
AW
148}
149