Files
FanDevice/fandevicefw/main.cpp
2024-06-11 16:08:53 +02:00

174 lines
2.9 KiB
C++

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <stdbool.h>
#include <avr/cpufunc.h>
#include <avr/eeprom.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
extern "C" {
#include "usbdrv.h"
}
enum {
COMMAND_HEARTBEAT = 1,
COMMAND_SET_FAN = 2,
};
volatile uint32_t second;
volatile uint32_t lastSeenSec;
ISR(RTC_PIT_vect)
{
RTC_PITINTFLAGS = RTC_PI_bm;
PORTC_OUTTGL = PIN3_bm;
++second;
}
constexpr uint8_t FAN_A_PIN = PIN6_bm;
constexpr uint8_t FAN_B_PIN = PIN4_bm;
constexpr uint8_t FAN_C_PIN = PIN7_bm;
constexpr uint8_t FAN_D_PIN = PIN5_bm;
constexpr uint8_t fanNumToPin(uint8_t num)
{
switch(num)
{
case 0:
return FAN_A_PIN;
case 1:
return FAN_B_PIN;
case 2:
return FAN_C_PIN;
case 3:
return FAN_D_PIN;
}
return FAN_A_PIN;
};
volatile bool irq = true;
static uint8_t fanSpeeds[4] = {0x07, 0x07, 0x07, 0x07};
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (usbRequest_t *)data;
static uint8_t dataBuffer[8];
usbMsgLen_t ret = 0;
if(rq->bRequest == COMMAND_HEARTBEAT)
{
lastSeenSec = second;
ret = 0;
}
else if(rq->bRequest == COMMAND_SET_FAN)
{
lastSeenSec = second;
if(rq->wIndex.word > 3 || rq->wValue.word > 255)
{
dataBuffer[0] = 0xFF;
}
else
{
PORTC_OUTSET = PIN3_bm;
fanSpeeds[rq->wIndex.word] = rq->wValue.word>>4;
dataBuffer[0] = 0;
}
ret = 1;
}
usbMsgPtr = (short unsigned int)dataBuffer;
return ret;
}
static void setup_tca(void)
{
PORTB_DIR |= PIN0_bm | PIN1_bm;
TCA0_SINGLE_CMP0 = 1000;
TCA0_SINGLE_CTRLA = TCA_SINGLE_ENABLE_bm; //enable TCA with /1 clock scaler
TCA0_SINGLE_CTRLB = 1 | TCA_SINGLE_CMP0EN_bm; //output on WO0
}
static void setup_tcb(void)
{
TCB0_CTRLA = TCB_ENABLE_bm;
}
static void setup_pit(void)
{
while(RTC_PITSTATUS & RTC_CTRLBUSY_bm);
RTC_PITINTCTRL = RTC_PI_bm; // enable pit isr
while(RTC_PITSTATUS & RTC_CTRLBUSY_bm);
RTC_PITCTRLA = RTC_PERIOD_CYC32768_gc | RTC_PITEN_bm; // 256hz
RTC_CNT = 0;
}
void setup_clock(void)
{
CPU_CCP = CCP_IOREG_gc; //unlock MCLKCTRLB
CLKCTRL_MCLKCTRLB = 0; //disable main clock divider
_PROTECTED_WRITE(CLKCTRL_OSC20MCALIBA, 42);
}
int main(void)
{
PORTA_DIR |= fanNumToPin(0) | fanNumToPin(1) | fanNumToPin(2) | fanNumToPin(3);
PORTC_DIR |= PIN2_bm | PIN3_bm;
_delay_ms(100);
setup_clock();
setup_tca();
setup_pit();
setup_tcb();
usbInit();
usbDeviceDisconnect();
PORTC_OUTSET = PIN2_bm;
usbDeviceConnect();
sei();
uint8_t pwmTimer = 0;
while(true)
{
usbPoll();
if(second-lastSeenSec > 60)
{
for(uint8_t i = 0; i < 4; ++i)
fanSpeeds[i] = 0x07;
}
if(TCB0_CNT > 100)
{
if(++pwmTimer > 0x0F)
{
for(uint8_t i = 0; i < 4; ++i)
{
if(fanSpeeds[i] > 0)
PORTA_OUTSET = fanNumToPin(i);
}
pwmTimer = 0;
}
for(uint8_t i = 0; i < 4; ++i)
{
if(fanSpeeds[i] < pwmTimer)
PORTA_OUTCLR = fanNumToPin(i);
}
TCB0_CNT = 0;
}
}
}