Implement an initial Motion ISR for AVR

This is a tentative/crude implementation of an Init and ISR for the MMU
in order to check the motion API.

We remove the "extern void Isr", declaring it "static inline" instead.
We need to inline the ISR here in order to avoid the function call.

Include the missing speed_table data in the executable. This bumps the
code size to ~60% of the flash.

Implemement motion::Init to setup the ISR and timers, and replace the
call in main from tmc::Init to motion::Init. Motion will init each
driver every time the axis is enabled, so there should be no need for
a global module initialization (we need SPI, but this is initialized
earlier on by it's own module anyway).

The timer is currently setup without any HAL or proper TIMER1 wrapper.
This is to be improved later.

The real MMU unit seems to slow down quite a bit during acceleration.
At this point we need to inline some methods in PulseGen to avoid
overhead, however this breaks the stubs.
pull/100/head
Yuri D'Elia 2021-08-16 13:28:37 +02:00 committed by DRracer
parent 1b0a67826a
commit c7f3fae266
4 changed files with 57 additions and 4 deletions

View File

@ -19,6 +19,7 @@
#include "modules/selector.h"
#include "modules/user_input.h"
#include "modules/timebase.h"
#include "modules/motion.h"
#include "logic/command_base.h"
#include "logic/cut_filament.h"
@ -126,7 +127,7 @@ void setup() {
ml::leds.SetMode(2, ml::Color::green, ml::Mode::on);
ml::leds.Step();
// tmc::Init()
mm::Init();
ml::leds.SetMode(1, ml::Color::green, ml::Mode::on);
ml::leds.Step();

View File

@ -12,6 +12,7 @@ target_sources(
movable_base.cpp
permanent_storage.cpp
selector.cpp
speed_table.cpp
timebase.cpp
user_input.cpp
pulse_gen.cpp

View File

@ -1,5 +1,12 @@
#include "motion.h"
// TODO: use proper timer abstraction
#ifdef __AVR__
#include <avr/interrupt.h>
#else
//#include "../hal/timers.h"
#endif
namespace modules {
namespace motion {
@ -89,7 +96,51 @@ st_timer_t Motion::Step() {
return next;
}
void Isr() {}
static inline void Isr() {
st_timer_t next = motion.Step();
#ifdef __AVR__
// TODO: use proper timer abstraction
if (next)
OCR1A = next;
else {
// Idling: plan the next interrupt after 8ms from now.
OCR1A = 0x4000;
}
#endif
}
void Init() {
#ifdef __AVR__
// TODO: use proper timer abstraction
// waveform generation = 0100 = CTC
TCCR1B &= ~(1 << WGM13);
TCCR1B |= (1 << WGM12);
TCCR1A &= ~(1 << WGM11);
TCCR1A &= ~(1 << WGM10);
// output mode = 00 (disconnected)
TCCR1A &= ~(3 << COM1A0);
TCCR1A &= ~(3 << COM1B0);
// Set the timer pre-scaler
// We use divider of 8, resulting in a 2MHz timer frequency on a 16MHz MCU
TCCR1B = (TCCR1B & ~(0x07 << CS10)) | (2 << CS10);
// Plan the first interrupt after 8ms from now.
OCR1A = 0x4000;
TCNT1 = 0;
// Enable interrupt
TIMSK1 |= (1 << OCIE1A);
#endif
}
} // namespace motion
} // namespace modules
#ifdef __AVR__
ISR(TIMER1_COMPA_vect) {
modules::motion::Isr();
}
#endif

View File

@ -250,8 +250,8 @@ private:
};
};
/// ISR stepping routine
//extern void Isr();
/// ISR initialization
extern void Init();
extern Motion motion;