First functioning version

This commit is contained in:
2022-01-21 12:30:33 +01:00
parent 0584796a67
commit cc9dd6eb19
4 changed files with 190 additions and 274 deletions

40
adc.cpp
View File

@ -1,40 +0,0 @@
#include "adc.h"
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(ADC_vect)
{
uint16_t sample = ADCL;
sample |= ADCH << 8;
if(Adc::sampleCallback_) Adc::sampleCallback_(sample, Adc::userData_);
}
Adc::Adc(void (*sampleCallback)(uint16_t sample, void* userData), void* userData, uint8_t input, uint8_t referance)
{
userData_ = userData;
sampleCallback_ = sampleCallback;
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
setInput(input);
setReferance(referance);
}
Adc::~Adc()
{
ADCSRA = 0;
}
void Adc::setInput(const uint8_t input)
{
ADMUX = (ADMUX & 0b11110000) | (input & 0b00001111);
}
void Adc::setReferance(const uint8_t input)
{
ADMUX = (ADMUX & 0b00101111) | ((input & 0b00000100) << 2) | ((input & 0b00000011) << 6);
}
void Adc::aquire()
{
ADCSRA |= 1 << ADSC;
}

28
adc.h
View File

@ -1,28 +0,0 @@
#pragma once
#include <stdint.h>
class Adc
{
public:
inline static void* userData_ = nullptr;
inline static void (*sampleCallback_)(uint16_t sample, void* userData) = nullptr;
static constexpr uint8_t VREF_VCC = 0b0000;
static constexpr uint8_t VREF_1_1 = 0b0010;
static constexpr uint8_t VREF_2_56 = 0b0110;
static constexpr uint8_t VREF_EXT = 0b0001;
static constexpr uint8_t IN_ADC0 = 0b0000;
static constexpr uint8_t IN_ADC1 = 0b0001;
static constexpr uint8_t IN_ADC2 = 0b0010;
static constexpr uint8_t IN_ADC3 = 0b0011;
static constexpr uint8_t IN_ADC4 = 0b1111;
Adc(void (*sampleCallback)(uint16_t sample, void* userData), void* userData = nullptr, uint8_t input = IN_ADC0, uint8_t referance = VREF_2_56);
~Adc();
void setInput(const uint8_t input);
void setReferance(const uint8_t referance);
void aquire();
};

172
main.cpp
View File

