Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Smoothie by
SlowTicker.cpp
00001 /* 00002 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). 00003 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. 00004 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. 00005 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 00006 */ 00007 00008 using namespace std; 00009 #include <vector> 00010 #include "libs/nuts_bolts.h" 00011 #include "libs/Module.h" 00012 #include "libs/Kernel.h" 00013 #include "SlowTicker.h" 00014 #include "libs/Hook.h" 00015 #include "modules/robot/Conveyor.h" 00016 00017 // This module uses a Timer to periodically call hooks 00018 // Modules register with a function ( callback ) and a frequency, and we then call that function at the given frequency. 00019 00020 SlowTicker* global_slow_ticker; 00021 00022 SlowTicker::SlowTicker(){ 00023 max_frequency = 0; 00024 global_slow_ticker = this; 00025 00026 // TODO: What is this ?? 00027 flag_1s_flag = 0; 00028 flag_1s_count = SystemCoreClock>>2; 00029 00030 g4_ticks = 0; 00031 g4_pause = false; 00032 } 00033 00034 void SlowTicker::on_module_loaded(){ 00035 register_for_event(ON_IDLE); 00036 register_for_event(ON_GCODE_RECEIVED); 00037 register_for_event(ON_GCODE_EXECUTE); 00038 } 00039 00040 // Set the base frequency we use for all sub-frequencies 00041 void SlowTicker::set_frequency( int frequency ){ 00042 this->interval = (SystemCoreClock >> 2) / frequency; // SystemCoreClock/4 = Timer increments in a second 00043 flag_1s_count= SystemCoreClock>>2; 00044 } 00045 00046 // The actual interrupt being called by the timer, this is where work is done 00047 void SlowTicker::tick(){ 00048 00049 // Call all hooks that need to be called ( bresenham ) 00050 for (uint32_t i=0; i<this->hooks.size(); i++){ 00051 Hook* hook = this->hooks.at(i); 00052 hook->countdown -= this->interval; 00053 if (hook->countdown < 0) 00054 { 00055 hook->countdown += hook->interval; 00056 hook->call(); 00057 } 00058 } 00059 00060 // deduct tick time from secound counter 00061 flag_1s_count -= this->interval; 00062 // if a whole second has elapsed, 00063 if (flag_1s_count < 0) 00064 { 00065 // add a second to our counter 00066 flag_1s_count += SystemCoreClock >> 2; 00067 // and set a flag for idle event to pick up 00068 flag_1s_flag++; 00069 } 00070 00071 // if we're counting down a pause 00072 if (g4_ticks > 0) 00073 { 00074 // deduct tick time from timeout 00075 if (g4_ticks > interval) 00076 g4_ticks -= interval; 00077 else 00078 g4_ticks = 0; 00079 } 00080 } 00081 00082 bool SlowTicker::flag_1s(){ 00083 // atomic flag check routine 00084 // first disable interrupts 00085 __disable_irq(); 00086 // then check for a flag 00087 if (flag_1s_flag) 00088 { 00089 // if we have a flag, decrement the counter 00090 flag_1s_flag--; 00091 // re-enable interrupts 00092 __enable_irq(); 00093 // and tell caller that we consumed a flag 00094 return true; 00095 } 00096 // if no flag, re-enable interrupts and return false 00097 __enable_irq(); 00098 return false; 00099 } 00100 00101 #include "gpio.h" 00102 extern GPIO leds[]; 00103 void SlowTicker::on_idle(void*) 00104 { 00105 static uint16_t ledcnt= 0; 00106 if(THEKERNEL->use_leds) { 00107 // flash led 3 to show we are alive 00108 leds[2]= (ledcnt++ & 0x1000) ? 1 : 0; 00109 } 00110 00111 // if interrupt has set the 1 second flag 00112 if (flag_1s()) 00113 // fire the on_second_tick event 00114 THEKERNEL->call_event(ON_SECOND_TICK); 00115 00116 // if G4 has finished, release our pause 00117 if (g4_pause && (g4_ticks == 0)) 00118 { 00119 g4_pause = false; 00120 THEKERNEL->pauser->release(); 00121 } 00122 } 00123 00124 // When a G4-type gcode is received, add it to the queue so we can execute it in time 00125 void SlowTicker::on_gcode_received(void* argument){ 00126 Gcode* gcode = static_cast<Gcode*>(argument); 00127 // Add the gcode to the queue ourselves if we need it 00128 if( gcode->has_g && gcode->g == 4 ){ 00129 THEKERNEL->conveyor->append_gcode(gcode); 00130 // ensure that no subsequent gcodes get executed along with our G4 00131 THEKERNEL->conveyor->queue_head_block(); 00132 } 00133 } 00134 00135 // When a G4-type gcode is executed, start the pause 00136 void SlowTicker::on_gcode_execute(void* argument){ 00137 Gcode* gcode = static_cast<Gcode*>(argument); 00138 00139 if (gcode->has_g){ 00140 if (gcode->g == 4){ 00141 gcode->mark_as_taken(); 00142 bool updated = false; 00143 if (gcode->has_letter('P')) { 00144 updated = true; 00145 g4_ticks += gcode->get_int('P') * ((SystemCoreClock >> 2) / 1000UL); 00146 } 00147 if (gcode->has_letter('S')) { 00148 updated = true; 00149 g4_ticks += gcode->get_int('S') * (SystemCoreClock >> 2); 00150 } 00151 if (updated){ 00152 // G4 Smm Pnn should pause for mm seconds + nn milliseconds 00153 // at 120MHz core clock, the longest possible delay is (2^32 / (120MHz / 4)) = 143 seconds 00154 if (!g4_pause){ 00155 g4_pause = true; 00156 THEKERNEL->pauser->take(); 00157 } 00158 } 00159 } 00160 } 00161 } 00162 00163 extern "C" void TIMER2_IRQHandler (void){ 00164 global_slow_ticker->tick(); 00165 }
Generated on Tue Jul 12 2022 20:09:02 by
1.7.2
