Pow function with mikroC demo version

General discussion on mikroC PRO for PIC.
Post Reply
Author
Message
Virgus
Posts: 16
Joined: 14 Feb 2014 17:53

Pow function with mikroC demo version

#1 Post by Virgus » 14 Feb 2014 18:11

Hello,
I just installed MikroC to try some code on the net.
I am currently using Oshonsoft basic compiler and want to learn also some C.

I need to use pow function and I have PIC16F628A and PIC18F44K22 to try it,
but I'm having several problems; if I try to compile for the PIC16F628A I get:
0 122 Compilation Started Test.c
8 123 Compiled Successfully Test.c
0 127 All files Compiled in 63 ms
102 342 There is not enough ROM space __Lib_MathDouble.c
4 392 Address must be greater than 0 main Test.c
134 392 Address must be greater than 0 __CC2DW __Lib_System.c
370 392 Address must be greater than 0 pow __Lib_CMath.c
If I try to compile for the PIC18 I get the error:
0 434 Demo Limit Demo Limit
My code is found on the net and googling about pow nobody seems to have problems using it,
despite of this the demo limit error is weird as there are only a few lines of code:

Code: Select all

double co_y;
double co_x = 5;

void main() {

  co_y = pow(co_x,2);

}
Can somebody point me to the solution for this issue?

Thanks,
V.

p.erasmus
Posts: 3391
Joined: 05 Mar 2009 10:28

Re: Pow function with mikroC demo version

#2 Post by p.erasmus » 14 Feb 2014 19:56

yes the answer is easy by a license
pow functions are large functions using quite a bit of resources
P.Erasmus
Saratov,Russia
--------------------------------------------------------------

Virgus
Posts: 16
Joined: 14 Feb 2014 17:53

Re: Pow function with mikroC demo version

#3 Post by Virgus » 14 Feb 2014 20:17

Thanks for your reply,
yes buying a licence is an option, meanwhile I'll test other compilers too.

I'd like to understand why I got "There is not enough ROM space __Lib_MathDouble.c" error
Why is ROM implicated with a C function which operates in RAM?
Are c libraries stored in EEPROM after compiling? Shouldn't they be inside the flash hex file with the rest of the code?

Has anybody used successfully pow function with a PIC16FXXX?

Cheers,
V.

Acetronics
Posts: 715
Joined: 27 Dec 2006 14:33
Location: Le Tréport , FRANCE

Re: Pow function with mikroC demo version

#4 Post by Acetronics » 14 Feb 2014 21:08

Virgus wrote:

Code: Select all

double co_y;
double co_x = 5;

void main() {

  co_y = pow(co_x,2);

}
Can somebody point me to the solution for this issue?

Thanks,
V.
Yes ... of course a good solution ...

Code: Select all

double co_y;
double co_x = 5;

void main() {

  co_y = co_x * co_x;

}
obvious, no ?
:lol: :lol:
:roll:

Virgus
Posts: 16
Joined: 14 Feb 2014 17:53

Re: Pow function with mikroC demo version

#5 Post by Virgus » 15 Feb 2014 12:42

Hello acetronics, you made me laugh. :D

If I understood correctly, in MikroC and MikroBasic, ROM is used to store
part of the libraries once the hex is compiled, that makes difficult
(or better, impossible if using some libraries like Math) to use these compilers
with the "small PICs". Am I correct?

...unless there's an option to avoid using ROM. Is there such an option?

Cheers,
V.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Pow function with mikroC demo version

#6 Post by janni » 15 Feb 2014 13:15

Virgus wrote:If I understood correctly, in MikroC and MikroBasic, ROM is used to store
part of the libraries once the hex is compiled, that makes difficult
(or better, impossible if using some libraries like Math) to use these compilers
with the "small PICs". Am I correct?
No. "ROM" is used in compiler messages as synonym of program memory, whether it's OTP or Flash. All code is naturally stored in program memory, and what's preventing use of floating-point math in 'small' processors, or crossing demo limit in 'bigger' ones is the size of the library.

Acetronics
Posts: 715
Joined: 27 Dec 2006 14:33
Location: Le Tréport , FRANCE

Re: Pow function with mikroC demo version

#7 Post by Acetronics » 15 Feb 2014 14:18

Virgus wrote:Hello acetronics, you made me laugh. :D

V.
So, I'm really glad you laughed ! :mrgreen:

Being a bit serious ...

you just want to make heavy calculations with a nano sized processor ...

You have to take the chip that is able to do that.
just have a look to see how power function is realised in soft ...

remember a 16F628 is a " low" 8 bits only :roll: chip and you want it to make 32 x 32 bits calculations ... so you need room !!!

now, It's really exceptionnal to need 32 bits for real life :roll:

and it exists something called " retrieve tables " + interpolation , no ???

Alain

Virgus
Posts: 16
Joined: 14 Feb 2014 17:53

Re: Pow function with mikroC demo version

#8 Post by Virgus » 17 Feb 2014 18:55

Thanks Janni for your reply.

Acetronics, I'm quite new to Microcontrollers' programming,
could you please point me to retrieve tables / interpolation examples?

Maybe it's easier to say what I'm trying to do:
I'd like to store midi notes/ durations sequences in the smallest format possible
that is to say 7bit for midi notes and 8 bit for durations (considering 256 ms multiplied
by 10 that makes for each note a maximum duration possible of 2.5 seconds)
and then translate them to frequency in the function that reads the array (or EEPROM
location) and plays it back...

Now I'm obliged to use 2 bytes to store frequency values from 0x00 to 0x30FF (G11 = 12543 Hz)
and I'm using a PC script for conversion from midi file format to hex values but it would be
great to have one byte only for both notes and durations and have them in pairs sequence...

One solution I'm thinking about could be to store a table with A frequency values for each octave
and then multiply each time one of that values by 2^(1/12) constant the number of times necessary
to get to the correct note frequency. That would be a maximum of 11 multiplication possible for each note...

But then I'd need to round a float to an integer, thus I'd need the same Math library unsuitable for small PICs!

...no idea really how to do this without migrating to a more powerful PIC,
but I'm still thinking there might be a way of doing it...

Cheers
V.

aCkO
Posts: 1119
Joined: 14 Feb 2011 04:07
Location: Bar, Montenegro

Re: Pow function with mikroC demo version

#9 Post by aCkO » 17 Feb 2014 23:54

There is no need for floating-point arithmetic in music :)
Virgus wrote:I'd like to store midi notes/ durations sequences in the smallest format possible
that is to say 7bit for midi notes and 8 bit for durations (considering 256 ms multiplied
by 10 that makes for each note a maximum duration possible of 2.5 seconds)
and then translate them to frequency in the function that reads the array (or EEPROM
location) and plays it back...
Thats only 2 bytes per symbol (1 for note and 1 for duration).
Virgus wrote:it would be
great to have one byte only for both notes and durations and have them in pairs sequence...
If your goal is to use the same indexing for notes and durations then you can use two char arrays (1 for notes and 1 for durations) or one int array (e.g. high byte for note low byte for duration). The second one is more compact.
Virgus wrote:One solution I'm thinking about could be to store a table with A frequency values for each octave
and then multiply each time one of that values by 2^(1/12) constant the number of times necessary
to get to the correct note frequency. That would be a maximum of 11 multiplication possible for each note...
Wrong approach and counter intuitive to the definition of an octave (you are assuming that an octave is even tempered). If you store the note frequencies belonging to the same octave in one table, then higher/lower notes can be calculated by doubling/halfing those frequencies. This is the same as shifting integers left/right, i.e. not computationally intensive compared to f-p operations.

Here's what I would do:

1. First we need to determine the limits. Let's say those are C0 (16.35 Hz) and B9 (15804.264 Hz).
2. To get rid of floating-point values, we convert everything to milihertz: C0 = 16350 mHz, B9 = 15804264 mHz.
3. To store that kind of values we need to use 4-byte integers (unsigned long)
4. The frequency table will look like this:
table.png
table.png (20.66 KiB) Viewed 6717 times
5. This table requires 12 * 10 * 4 = 480 bytes of ROM space. We can make it 10 times smaller if we store only the 0-octave and calculate note frequencies for the others by left shifting (doubling) the 0-note frequency n times:

