Go Down

Topic: char arrays and indexing -SOLVED- (Read 1 time) previous topic - next topic

jano

Feb 23, 2011, 07:35 am Last Edit: Mar 01, 2011, 12:39 am by jano Reason: 1
hi again!

i'm trying to make a lfo with pushbutton to choose the wave form, so i make some tables, store them on flash, and output it via pwm on timer 2, all fine until here if i call the table directly but now i want to add the button (for testing i just point the index to '0'), so i put an array of char (char*) for indexing the tables and i have only garbage at pwm output
i checked the option of the array by putting a serialprint and it says the 'correct' name of the string, but for some reason the function to assign the table in memory don't works
any help will be appreciated :)

here is the code:

Code: [Select]

#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <pins_arduino.h>

//tabla seno para lfo, un ciclo
PROGMEM prog_uchar sine[] = {
 127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
 242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
 221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
 76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
 33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124};

PROGMEM prog_uchar squa[] = {
 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};




//funciones clear bit y set bit
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

//variables para lfo
int lfo_speed;
boolean lfo_rotate;
const int lfo_rotate_pin=2;
int lfo_wave_num=0;
char* lfo_wave[]= {"sine", "squa"};

// variables en la interrupcion 2 (lfo + velocity)
volatile byte icnt;              // var inside interrupt
volatile byte icnt1;             // var inside interrupt
volatile byte c4ms;              // counter incremented all 4ms
volatile unsigned long phaccu;   // pahse accumulator
volatile unsigned long tword_lfo;  // dds tuning word m

void setup() {


 pinMode(11,OUTPUT);      // pin11= PWM del LFO - timer 2 - OC2A
 pinMode(3, OUTPUT);   // pin3=  PWM Velocity - timer 2 - OC2B

 cli();


 Setup_timer2();

 sbi (TIMSK2,TOIE2);           //habilita la interrupcion del timer 2

 sei();

}

void loop () {

if (c4ms > 10) {                 // lee cada 10ms

   
   c4ms=0;
   lfo_speed=analogRead(2);      // lee el potenciometro conectado en 2 LFO_Speed
   tword_lfo=50000*lfo_speed+1000;          
 }

}

void Setup_timer2() {

 // Timer2 Clock Prescaler to : 1
 sbi (TCCR2B, CS20);
 cbi (TCCR2B, CS21);
 cbi (TCCR2B, CS22);

 // Timer2 PWM Mode set to Phase Correct PWM
 cbi (TCCR2A, COM2A0);  // clear Compare Match
 sbi (TCCR2A, COM2B1);
 sbi (TCCR2A, COM2A1);

 sbi (TCCR2A, WGM20);  // Mode 1  / Phase Correct PWM
 cbi (TCCR2A, WGM21);
 cbi (TCCR2B, WGM22);
}

ISR(TIMER2_OVF_vect) {

 phaccu=phaccu+tword_lfo; // soft DDS, phase accu with 32 bits
 icnt=phaccu >> 24;     // use upper 8 bits for phase accu as frequency information
 // read value fron ROM sine table and send to PWM

// OCR2A=pgm_read_byte_near(sine + icnt); // pin 11 lfo
 OCR2B=pgm_read_byte_near(lfo_wave[lfo_wave_num] + icnt); // pin 3 velocity

 if (icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds
   c4ms++;
   icnt1=0;
 }  
   

}

johnwasser

Your table contains character strings with the NAMES of the two tables, not a reference to the table itself.

I think you want something like:

prog_uchar* lfo_wave[]= {sine, squa};
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

davekw7x

#2
Feb 23, 2011, 06:34 pm Last Edit: Feb 24, 2011, 01:47 am by davekw7x Reason: 1
One way:
Code: [Select]

//
// Illustration of multiple function lookup tables (arrays) in Program Memory
//
//  davekw7x
//
#include <avr/pgmspace.h>

PROGMEM const prog_uchar f1[256] =
   //Put 256 values for the first function lookup table here
   { 1, 2, 3, 4, 5, 6, /*...*/};

PROGMEM const prog_uchar f2[256] =
   //Put 256 values for the second function lookup table here
   {101, 102, 103, 104, 105, 106/*...*/};

// As many as you want


//
// Table of pointers.  Entries are the addresses of the first elements of the function arrays
//
PROGMEM const prog_uchar *functionTables[] = {f1, f2};

//
//If you want names, define one for each function
//
PROGMEM const prog_char name1[] = "Potrzebie";
PROGMEM const prog_char name2[] = "Zaphod Beeblebrox";


