#include "libs/Kernel.h"
#include "SlowTicker.h"
#include "libs/Hook.h"
+#include "modules/robot/Conveyor.h"
#include <mri.h>
+// This module uses a Timer to periodically call hooks
+// Modules register with a function ( callback ) and a frequency, and we then call that function at the given frequency.
+
SlowTicker* global_slow_ticker;
SlowTicker::SlowTicker(){
max_frequency = 0;
global_slow_ticker = this;
+
+ // Configure the actual timer
LPC_SC->PCONP |= (1 << 22); // Power Ticker ON
- LPC_TIM2->MR0 = 10000; // Initial dummy value for Match Register
+ LPC_TIM2->MR0 = 10000; // Initial dummy value for Match Register
LPC_TIM2->MCR = 3; // Match on MR0, reset on MR0
LPC_TIM2->TCR = 1; // Enable interrupt
NVIC_EnableIRQ(TIMER2_IRQn); // Enable interrupt handler
+ // ISP button
ispbtn.from_string("2.10")->as_input()->pull_up();
+ // TODO: What is this ??
flag_1s_flag = 0;
- flag_1s_count = SystemCoreClock;
+ flag_1s_count = SystemCoreClock>>2;
g4_ticks = 0;
g4_pause = false;
}
-void SlowTicker::on_module_loaded()
-{
+void SlowTicker::on_module_loaded(){
register_for_event(ON_IDLE);
+ register_for_event(ON_GCODE_RECEIVED);
register_for_event(ON_GCODE_EXECUTE);
}
+// Set the base frequency we use for all sub-frequencies
void SlowTicker::set_frequency( int frequency ){
this->interval = (SystemCoreClock >> 2) / frequency; // SystemCoreClock/4 = Timer increments in a second
LPC_TIM2->MR0 = this->interval;
LPC_TIM2->TCR = 3; // Reset
LPC_TIM2->TCR = 1; // Reset
+ flag_1s_count= SystemCoreClock>>2;
}
-void SlowTicker::tick()
-{
- _isr_context = true;
-
- LPC_GPIO1->FIODIR |= 1<<20;
- LPC_GPIO1->FIOSET = 1<<20;
+// The actual interrupt being called by the timer, this is where work is done
+void SlowTicker::tick(){
+ // Call all hooks that need to be called ( bresenham )
for (uint32_t i=0; i<this->hooks.size(); i++){
Hook* hook = this->hooks.at(i);
hook->countdown -= this->interval;
}
}
+ // deduct tick time from secound counter
flag_1s_count -= this->interval;
+ // if a whole second has elapsed,
if (flag_1s_count < 0)
{
+ // add a second to our counter
flag_1s_count += SystemCoreClock >> 2;
+ // and set a flag for idle event to pick up
flag_1s_flag++;
}
+ // if we're counting down a pause
if (g4_ticks > 0)
{
+ // deduct tick time from timeout
if (g4_ticks > interval)
g4_ticks -= interval;
else
g4_ticks = 0;
}
- LPC_GPIO1->FIOCLR = 1<<20;
-
+ // Enter MRI mode if the ISP button is pressed
+ // TODO: This should have it's own module
if (ispbtn.get() == 0)
__debugbreak();
- _isr_context = false;
}
bool SlowTicker::flag_1s(){
+ // atomic flag check routine
+ // first disable interrupts
__disable_irq();
+ // then check for a flag
if (flag_1s_flag)
{
+ // if we have a flag, decrement the counter
flag_1s_flag--;
+ // re-enable interrupts
__enable_irq();
+ // and tell caller that we consumed a flag
return true;
}
+ // if no flag, re-enable interrupts and return false
__enable_irq();
return false;
}
+#include "gpio.h"
+extern GPIO leds[];
void SlowTicker::on_idle(void*)
{
+ static uint16_t ledcnt= 0;
+ if(THEKERNEL->use_leds) {
+ // flash led 3 to show we are alive
+ leds[2]= (ledcnt++ & 0x1000) ? 1 : 0;
+ }
+
+ // if interrupt has set the 1 second flag
if (flag_1s())
- kernel->call_event(ON_SECOND_TICK);
+ // fire the on_second_tick event
+ THEKERNEL->call_event(ON_SECOND_TICK);
// if G4 has finished, release our pause
if (g4_pause && (g4_ticks == 0))
{
g4_pause = false;
- kernel->pauser->release();
+ THEKERNEL->pauser->release();
}
}
-void SlowTicker::on_gcode_execute(void* argument)
-{
+// When a G4-type gcode is received, add it to the queue so we can execute it in time
+void SlowTicker::on_gcode_received(void* argument){
Gcode* gcode = static_cast<Gcode*>(argument);
+ // Add the gcode to the queue ourselves if we need it
+ if( gcode->has_g && gcode->g == 4 ){
+ THEKERNEL->conveyor->append_gcode(gcode);
+ }
+}
- if (gcode->has_g)
- {
- if (gcode->g == 4)
- {
- if (gcode->has_letter('P'))
- {
- // G4 Pnn should pause for nn milliseconds
+// When a G4-type gcode is executed, start the pause
+void SlowTicker::on_gcode_execute(void* argument){
+ Gcode* gcode = static_cast<Gcode*>(argument);
+
+ if (gcode->has_g){
+ if (gcode->g == 4){
+ gcode->mark_as_taken();
+ bool updated = false;
+ if (gcode->has_letter('P')) {
+ updated = true;
+ g4_ticks += gcode->get_int('P') * ((SystemCoreClock >> 2) / 1000UL);
+ }
+ if (gcode->has_letter('S')) {
+ updated = true;
+ g4_ticks += gcode->get_int('S') * (SystemCoreClock >> 2);
+ }
+ if (updated){
+ // G4 Smm Pnn should pause for mm seconds + nn milliseconds
// at 120MHz core clock, the longest possible delay is (2^32 / (120MHz / 4)) = 143 seconds
- if (g4_pause)
- {
- g4_ticks += gcode->get_int('P') * ((SystemCoreClock >> 2) / 1000UL);
- }
- else
- {
- g4_ticks = gcode->get_int('P') * ((SystemCoreClock >> 2) / 1000UL);
+ if (!g4_pause){
g4_pause = true;
- kernel->pauser->take();
+ THEKERNEL->pauser->take();
}
}
}