Code: Select all

unsigned long oct[12] = {16350, 17320, 18350, 19450, 20600, 21830, 
                         23120, 24500, 25960, 27500, 29140, 30870};
6. To store a note we use only one byte (high nibble for column and low nibble for row of the frequency table)
Let's say we want to encode sequence: C2, E5, F3. If we assign indexes to the columns then C=0, C#=1, D=2, ..., B=11
Our sequence becomes: 0x02, 0x45, 0x53
Our frequencies are:

Code: Select all

(oct[0] << 2), (oct[3] << 5), (oct[5] << 3) = 
= (16350 << 2), (19450 << 5), (21830 << 3) = 
= 65400, 659200, 174640 = 
= 65.4 Hz, 659.2 Hz, 174.64 Hz
Example:

Code: Select all

#include "built_in.h"

const unsigned long oct[12] = {16350, 17320, 18350, 19450, 20600, 21830,
                               23120, 24500, 25960, 27500, 29140, 30870};

// C2 = 0x020A; // Duration: 0x0A = 10 * 10 ms = 100 ms
// E5 = 0x450F; // Duration: 0x0F = 15 * 10 ms = 150 ms
// F3 = 0x5314; // Duration: 0x14 = 20 * 10 ms = 200 ms

unsigned int seq[] = {0x020A, 0x450F, 0x5314};  // C2, E5, F3 sequence

void PlaySound(unsigned long freq, unsigned int duration) {
   // your code for playing sounds
}

void main() {
   int i;
   unsigned long freq;

   // play sequence
   for (i = 0; i < 3; i++) {
      //      High-byte high-nibble      High-byte low-nibble
      freq  =  oct[Hi(seq[i]) >> 4]  <<  (Hi(seq[i]) & 0x0F);
      PlaySound(freq, Lo(seq[i]));
   }
}
or if you wish to separate notes and durations:

Code: Select all

#include "built_in.h"

const unsigned long oct[12] = {16350, 17320, 18350, 19450, 20600, 21830,
                               23120, 24500, 25960, 27500, 29140, 30870};

// C2 = 0x020A; // Duration: 0x0A = 10 * 10 ms = 100 ms
// E5 = 0x450F; // Duration: 0x0F = 15 * 10 ms = 150 ms
// F3 = 0x6314; // Duration: 0x14 = 20 * 10 ms = 200 ms

unsigned char seq_note[]     = {0x02, 0x45, 0x53};  // C2, E5, F3 sequence
unsigned char seq_duration[] = {0x0A, 0x0F, 0x14};  // 10, 15, 20 ms duration

void PlaySound(unsigned long freq, unsigned int duration) {
   // your code for playing sounds
}

void main() {
   int i;
   unsigned long freq;

   // play sequence
   for (i = 0; i < 3; i++) {
      //           high-nibble                low-nibble
      freq  =  oct[seq_note[i] >> 4]  <<  (seq_note[i] & 0x0F);
      PlaySound(freq, seq_duration[i]);
   }
}
Regards
Last edited by aCkO on 18 Feb 2014 02:31, edited 3 times in total.

Virgus
Posts: 16
Joined: 14 Feb 2014 17:53

Re: Pow function with mikroC demo version

#10 Post by Virgus » 18 Feb 2014 00:46

Hello aCkO,
amazing and unexpected reply! :D

You left me only two lines of code to add to yours ( I appreciated that you left me something to do :wink: ):

Code: Select all

// your code for playing sounds
freq  = freq / 1000;
Sound_Play(freq, duration * 10);
It's a great solution, I'll have a few things to add and it will be perfect for my needs.

Thanks!!!!!!

BTW for those interested in midi to pic, to translate a midifile to txt I'm using this wonderful utility
http://www.tima.uk.com/midianal.htm
and then I script the according transformations to hex data from the csv generated file...

Post Reply

Return to “mikroC PRO for PIC General”