#pragma once

#include "hpgl.h"
#include "clock.h"

// PWM coordinate output settings (reoslution also determines the movement
// timer tick frequency)
#define OUTPUT_PWM_RESOLUTION   15  // In bits
#define OUTPUT_PWM_OFFSET       300 // Minimum value

// Resolution for coordinate values as parsed from HPGL
#define OUTPUT_RESOLUTION       14  // In bits
#define OUTPUT_COORDINATE_LIMIT ((1 << OUTPUT_RESOLUTION) - 1)

// Scale for length and velocity values to allow speeds slower than 1 axis
// resolution bit per tick. Adjust carefully as values too high can lead to
// overflows during coordinate calculations.
#define OUTPUT_LENGTH_SCALE     (1 << 3)

// Delay after initiating pen-up/-down before continuing movements
#define OUTPUT_PEN_UP_DELAY     200 // In movement timer ticks
#define OUTPUT_PEN_DOWN_DELAY   20  // In movement timer ticks

// PWM frequency for the pen state output
#define OUTPUT_PEN_FREQUENCY    120 // In Hertz

// Resulting timer settings for pen PWM output
#define OUTPUT_PEN_PRESCALER    (CLOCK_APB1 / OUTPUT_PEN_FREQUENCY / 65535 + 1)
#define OUTPUT_PEN_RELOAD       ((uint16_t)(CLOCK_APB1 / OUTPUT_PEN_FREQUENCY \
                                / OUTPUT_PEN_PRESCALER - 1))
#define OUTPUT_PEN_UP           0
#define OUTPUT_PEN_DOWN         (OUTPUT_PEN_RELOAD + 1)

// Start and stop duty cycles and duty cycle step (per movement timer tick) for
// gracefully lowering the pen
#define OUTPUT_PEN_START        ((unsigned int)(0.4 * OUTPUT_PEN_RELOAD))
#define OUTPUT_PEN_STOP         ((unsigned int)(0.43 * OUTPUT_PEN_RELOAD))
#define OUTPUT_PEN_STEP         ((unsigned int)(0.0001 * OUTPUT_PEN_RELOAD))

void Output_Init(void);
bool Output_EnqueueMovement(HPGL_Movement_t movement);
