Inital commit Version 1.0
This commit is contained in:
commit
0584796a67
40
adc.cpp
Normal file
40
adc.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#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
Normal file
28
adc.h
Normal file
@ -0,0 +1,28 @@
|
||||
#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();
|
||||
};
|
124
main.cpp
Normal file
124
main.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/sleep.h>
|
||||
#include "adc.h"
|
||||
#include "writepin.h"
|
||||
#include "ringbuffer.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "usbdrv.h"
|
||||
|
||||
}
|
||||
|
||||
volatile uint16_t sampleId = 0;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
extern "C" usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
{
|
||||
usbRequest_t *rq = (usbRequest_t *)data;
|
||||
static uchar dataBuffer[8];
|
||||
|
||||
if(rq->bRequest == 0)
|
||||
{
|
||||
if(!buffer.isEmpty() && !buffer.isEmpty() && rq->wLength.word >= 4 )
|
||||
{
|
||||
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)
|
||||
{
|
||||
buffer.write(sample);
|
||||
sampleId++;
|
||||
}
|
||||
|
||||
void timer0InterruptEnable(const bool enable)
|
||||
{
|
||||
if(enable) TIMSK = TIMSK | (1 << TOIE0);
|
||||
else TIMSK = TIMSK & ~(1 << TOIE0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
DIDR0 |= (1 << PB2);
|
||||
TCCR0B = (1<<CS02); // run timer0 with /256 scaler
|
||||
timer0InterruptEnable(true);
|
||||
usbInit();
|
||||
usbDeviceDisconnect(); // enforce re-enumeration, do this while interrupts are disabled!
|
||||
_delay_ms(250);
|
||||
|
||||
usbDeviceConnect();
|
||||
|
||||
sei();
|
||||
while(true)
|
||||
{
|
||||
usbPoll();
|
||||
}
|
||||
}
|
||||
|
126
ringbuffer.h
Executable file
126
ringbuffer.h
Executable file
@ -0,0 +1,126 @@
|
||||
/*UVOS*/
|
||||
|
||||
/* This file is part of TelemetrySystem.
|
||||
*
|
||||
* TelemetrySystem 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
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* TelemetrySystem is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with TelemetrySystem. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
template < int BUFFER_SIZE, typename T = uint8_t >
|
||||
class RingBuffer
|
||||
{
|
||||
private:
|
||||
|
||||
volatile uint_fast16_t _headIndex = 0;
|
||||
volatile uint_fast16_t _tailIndex = 0;
|
||||
volatile bool _overrun = false;
|
||||
volatile T _buffer[BUFFER_SIZE];
|
||||
|
||||
public:
|
||||
|
||||
RingBuffer()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
uint_fast16_t remaining() const volatile
|
||||
{
|
||||
return (_headIndex-_tailIndex);
|
||||
}
|
||||
|
||||
uint_fast16_t remainingCapacity() const volatile
|
||||
{
|
||||
return BUFFER_SIZE - (_headIndex-_tailIndex);
|
||||
}
|
||||
|
||||
bool isOverun() volatile
|
||||
{
|
||||
bool returnVal = _overrun;
|
||||
_overrun = false;
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
bool isEmpty() const volatile
|
||||
{
|
||||
return _tailIndex >= _headIndex;
|
||||
}
|
||||
|
||||
T read() volatile
|
||||
{
|
||||
if(!isEmpty())
|
||||
{
|
||||
_tailIndex++;
|
||||
return _buffer[(_tailIndex - 1) % BUFFER_SIZE];
|
||||
}
|
||||
else return '\0';
|
||||
}
|
||||
|
||||
unsigned int read( T* buffer, unsigned int length ) volatile
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for(; i < length && !isEmpty(); i++)
|
||||
{
|
||||
buffer[i] = read();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void write( T in ) volatile
|
||||
{
|
||||
if (_headIndex - BUFFER_SIZE > 0 && _tailIndex - BUFFER_SIZE > 0)
|
||||
{
|
||||
_headIndex -= BUFFER_SIZE;
|
||||
_tailIndex -= BUFFER_SIZE;
|
||||
}
|
||||
_buffer[_headIndex % BUFFER_SIZE] = in;
|
||||
_headIndex++;
|
||||
if(remaining() > BUFFER_SIZE)
|
||||
{
|
||||
_overrun = true;
|
||||
_tailIndex = _headIndex - BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void write( T* buffer, const unsigned int length ) volatile
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++) write(buffer[i]);
|
||||
}
|
||||
|
||||
void flush(T flushCharacter = ' ') volatile
|
||||
{
|
||||
_headIndex = 0;
|
||||
_tailIndex = 0;
|
||||
for(int i = 0; i < BUFFER_SIZE; i++) _buffer[i] = flushCharacter;
|
||||
_overrun = false;
|
||||
}
|
||||
|
||||
unsigned int getString(T terminator, T* buffer, const unsigned int bufferLength) volatile
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for(; i <= remaining() && i <= BUFFER_SIZE && _buffer[(_tailIndex+i) % BUFFER_SIZE] != terminator; i++);
|
||||
|
||||
if( i < remaining() && i > 0)
|
||||
{
|
||||
if(i > bufferLength-1) i = bufferLength-1;
|
||||
read(buffer, i);
|
||||
buffer[i]='\0';
|
||||
_tailIndex++;
|
||||
}
|
||||
else if(i == 0) _tailIndex++;
|
||||
else i = 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
};
|
21
writepin.cpp
Normal file
21
writepin.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "writepin.h"
|
||||
|
||||
void writePin(volatile unsigned char * const port, const unsigned char pin, const bool state)
|
||||
{
|
||||
*port = (*port & ~(1 << pin)) | (1 << pin)*state;
|
||||
}
|
||||
|
||||
void setBit( volatile unsigned char * const reg, const unsigned char bit, const bool value )
|
||||
{
|
||||
writePin(reg, bit, value);
|
||||
}
|
||||
|
||||
void setDirection( volatile unsigned char * const portDirReg, const unsigned char pin, const bool makeOutput )
|
||||
{
|
||||
writePin(portDirReg, pin, makeOutput);
|
||||
}
|
||||
|
||||
bool readPin( volatile const unsigned char * const inPort, const unsigned char pin)
|
||||
{
|
||||
return (bool) (*inPort & (1 << pin));
|
||||
}
|
13
writepin.h
Normal file
13
writepin.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef WRITEPIN_H
|
||||
#define WRITEPIN_H
|
||||
#include <avr/io.h>
|
||||
|
||||
void writePin(volatile unsigned char * const port, const unsigned char pin, const bool state);
|
||||
|
||||
void setBit( volatile unsigned char * const reg, const unsigned char bit, const bool value );
|
||||
|
||||
void setDirection( volatile unsigned char * const portDirReg, const unsigned char pin, const bool makeOutput );
|
||||
|
||||
bool readPin( volatile const unsigned char * const inPort, const unsigned char pin);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user