diff --git a/src/libraries/Pixy.h b/src/libraries/Pixy.h new file mode 100644 index 0000000..bce3b68 --- /dev/null +++ b/src/libraries/Pixy.h @@ -0,0 +1,113 @@ +// +// begin license header +// +// This file is part of Pixy CMUcam5 or "Pixy" for short +// +// All Pixy source code is provided under the terms of the +// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html). +// Those wishing to use Pixy source code, software and/or +// technologies under different licensing terms should contact us at +// cmucam@cs.cmu.edu. Such licensing terms are available for +// all portions of the Pixy codebase presented here. +// +// end license header +// + +/* + Pixy.h - Library for interfacing with Pixy. + Created by Scott Robinson, October 22, 2013. + Released into the public domain. + + 06.04.2014 v0.1.3 John Leimon + + LinkSPI.init() should be called from the setup() + function instead of being called automatically from + the TPixy constructor in global scope. This + is a workaround for a bug (?) in the Arduino DUE in which + calling SPI.begin() from global scope (via a constructor) + inhibits the operation of the Serial peripheral in the + DUE. [As of: Arduino 1.5.6-r2] +*/ + +#ifndef PIXY_H +#define PIXY_H + +#include "TPixy.h" +#include "SPI.h" +#include + + +#define PIXY_SYNC_BYTE 0x5a +#define PIXY_SYNC_BYTE_DATA 0x5b +#define PIXY_OUTBUF_SIZE 6 + +class LinkSPI +{ + public: + void init() + { + outLen = 0; + SPI.begin(); + + #ifdef __SAM3X8E__ + // DUE clock divider // + SPI.setClockDivider(84); + #else + // Default clock divider // + SPI.setClockDivider(SPI_CLOCK_DIV16); + #endif + } + + uint16_t getWord() + { + // ordering is different because Pixy is sending 16 bits through SPI + // instead of 2 bytes in a 16-bit word as with I2C + uint16_t w; + uint8_t c, cout = 0; + + if (outLen) + { + w = SPI.transfer(PIXY_SYNC_BYTE_DATA); + cout = outBuf[outIndex++]; + if (outIndex==outLen) + outLen = 0; + } + else + w = SPI.transfer(PIXY_SYNC_BYTE); + w <<= 8; + c = SPI.transfer(cout); + w |= c; + + return w; + } + + uint8_t getByte() + { + return SPI.transfer(0x00); + } + + int8_t send(uint8_t *data, uint8_t len) + { + if (len>PIXY_OUTBUF_SIZE || outLen!=0) + return -1; + memcpy(outBuf, data, len); + outLen = len; + outIndex = 0; + return len; + } + + void setAddress(uint8_t addr) + { + addr_ = addr; + } + + private: + uint8_t outBuf[PIXY_OUTBUF_SIZE]; + uint8_t outLen; + uint8_t outIndex; + uint8_t addr_; +}; + + +typedef TPixy Pixy; + +#endif \ No newline at end of file diff --git a/src/libraries/TPixy.h b/src/libraries/TPixy.h new file mode 100644 index 0000000..4bbf570 --- /dev/null +++ b/src/libraries/TPixy.h @@ -0,0 +1,229 @@ +// +// begin license header +// +// This file is part of Pixy CMUcam5 or "Pixy" for short +// +// All Pixy source code is provided under the terms of the +// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html). +// Those wishing to use Pixy source code, software and/or +// technologies under different licensing terms should contact us at +// cmucam@cs.cmu.edu. Such licensing terms are available for +// all portions of the Pixy codebase presented here. +// +// end license header +// + +/* + 06.04.2014 v0.1.3 John Leimon + + Added init() for initializing Pixy, which should + be called from the setup() function. See comment + in Pixy.h for details. +*/ + +#ifndef _TPIXY_H +#define _TPIXY_H + +#include + +#define PIXY_INITIAL_ARRAYSIZE 30 +#define PIXY_MAXIMUM_ARRAYSIZE 130 +#define PIXY_START_WORD 0xaa55 +#define PIXY_START_WORD_CC 0xaa56 +#define PIXY_START_WORDX 0x55aa +#define PIXY_DEFAULT_ADDR 0x54 // I2C + +enum BlockType +{ + NORMAL_BLOCK, + CC_BLOCK +}; + +struct Block +{ + void print() + { + // char buf[64]; + + printf("sig: %d x: %d y: %d width: %d height: %d angle %d\n", signature, x, y, width, height, angle); + // Serial.print(buf); + } + uint16_t signature; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + uint16_t angle; +}; + + + +template class TPixy +{ +public: + TPixy(uint8_t addr=PIXY_DEFAULT_ADDR); + ~TPixy(); + + uint16_t getBlocks(uint16_t maxBlocks=1000); + int8_t setServos(uint16_t s0, uint16_t s1); + void init(); + + Block getBlock (int s); + + Block *blocks; + +private: + boolean getStart(); + void resize(); + + LinkType link; + boolean skipStart; + BlockType blockType; + uint16_t blockCount; + uint16_t blockArraySize; +}; + + +template TPixy::TPixy(uint8_t addr) +{ + skipStart = false; + blockCount = 0; + blockArraySize = PIXY_INITIAL_ARRAYSIZE; + blocks = (Block *)malloc(sizeof(Block)*blockArraySize); + link.setAddress(addr); +} + +template void TPixy::init() +{ + link.init(); +} + +template TPixy::~TPixy() +{ + free(blocks); +} + +template Block TPixy::getBlock(int s) +{ + return blocks[s]; +} + +template boolean TPixy::getStart() +{ + uint16_t w, lastw; + + lastw = 0xffff; + + while(true) + { + w = link.getWord(); + if (w==0 && lastw==0) + { + delayMicroseconds(10); + return false; + } + else if (w==PIXY_START_WORD && lastw==PIXY_START_WORD) + { + blockType = NORMAL_BLOCK; + return true; + } + else if (w==PIXY_START_WORD_CC && lastw==PIXY_START_WORD) + { + blockType = CC_BLOCK; + return true; + } + else if (w==PIXY_START_WORDX) + { + // Serial.println("reorder"); + printf ("reorder"); + link.getByte(); // resync + } + lastw = w; + } +} + +template void TPixy::resize() +{ + blockArraySize += PIXY_INITIAL_ARRAYSIZE; + blocks = (Block *)realloc(blocks, sizeof(Block)*blockArraySize); +} + +template uint16_t TPixy::getBlocks(uint16_t maxBlocks) +{ + uint8_t i; + uint16_t w, checksum, sum; + Block *block; + + if (!skipStart) + { + if (getStart()==false) + return 0; + } + else + skipStart = false; + + for(blockCount=0; blockCountblockArraySize) + resize(); + + block = blocks + blockCount; + + for (i=0, sum=0; i=5) // skip + { + block->angle = 0; + break; + } + w = link.getWord(); + sum += w; + *((uint16_t *)block + i) = w; + } + + if (checksum==sum) + blockCount++; + else + // Serial.println("cs error"); + printf ("cs error"); + + w = link.getWord(); + if (w==PIXY_START_WORD) + blockType = NORMAL_BLOCK; + else if (w==PIXY_START_WORD_CC) + blockType = CC_BLOCK; + else + return blockCount; + } +} + +template int8_t TPixy::setServos(uint16_t s0, uint16_t s1) +{ + uint8_t outBuf[6]; + + outBuf[0] = 0x00; + outBuf[1] = 0xff; + *(uint16_t *)(outBuf + 2) = s0; + *(uint16_t *)(outBuf + 4) = s1; + + return link.send(outBuf, 6); +} + +#endif \ No newline at end of file