I love pain
							parent
							
								
									cdaec86e47
								
							
						
					
					
						commit
						cce4bee718
					
				@ -0,0 +1,209 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					  FlexiTimer2.h - Using timer2 with a configurable resolution
 | 
				
			||||||
 | 
					  Wim Leers <work@wimleers.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Based on MsTimer2
 | 
				
			||||||
 | 
					  Javier Valencia <javiervalencia80@gmail.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  History:
 | 
				
			||||||
 | 
					    16/Dec/2011 - Added Teensy/Teensy++ support (bperrybap)
 | 
				
			||||||
 | 
							   note: teensy uses timer4 instead of timer2
 | 
				
			||||||
 | 
					    25/April/10 - Based on MsTimer2 V0.5 (from 29/May/09)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					  modify it under the terms of the GNU Lesser General Public
 | 
				
			||||||
 | 
					  License as published by the Free Software Foundation; either
 | 
				
			||||||
 | 
					  version 2.1 of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This library 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
 | 
				
			||||||
 | 
					  Lesser General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					  License along with this library; if not, write to the Free Software
 | 
				
			||||||
 | 
					  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "FlexiTimer2.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned long FlexiTimer2::time_units;
 | 
				
			||||||
 | 
					void (*FlexiTimer2::func)();
 | 
				
			||||||
 | 
					volatile unsigned long FlexiTimer2::count;
 | 
				
			||||||
 | 
					volatile char FlexiTimer2::overflowing;
 | 
				
			||||||
 | 
					volatile unsigned int FlexiTimer2::tcnt2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FlexiTimer2::set(unsigned long ms, void (*f)()) {
 | 
				
			||||||
 | 
					    FlexiTimer2::set(ms, 0.001, f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param resolution
 | 
				
			||||||
 | 
					 *   0.001 implies a 1 ms (1/1000s = 0.001s = 1ms) resolution. Therefore,
 | 
				
			||||||
 | 
					 *   0.0005 implies a 0.5 ms (1/2000s) resolution. And so on.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void FlexiTimer2::set(unsigned long units, double resolution, void (*f)()) {
 | 
				
			||||||
 | 
						float prescaler = 0.0;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (units == 0)
 | 
				
			||||||
 | 
							time_units = 1;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							time_units = units;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						func = f;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
 | 
				
			||||||
 | 
						TIMSK2 &= ~(1<<TOIE2);
 | 
				
			||||||
 | 
						TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
 | 
				
			||||||
 | 
						TCCR2B &= ~(1<<WGM22);
 | 
				
			||||||
 | 
						ASSR &= ~(1<<AS2);
 | 
				
			||||||
 | 
						TIMSK2 &= ~(1<<OCIE2A);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) {	// prescaler set to 64
 | 
				
			||||||
 | 
							TCCR2B |= (1<<CS22);
 | 
				
			||||||
 | 
							TCCR2B &= ~((1<<CS21) | (1<<CS20));
 | 
				
			||||||
 | 
							prescaler = 64.0;
 | 
				
			||||||
 | 
						} else if (F_CPU < 1000000UL) {	// prescaler set to 8
 | 
				
			||||||
 | 
							TCCR2B |= (1<<CS21);
 | 
				
			||||||
 | 
							TCCR2B &= ~((1<<CS22) | (1<<CS20));
 | 
				
			||||||
 | 
							prescaler = 8.0;
 | 
				
			||||||
 | 
						} else { // F_CPU > 16Mhz, prescaler set to 128
 | 
				
			||||||
 | 
							TCCR2B |= ((1<<CS22) | (1<<CS20));
 | 
				
			||||||
 | 
							TCCR2B &= ~(1<<CS21);
 | 
				
			||||||
 | 
							prescaler = 128.0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega8__)
 | 
				
			||||||
 | 
						TIMSK &= ~(1<<TOIE2);
 | 
				
			||||||
 | 
						TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
 | 
				
			||||||
 | 
						TIMSK &= ~(1<<OCIE2);
 | 
				
			||||||
 | 
						ASSR &= ~(1<<AS2);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) {	// prescaler set to 64
 | 
				
			||||||
 | 
							TCCR2 |= (1<<CS22);
 | 
				
			||||||
 | 
							TCCR2 &= ~((1<<CS21) | (1<<CS20));
 | 
				
			||||||
 | 
							prescaler = 64.0;
 | 
				
			||||||
 | 
						} else if (F_CPU < 1000000UL) {	// prescaler set to 8
 | 
				
			||||||
 | 
							TCCR2 |= (1<<CS21);
 | 
				
			||||||
 | 
							TCCR2 &= ~((1<<CS22) | (1<<CS20));
 | 
				
			||||||
 | 
							prescaler = 8.0;
 | 
				
			||||||
 | 
						} else { // F_CPU > 16Mhz, prescaler set to 128
 | 
				
			||||||
 | 
							TCCR2 |= ((1<<CS22) && (1<<CS20));
 | 
				
			||||||
 | 
							TCCR2 &= ~(1<<CS21);
 | 
				
			||||||
 | 
							prescaler = 128.0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega128__)
 | 
				
			||||||
 | 
						TIMSK &= ~(1<<TOIE2);
 | 
				
			||||||
 | 
						TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
 | 
				
			||||||
 | 
						TIMSK &= ~(1<<OCIE2);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) {	// prescaler set to 64
 | 
				
			||||||
 | 
							TCCR2 |= ((1<<CS21) | (1<<CS20));
 | 
				
			||||||
 | 
							TCCR2 &= ~(1<<CS22);
 | 
				
			||||||
 | 
							prescaler = 64.0;
 | 
				
			||||||
 | 
						} else if (F_CPU < 1000000UL) {	// prescaler set to 8
 | 
				
			||||||
 | 
							TCCR2 |= (1<<CS21);
 | 
				
			||||||
 | 
							TCCR2 &= ~((1<<CS22) | (1<<CS20));
 | 
				
			||||||
 | 
							prescaler = 8.0;
 | 
				
			||||||
 | 
						} else { // F_CPU > 16Mhz, prescaler set to 256
 | 
				
			||||||
 | 
							TCCR2 |= (1<<CS22);
 | 
				
			||||||
 | 
							TCCR2 &= ~((1<<CS21) | (1<<CS20));
 | 
				
			||||||
 | 
							prescaler = 256.0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega32U4__)
 | 
				
			||||||
 | 
						TCCR4B = 0;
 | 
				
			||||||
 | 
						TCCR4A = 0;
 | 
				
			||||||
 | 
						TCCR4C = 0;
 | 
				
			||||||
 | 
						TCCR4D = 0;
 | 
				
			||||||
 | 
						TCCR4E = 0;
 | 
				
			||||||
 | 
						if (F_CPU >= 16000000L) {
 | 
				
			||||||
 | 
							TCCR4B = (1<<CS43) | (1<<PSR4);
 | 
				
			||||||
 | 
							prescaler = 128.0;
 | 
				
			||||||
 | 
						} else if (F_CPU >= 8000000L) {
 | 
				
			||||||
 | 
							TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4);
 | 
				
			||||||
 | 
							prescaler = 64.0;
 | 
				
			||||||
 | 
						} else if (F_CPU >= 4000000L) {
 | 
				
			||||||
 | 
							TCCR4B = (1<<CS42) | (1<<CS41) | (1<<PSR4);
 | 
				
			||||||
 | 
							prescaler = 32.0;
 | 
				
			||||||
 | 
						} else if (F_CPU >= 2000000L) {
 | 
				
			||||||
 | 
							TCCR4B = (1<<CS42) | (1<<CS40) | (1<<PSR4);
 | 
				
			||||||
 | 
							prescaler = 16.0;
 | 
				
			||||||
 | 
						} else if (F_CPU >= 1000000L) {
 | 
				
			||||||
 | 
							TCCR4B = (1<<CS42) | (1<<PSR4);
 | 
				
			||||||
 | 
							prescaler = 8.0;
 | 
				
			||||||
 | 
						} else if (F_CPU >= 500000L) {
 | 
				
			||||||
 | 
							TCCR4B = (1<<CS41) | (1<<CS40) | (1<<PSR4);
 | 
				
			||||||
 | 
							prescaler = 4.0;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							TCCR4B = (1<<CS41) | (1<<PSR4);
 | 
				
			||||||
 | 
							prescaler = 2.0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tcnt2 = (int)((float)F_CPU * resolution / prescaler) - 1;
 | 
				
			||||||
 | 
						OCR4C = tcnt2;
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#error Unsupported CPU type
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						tcnt2 = 256 - (int)((float)F_CPU * resolution / prescaler);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FlexiTimer2::start() {
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						overflowing = 0;
 | 
				
			||||||
 | 
					#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
 | 
				
			||||||
 | 
						TCNT2 = tcnt2;
 | 
				
			||||||
 | 
						TIMSK2 |= (1<<TOIE2);
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega128__)
 | 
				
			||||||
 | 
						TCNT2 = tcnt2;
 | 
				
			||||||
 | 
						TIMSK |= (1<<TOIE2);
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega8__)
 | 
				
			||||||
 | 
						TCNT2 = tcnt2;
 | 
				
			||||||
 | 
						TIMSK |= (1<<TOIE2);
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega32U4__)
 | 
				
			||||||
 | 
						TIFR4 = (1<<TOV4);
 | 
				
			||||||
 | 
						TCNT4 = 0;
 | 
				
			||||||
 | 
						TIMSK4 = (1<<TOIE4);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FlexiTimer2::stop() {
 | 
				
			||||||
 | 
					#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
 | 
				
			||||||
 | 
						TIMSK2 &= ~(1<<TOIE2);
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega128__)
 | 
				
			||||||
 | 
						TIMSK &= ~(1<<TOIE2);
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega8__)
 | 
				
			||||||
 | 
						TIMSK &= ~(1<<TOIE2);
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega32U4__)
 | 
				
			||||||
 | 
						TIMSK4 = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FlexiTimer2::_overflow() {
 | 
				
			||||||
 | 
						count += 1;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (count >= time_units && !overflowing) {
 | 
				
			||||||
 | 
							overflowing = 1;
 | 
				
			||||||
 | 
							count = count - time_units; // subtract time_uints to catch missed overflows
 | 
				
			||||||
 | 
										// set to 0 if you don't want this.
 | 
				
			||||||
 | 
							(*func)();
 | 
				
			||||||
 | 
							overflowing = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#if defined (__AVR_ATmega32U4__)
 | 
				
			||||||
 | 
					ISR(TIMER4_OVF_vect) {
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					ISR(TIMER2_OVF_vect) {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
 | 
				
			||||||
 | 
						TCNT2 = FlexiTimer2::tcnt2;
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega128__)
 | 
				
			||||||
 | 
						TCNT2 = FlexiTimer2::tcnt2;
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega8__)
 | 
				
			||||||
 | 
						TCNT2 = FlexiTimer2::tcnt2;
 | 
				
			||||||
 | 
					#elif defined (__AVR_ATmega32U4__)
 | 
				
			||||||
 | 
						// not necessary on 32u4's high speed timer4
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						FlexiTimer2::_overflow();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					#ifndef FlexiTimer2_h
 | 
				
			||||||
 | 
					#define FlexiTimer2_h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __AVR__
 | 
				
			||||||
 | 
					#include <avr/interrupt.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#error FlexiTimer2 library only works on AVR architecture
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace FlexiTimer2 {
 | 
				
			||||||
 | 
						extern unsigned long time_units;
 | 
				
			||||||
 | 
						extern void (*func)();
 | 
				
			||||||
 | 
						extern volatile unsigned long count;
 | 
				
			||||||
 | 
						extern volatile char overflowing;
 | 
				
			||||||
 | 
						extern volatile unsigned int tcnt2;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						void set(unsigned long ms, void (*f)());
 | 
				
			||||||
 | 
						void set(unsigned long units, double resolution, void (*f)());
 | 
				
			||||||
 | 
						void start();
 | 
				
			||||||
 | 
						void stop();
 | 
				
			||||||
 | 
						void _overflow();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -0,0 +1,261 @@
 | 
				
			|||||||
 | 
					#include "GoBLE.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_GoBLE Goble;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					   The following constants tell, for each accelerometer
 | 
				
			||||||
 | 
					   axis, which values are returned when the axis measures
 | 
				
			||||||
 | 
					   zero acceleration.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_GoBLE::_GoBLE() {
 | 
				
			||||||
 | 
					  initRecvDataPack();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _joystickX = 127;
 | 
				
			||||||
 | 
					  _joystickY = 127;
 | 
				
			||||||
 | 
					  for (int i = 0; i < MAXBUTTONID; i++) {
 | 
				
			||||||
 | 
					    _button[i] = RELEASED;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (int i = 0; i < 20; i++) bleQueue.push(0x00);
 | 
				
			||||||
 | 
					  for (int i = 0; i < 20; i++) bleQueue.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					boolean _GoBLE::available() {
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
 | 
					    function introduction:
 | 
				
			||||||
 | 
					  	 push the new valid data to the data buffer package
 | 
				
			||||||
 | 
					  	 throw away the invalid byte
 | 
				
			||||||
 | 
					  	 parse the data package when the command length is matching the protocol
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (Serial.available())  bleDataReceiver();
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					  if (DEBUGDATARAW) {
 | 
				
			||||||
 | 
					    Serial.println("GoBLE availalbe -> new data package!");
 | 
				
			||||||
 | 
					    for (int i = 0; i < rDataPack.commandLength; i++) {
 | 
				
			||||||
 | 
					      Serial.print(bleQueue.pop(), HEX);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Serial.println();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (DEBUGPARSER) {
 | 
				
			||||||
 | 
					    Serial.print("GoBLE availalbe -> bleQueue Counter: ");
 | 
				
			||||||
 | 
					    Serial.print(bleQueue.count());
 | 
				
			||||||
 | 
					    Serial.println();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					  if (rDataPack.commandFlag && bleQueue.count() == rDataPack.commandLength) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rDataPack.parseState = bleDataPackageParser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rDataPack.parseState == PARSESUCCESS) {
 | 
				
			||||||
 | 
					      updateJoystickVal();
 | 
				
			||||||
 | 
					      updateButtonState();
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int _GoBLE::readJoystickX() {
 | 
				
			||||||
 | 
					  return  _joystickX;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					int _GoBLE::readJoystickY() {
 | 
				
			||||||
 | 
					  return  _joystickY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					boolean _GoBLE::readSwitchUp() {
 | 
				
			||||||
 | 
					  return _button[SWITCH_UP];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					boolean _GoBLE::readSwitchDown() {
 | 
				
			||||||
 | 
					  return _button[SWITCH_DOWN];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					boolean _GoBLE::readSwitchLeft() {
 | 
				
			||||||
 | 
					  return _button[SWITCH_LEFT];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					boolean _GoBLE::readSwitchRight() {
 | 
				
			||||||
 | 
					  return _button[SWITCH_RIGHT];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					boolean _GoBLE::readSwitchSelect() {
 | 
				
			||||||
 | 
					  return _button[SWITCH_SELECT];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					boolean _GoBLE::readSwitchStart() {
 | 
				
			||||||
 | 
					  return _button[SWITCH_START];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Private functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int _GoBLE::bleDataPackageParser() {
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
 | 
					    0x10  - Parse success
 | 
				
			||||||
 | 
					    0x11  - Wrong header charactors
 | 
				
			||||||
 | 
					    0x12  - Wrong button number
 | 
				
			||||||
 | 
					    0x13  - Check Sum Error
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					  byte calculateSum = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rDataPack.header1 = bleQueue.pop(), calculateSum +=  rDataPack.header1;
 | 
				
			||||||
 | 
					  rDataPack.header2 = bleQueue.pop(), calculateSum +=  rDataPack.header2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (rDataPack.header1 != DEFAULTHEADER1)     return 0x11;
 | 
				
			||||||
 | 
					  if (rDataPack.header2 != DEFAULTHEADER2)     return 0x11;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rDataPack.address = bleQueue.pop(), calculateSum +=  rDataPack.address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rDataPack.latestDigitalButtonNumber = rDataPack.digitalButtonNumber;
 | 
				
			||||||
 | 
					  rDataPack.digitalButtonNumber = bleQueue.pop(), calculateSum +=  rDataPack.digitalButtonNumber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int digitalButtonLength = rDataPack.digitalButtonNumber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (DEBUGCHECKSUM) {
 | 
				
			||||||
 | 
					    Serial.print("Parser -> digitalButtonLength: ");
 | 
				
			||||||
 | 
					    Serial.println(digitalButtonLength);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (digitalButtonLength > MAXBUTTONNUMBER)   return 0x12;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rDataPack.joystickPosition = bleQueue.pop(), calculateSum +=  rDataPack.joystickPosition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // read button data package - dynamic button payload length
 | 
				
			||||||
 | 
					  for (int buttonPayloadPointer = 0; buttonPayloadPointer < digitalButtonLength; buttonPayloadPointer++) {
 | 
				
			||||||
 | 
					    rDataPack.buttonPayload[buttonPayloadPointer] = bleQueue.pop();
 | 
				
			||||||
 | 
					    calculateSum +=  rDataPack.buttonPayload[buttonPayloadPointer];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // read 4 byte joystick data package
 | 
				
			||||||
 | 
					  for (int i = 0; i < 4; i++)  rDataPack.joystickPayload[i] = bleQueue.pop(), calculateSum +=  rDataPack.joystickPayload[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rDataPack.checkSum = bleQueue.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (DEBUGCHECKSUM) {
 | 
				
			||||||
 | 
					    Serial.print("Parser -> sum calculation: ");
 | 
				
			||||||
 | 
					    Serial.println(calculateSum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Serial.print("Parser -> checkSum byte value: ");
 | 
				
			||||||
 | 
					    Serial.println(rDataPack.checkSum);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check sum and update the parse state value
 | 
				
			||||||
 | 
					  // if the checksum byte is not correct, return 0x12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rDataPack.commandFlag = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (rDataPack.checkSum == calculateSum)     return PARSESUCCESS;
 | 
				
			||||||
 | 
					  else                                        return 0x13;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void  _GoBLE::bleDataReceiver() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte inputByte = Serial.read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (DEBUGDATARECEIVER) {
 | 
				
			||||||
 | 
					    Serial.print("bleDataReceiver -> new data:");
 | 
				
			||||||
 | 
					    Serial.println(inputByte, HEX);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // throw the trash data and restore the useful data to the queue buffer
 | 
				
			||||||
 | 
					  if (inputByte == DEFAULTHEADER1 || rDataPack.commandFlag == true) {
 | 
				
			||||||
 | 
					    bleQueue.push(inputByte);
 | 
				
			||||||
 | 
					    rDataPack.commandFlag = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // auto adjust the command length based on the button command value
 | 
				
			||||||
 | 
					    if (bleQueue.count() == PACKBUTTONSIGN) {
 | 
				
			||||||
 | 
					      // max button input at one moment should less than 6 buttons
 | 
				
			||||||
 | 
					      if (inputByte > 0 && inputByte < MAXBUTTONNUMBER) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // default command length + button number
 | 
				
			||||||
 | 
					        rDataPack.commandLength = DEFAULTPACKLENGTH + inputByte;
 | 
				
			||||||
 | 
					        if (DEBUGDATARECEIVER)	Serial.print("bleDataReceiver -> Command Length:"), Serial.println(rDataPack.commandLength);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else	rDataPack.commandLength = DEFAULTPACKLENGTH;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void  _GoBLE::initRecvDataPack() {
 | 
				
			||||||
 | 
					  rDataPack.commandFlag         = false;
 | 
				
			||||||
 | 
					  rDataPack.commandLength       = DEFAULTPACKLENGTH;
 | 
				
			||||||
 | 
					  rDataPack.parseState          = PARSESUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rDataPack.digitalButtonNumber = 0;
 | 
				
			||||||
 | 
					  rDataPack.latestDigitalButtonNumber = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _GoBLE::updateJoystickVal() {
 | 
				
			||||||
 | 
					  _joystickX = rDataPack.joystickPayload[0];
 | 
				
			||||||
 | 
					  _joystickY = rDataPack.joystickPayload[1];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _GoBLE::updateButtonState() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (rDataPack.digitalButtonNumber == 0 && rDataPack.latestDigitalButtonNumber != 0) {
 | 
				
			||||||
 | 
					    for (int i = 0; i < MAXBUTTONID; i++) {
 | 
				
			||||||
 | 
					      if (_button[i] == PRESSED) {
 | 
				
			||||||
 | 
					        if (DEBUGUPDATEBUTTON) {
 | 
				
			||||||
 | 
					          Serial.print("updateButtonState -> clear Pressed button number: ");
 | 
				
			||||||
 | 
					          Serial.println(i);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _button[i] = RELEASED;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (int i = 0; i < rDataPack.digitalButtonNumber; i++)   _button[rDataPack.buttonPayload[i]] = PRESSED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					  unsigned int _GoBLE::readChannel(byte channel) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  digitalWrite(MUX_ADDR_PINS[0], (channel & 1) ? HIGH : LOW);
 | 
				
			||||||
 | 
					  digitalWrite(MUX_ADDR_PINS[1], (channel & 2) ? HIGH : LOW);
 | 
				
			||||||
 | 
					  digitalWrite(MUX_ADDR_PINS[2], (channel & 4) ? HIGH : LOW);
 | 
				
			||||||
 | 
					  digitalWrite(MUX_ADDR_PINS[3], (channel & 8) ? HIGH : LOW);
 | 
				
			||||||
 | 
					  // workaround to cope with lack of pullup resistor on joystick switch
 | 
				
			||||||
 | 
					  if (channel == CH_JOYSTICK_SW) {
 | 
				
			||||||
 | 
					    pinMode(MUX_COM_PIN, INPUT_PULLUP);
 | 
				
			||||||
 | 
					    unsigned int joystickSwitchState = (digitalRead(MUX_COM_PIN) == HIGH) ? 1023 : 0;
 | 
				
			||||||
 | 
					    digitalWrite(MUX_COM_PIN, LOW);
 | 
				
			||||||
 | 
					    return joystickSwitchState;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    return analogRead(MUX_COM_PIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  boolean _GoBLE::readButton(byte ch) {
 | 
				
			||||||
 | 
					  if (ch >= SWITCH_1 && ch <= SWITCH_5) {
 | 
				
			||||||
 | 
					    ch;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch(ch) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unsigned int val = readChannel(ch);
 | 
				
			||||||
 | 
					  return (val > 512) ? HIGH : LOW;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  boolean _GoBLE::readJoystickButton() {
 | 
				
			||||||
 | 
					  if (readChannel(CH_JOYSTICK_SW) == 1023) {
 | 
				
			||||||
 | 
					  return HIGH;
 | 
				
			||||||
 | 
					  } else if (readChannel(CH_JOYSTICK_SW) == 0) {
 | 
				
			||||||
 | 
					  return LOW;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					#ifndef GOBLE_H_
 | 
				
			||||||
 | 
					#define GOBLE_H_
 | 
				
			||||||
 | 
					#include "QueueArray.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**************** Debugger Configuration ******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEBUGDATARECEIVER	0
 | 
				
			||||||
 | 
					#define DEBUGDATARAW     	0
 | 
				
			||||||
 | 
					#define DEBUGPARSER      	0
 | 
				
			||||||
 | 
					#define DEBUGCHECKSUM     0
 | 
				
			||||||
 | 
					#define DEBUGUPDATEBUTTON	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const byte SWITCH_1       = 1;
 | 
				
			||||||
 | 
					const byte SWITCH_2       = 2;
 | 
				
			||||||
 | 
					const byte SWITCH_3       = 3;
 | 
				
			||||||
 | 
					const byte SWITCH_4       = 4;
 | 
				
			||||||
 | 
					const byte SWITCH_5       = 5;
 | 
				
			||||||
 | 
					const byte SWITCH_6       = 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const byte SWITCH_UP    	= SWITCH_1;
 | 
				
			||||||
 | 
					const byte SWITCH_RIGHT 	= SWITCH_2;
 | 
				
			||||||
 | 
					const byte SWITCH_DOWN  	= SWITCH_3;
 | 
				
			||||||
 | 
					const byte SWITCH_LEFT 		= SWITCH_4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const byte SWITCH_SELECT 	= SWITCH_5;
 | 
				
			||||||
 | 
					const byte SWITCH_START 	= SWITCH_6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					   These constants can be use for comparison with the value returned
 | 
				
			||||||
 | 
					   by the readButton() method.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					const boolean PRESSED   = LOW;
 | 
				
			||||||
 | 
					const boolean RELEASED  = HIGH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					   Data structure for the command buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Package protocol configuration
 | 
				
			||||||
 | 
					#define PACKHEADER	        1
 | 
				
			||||||
 | 
					#define PACKHEADER2		2
 | 
				
			||||||
 | 
					#define PACKADDRESS		3
 | 
				
			||||||
 | 
					#define PACKBUTTONSIGN		4
 | 
				
			||||||
 | 
					#define PACKJOYSTICKSIGN	5
 | 
				
			||||||
 | 
					#define PACKPAYLOAD             6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEFAULTHEADER1          0x55
 | 
				
			||||||
 | 
					#define DEFAULTHEADER2          0xAA
 | 
				
			||||||
 | 
					#define DEFAULTADDRESS          0x11
 | 
				
			||||||
 | 
					#define DEFAULTPACKLENGTH	10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAXBUTTONNUMBER         6
 | 
				
			||||||
 | 
					#define MAXBUTTONID             7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARSESUCCESS            0x10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//DL package
 | 
				
			||||||
 | 
					#pragma pack(1)
 | 
				
			||||||
 | 
					typedef struct
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  byte  header1;          // 0x55
 | 
				
			||||||
 | 
					  byte  header2;          // 0xAA
 | 
				
			||||||
 | 
					  byte  address;          // 0x11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte  latestDigitalButtonNumber;
 | 
				
			||||||
 | 
					  byte  digitalButtonNumber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte  joystickPosition;
 | 
				
			||||||
 | 
					  byte	buttonPayload[MAXBUTTONNUMBER];
 | 
				
			||||||
 | 
					  byte	joystickPayload[4];
 | 
				
			||||||
 | 
					  byte  checkSum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte  commandLength;
 | 
				
			||||||
 | 
					  byte  parseState;
 | 
				
			||||||
 | 
					  boolean commandFlag;
 | 
				
			||||||
 | 
					} sDataLink;
 | 
				
			||||||
 | 
					#pragma pack()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _GoBLE {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    _GoBLE();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    boolean available();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int readJoystickX();
 | 
				
			||||||
 | 
					    int readJoystickY();
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					       Reads the current state of a button. It will return
 | 
				
			||||||
 | 
					       LOW if the button is pressed, and HIGH otherwise.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    boolean readSwitchUp();
 | 
				
			||||||
 | 
					    boolean readSwitchDown();
 | 
				
			||||||
 | 
					    boolean readSwitchLeft();
 | 
				
			||||||
 | 
					    boolean readSwitchRight();
 | 
				
			||||||
 | 
					    boolean readSwitchSelect();
 | 
				
			||||||
 | 
					    boolean readSwitchStart();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sDataLink rDataPack;
 | 
				
			||||||
 | 
					    // create a queue of characters.
 | 
				
			||||||
 | 
					    QueueArray <byte> bleQueue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int _joystickX, _joystickY;
 | 
				
			||||||
 | 
					    int _button[MAXBUTTONID];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void updateJoystickVal();
 | 
				
			||||||
 | 
					    void updateButtonState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void initRecvDataPack();
 | 
				
			||||||
 | 
					    int bleDataPackageParser();
 | 
				
			||||||
 | 
					    void bleDataReceiver();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern _GoBLE Goble;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // GOBLE_H_
 | 
				
			||||||
@ -0,0 +1,313 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  QueueArray.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Library implementing a generic, dynamic queue (array version).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  ---
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Copyright (C) 2010  Efstathios Chatzikyriakidis (contact@efxa.org)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 *  it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 *  the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 *  (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  ---
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Version 1.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    2014-02-03  Brian Fletcher  <brian.jf.fletcher@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      - added enqueue(), dequeue() and front().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    2010-09-29  Efstathios Chatzikyriakidis  <contact@efxa.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      - added resize(): for growing, shrinking the array size.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    2010-09-25  Efstathios Chatzikyriakidis  <contact@efxa.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      - added exit(), blink(): error reporting and handling methods.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    2010-09-24  Alexander Brevig  <alexanderbrevig@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      - added setPrinter(): indirectly reference a Serial object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    2010-09-20  Efstathios Chatzikyriakidis  <contact@efxa.org>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      - initial release of the library.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  ---
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  For the latest version see: http://www.arduino.cc/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// header defining the interface of the source.
 | 
				
			||||||
 | 
					#ifndef _QUEUEARRAY_H
 | 
				
			||||||
 | 
					#define _QUEUEARRAY_H
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					// the definition of the queue class.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					class QueueArray {
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    // init the queue (constructor).
 | 
				
			||||||
 | 
					    QueueArray ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // clear the queue (destructor).
 | 
				
			||||||
 | 
					    ~QueueArray ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // add an item to the queue.
 | 
				
			||||||
 | 
					    void enqueue (const T i);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // remove an item from the queue.
 | 
				
			||||||
 | 
					    T dequeue ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // push an item to the queue.
 | 
				
			||||||
 | 
					    void push (const T i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // pop an item from the queue.
 | 
				
			||||||
 | 
					    T pop ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // get the front of the queue.
 | 
				
			||||||
 | 
					    T front () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // get an item from the queue.
 | 
				
			||||||
 | 
					    T peek () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check if the queue is empty.
 | 
				
			||||||
 | 
					    bool isEmpty () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // get the number of items in the queue.
 | 
				
			||||||
 | 
					    int count () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check if the queue is full.
 | 
				
			||||||
 | 
					    bool isFull () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set the printer of the queue.
 | 
				
			||||||
 | 
					    void setPrinter (Print & p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    // resize the size of the queue.
 | 
				
			||||||
 | 
					    void resize (const int s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // exit report method in case of error.
 | 
				
			||||||
 | 
					    void exit (const char * m) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // led blinking method in case of error.
 | 
				
			||||||
 | 
					    void blink () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // the initial size of the queue.
 | 
				
			||||||
 | 
					    static const int initialSize = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // the pin number of the on-board led.
 | 
				
			||||||
 | 
					    static const int ledPin = 13;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Print * printer; // the printer of the queue.
 | 
				
			||||||
 | 
					    T * contents;    // the array of the queue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int size;        // the size of the queue.
 | 
				
			||||||
 | 
					    int items;       // the number of items of the queue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int head;        // the head of the queue.
 | 
				
			||||||
 | 
					    int tail;        // the tail of the queue.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// init the queue (constructor).
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					QueueArray<T>::QueueArray () {
 | 
				
			||||||
 | 
					  size = 0;       // set the size of queue to zero.
 | 
				
			||||||
 | 
					  items = 0;      // set the number of items of queue to zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  head = 0;       // set the head of the queue to zero.
 | 
				
			||||||
 | 
					  tail = 0;       // set the tail of the queue to zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  printer = NULL; // set the printer of queue to point nowhere.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // allocate enough memory for the array.
 | 
				
			||||||
 | 
					  contents = (T *) malloc (sizeof (T) * initialSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // if there is a memory allocation error.
 | 
				
			||||||
 | 
					  if (contents == NULL)
 | 
				
			||||||
 | 
					    exit ("QUEUE: insufficient memory to initialize queue.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set the initial size of the queue.
 | 
				
			||||||
 | 
					  size = initialSize;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// clear the queue (destructor).
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					QueueArray<T>::~QueueArray () {
 | 
				
			||||||
 | 
					  free (contents); // deallocate the array of the queue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  contents = NULL; // set queue's array pointer to nowhere.
 | 
				
			||||||
 | 
					  printer = NULL;  // set the printer of queue to point nowhere.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  size = 0;        // set the size of queue to zero.
 | 
				
			||||||
 | 
					  items = 0;       // set the number of items of queue to zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  head = 0;        // set the head of the queue to zero.
 | 
				
			||||||
 | 
					  tail = 0;        // set the tail of the queue to zero.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// resize the size of the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueArray<T>::resize (const int s) {
 | 
				
			||||||
 | 
					  // defensive issue.
 | 
				
			||||||
 | 
					  if (s <= 0)
 | 
				
			||||||
 | 
					    exit ("QUEUE: error due to undesirable size for queue size.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // allocate enough memory for the temporary array.
 | 
				
			||||||
 | 
					  T * temp = (T *) malloc (sizeof (T) * s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // if there is a memory allocation error.
 | 
				
			||||||
 | 
					  if (temp == NULL)
 | 
				
			||||||
 | 
					    exit ("QUEUE: insufficient memory to initialize temporary queue.");
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // copy the items from the old queue to the new one.
 | 
				
			||||||
 | 
					  for (int i = 0; i < items; i++)
 | 
				
			||||||
 | 
					    temp[i] = contents[(head + i) % size];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // deallocate the old array of the queue.
 | 
				
			||||||
 | 
					  free (contents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // copy the pointer of the new queue.
 | 
				
			||||||
 | 
					  contents = temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set the head and tail of the new queue.
 | 
				
			||||||
 | 
					  head = 0; tail = items;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set the new size of the queue.
 | 
				
			||||||
 | 
					  size = s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// add an item to the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueArray<T>::enqueue (const T i) {
 | 
				
			||||||
 | 
					  // check if the queue is full.
 | 
				
			||||||
 | 
					  if (isFull ())
 | 
				
			||||||
 | 
					    // double size of array.
 | 
				
			||||||
 | 
					    resize (size * 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // store the item to the array.
 | 
				
			||||||
 | 
					  contents[tail++] = i;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // wrap-around index.
 | 
				
			||||||
 | 
					  if (tail == size) tail = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // increase the items.
 | 
				
			||||||
 | 
					  items++;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// push an item to the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueArray<T>::push (const T i) {
 | 
				
			||||||
 | 
					  enqueue(i);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// remove an item from the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T QueueArray<T>::dequeue () {
 | 
				
			||||||
 | 
					  // check if the queue is empty.
 | 
				
			||||||
 | 
					  if (isEmpty ())
 | 
				
			||||||
 | 
					    exit ("QUEUE: can't pop item from queue: queue is empty.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // fetch the item from the array.
 | 
				
			||||||
 | 
					  T item = contents[head++];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // decrease the items.
 | 
				
			||||||
 | 
					  items--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // wrap-around index.
 | 
				
			||||||
 | 
					  if (head == size) head = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // shrink size of array if necessary.
 | 
				
			||||||
 | 
					  if (!isEmpty () && (items <= size / 4))
 | 
				
			||||||
 | 
					    resize (size / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // return the item from the array.
 | 
				
			||||||
 | 
					  return item;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// pop an item from the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T QueueArray<T>::pop () {
 | 
				
			||||||
 | 
					  return dequeue();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// get the front of the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T QueueArray<T>::front () const {
 | 
				
			||||||
 | 
					  // check if the queue is empty.
 | 
				
			||||||
 | 
					  if (isEmpty ())
 | 
				
			||||||
 | 
					    exit ("QUEUE: can't get the front item of queue: queue is empty.");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  // get the item from the array.
 | 
				
			||||||
 | 
					  return contents[head];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// get an item from the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T QueueArray<T>::peek () const {
 | 
				
			||||||
 | 
					  return front();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// check if the queue is empty.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool QueueArray<T>::isEmpty () const {
 | 
				
			||||||
 | 
					  return items == 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// check if the queue is full.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool QueueArray<T>::isFull () const {
 | 
				
			||||||
 | 
					  return items == size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// get the number of items in the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					int QueueArray<T>::count () const {
 | 
				
			||||||
 | 
					  return items;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// set the printer of the queue.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueArray<T>::setPrinter (Print & p) {
 | 
				
			||||||
 | 
					  printer = &p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// exit report method in case of error.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueArray<T>::exit (const char * m) const {
 | 
				
			||||||
 | 
					  // print the message if there is a printer.
 | 
				
			||||||
 | 
					  if (printer)
 | 
				
			||||||
 | 
					    printer->println (m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // loop blinking until hardware reset.
 | 
				
			||||||
 | 
					  blink ();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// led blinking method in case of error.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueArray<T>::blink () const {
 | 
				
			||||||
 | 
					  // set led pin as output.
 | 
				
			||||||
 | 
					  pinMode (ledPin, OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // continue looping until hardware reset.
 | 
				
			||||||
 | 
					  while (true) {
 | 
				
			||||||
 | 
					    digitalWrite (ledPin, HIGH); // sets the LED on.
 | 
				
			||||||
 | 
					    delay (250);                 // pauses 1/4 of second.
 | 
				
			||||||
 | 
					    digitalWrite (ledPin, LOW);  // sets the LED off.
 | 
				
			||||||
 | 
					    delay (250);                 // pauses 1/4 of second.
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // solution selected due to lack of exit() and assert().
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _QUEUEARRAY_H
 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								
					Loading…
					
					
				
		Reference in New Issue