//
// Table of pointers.  Entries are the addresses of the first chars of the name strings
//
PROGMEM const prog_char *functionNames[] = {name1, name2};


void setup()
{
   Serial.begin(9600);
   for (int functionNumber = 0; functionNumber < 2; functionNumber++) {

       char nameBuffer[80] = {0}; // Must be large enough to hold longest name (+ 1 char for terminating zero)

       // Read pointer from table of pointers
       prog_char *namePointer = (prog_char *)pgm_read_word(&functionNames[functionNumber]);
       // Could write it like this:
       //prog_char *namePointer = (prog_char *)pgm_read_word(functionNames + functionNumber);
       
       // Copy the name from the name table to the buffer for printing.
       strncpy_P(nameBuffer, (char *)namePointer, sizeof(nameBuffer)-1);
       Serial.print("Function number ");Serial.print(functionNumber);Serial.print(": Name is '");
       Serial.print(nameBuffer);Serial.println("'");
       for (int icnt = 0; icnt < 6; icnt++) {

           // Read pointer from table of pointers
           prog_uchar *functionPointer = (prog_uchar *)pgm_read_word(&functionTables[functionNumber]);
           // Could write it like this:
           //prog_uchar *functionPointer = (prog_uchar *)pgm_read_word(functionTables+functionNumber);
           
           // Read byte from the table
           byte x = pgm_read_byte(&functionPointer[icnt]);
           //Could write it like this:
           //byte x = pgm_read_byte(functionPointer+icnt);

           Serial.print("  ");Serial.print(icnt);Serial.print(": ");Serial.println(x,DEC);
       }
       Serial.println();
   }
}

void loop(){}


Output:


Function number 0: Name is 'Potrzebie'
 0: 1
 1: 2
 2: 3
 3: 4
 4: 5
 5: 6

Function number 1: Name is 'Zaphod Beeblebrox'
 0: 101
 1: 102
 2: 103
 3: 104
 4: 105
 5: 106



Regards,

Dave

jano

thanks for reply! i will try as soon as i can do  :smiley-roll-blue:

jano

yes! it works!

thanks Dave for the hint. here is the working code (far to be complete, but get closing):

Code: [Select]
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <pins_arduino.h>

//tabla seno para lfo, un ciclo
PROGMEM const prog_uchar seno[] = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124};

PROGMEM const prog_uchar squa[] = {
  250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
  250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
  250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

PROGMEM const prog_uchar *functionTables[] = {seno, squa};


//funciones clear bit y set bit
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

//variables para lfo
int lfo_speed;
boolean lfo_rotate;
const int lfo_rotate_pin=2;
int lfo_wave_num=1;


// variables en la interrupcion 2 (lfo + velocity)
volatile byte icnt;              // var inside interrupt
volatile byte icnt1;             // var inside interrupt
volatile byte c4ms;              // counter incremented all 4ms
volatile unsigned long phaccu;   // pahse accumulator
volatile unsigned long tword_lfo;  // dds tuning word m

void setup() {


  pinMode(11,OUTPUT);      // pin11= PWM del LFO - timer 2 - OC2A
  pinMode(3, OUTPUT);    // pin3=  PWM Velocity - timer 2 - OC2B

  cli();


  Setup_timer2();

  sbi (TIMSK2,TOIE2);           //habilita la interrupcion del timer 2

  sei();

}

void loop () {

if (c4ms > 10) {                 // lee cada 10ms

   
    c4ms=0;
    lfo_speed=analogRead(2);      // lee el potenciometro conectado en 2 LFO_Speed
    tword_lfo=50000*lfo_speed+1000;           
  }
 
 

   
 
}

void Setup_timer2() {

  // Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);

  // Timer2 PWM Mode set to Phase Correct PWM
  cbi (TCCR2A, COM2A0);  // clear Compare Match
  sbi (TCCR2A, COM2B1);
  sbi (TCCR2A, COM2A1);

  sbi (TCCR2A, WGM20);  // Mode 1  / Phase Correct PWM
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);
}

ISR(TIMER2_OVF_vect) {

  phaccu=phaccu+tword_lfo; // soft DDS, phase accu with 32 bits
  icnt=phaccu >> 24;     // use upper 8 bits for phase accu as frequency information
 
  // read value fron ROM sine table and send to PWM
  prog_uchar *functionPointer = (prog_uchar *)pgm_read_word(&functionTables[lfo_wave_num]);
  OCR2A=pgm_read_byte(&functionPointer[icnt]); // pin 11 lfo

  if (icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds
    c4ms++;
    icnt1=0;
  }   
     

}

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy