Pages: [1]   Go Down
Author Topic: Pass array size to class constructor  (Read 994 times)
0 Members and 1 Guest are viewing this topic.
Southern Ontario
Offline Offline
Sr. Member
****
Karma: 2
Posts: 279
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm creating a library to control an led ring board..  I have everything working perfectly without any classes..  The code allows the user to change the number of boards to control (they're running 5925's), so for the led status array I am using I won't know how many led boards there will be..  In normal procedural I used the fairly standard
Code:
#define NUM_RINGS 3
uint16_t ringState[NUM_RINGS] = 0;

however I am unsure how to proceed once I moved everything to it's own class...  Everything seems to be working, but it's not working... I have a feeling it has something to do with how the memory is getting allocated, but my knowledge in that area is severely lacking smiley-sad

I guess a tl;dr would be:

How would I create/define an object that would allow me to pass the size of a member array (two to be exact) in the constructor?

Code below:

Header
Code:
/*
  ledRings.h - Library for the Mayhew Labs Rotary Encoder LED Ring.
  Created by Nick Van Dorsten, April 03, 2011.
  Version 1: initial release
  Released into the public domain.
*/

#ifndef ledRings_h
#define ledRings_h
#include "WProgram.h"

class ledRings {
  public:
    byte dutyCycle;
    byte oldDutyCycle;
    byte num_led_rings;
    byte sdi;
    byte clk;
    byte le;
    uint16_t ringState[];
    uint16_t lastRingState[];
//    static const byte _NUM_LEDS_RING_ARC = 15;
//    static const byte _LED_RING_BOTTOM = 15;

    ledRings(byte sdi, byte clk, byte le, byte numRings);
    void setRingBrightness(byte dC);
    void updateLEDRings();
    void allRingsOff();
    void setRingState(byte ringNum, uint16_t state);
    void setRingLed(byte ringNum, byte ledNum, boolean state);
    void ringAllArcLedsOn(byte ringNum);
    void blinkRing(byte ringNum, byte cnt, uint16_t dly);
    void blinkAllRings(byte cnt, uint16_t dly);
};
#endif

Main Class
Code:
/*
  ledRings.cpp - Library for the Mayhew Labs Rotary Encoder LED Ring.
  Created by Nick Van Dorsten, April 03, 2011.
  Version 1: initial release
  Released into the public domain.
*/

#include "WProgram.h"
#include "ledRings.h"

ledRings::ledRings(byte sdiPin, byte clkPin, byte lePin, byte numRings) {
  for (byte i=0;i<numRings;i++) {
    ringState[i] = 0;
    lastRingState[i] = 1;
  }
  // Set SPI pins to output
  sdi = sdiPin;
  clk = clkPin;
  le = lePin;
  pinMode(sdi, OUTPUT);
  pinMode(clk, OUTPUT);
  pinMode(le,OUTPUT);
  num_led_rings = numRings;
  dutyCycle = 0;
  oldDutyCycle = 255;
}

void ledRings::setRingBrightness(byte dC) {
  dutyCycle = constrain(dC, 0, 255);
}

void ledRings::updateLEDRings() {
  // update the ring
  digitalWrite(le,LOW);
  for (int currentRing = num_led_rings-1;currentRing >= 0;currentRing--) {
    Serial.println(ringState[currentRing],BIN);
    shiftOut(sdi,clk,MSBFIRST,(ringState[currentRing] >> 8));    //High byte first
    shiftOut(sdi,clk,MSBFIRST,ringState[currentRing]);           //Low byte second
  }
  digitalWrite(le,HIGH);
}

void ledRings::allRingsOff() {
  // turn all leds off;
  for (byte i=0;i<num_led_rings;i++) {
    lastRingState[i] = 1;
    ringState[i] = 0;
  }
}

void ledRings::setRingState(byte ringNum, uint16_t state) {
  ringState[ringNum] = state;
}

void ledRings::setRingLed(byte ringNum, byte ledNum, boolean state) {
  bitWrite(ringState[ringNum], ledNum, state);
}

void ledRings::ringAllArcLedsOn(byte ringNum) {
  ringState[ringNum] = 0x7FFF;
}

void ledRings::blinkAllRings(byte cnt, uint16_t dly) {
  for (byte x=0;x<cnt;x++) {
    for (byte i=0;i<num_led_rings;i++) ringState[i] = 0xFFFF;
    delay(dly);
    for (byte i=0;i<num_led_rings;i++) ringState[i] = 0;
    delay(dly);
  }
}

void ledRings::blinkRing(byte ringNum, byte cnt, uint16_t dly) {
  for (byte i=0;i<cnt;i++) {
    ringState[ringNum] = 0xFFFF;
    delay(dly);
    ringState[ringNum] = 0;
    delay(dly);
  }
}
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In your header, you have defined the arrays to have 0 elements. What you then do in the constructor can not change the size of those arrays. You need to use malloc and pointers, instead:

In the header:
Code:
    uint16_t *ringState;
    uint16_t *lastRingState;

In the source code, in the constructor:
Code:
ringState = (uint16_t *)malloc(sizeof(uint16_t) * numRings);
lastRingState = (uint16_t *)malloc(sizeof(uint16_t) * numRings);

After allocating the memory, you can access the memory as though it was an array (since it is), just like you are now doing.
Logged

Southern Ontario
Offline Offline
Sr. Member
****
Karma: 2
Posts: 279
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks again as always Paul.. That worked perfectly smiley

Would you be so kind as to explain what the line does?  I get the malloc half, but the "(uint16_t *)malloc" half is a little confusing.  It looks as though you're casting the return of malloc, but that can't be right... Can it?
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Would you be so kind as to explain what the line does?
Sure. The malloc function allocates bytes of memory, and returns a pointer to that memory. The type that it returns is void *, so it almost always needs to be cast to the correct type. In your case, the (uint16_t *) cast is doing just that.

Inside the parentheses, you need to define how many bytes to allocate. The number of bytes is defined by the number of elements that the pointer points to (numRings) times the number of bytes in each element (sizeof(uint16_t)).
Logged

Pages: [1]   Go Up
Jump to: