Inital commit Version 1.0
This commit is contained in:
		
						commit
						0584796a67
					
				
					 6 changed files with 352 additions and 0 deletions
				
			
		
							
								
								
									
										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…
	
	Add table
		Add a link
		
	
		Reference in a new issue