@ -3,122 +3,96 @@
#include <util/delay.h> #include <util/delay.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/sleep.h> #include <avr/sleep.h>
#include "adc.h"
#include "writepin.h" #include "writepin.h"
#include "ringbuffer.h" #include "decoder.h"
extern "C"
{
#include "usbdrv.h"
static constexpr uint8_t T0_A = PB0;
static constexpr uint8_t T0_B = PB1;
static constexpr uint8_t T1_A = PB3;
static constexpr uint8_t T1_B = PB4;
static volatile bool turnout0Flag = false;
static volatile bool turnout1Flag = false;
void handler(uint16_t data, void *user_data)
{
(void)user_data;
if(((bool)(data & (1 << 9))) != ((bool)(data & (1 << 8))) ||
((bool)(data & (1 << 7))) != ((bool)(data & (1 << 6))) ||
((bool)(data & (1 << 5))) != ((bool)(data & (1 << 4))))
return;
bool set = data & (1 << 9);
if(data & (1 << 7))
turnout0Flag = set;
if(data & (1 << 5))
turnout1Flag = set;
} }
volatile uint16_t sampleId = 0; static void setTurnout0(bool in)
void adcConversionCallback(uint16_t sample, void* userData);
Adc adc(&adcConversionCallback, nullptr, Adc::IN_ADC1, Adc::VREF_VCC);
RingBuffer<32, uint16_t> buffer;
ISR(TIMER0_OVF_vect)
{ {
adc.aquire(); writePin(&PORTB, T0_A, in);
writePin(&PORTB, T0_B, !in);
_delay_ms(50);
writePin(&PORTB, T0_A, false);
writePin(&PORTB, T0_B, false);
} }
static void setTurnout1(bool in)
extern "C" usbMsgLen_t usbFunctionSetup(uchar data[8])
{ {
usbRequest_t *rq = (usbRequest_t *)data; writePin(&PORTB, T1_A, in);
static uchar dataBuffer[8]; writePin(&PORTB, T1_B, !in);
_delay_ms(50);
if(rq->bRequest == 0)
{ writePin(&PORTB, T1_A, false);
if(!buffer.isEmpty() && !buffer.isEmpty() && rq->wLength.word >= 4 ) writePin(&PORTB, T1_B, false);
{
usbMsgLen_t length = buffer.remaining()+2;
if(length > 8) length = 8;
if(length > rq->wLength.word) length = rq->wLength.word;
dataBuffer[0] = sampleId-buffer.remaining() >> 8;
dataBuffer[1] = sampleId-buffer.remaining() & 0x00FF;
for(usbMsgLen_t i = 2; i+1 < length; i+=2)
{
uint16_t sample = buffer.read();
dataBuffer[i] = sample >> 8;
dataBuffer[i+1] = sample & 0x00FF;
}
usbMsgPtr = (short unsigned int)dataBuffer;
return length;
}
}
if(rq->bRequest == 1)
{
if(rq->wValue.word == 0) adc.setInput(Adc::IN_ADC1);
else adc.setInput(Adc::IN_ADC0);
buffer.flush();
return 0;
}
if(rq->bRequest == 2)
{
if(rq->wValue.word == 0) adc.setReferance(Adc::VREF_VCC);
else if(rq->wValue.word == 1) adc.setReferance(Adc::VREF_1_1);
else adc.setReferance(Adc::VREF_2_56);
buffer.flush();
return 0;
}
else if(rq->bRequest == 128)
{
dataBuffer[0] = 55;
dataBuffer[1] = 55;
dataBuffer[2] = 55;
dataBuffer[3] = 55;
usbMsgPtr = (short unsigned int)dataBuffer;
return 4;
}
else if(rq->bRequest == 129)
{
dataBuffer[0] = ADCSRA;
dataBuffer[1] = ADMUX;
usbMsgPtr = (short unsigned int)dataBuffer;
return 2;
}
if(rq->bRequest == 130)
{
constexpr uint16_t freq = 30518;
dataBuffer[0] = freq >> 8;
dataBuffer[1] = freq & 0x00FF;
usbMsgPtr = (short unsigned int)dataBuffer;
return 2;
}
return 0;
} }
void adcConversionCallback(uint16_t sample, void* userData) Decoder decoder(&PINB, PB2, &TCNT1, &handler);
ISR(TIMER1_OVF_vect)
{ {
buffer.write(sample); decoder.overflowInterrupt();
sampleId++;
} }
void timer0InterruptEnable(const bool enable) ISR(INT0_vect)
{ {
if(enable) TIMSK = TIMSK | (1 << TOIE0); decoder.interrupt();
else TIMSK = TIMSK & ~(1 << TOIE0);
} }
int main() int main()
{ {
DIDR0 |= (1 << PB2); DDRB = (1 << PB0) | (1 << PB1) | (1 << PB3) | (1 << PB4);
TCCR0B = (1<<CS02); // run timer0 with /256 scaler
timer0InterruptEnable(true); bool turnout0 = false;
usbInit(); bool turnout1 = false;
usbDeviceDisconnect(); // enforce re-enumeration, do this while interrupts are disabled! _delay_ms(100);
_delay_ms(250); setTurnout0(true);
setTurnout1(true);
usbDeviceConnect(); _delay_ms(500);
setTurnout0(false);
sei(); setTurnout1(false);
while(true)
{ MCUCR = (1 << ISC00); //enable rising and falling irq on INT0
usbPoll(); GIMSK = (1 << INT0); //unmask INT0
} TIMSK = (1 << TOIE1); //enable timer 1 overflow irq
TCCR1 = (1 << CS12) | (1 << CS10); //enable timer 1 with /16 timer
sei();
while(true)
{
if(turnout0 != turnout0Flag)
{
turnout0 = turnout0Flag;
setTurnout0(turnout0);
}
if(turnout1 != turnout1Flag)
{
turnout1 = turnout1Flag;
setTurnout1(turnout1);
}
}
} }

View File

