Main Site Documentation

Rlp procedure cutdown


#1

RLP.enable() command reserves 10 kB of ram. I have Panda 2 and I am trying to load elf file containing procedures. Of course I got memory exception, then I shrinked elf file by removing two last procedures and it worked. I was wondering is there any way to break 10 kB barrier by reserving more memory? I have tried changing the data types from double to float for example but that wasn’t enough.
This is my code:


 #include "RLP.h"
 #define ADC_DATA_BASE_ADDRESS 0xE0034010
 #define RLP_ADDRESS		0x40000440
 #define RLP_SIZE		0x000027FC

int GHAL_AnalogIn_Read(unsigned char channel)
{
        return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,
              unsigned int *argSize)
{
        unsigned char *buffer = (unsigned char*)args[0];
        int buffer_lengh = argSize[0];
        unsigned char channel = *(unsigned char*)args[1];
        int i=0;
        while(i<buffer_lengh)
        {
           buffer[i] = GHAL_AnalogIn_Read(channel);
           i++;
           RLPext->Delay(125);
        }
        return 0;
}

float cos(float x)
{
    x+=1.5707963267944118;
    float x2 = x*x;
    float x4 = x2*x2;
    float t1 = x * (1.0 - x2 / (2*3));
    float x5 = x * x4;
    float t2 = x5 * (1.0 - x2 / (6*7)) / (1.0* 2*3*4*5);
    float x9 = x5 * x4;
    float t3 = x9 * (1.0 - x2 / (10*11)) / (1.0* 2*3*4*5*6*7*8*9);
    float x13 = x9 * x4;
    float t4 = x13 * (1.0 - x2 / (14*15)) / (1.0* 2*3*4*5*6*7*8*9*10*11*12*13);
    float result = t4;
    result += t3;
    result += t2;
    result += t1;

    return result;
}

void PlainFFTwindowing(double *vData)
{
    unsigned i = 0;
    for (i = 0; i < (128 >> 1); i++)
    {
        unsigned indexMinusOne = i;
        double ratio = (indexMinusOne / 127);
        float weighingFactor = 1.0;
        weighingFactor = 0.54 - (0.46 * cos(2.0 * 3.141592653 * ratio));
        vData[i] *= weighingFactor;
        vData[128 - (i + 1)] *= weighingFactor;
    }
}

void swap(double *i, double *j)
{
  double temp;
  temp = *i;
  *i = *j;
  *j = temp;
}
float sqrt(float m)
{
     float i=0;
   float x1,x2;
   while( (i*i) <= m )
          i+=0.1;
   x1=i;
   int j;
   for(j=0;j<10;j++)
   {
        x2=m;
      x2/=x1;
      x2+=x1;
      x2/=2;
      x1=x2;
   }
   return x2;
}
double PlainFFTcomplexToMagnitude(double *vR, double *vI)
{
    double freq,max;
    unsigned i,maxIndex;
    maxIndex=1;
    max=0.0;

    for (i = 0; i < 128; i++)
    {
        vR[i] = sqrt((vR[i])*(vR[i]) + (vI[i])*(vI[i]));
    }

    for(i=1;i<64;i++)
    {
        if(vR[i]>max)
        {
            max=vR[i];
            maxIndex=i;
        }
    }
    freq = maxIndex * 10000 / 128;
    return freq;
}

void PlainFFTcompute(double *vR, double *vI, unsigned samples)
{
    unsigned j = 0;
    unsigned i;
    for (i = 0; i < 127; i++)
    {
        if (i < j)
        {
             swap(&vR[i], &vR[j]);
             swap(&vI[i], &vI[j]);
        }
        unsigned k = (128 >> 1);
        while (k <= j)
        {
             j -= k;
             k >>= 1;
        }
        j += k;
    }
    double c1 = -1.0;
    double c2 = 0.0;
    unsigned l2 = 1;
    unsigned l;
    for (l = 0; l < 7; l++)
    {
        unsigned l1 = l2;
        l2 <<= 1;
        double u1 = 1.0;
        double u2 = 0.0;
        for (j = 0; j < l1; j++)
        {
             unsigned i;
             for (i = j; i < 128; i += l2)
             {
                    unsigned i1 = i + l1;
                    double t1 = u1 * vR[i1] - u2 * vI[i1];
                    double t2 = u1 * vI[i1] + u2 * vR[i1];
                    vR[i1] = vR[i] - t1;
                    vI[i1] = vI[i] - t2;
                    vR[i] += t1;
                    vI[i] += t2;
             }
             double z = (u1 * c1) - (u2 * c2);
             u2 = (u1 * c2) + (u2 * c1);
             u1 = z;
        }
        c2 = sqrt((1.0 - c1) / 2.0);
        c2 = -c2;
        c1 = sqrt((1.0 + c1) / 2.0);
    }
        unsigned p;
       for (p = 0; p < 128; p++)
        {
             vR[p] /= 128;
             vI[p] /= 128;
        }
}


#2

FFT! I love the sound of that :slight_smile: Can you tell us more about what you are doing?

Did enable optimization? 10KB is plenty in most cases.


#3

I got some c code, modified it a little bit and tested it in codeblocks and it works. Now I have modified it a little bit more and I am trying to implement it on Panda. Max readable frequency is 4000 Hz. I have tried to change variable types but that still isn’t enough. I could make few smaller elf files and then cycle through call-flush but that will probably cause too much delay.


#4

Compiler optimization?


#5

I’ll get back to you when I come up with something.


#6

How big is your bin file?

I get 2,336 bytes.

The elf file is 13,623 bytes but most should be dumped after procedure extraction…


#7

I’m using yagarto tool. When I compile posted code I get elf file weighting 18158 bytes. I changed all doubles to floats and did some loops optimisation but I have come as far as aprox 16000 bytes. Minimum size for elf file that can be successfully loaded on Panda is 15360 bytes. I tried to load multiple smaller elf files but that just caused some mess, I think garbage collector wasn’t doing it’s job so frequently.

@ Errol, how did you managed to get 13623 byte elf, and what exactly you mean by bin file?


#8

That is your ELF size, not your application size. The reserved 10KB is for your application not the ELF.

see this on removing symbols http://www.tinyclr.com/forum/17/3257/#/1/msg34912


#9

The elf file contains a lot of debug info. If you open it in something like notepad++ then you will see that the paths of source files are included etc. The bin file doesn’t include all this info, but that means that RPL can’t extract the procedure locations. Then you must provide all the data manually by reading the MAP file.

I made some changes to my makefile. Maybe that helps…

####################################################
 ###### Copyright(c) GHI Electronics, LLC ######
 ####################################################

OUTFILE=RLP_Native
LINKERSCRIPT = RLP_LinkScript.lds


INCL=./include

CC		=arm-none-eabi-gcc
LD		=arm-none-eabi-gcc

CCFLAGS=  -g -mlittle-endian -mcpu=arm7tdmi  -Wall -I. -I$(INCL)
 #Added -Os
CCFLAGS+= -mapcs-frame -fno-builtin -g0 -Os

LDFLAGS =-nostartfiles -Wl,--Map -Wl,./Output/$(OUTFILE).map
LDFLAGS+=-lc -lgcc -Wl,--omagic
LDFLAGS+=-T $(LINKERSCRIPT)

OBJS+= RLP_Native.o \

rebuild: clean all del_o

all: $(OBJS)
	$(LD) $(LDFLAGS) -o ./Output/$(OUTFILE).elf $(OBJS)
	#arm-none-eabi-objcopy -O binary ./Output/$(OUTFILE).elf ./Output/$(OUTFILE).bin

RLP_Native.o: RLP_Native.c 
	$(CC) -c $(CCFLAGS) RLP_Native.c -o RLP_Native.o

clean:
	-rm *.o ./Output/*.elf ./Output/*.map

del_o:
	-rm *.o

del_map:
	-rm ./Output/*.map


#10

@ Dr_Freeman: have you already enabled optimisation in your makefile like Gus suggested? I think it’s the -O3 option you need to add to CCFLAGS


#11

@ Errol, thank you, I have managed to shrink elf file and it works like a charm. There are some microphone issues, I will post another topic. Just one little step and it’s done, I just need to be sure. Thank you all.


#12

This is the final code, works to max 5kHz.

Native:


 #include "RLP.h"

 #define ADC_DATA_BASE_ADDRESS 0xE0034010
 #define RLP_ADDRESS		0x40000440
 #define RLP_SIZE		0x000027FC

 #define pi 3.14159265358979323846

float vReal[128];
float vImag[128];
float samples=128;
float sampling=10000;

float sqrt(float m)
{
   float i=0;
   float x1,x2;
   while( (i*i) <= m )
          i+=0.1;
   x1=i;
   int j;
   for(j=0;j<10;j++)
   {
        x2=m;
      x2/=x1;
      x2+=x1;
      x2/=2;
      x1=x2;
   }
   return x2;
}

float cos(float x)
{
    x+=1.5707963267944118;
    float x2 = x*x;
    float x4 = x2*x2;
    float t1 = x * (1.0 - x2 / (2*3));
    float x5 = x * x4;
    float t2 = x5 * (1.0 - x2 / (6*7)) / (1.0* 2*3*4*5);
    float x9 = x5 * x4;
    float t3 = x9 * (1.0 - x2 / (10*11)) / (1.0* 2*3*4*5*6*7*8*9);
    float x13 = x9 * x4;
    float t4 = x13 * (1.0 - x2 / (14*15)) / (1.0* 2*3*4*5*6*7*8*9*10*11*12*13);
    float result = t4;
    result += t3;
    result += t2;
    result += t1;

    return result;
}



void Windowing(float *vData,unsigned samples)
{
    unsigned i;
    for (i = 0; i < (samples >> 1); i++)
    {
        float indexMinusOne = i;
        float ratio = (indexMinusOne / (samples-1));
        float weighingFactor = 1.0;
        weighingFactor = 0.54 - (0.46 * cos(2.0 * 3.141592653 * ratio));
        vData[i] *= weighingFactor;
        vData[samples - (i + 1)] *= weighingFactor;
    }
}

void swap(float *i, float *j)
{
  float temp;

  temp = *i;
  *i = *j;
  *j = temp;
}
void Fft(float *vR, float *vI,unsigned samples)
{
    unsigned j = 0;
    unsigned i;
    for (i = 0; i < (samples-1); i++)
    {
        if (i < j)
        {
             swap(&vR[i], &vR[j]);
             swap(&vI[i], &vI[j]);
        }
        unsigned k = (samples >> 1);
        while (k <= j)
        {
             j -= k;
             k >>= 1;
        }
        j += k;
    }
    float c1 = -1.0;
    float c2 = 0.0;
    unsigned l2 = 1;
    unsigned l;
    for (l = 0; l < 7; l++)// 7=exponent(samples)
    {
        unsigned l1 = l2;
        l2 <<= 1;
        float u1 = 1.0;
        float u2 = 0.0;
        for (j = 0; j < l1; j++)
        {
            unsigned i;
             for (i = j; i < samples; i += l2)
             {
                    unsigned i1 = i + l1;
                    float t1 = u1 * vR[i1] - u2 * vI[i1];
                    float t2 = u1 * vI[i1] + u2 * vR[i1];
                    vR[i1] = vR[i] - t1;
                    vI[i1] = vI[i] - t2;
                    vR[i] += t1;
                    vI[i] += t2;
             }
             float z = (u1 * c1) - (u2 * c2);
             u2 = (u1 * c2) + (u2 * c1);
             u1 = z;
        }
        c2 = sqrt((1.0 - c1) / 2.0);
        c2 = -c2;
        c1 = sqrt((1.0 + c1) / 2.0);
    }
       for (i = 0; i < samples; i++)
        {
             vR[i] /= samples;
             vI[i] /= samples;
        }
}

float getFundamental(float *vR, float *vI,unsigned samples)
{
    float freq,max;
    unsigned i,maxIndex;
    maxIndex=1;
    max=0.0;
    for (i = 0; i < samples; i++)
    {
        vR[i] = sqrt((vR[i])*(vR[i]) + (vI[i])*(vI[i]));
    }

    for(i=1;i<samples/2;i++)
    {
        if(vR[i]>max)
        {
            max=vR[i];
            maxIndex=i;
        }
    }
    freq = maxIndex * sampling / samples;
    return freq;
}

int GHAL_AnalogIn_Read(unsigned char channel)
{
        return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{

        int i=0;
        float x;
        unsigned char channel = *(unsigned char*)args[0];
        while(i<samples)
        {
           vImag[i]=0;
           vReal[i] =(unsigned char)GHAL_AnalogIn_Read(channel)-120;//-120 because of my mic, but it's not necessary
           i++;
           RLPext->Delay(100);
        }


        Windowing(vReal,samples);
        Fft(vReal, vImag,samples);
        x=getFundamental(vReal, vImag,samples);


    return x;
}



Managed:


using System;
using System.IO;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Native;

namespace rlp1
{
    public class Program

    {
        
        static RLP.Procedure ReadAudio;
        static byte[] dataRPLWave = new byte[128];
        static AnalogOut aout = new AnalogOut(AnalogOut.Pin.Aout0);
        public static void Main()
        {
            Debug.GC(true);
            RLP.Enable();
            RLP.Unlock("removed by admin!");

            byte[] elf_file = Resources.GetBytes(Resources.BinaryResources.FFT1);
            RLP.LoadELF(elf_file);
            RLP.InitializeBSSRegion(elf_file); 
            ReadAudio = RLP.GetProcedure(elf_file, "ReadAudio");
            elf_file = null;
            Debug.GC(true);
          
            int i = 0;
            while (true)
            {
                AnalogIn ain = new AnalogIn(AnalogIn.Pin.Ain1);
                Debug.Print(ReadAudio.Invoke((byte)AnalogIn.Pin.Ain1).ToString());
                ain.Dispose();
                i++;
                Thread.Sleep(1);
            }
          
        }

    }
}

You are welcome to test it…


#13

This is the final code, works to max 5kHz.

Native:


 #include "RLP.h"

 #define ADC_DATA_BASE_ADDRESS 0xE0034010
 #define RLP_ADDRESS		0x40000440
 #define RLP_SIZE		0x000027FC

 #define pi 3.14159265358979323846

float vReal[128];
float vImag[128];
float samples=128;
float sampling=10000;

float sqrt(float m)
{
   float i=0;
   float x1,x2;
   while( (i*i) <= m )
          i+=0.1;
   x1=i;
   int j;
   for(j=0;j<10;j++)
   {
        x2=m;
      x2/=x1;
      x2+=x1;
      x2/=2;
      x1=x2;
   }
   return x2;
}

float cos(float x)
{
    x+=1.5707963267944118;
    float x2 = x*x;
    float x4 = x2*x2;
    float t1 = x * (1.0 - x2 / (2*3));
    float x5 = x * x4;
    float t2 = x5 * (1.0 - x2 / (6*7)) / (1.0* 2*3*4*5);
    float x9 = x5 * x4;
    float t3 = x9 * (1.0 - x2 / (10*11)) / (1.0* 2*3*4*5*6*7*8*9);
    float x13 = x9 * x4;
    float t4 = x13 * (1.0 - x2 / (14*15)) / (1.0* 2*3*4*5*6*7*8*9*10*11*12*13);
    float result = t4;
    result += t3;
    result += t2;
    result += t1;

    return result;
}



void Windowing(float *vData,unsigned samples)
{
    unsigned i;
    for (i = 0; i < (samples >> 1); i++)
    {
        float indexMinusOne = i;
        float ratio = (indexMinusOne / (samples-1));
        float weighingFactor = 1.0;
        weighingFactor = 0.54 - (0.46 * cos(2.0 * 3.141592653 * ratio));
        vData[i] *= weighingFactor;
        vData[samples - (i + 1)] *= weighingFactor;
    }
}

void swap(float *i, float *j)
{
  float temp;

  temp = *i;
  *i = *j;
  *j = temp;
}
void Fft(float *vR, float *vI,unsigned samples)
{
    unsigned j = 0;
    unsigned i;
    for (i = 0; i < (samples-1); i++)
    {
        if (i < j)
        {
             swap(&vR[i], &vR[j]);
             swap(&vI[i], &vI[j]);
        }
        unsigned k = (samples >> 1);
        while (k <= j)
        {
             j -= k;
             k >>= 1;
        }
        j += k;
    }
    float c1 = -1.0;
    float c2 = 0.0;
    unsigned l2 = 1;
    unsigned l;
    for (l = 0; l < 7; l++)// 7=exponent(samples)
    {
        unsigned l1 = l2;
        l2 <<= 1;
        float u1 = 1.0;
        float u2 = 0.0;
        for (j = 0; j < l1; j++)
        {
            unsigned i;
             for (i = j; i < samples; i += l2)
             {
                    unsigned i1 = i + l1;
                    float t1 = u1 * vR[i1] - u2 * vI[i1];
                    float t2 = u1 * vI[i1] + u2 * vR[i1];
                    vR[i1] = vR[i] - t1;
                    vI[i1] = vI[i] - t2;
                    vR[i] += t1;
                    vI[i] += t2;
             }
             float z = (u1 * c1) - (u2 * c2);
             u2 = (u1 * c2) + (u2 * c1);
             u1 = z;
        }
        c2 = sqrt((1.0 - c1) / 2.0);
        c2 = -c2;
        c1 = sqrt((1.0 + c1) / 2.0);
    }
       for (i = 0; i < samples; i++)
        {
             vR[i] /= samples;
             vI[i] /= samples;
        }
}

float getFundamental(float *vR, float *vI,unsigned samples)
{
    float freq,max;
    unsigned i,maxIndex;
    maxIndex=1;
    max=0.0;
    for (i = 0; i < samples; i++)
    {
        vR[i] = sqrt((vR[i])*(vR[i]) + (vI[i])*(vI[i]));
    }

    for(i=1;i<samples/2;i++)
    {
        if(vR[i]>max)
        {
            max=vR[i];
            maxIndex=i;
        }
    }
    freq = maxIndex * sampling / samples;
    return freq;
}

int GHAL_AnalogIn_Read(unsigned char channel)
{
        return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{

        int i=0;
        float x;
        unsigned char channel = *(unsigned char*)args[0];
        while(i<samples)
        {
           vImag[i]=0;
           vReal[i] =(unsigned char)GHAL_AnalogIn_Read(channel)-120;//-120 because of my mic, but it's not necessary
           i++;
           RLPext->Delay(100);
        }


        Windowing(vReal,samples);
        Fft(vReal, vImag,samples);
        x=getFundamental(vReal, vImag,samples);


    return x;
}



Managed:


using System;
using System.IO;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Native;

namespace rlp1
{
    public class Program

    {
        
        static RLP.Procedure ReadAudio;
        static byte[] dataRPLWave = new byte[128];
        static AnalogOut aout = new AnalogOut(AnalogOut.Pin.Aout0);
        public static void Main()
        {
            Debug.GC(true);
            RLP.Enable();
            RLP.Unlock("removed by admin!");

            byte[] elf_file = Resources.GetBytes(Resources.BinaryResources.FFT1);
            RLP.LoadELF(elf_file);
            RLP.InitializeBSSRegion(elf_file); 
            ReadAudio = RLP.GetProcedure(elf_file, "ReadAudio");
            elf_file = null;
            Debug.GC(true);
          
            int i = 0;
            while (true)
            {
                AnalogIn ain = new AnalogIn(AnalogIn.Pin.Ain1);
                Debug.Print(ReadAudio.Invoke((byte)AnalogIn.Pin.Ain1).ToString());
                ain.Dispose();
                i++;
                Thread.Sleep(1);
            }
          
        }

    }
}

You are welcome to test it…


#14

This is the final code, works to max 5kHz.

Native:


 #include "RLP.h"

 #define ADC_DATA_BASE_ADDRESS 0xE0034010
 #define RLP_ADDRESS		0x40000440
 #define RLP_SIZE		0x000027FC

 #define pi 3.14159265358979323846

float vReal[128];
float vImag[128];
float samples=128;
float sampling=10000;

float sqrt(float m)
{
   float i=0;
   float x1,x2;
   while( (i*i) <= m )
          i+=0.1;
   x1=i;
   int j;
   for(j=0;j<10;j++)
   {
        x2=m;
      x2/=x1;
      x2+=x1;
      x2/=2;
      x1=x2;
   }
   return x2;
}

float cos(float x)
{
    x+=1.5707963267944118;
    float x2 = x*x;
    float x4 = x2*x2;
    float t1 = x * (1.0 - x2 / (2*3));
    float x5 = x * x4;
    float t2 = x5 * (1.0 - x2 / (6*7)) / (1.0* 2*3*4*5);
    float x9 = x5 * x4;
    float t3 = x9 * (1.0 - x2 / (10*11)) / (1.0* 2*3*4*5*6*7*8*9);
    float x13 = x9 * x4;
    float t4 = x13 * (1.0 - x2 / (14*15)) / (1.0* 2*3*4*5*6*7*8*9*10*11*12*13);
    float result = t4;
    result += t3;
    result += t2;
    result += t1;

    return result;
}



void Windowing(float *vData,unsigned samples)
{
    unsigned i;
    for (i = 0; i < (samples >> 1); i++)
    {
        float indexMinusOne = i;
        float ratio = (indexMinusOne / (samples-1));
        float weighingFactor = 1.0;
        weighingFactor = 0.54 - (0.46 * cos(2.0 * 3.141592653 * ratio));
        vData[i] *= weighingFactor;
        vData[samples - (i + 1)] *= weighingFactor;
    }
}

void swap(float *i, float *j)
{
  float temp;

  temp = *i;
  *i = *j;
  *j = temp;
}
void Fft(float *vR, float *vI,unsigned samples)
{
    unsigned j = 0;
    unsigned i;
    for (i = 0; i < (samples-1); i++)
    {
        if (i < j)
        {
             swap(&vR[i], &vR[j]);
             swap(&vI[i], &vI[j]);
        }
        unsigned k = (samples >> 1);
        while (k <= j)
        {
             j -= k;
             k >>= 1;
        }
        j += k;
    }
    float c1 = -1.0;
    float c2 = 0.0;
    unsigned l2 = 1;
    unsigned l;
    for (l = 0; l < 7; l++)// 7=exponent(samples)
    {
        unsigned l1 = l2;
        l2 <<= 1;
        float u1 = 1.0;
        float u2 = 0.0;
        for (j = 0; j < l1; j++)
        {
            unsigned i;
             for (i = j; i < samples; i += l2)
             {
                    unsigned i1 = i + l1;
                    float t1 = u1 * vR[i1] - u2 * vI[i1];
                    float t2 = u1 * vI[i1] + u2 * vR[i1];
                    vR[i1] = vR[i] - t1;
                    vI[i1] = vI[i] - t2;
                    vR[i] += t1;
                    vI[i] += t2;
             }
             float z = (u1 * c1) - (u2 * c2);
             u2 = (u1 * c2) + (u2 * c1);
             u1 = z;
        }
        c2 = sqrt((1.0 - c1) / 2.0);
        c2 = -c2;
        c1 = sqrt((1.0 + c1) / 2.0);
    }
       for (i = 0; i < samples; i++)
        {
             vR[i] /= samples;
             vI[i] /= samples;
        }
}

float getFundamental(float *vR, float *vI,unsigned samples)
{
    float freq,max;
    unsigned i,maxIndex;
    maxIndex=1;
    max=0.0;
    for (i = 0; i < samples; i++)
    {
        vR[i] = sqrt((vR[i])*(vR[i]) + (vI[i])*(vI[i]));
    }

    for(i=1;i<samples/2;i++)
    {
        if(vR[i]>max)
        {
            max=vR[i];
            maxIndex=i;
        }
    }
    freq = maxIndex * sampling / samples;
    return freq;
}

int GHAL_AnalogIn_Read(unsigned char channel)
{
        return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{

        int i=0;
        float x;
        unsigned char channel = *(unsigned char*)args[0];
        while(i<samples)
        {
           vImag[i]=0;
           vReal[i] =(unsigned char)GHAL_AnalogIn_Read(channel)-120;//-120 because of my mic, but it's not necessary
           i++;
           RLPext->Delay(100);
        }


        Windowing(vReal,samples);
        Fft(vReal, vImag,samples);
        x=getFundamental(vReal, vImag,samples);


    return x;
}



Managed:


using System;
using System.IO;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Native;

namespace rlp1
{
    public class Program

    {
        
        static RLP.Procedure ReadAudio;
        static byte[] dataRPLWave = new byte[128];
        static AnalogOut aout = new AnalogOut(AnalogOut.Pin.Aout0);
        public static void Main()
        {
            Debug.GC(true);
            RLP.Enable();
            RLP.Unlock("Removed by admin!");

            byte[] elf_file = Resources.GetBytes(Resources.BinaryResources.FFT1);
            RLP.LoadELF(elf_file);
            RLP.InitializeBSSRegion(elf_file); 
            ReadAudio = RLP.GetProcedure(elf_file, "ReadAudio");
            elf_file = null;
            Debug.GC(true);
          
            int i = 0;
            while (true)
            {
                AnalogIn ain = new AnalogIn(AnalogIn.Pin.Ain1);
                Debug.Print(ReadAudio.Invoke((byte)AnalogIn.Pin.Ain1).ToString());
                ain.Dispose();
                i++;
                Thread.Sleep(1);
            }
          
        }

    }
}

You are welcome to test it…


#15

This is the final code, works to max 5kHz.

Native:


 #include "RLP.h"

 #define ADC_DATA_BASE_ADDRESS 0xE0034010
 #define RLP_ADDRESS		0x40000440
 #define RLP_SIZE		0x000027FC

 #define pi 3.14159265358979323846

float vReal[128];
float vImag[128];
float samples=128;
float sampling=10000;

float sqrt(float m)
{
   float i=0;
   float x1,x2;
   while( (i*i) <= m )
          i+=0.1;
   x1=i;
   int j;
   for(j=0;j<10;j++)
   {
        x2=m;
      x2/=x1;
      x2+=x1;
      x2/=2;
      x1=x2;
   }
   return x2;
}

float cos(float x)
{
    x+=1.5707963267944118;
    float x2 = x*x;
    float x4 = x2*x2;
    float t1 = x * (1.0 - x2 / (2*3));
    float x5 = x * x4;
    float t2 = x5 * (1.0 - x2 / (6*7)) / (1.0* 2*3*4*5);
    float x9 = x5 * x4;
    float t3 = x9 * (1.0 - x2 / (10*11)) / (1.0* 2*3*4*5*6*7*8*9);
    float x13 = x9 * x4;
    float t4 = x13 * (1.0 - x2 / (14*15)) / (1.0* 2*3*4*5*6*7*8*9*10*11*12*13);
    float result = t4;
    result += t3;
    result += t2;
    result += t1;

    return result;
}



void Windowing(float *vData,unsigned samples)
{
    unsigned i;
    for (i = 0; i < (samples >> 1); i++)
    {
        float indexMinusOne = i;
        float ratio = (indexMinusOne / (samples-1));
        float weighingFactor = 1.0;
        weighingFactor = 0.54 - (0.46 * cos(2.0 * 3.141592653 * ratio));
        vData[i] *= weighingFactor;
        vData[samples - (i + 1)] *= weighingFactor;
    }
}

void swap(float *i, float *j)
{
  float temp;

  temp = *i;
  *i = *j;
  *j = temp;
}
void Fft(float *vR, float *vI,unsigned samples)
{
    unsigned j = 0;
    unsigned i;
    for (i = 0; i < (samples-1); i++)
    {
        if (i < j)
        {
             swap(&vR[i], &vR[j]);
             swap(&vI[i], &vI[j]);
        }
        unsigned k = (samples >> 1);
        while (k <= j)
        {
             j -= k;
             k >>= 1;
        }
        j += k;
    }
    float c1 = -1.0;
    float c2 = 0.0;
    unsigned l2 = 1;
    unsigned l;
    for (l = 0; l < 7; l++)// 7=exponent(samples)
    {
        unsigned l1 = l2;
        l2 <<= 1;
        float u1 = 1.0;
        float u2 = 0.0;
        for (j = 0; j < l1; j++)
        {
            unsigned i;
             for (i = j; i < samples; i += l2)
             {
                    unsigned i1 = i + l1;
                    float t1 = u1 * vR[i1] - u2 * vI[i1];
                    float t2 = u1 * vI[i1] + u2 * vR[i1];
                    vR[i1] = vR[i] - t1;
                    vI[i1] = vI[i] - t2;
                    vR[i] += t1;
                    vI[i] += t2;
             }
             float z = (u1 * c1) - (u2 * c2);
             u2 = (u1 * c2) + (u2 * c1);
             u1 = z;
        }
        c2 = sqrt((1.0 - c1) / 2.0);
        c2 = -c2;
        c1 = sqrt((1.0 + c1) / 2.0);
    }
       for (i = 0; i < samples; i++)
        {
             vR[i] /= samples;
             vI[i] /= samples;
        }
}

float getFundamental(float *vR, float *vI,unsigned samples)
{
    float freq,max;
    unsigned i,maxIndex;
    maxIndex=1;
    max=0.0;
    for (i = 0; i < samples; i++)
    {
        vR[i] = sqrt((vR[i])*(vR[i]) + (vI[i])*(vI[i]));
    }

    for(i=1;i<samples/2;i++)
    {
        if(vR[i]>max)
        {
            max=vR[i];
            maxIndex=i;
        }
    }
    freq = maxIndex * sampling / samples;
    return freq;
}

int GHAL_AnalogIn_Read(unsigned char channel)
{
        return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{

        int i=0;
        float x;
        unsigned char channel = *(unsigned char*)args[0];
        while(i<samples)
        {
           vImag[i]=0;
           vReal[i] =(unsigned char)GHAL_AnalogIn_Read(channel)-120;//-120 because of my mic, but it's not necessary
           i++;
           RLPext->Delay(100);
        }


        Windowing(vReal,samples);
        Fft(vReal, vImag,samples);
        x=getFundamental(vReal, vImag,samples);


    return x;
}



Managed:


using System;
using System.IO;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Native;

namespace rlp1
{
    public class Program

    {
        
        static RLP.Procedure ReadAudio;
        static AnalogOut aout = new AnalogOut(AnalogOut.Pin.Aout0);
        public static void Main()
        {
            Debug.GC(true);
            byte[] elf_file = Resources.GetBytes(Resources.BinaryResources.FFT1);
            RLP.LoadELF(elf_file);
            RLP.InitializeBSSRegion(elf_file); 
            ReadAudio = RLP.GetProcedure(elf_file, "ReadAudio");
            elf_file = null;
            Debug.GC(true);
 
            while (true)
            {
                Debug.Print(ReadAudio.Invoke((byte)AnalogIn.Pin.Ain1).ToString());
                Thread.Sleep(1);
            }
          
        }

    }
}

You are welcome to test it…


#16

Can one of the forum admins please help to remove Freemans RLP unlock codes from his posts? :o


#17

This is very cool. Can you please post this on code.tinyclr.com? I am sire this will be needed by someone.

Also, please do not post your RLP key on the forum. This is private to you.


#18

Sorry about that I had some technical issues, my intention was to edit post not to copy it 3 times… I latter saw that I posted RLP, that’s why I was editing in the first place. I posted code on code.tinyclr.com.


#19

Just by the way.
The Cerberus(release immenent?) will be kicking fft butt. It runs at 160MHz(?), and can do 2 sixteen bit multiply and accumelates(MAC) per cycle. Or one MAC of 32 bit or one MAC of floats per cycle. On top of that it supports SIMD(single instruction, multiple data) to execute the same instruction on a block of data…

Trying to get fft running on this CPU. They have a sample for 1024 bin fft…


#20

Thanks for pre-announcing the Cerberus! :smiley: