Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Committer:
Bigcheese
Date:
Sun Mar 02 06:33:08 2014 +0000
Revision:
3:f151d08d335c
Parent:
2:1df0b61d3b5a
Bunch of stuff. Need to locally merge in updated USB changes.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Michael J. Spencer 2:1df0b61d3b5a 1 /*
scachat 0:31e91bb0ef3c 2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
scachat 0:31e91bb0ef3c 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.
scachat 0:31e91bb0ef3c 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.
Michael J. Spencer 2:1df0b61d3b5a 5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
scachat 0:31e91bb0ef3c 6 */
scachat 0:31e91bb0ef3c 7
scachat 0:31e91bb0ef3c 8 using namespace std;
scachat 0:31e91bb0ef3c 9 #include <vector>
scachat 0:31e91bb0ef3c 10 #include "libs/nuts_bolts.h"
scachat 0:31e91bb0ef3c 11 #include "libs/Module.h"
scachat 0:31e91bb0ef3c 12 #include "libs/Kernel.h"
scachat 0:31e91bb0ef3c 13 #include "SlowTicker.h"
scachat 0:31e91bb0ef3c 14 #include "libs/Hook.h"
Michael J. Spencer 2:1df0b61d3b5a 15 #include "modules/robot/Conveyor.h"
scachat 0:31e91bb0ef3c 16
Michael J. Spencer 2:1df0b61d3b5a 17 // This module uses a Timer to periodically call hooks
Michael J. Spencer 2:1df0b61d3b5a 18 // Modules register with a function ( callback ) and a frequency, and we then call that function at the given frequency.
scachat 0:31e91bb0ef3c 19
scachat 0:31e91bb0ef3c 20 SlowTicker* global_slow_ticker;
scachat 0:31e91bb0ef3c 21
scachat 0:31e91bb0ef3c 22 SlowTicker::SlowTicker(){
Michael J. Spencer 2:1df0b61d3b5a 23 max_frequency = 0;
scachat 0:31e91bb0ef3c 24 global_slow_ticker = this;
Michael J. Spencer 2:1df0b61d3b5a 25
Michael J. Spencer 2:1df0b61d3b5a 26 // TODO: What is this ??
Michael J. Spencer 2:1df0b61d3b5a 27 flag_1s_flag = 0;
Michael J. Spencer 2:1df0b61d3b5a 28 flag_1s_count = SystemCoreClock>>2;
Michael J. Spencer 2:1df0b61d3b5a 29
Michael J. Spencer 2:1df0b61d3b5a 30 g4_ticks = 0;
Michael J. Spencer 2:1df0b61d3b5a 31 g4_pause = false;
Michael J. Spencer 2:1df0b61d3b5a 32 }
Michael J. Spencer 2:1df0b61d3b5a 33
Michael J. Spencer 2:1df0b61d3b5a 34 void SlowTicker::on_module_loaded(){
Michael J. Spencer 2:1df0b61d3b5a 35 register_for_event(ON_IDLE);
Michael J. Spencer 2:1df0b61d3b5a 36 register_for_event(ON_GCODE_RECEIVED);
Michael J. Spencer 2:1df0b61d3b5a 37 register_for_event(ON_GCODE_EXECUTE);
Michael J. Spencer 2:1df0b61d3b5a 38 }
Michael J. Spencer 2:1df0b61d3b5a 39
Michael J. Spencer 2:1df0b61d3b5a 40 // Set the base frequency we use for all sub-frequencies
Michael J. Spencer 2:1df0b61d3b5a 41 void SlowTicker::set_frequency( int frequency ){
Michael J. Spencer 2:1df0b61d3b5a 42 this->interval = (SystemCoreClock >> 2) / frequency; // SystemCoreClock/4 = Timer increments in a second
Michael J. Spencer 2:1df0b61d3b5a 43 flag_1s_count= SystemCoreClock>>2;
scachat 0:31e91bb0ef3c 44 }
scachat 0:31e91bb0ef3c 45
Michael J. Spencer 2:1df0b61d3b5a 46 // The actual interrupt being called by the timer, this is where work is done
Michael J. Spencer 2:1df0b61d3b5a 47 void SlowTicker::tick(){
Michael J. Spencer 2:1df0b61d3b5a 48
Michael J. Spencer 2:1df0b61d3b5a 49 // Call all hooks that need to be called ( bresenham )
Michael J. Spencer 2:1df0b61d3b5a 50 for (uint32_t i=0; i<this->hooks.size(); i++){
Michael J. Spencer 2:1df0b61d3b5a 51 Hook* hook = this->hooks.at(i);
Michael J. Spencer 2:1df0b61d3b5a 52 hook->countdown -= this->interval;
Michael J. Spencer 2:1df0b61d3b5a 53 if (hook->countdown < 0)
Michael J. Spencer 2:1df0b61d3b5a 54 {
Michael J. Spencer 2:1df0b61d3b5a 55 hook->countdown += hook->interval;
Michael J. Spencer 2:1df0b61d3b5a 56 hook->call();
Michael J. Spencer 2:1df0b61d3b5a 57 }
Michael J. Spencer 2:1df0b61d3b5a 58 }
Michael J. Spencer 2:1df0b61d3b5a 59
Michael J. Spencer 2:1df0b61d3b5a 60 // deduct tick time from secound counter
Michael J. Spencer 2:1df0b61d3b5a 61 flag_1s_count -= this->interval;
Michael J. Spencer 2:1df0b61d3b5a 62 // if a whole second has elapsed,
Michael J. Spencer 2:1df0b61d3b5a 63 if (flag_1s_count < 0)
Michael J. Spencer 2:1df0b61d3b5a 64 {
Michael J. Spencer 2:1df0b61d3b5a 65 // add a second to our counter
Michael J. Spencer 2:1df0b61d3b5a 66 flag_1s_count += SystemCoreClock >> 2;
Michael J. Spencer 2:1df0b61d3b5a 67 // and set a flag for idle event to pick up
Michael J. Spencer 2:1df0b61d3b5a 68 flag_1s_flag++;
Michael J. Spencer 2:1df0b61d3b5a 69 }
Michael J. Spencer 2:1df0b61d3b5a 70
Michael J. Spencer 2:1df0b61d3b5a 71 // if we're counting down a pause
Michael J. Spencer 2:1df0b61d3b5a 72 if (g4_ticks > 0)
Michael J. Spencer 2:1df0b61d3b5a 73 {
Michael J. Spencer 2:1df0b61d3b5a 74 // deduct tick time from timeout
Michael J. Spencer 2:1df0b61d3b5a 75 if (g4_ticks > interval)
Michael J. Spencer 2:1df0b61d3b5a 76 g4_ticks -= interval;
Michael J. Spencer 2:1df0b61d3b5a 77 else
Michael J. Spencer 2:1df0b61d3b5a 78 g4_ticks = 0;
Michael J. Spencer 2:1df0b61d3b5a 79 }
scachat 0:31e91bb0ef3c 80 }
scachat 0:31e91bb0ef3c 81
Michael J. Spencer 2:1df0b61d3b5a 82 bool SlowTicker::flag_1s(){
Michael J. Spencer 2:1df0b61d3b5a 83 // atomic flag check routine
Michael J. Spencer 2:1df0b61d3b5a 84 // first disable interrupts
Michael J. Spencer 2:1df0b61d3b5a 85 __disable_irq();
Michael J. Spencer 2:1df0b61d3b5a 86 // then check for a flag
Michael J. Spencer 2:1df0b61d3b5a 87 if (flag_1s_flag)
Michael J. Spencer 2:1df0b61d3b5a 88 {
Michael J. Spencer 2:1df0b61d3b5a 89 // if we have a flag, decrement the counter
Michael J. Spencer 2:1df0b61d3b5a 90 flag_1s_flag--;
Michael J. Spencer 2:1df0b61d3b5a 91 // re-enable interrupts
Michael J. Spencer 2:1df0b61d3b5a 92 __enable_irq();
Michael J. Spencer 2:1df0b61d3b5a 93 // and tell caller that we consumed a flag
Michael J. Spencer 2:1df0b61d3b5a 94 return true;
Michael J. Spencer 2:1df0b61d3b5a 95 }
Michael J. Spencer 2:1df0b61d3b5a 96 // if no flag, re-enable interrupts and return false
Michael J. Spencer 2:1df0b61d3b5a 97 __enable_irq();
Michael J. Spencer 2:1df0b61d3b5a 98 return false;
Michael J. Spencer 2:1df0b61d3b5a 99 }
Michael J. Spencer 2:1df0b61d3b5a 100
Michael J. Spencer 2:1df0b61d3b5a 101 #include "gpio.h"
Michael J. Spencer 2:1df0b61d3b5a 102 extern GPIO leds[];
Michael J. Spencer 2:1df0b61d3b5a 103 void SlowTicker::on_idle(void*)
Michael J. Spencer 2:1df0b61d3b5a 104 {
Michael J. Spencer 2:1df0b61d3b5a 105 static uint16_t ledcnt= 0;
Michael J. Spencer 2:1df0b61d3b5a 106 if(THEKERNEL->use_leds) {
Michael J. Spencer 2:1df0b61d3b5a 107 // flash led 3 to show we are alive
Michael J. Spencer 2:1df0b61d3b5a 108 leds[2]= (ledcnt++ & 0x1000) ? 1 : 0;
Michael J. Spencer 2:1df0b61d3b5a 109 }
Michael J. Spencer 2:1df0b61d3b5a 110
Michael J. Spencer 2:1df0b61d3b5a 111 // if interrupt has set the 1 second flag
Michael J. Spencer 2:1df0b61d3b5a 112 if (flag_1s())
Michael J. Spencer 2:1df0b61d3b5a 113 // fire the on_second_tick event
Michael J. Spencer 2:1df0b61d3b5a 114 THEKERNEL->call_event(ON_SECOND_TICK);
Michael J. Spencer 2:1df0b61d3b5a 115
Michael J. Spencer 2:1df0b61d3b5a 116 // if G4 has finished, release our pause
Michael J. Spencer 2:1df0b61d3b5a 117 if (g4_pause && (g4_ticks == 0))
Michael J. Spencer 2:1df0b61d3b5a 118 {
Michael J. Spencer 2:1df0b61d3b5a 119 g4_pause = false;
Michael J. Spencer 2:1df0b61d3b5a 120 THEKERNEL->pauser->release();
Michael J. Spencer 2:1df0b61d3b5a 121 }
Michael J. Spencer 2:1df0b61d3b5a 122 }
Michael J. Spencer 2:1df0b61d3b5a 123
Michael J. Spencer 2:1df0b61d3b5a 124 // When a G4-type gcode is received, add it to the queue so we can execute it in time
Michael J. Spencer 2:1df0b61d3b5a 125 void SlowTicker::on_gcode_received(void* argument){
Michael J. Spencer 2:1df0b61d3b5a 126 Gcode* gcode = static_cast<Gcode*>(argument);
Michael J. Spencer 2:1df0b61d3b5a 127 // Add the gcode to the queue ourselves if we need it
Michael J. Spencer 2:1df0b61d3b5a 128 if( gcode->has_g && gcode->g == 4 ){
Michael J. Spencer 2:1df0b61d3b5a 129 THEKERNEL->conveyor->append_gcode(gcode);
Michael J. Spencer 2:1df0b61d3b5a 130 // ensure that no subsequent gcodes get executed along with our G4
Michael J. Spencer 2:1df0b61d3b5a 131 THEKERNEL->conveyor->queue_head_block();
Michael J. Spencer 2:1df0b61d3b5a 132 }
Michael J. Spencer 2:1df0b61d3b5a 133 }
Michael J. Spencer 2:1df0b61d3b5a 134
Michael J. Spencer 2:1df0b61d3b5a 135 // When a G4-type gcode is executed, start the pause
Michael J. Spencer 2:1df0b61d3b5a 136 void SlowTicker::on_gcode_execute(void* argument){
Michael J. Spencer 2:1df0b61d3b5a 137 Gcode* gcode = static_cast<Gcode*>(argument);
Michael J. Spencer 2:1df0b61d3b5a 138
Michael J. Spencer 2:1df0b61d3b5a 139 if (gcode->has_g){
Michael J. Spencer 2:1df0b61d3b5a 140 if (gcode->g == 4){
Michael J. Spencer 2:1df0b61d3b5a 141 gcode->mark_as_taken();
Michael J. Spencer 2:1df0b61d3b5a 142 bool updated = false;
Michael J. Spencer 2:1df0b61d3b5a 143 if (gcode->has_letter('P')) {
Michael J. Spencer 2:1df0b61d3b5a 144 updated = true;
Michael J. Spencer 2:1df0b61d3b5a 145 g4_ticks += gcode->get_int('P') * ((SystemCoreClock >> 2) / 1000UL);
Michael J. Spencer 2:1df0b61d3b5a 146 }
Michael J. Spencer 2:1df0b61d3b5a 147 if (gcode->has_letter('S')) {
Michael J. Spencer 2:1df0b61d3b5a 148 updated = true;
Michael J. Spencer 2:1df0b61d3b5a 149 g4_ticks += gcode->get_int('S') * (SystemCoreClock >> 2);
Michael J. Spencer 2:1df0b61d3b5a 150 }
Michael J. Spencer 2:1df0b61d3b5a 151 if (updated){
Michael J. Spencer 2:1df0b61d3b5a 152 // G4 Smm Pnn should pause for mm seconds + nn milliseconds
Michael J. Spencer 2:1df0b61d3b5a 153 // at 120MHz core clock, the longest possible delay is (2^32 / (120MHz / 4)) = 143 seconds
Michael J. Spencer 2:1df0b61d3b5a 154 if (!g4_pause){
Michael J. Spencer 2:1df0b61d3b5a 155 g4_pause = true;
Michael J. Spencer 2:1df0b61d3b5a 156 THEKERNEL->pauser->take();
Michael J. Spencer 2:1df0b61d3b5a 157 }
Michael J. Spencer 2:1df0b61d3b5a 158 }
Michael J. Spencer 2:1df0b61d3b5a 159 }
scachat 0:31e91bb0ef3c 160 }
scachat 0:31e91bb0ef3c 161 }
scachat 0:31e91bb0ef3c 162
scachat 0:31e91bb0ef3c 163 extern "C" void TIMER2_IRQHandler (void){
Michael J. Spencer 2:1df0b61d3b5a 164 global_slow_ticker->tick();
scachat 0:31e91bb0ef3c 165 }