@ -1,18 +1,18 @@
/*UVOS*/ /*UVOS*/
/* This file is part of TelemetrySystem. /* This file is part of UsbLedController.
* *
* TelemetrySystem is free software: you can redistribute it and/or modify * UsbLedController is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License (LGPL) version 3 as published by * it under the terms of the GNU Lesser General Public License (LGPL) version 3 as published by
* the Free Software Foundation. * the Free Software Foundation.
* *
* TelemetrySystem is distributed in the hope that it will be useful, * UsbLedController is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with TelemetrySystem. If not, see <http://www.gnu.org/licenses/>. * along with UsbLedController. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
@ -22,105 +22,115 @@ template < int BUFFER_SIZE, typename T = uint8_t >
class RingBuffer class RingBuffer
{ {
private: private:
volatile uint_fast16_t _headIndex = 0; volatile uint_fast16_t _headIndex = 0;
volatile uint_fast16_t _tailIndex = 0; volatile uint_fast16_t _tailIndex = 0;
volatile bool _overrun = false; volatile bool _overrun = false;
volatile T _buffer[BUFFER_SIZE]; volatile T _buffer[BUFFER_SIZE];
public: public:
RingBuffer() RingBuffer()
{ {
flush(); flush();
} }
uint_fast16_t remaining() const volatile uint_fast16_t remaining() const volatile
{ {
return (_headIndex-_tailIndex); return (_headIndex-_tailIndex);
} }
uint_fast16_t remainingCapacity() const volatile uint_fast16_t remainingCapacity() const volatile
{ {
return BUFFER_SIZE - (_headIndex-_tailIndex); return BUFFER_SIZE - (_headIndex-_tailIndex);
} }
bool isOverun() volatile unsigned capacity() const volatile
{ {
bool returnVal = _overrun; return BUFFER_SIZE;
_overrun = false; }
return returnVal;
} bool isOverun() volatile
{
bool isEmpty() const volatile bool returnVal = _overrun;
{ return returnVal;
return _tailIndex >= _headIndex; }
}
bool isEmpty() const volatile
T read() volatile {
{ return _tailIndex >= _headIndex;
if(!isEmpty()) }
{
_tailIndex++; const T operator[](uint_fast16_t idx) const volatile
return _buffer[(_tailIndex - 1) % BUFFER_SIZE]; {
} return _buffer[idx];
else return '\0'; }
}
T read() volatile
unsigned int read( T* buffer, unsigned int length ) volatile {
{ _overrun = false;
unsigned int i = 0; if(!isEmpty())
for(; i < length && !isEmpty(); i++) {
{ _tailIndex++;
buffer[i] = read(); return _buffer[(_tailIndex - 1) % BUFFER_SIZE];
} }
return i; else return '\0';
} }
void write( T in ) volatile unsigned int read( T* buffer, unsigned int length ) volatile
{ {
if (_headIndex - BUFFER_SIZE > 0 && _tailIndex - BUFFER_SIZE > 0) unsigned int i = 0;
{ for(; i < length && !isEmpty(); i++)
_headIndex -= BUFFER_SIZE; {
_tailIndex -= BUFFER_SIZE; buffer[i] = read();
} }
_buffer[_headIndex % BUFFER_SIZE] = in; return i;
_headIndex++; }
void write( T in ) volatile
{
if ((int)_headIndex - BUFFER_SIZE > 0 && (int)_tailIndex - BUFFER_SIZE > 0)
{
_headIndex -= BUFFER_SIZE;
_tailIndex -= BUFFER_SIZE;
}
_buffer[_headIndex % BUFFER_SIZE] = in;
_headIndex++;
if(remaining() > BUFFER_SIZE) if(remaining() > BUFFER_SIZE)
{ {
_overrun = true; _overrun = true;
_tailIndex = _headIndex - BUFFER_SIZE; _tailIndex = _headIndex - BUFFER_SIZE;
} }
} }
void write( T* buffer, const unsigned int length ) volatile void write( T* buffer, const unsigned int length ) volatile
{ {
for(unsigned int i = 0; i < length; i++) write(buffer[i]); for(unsigned int i = 0; i < length; i++) write(buffer[i]);
} }
void flush(T flushCharacter = ' ') volatile void flush(T flushCharacter = ' ') volatile
{ {
_headIndex = 0; _headIndex = 0;
_tailIndex = 0; _tailIndex = 0;
for(int i = 0; i < BUFFER_SIZE; i++) _buffer[i] = flushCharacter; for(int i = 0; i < BUFFER_SIZE; i++) _buffer[i] = flushCharacter;
_overrun = false; _overrun = false;
} }
unsigned int getString(T terminator, T* buffer, const unsigned int bufferLength) volatile unsigned int getString(T terminator, T* buffer, const unsigned int bufferLength) volatile
{ {
unsigned int i = 0; unsigned int i = 0;
for(; i <= remaining() && i <= BUFFER_SIZE && _buffer[(_tailIndex+i) % BUFFER_SIZE] != terminator; i++); for(; i <= remaining() && i <= BUFFER_SIZE && _buffer[(_tailIndex+i) % BUFFER_SIZE] != terminator; i++);
if( i < remaining() && i > 0) if( i < remaining() && i > 0)
{ {
if(i > bufferLength-1) i = bufferLength-1; if(i > bufferLength-1) i = bufferLength-1;
read(buffer, i); read(buffer, i);
buffer[i]='\0'; buffer[i]='\0';
_tailIndex++; _tailIndex++;
} }
else if(i == 0) _tailIndex++; else if(i == 0) _tailIndex++;
else i = 0; else i = 0;
return i; return i;
} }
}; };