I love pain

master
androiddrew 6 years ago
parent cdaec86e47
commit cce4bee718

1
.gitignore vendored

@ -32,3 +32,4 @@
# Debug files
*.dSYM/
.DS_Store

@ -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…
Cancel
Save