I'm writing a library to support steppers and other goodness on the high current sixteen channel shift register controlled board I sell (
http://www.logos-electro.com/ard-srg-ips4x4-1/). I'm having a terrible problem with what I think is the linker that's causing it to fail in my example code.
Here's the header file:
/*
ShiftStepper.h - ShiftStepper library for Arduino
v0.01a Alpha
(c) Logos Electromechanical LLC 2010
Licensed under CC-BY-SA 3.0
This library is intended to drive Logos Electromechanical
shift register boards
This library is free software; you can redistribute it and/or
modify it under the terms of the Creative Commons By-Attribution
Share-Alike 3.0 Unported license.
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.
*/
#ifndef ShiftStepper_h
#define ShiftStepper_h
#include <stdint.h>
#include <inttypes.h>
#include <avr/io.h>
#include <inttypes.h>
#define __channelsPerMotor__ 4
#define __maxMotorSpeed__ 256
// static const uint8_t default4StepSequence[4] = {0x1, 0x2, 0x4, 0x8};
static const uint8_t default4StepSequence[4] = {0x2, 0x4, 0x1, 0x8};
static const uint8_t default8StepSequence[8] = {0x1,0x3,0x2,0x6,0x4,0xc,0x8,0x9};
class shiftDevice
{
protected:
uint8_t *channels; // array of channels in the object relative to the board
uint8_t chanCount; // number of channels per device, in device units
public:
virtual void doDevTick (uint8_t bytesPerBoard, uint8_t *boardBytes);
uint8_t *getChannels (void); // gets the byte array that holds the channels
uint8_t getChanCount (void); // gets the number of channels, in object units
};
class shiftStepMotor : public shiftDevice
{
private:
uint8_t stepState; // current index in the step sequence
int16_t stepSpeed; // sign gives directions, 32768 - magnitude is
// the number of timer ticks per step
uint16_t lastStep; // number of timer ticks since last step
uint16_t stepsToGo; // number of steps to go until we finish the current set
// set to -1 for continuous rotation
const uint8_t *sequence; // an array of pin configurations that correspond to the steps
uint8_t seqSteps; // number of steps in the sequence
uint8_t channels[__channelsPerMotor__];
// the array of channels in the board that correspond to the
// drive channels for this motor, measured in bits
uint8_t chanCount; // number of channels in the array
void incrSeq (void); // increment the step sequence by 1
void decrSeq (void); // decrement the step sequence by 1
public:
shiftStepMotor (const uint8_t seqSteps, const uint8_t *sequence, const uint8_t *channels);
// creates a shiftStepMotor object
uint8_t incrStep (int8_t dir); // go one step in the commanded direction
uint8_t doSteps (uint16_t steps, int16_t speed); // do steps at speed
uint8_t setSpeed (int16_t speed); // set speed
int16_t getSpeed (void); // get the current speed
int16_t getStepsToGo (void); // get the number of steps to go in the current move
void doDevTick (uint8_t bytesPerBoard, uint8_t *boardBytes);
};
class shiftBoard
{
protected:
uint8_t byteCount; // number of bytes of shift register on the board
uint8_t firstChan; // first active channel/byte/bit on the board
uint8_t lastChan; // last active channel/byte/bit on the board
shiftDevice **devices; // an array of pointers to all of the objects associated with this board
uint8_t devCount; // number of entries in the device array
public:
virtual void doBoardTick (uint8_t chainSize, uint8_t firstByte, uint8_t *chainBytes);
uint8_t getDevCount (void); // get the number of objects associated with the board
shiftDevice *getDev (uint8_t index); // get object at index
uint8_t getBoardSize (void); // returns the size of the board's datastream, in bytes
};
class shiftSixteen : public shiftBoard
{
public:
shiftSixteen (uint8_t devCount, shiftDevice **devices);
void doBoardTick(uint8_t chainSize, uint8_t firstByte, uint8_t *chainBytes);
};
class shiftChain
{
private:
shiftBoard **boards; // array of pointers to the board objects
uint8_t boardCount; // number of boards in the chain
uint8_t byteCount; // nuber of bytes in the chain
uint8_t timerPrescaler; // prescaler value to set timer frequency
uint8_t timerVal; // the value the timer starts off at after each tick
// together, these two values control the tick frequency
uint8_t timer; // the timer number we're using
uint8_t dataPort; // shift register data pin
uint8_t clockPort; // shift register clock pin
uint8_t latchPort; // shift register latch pin
uint8_t resetPort;
uint8_t dataPinMask; // shift register data pin
uint8_t clockPinMask; // shift register clock pin
uint8_t latchPinMask; // shift register latch pin
uint8_t resetPinMask; // shift register master reset pin
volatile uint8_t *clk;
volatile uint8_t *dat;
volatile uint8_t *lat;
volatile uint8_t *rst;
void fastShiftOut (uint8_t byteCount, uint8_t *bytes);
public:
shiftChain (uint8_t boardCount,
shiftBoard **boards,
uint8_t dataPin,
uint8_t clockPin,
uint8_t latchPin,
uint8_t resetPin);
uint8_t getBoardCount (void);
shiftBoard *getBoard (uint8_t index);
uint8_t startTimer (uint8_t prescaler, uint8_t timerVal, uint8_t timer);
uint8_t stopTimer (void);
void doTick (void);
};
// This is some strange linker food required to make it all work
// see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=410870
__extension__ typedef int __guard __attribute__((mode (__DI__)));
extern "C" int __cxa_guard_acquire(__guard *);
extern "C" void __cxa_guard_release (__guard *);
extern "C" void __cxa_guard_abort (__guard *);
#endif
Continued in the next message...