RNG/PRNG using a MSP430 - c

I am currently trying to make a Random Number Generator using a MSP430 (MSP43 G2553) and then create an algorithm for a Pseudo Random Number Generator. I have a code for these two processes and also a code used to test the programs with LEDs.
For some reason, I encounter some errors that I cannot seem to resolve. I will attach the codes and the errors to get a second opinion on the syntax.
#include <msp430g2553.h>
#include "rand.h"
/**
* Random number generator.
*
* NOTE: This affects Timer A.
*
* Algorithm from TI SLAA338:
* http://www.ti.com/sc/docs/psheets/abstract/apps/slaa338.htm
*
* #return 16 random bits generated from a hardware source.
*/
unsigned int rand(); {
int i, j;
unsigned int result = 0;
/* Save state */
unsigned int TACCTL0_old = TACCTL0;
unsigned int TACTL_old = TACTL;
/* Set up timer */
TACCTL0 = CAP | CM_1 | CCIS_1; // Capture mode, positive edge
TACTL = TASSEL_2 | MC_2; // SMCLK, continuous up
/* Generate bits */
for (i = 0; i < 16; i++) {
unsigned int ones = 0;
for (j = 0; j < 5; j++) {
while (!(CCIFG & TACCTL0)); // Wait for interrupt
TACCTL0 &= ~CCIFG; // Clear interrupt
if (1 & TACCR0) // If LSb set, count it
ones++;
}
result >>= 1; // Save previous bits
if (ones >= 3) // Best out of 5
result |= 0x8000; // Set MSb
}
/* Restore state */
TACCTL0 = TACCTL0_old;
TACTL = TACTL_old;
return result;
}
/**
* Pseudo-random number generator.
*
* Implemented by a 16-bit linear congruential generator.
* NOTE: Only treat the MSB of the return value as random.
*
* #param state Previous state of the generator.
* #return Next state of the generator.
*/
unsigned int prand(unsigned int state) {
return (M * state + I); // Generate the next state of the LCG
}
This is the code for the RNG and PRNG. The list of errors:
Warning[Pa050]: non-native end of line sequence detected (this diagnostic is only issued once) E:\Downloads\msp430-rng-master\rand.h 1
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 18
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 39
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 41
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 45
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 47
Warning[Pe012]: parsing restarts here after previous syntax error E:\Downloads\msp430-rng-master\rand.c 50
Error[Pe077]: this declaration has no storage class or type specifier E:\Downloads\msp430-rng-master\rand.c 51
Error[Pe147]: declaration is incompatible with "unsigned short volatile TA0CTL # 0x160" (declared at line 527 of "C:\Program Files (x86)\IAR Systems\Embedded E:\Downloads\msp430-rng-master\rand.c 51
Workbench 6.5\430\inc\msp430g2553.h")
Error[Be022]: location address not allowed for initialized variables (writable variables without the __no_init attribute) E:\Downloads\msp430-rng-master\rand.c 51
Error[Pe020]: identifier "TACTL_old" is undefined E:\Downloads\msp430-rng-master\rand.c 51
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 53
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 54
Warning[Pe012]: parsing restarts here after previous syntax error E:\Downloads\msp430-rng-master\rand.c 68
The code for testing is:
#include <msp430g2553.h>
#include <signal.h>
#include <isr_compat.h>
#include "rand.h"
#define LED_OUT P1OUT
#define LED_DIR P1DIR
#define LED_RED BIT0
#define LED_GREEN BIT6
#define BLINK_DELAY 1200 // 200 ms at 6 KHz
#define BITS_RAND 16
#define BITS_PRAND 8 // Using only the MSB of the prand state
int failure = 0;
/**
* Set up the timers and blink!
*/
void prepare_to_blink() {
BCSCTL3 |= LFXT1S_2; // Set LF to VLO = 12 KHz
BCSCTL1 |= DIVA_1; // ACLK = LF / 2 = 6 KHz
TACCR0 = BLINK_DELAY; // Set the timer
TACTL = TASSEL_1 | MC_1; // TACLK = ACLK; up to CCR0
TACCTL1 = CCIE | OUTMOD_3; // TA1 interrupt enable; PWM set/reset
__bis_SR_register(LPM3_bits | GIE); // LPM3 w/ interrupt
}
int interrupt(TIMERA1_VECTOR) blink_LED (void) {
TACCTL1 &= ~CCIFG; // Unset interrupt flag
if (failure) // Toggle LEDs
LED_OUT ^= LED_RED;
else
LED_OUT ^= LED_GREEN;
}
/******************************************************************************
* Monobit
*
* SP 800-22 Rev. 1a
* http://csrc.nist.gov/publications/nistpubs/800-22-rev1a/SP800-22rev1a.pdf
******************************************************************************/
/* The hardware RNG is slow, so limit test to 400 bits. */
#define MONOBIT_TIMES_RAND 25 // 400 / BITS_RAND
/* Each 8-bit number tested with monobit contributes 8 bits, so in the worst
* case, the signed 16-bit bucket can store information about this many
* numbers: */
#define MONOBIT_TIMES_PRAND 4095 // (2 ^ 15 - 1) / BITS_PRAND
/* The maximum absolute value of the sum bucket after a monobit test, where
* 0.01 is the minimum P-value and inverfc is the inverse of the complementary
* error function. */
#define MONOBIT_MAX_VAL_RAND 51 // inverfc(0.01) * sqrt(2) * sqrt(400)
#define MONOBIT_MAX_VAL_PRAND 466 // inverfc(0.01) * sqrt(2) * sqrt(2 ^ 15 - 1)
/**
* Monobit test for rand().
*
* Returns 0 on success; otherwise otherwise.
*/
int monobit_rand() {
int sum = 0;
int i, j;
for (i = 0; i < MONOBIT_TIMES_RAND; i++) {
int r = rand();
/* Add up all the bits, taking 0 to mean -1. */
for (j = 0; j < BITS_RAND; j++) {
sum += r & 0x1 ? 1 : -1;
r >>= 1;
}
}
if (sum < 0)
sum = 0 - sum; // Absolute value
return sum > MONOBIT_MAX_VAL_RAND;
}
/**
* Monobit test for prand().
*
* Returns 0 on success; otherwise otherwise.
*/
int monobit_prand() {
int state = rand();
int sum = 0;
int i, j;
for (i = 0; i < MONOBIT_TIMES_PRAND; i++) {
int r = state >> (16 - BITS_PRAND); // Ignore the least significant bits
/* Add up all the bits, taking 0 to mean -1. */
for (j = 0; j < BITS_PRAND; j++) {
sum += r & 0x1 ? 1 : -1;
r >>= 1;
}
state = prand(state);
}
if (sum < 0)
sum = 0 - sum; // Absolute value
return sum > MONOBIT_MAX_VAL_PRAND;
}
/**
* Store the failure code on the top of the stack and alternate flashing the
* LEDs to signify failure.
*
* Never returns!
*/
void fail(int code) {
asm("push %0" : : "r" (code));
failure = 1;
LED_OUT &= ~LED_GREEN;
prepare_to_blink();
}
/**
* Run though all the tests.
*
* Both LEDs are lit up while testing, and one will blink once the tests are
* done, depending on the outcome.
*/
void main() {
LED_DIR |= LED_RED | LED_GREEN;
LED_OUT |= LED_RED | LED_GREEN;
if (monobit_rand())
fail(0xdead);
if (monobit_prand())
fail(0xbeef);
LED_OUT &= ~LED_RED;
prepare_to_blink();
}
And the list of errors when compiling:
Warning[Pa050]: non-native end of line sequence detected (this diagnostic is only issued once) E:\Downloads\msp430-rng-master\rand.h 1
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\test.c 34
Warning[Pe012]: parsing restarts here after previous syntax error E:\Downloads\msp430-rng-master\test.c 116
Warning[Pe1051]: standard requires that parameter "TIMERA1_VECTOR" be given a type by a subsequent declaration ("int" assumed) E:\Downloads\msp430-rng-master\test.c 34
Error[Pe130]: expected a "{" E:\Downloads\msp430-rng-master\test.c 117
Warning[Pe940]: missing return statement at end of non-void function "interrupt" E:\Downloads\msp430-rng-master\test.c 117
Error[Pe018]: expected a ")" E:\Downloads\msp430-rng-master\test.c 126
Warning[Pe223]: function "monobit_rand" declared implicitly E:\Downloads\msp430-rng-master\test.c 144
Warning[Pe223]: function "monobit_prand" declared implicitly E:\Downloads\msp430-rng-master\test.c 147

You have incorrect syntax. Please see the following line:
unsigned int rand(); {
This line should read:
unsigned int rand() {
Edit
In your test code, you have the following:
int interrupt(TIMERA1_VECTOR) blink_LED (void) {
I have never seen an interrupt service routine defined in this way. Instead it should be defined (in IAR EW430) like this:
#pragma vector=TIMERA1_VECTOR
__interrupt void blink_LED(void) {

Related

function never execute but code compile

I'm trying to run the following code in c on a beaglebone black (microcontroller running Debian).
The code compiles but terminates right when the pwm_init() function is called.
No printf will execute after this line, even the first in the pwm_init() function.
I tried removing pwm_init(), and then wait_for_pwm() will run normally.
This is a code to setup an interrupt timer on the beaglebone in order to communicate with a DAC through SPI.
The code was running and could communicate before this adding.
/*
*Filename: mems.c
*SPI test program to communicate with AD5666 DAC on Micro Mirror Driver board */
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include "iolib.h"
#include <unistd.h>
#define DELAY_NS 62500 // Timer period in ns
// PRU Interrupt control registers
#define PRU_INTC 0x00020000 // Start of PRU INTC registers TRM 4.3.1.2
#define PRU_INTC_GER ((volatile uint32_t *)(PRU_INTC + 0x10)) // Global Interrupt Enable, TRM 4.5.3.3
#define PRU_INTC_SICR ((volatile uint32_t *)(PRU_INTC + 0x24)) // Interrupt, TRM 4.5.3.6
#define PRU_INTC_GPIR ((volatile uint32_t *)(PRU_INTC + 0x80)) // Interrupt, TRM 4.5.3.11
// PRU ECAP control registers (i.e. PWM used as a timer)
#define ECAP 0x00030000 // ECAP0 offset, TRM 4.3.1.2
// Using APWM mode (TRM 15.3.2.1) to get timer (TRM 15.3.3.5.1)
#define ECAP_TSCTR ((volatile uint32_t *)(ECAP + 0x00)) // 32-bit counter register, TRM 15.3.4.1.1
#define ECAP_APRD ((volatile uint32_t *)(ECAP + 0x10)) // Period shadow, TRM 15.3.4.1.5, aka CAP3
#define ECAP_ECCTL2 ((volatile uint32_t *)(ECAP + 0x2a)) // Control 2, TRM 15.3.4.1.8
#define ECAP_ECEINT ((volatile uint16_t *)(ECAP + 0x2c)) // Enable interrupt, TRM 15.3.4.1.9
#define ECAP_ECCLR ((volatile uint16_t *)(ECAP + 0x30)) // Clear flags, TRM 15.3.4.1.11
// R30 is the GPIO register
// R31 is the interrupt register
#define NUMBER_OF_COEFS 87
int xn[NUMBER_OF_COEFS] = { 0 };
int ynn[NUMBER_OF_COEFS] = { 0 };
int xy[2];
static double coefs[NUMBER_OF_COEFS] = { -0.003874396983162784,-0.0037425007502381417,0.0007168162935488041,-0.0015837981969284466,0.001324731958160302,0.000940030114550933,0.002909179571989647,0.002970492669088027,0.0037475240063036684,0.003135242276391628,0.002431551570668268,0.0007465565198417194,-0.0010918847362976609,-0.0032610680167253635,-0.0050886443383995035,-0.0064219306251743396,-0.0067757336585719885,-0.00603689840577871,-0.004073405037328031,-0.001084864753089533,0.002607744624181485,0.006446336960328277,0.009805149887731802,0.012005211009068262,0.01248315933178856,0.010855477027307714,0.007038206816858291,0.0013011753812607633,-0.005726736257811221,-0.013085733616184817,-0.019608024169477135,-0.024024160014903175,-0.025137566107801428,-0.022018671074884637,-0.01412798218138592,-0.0014477915111131118,0.015482420337480308,0.03556527369143834,0.057256428960766804,0.07871540989639365,0.09799912606296178,0.1132905004893123,0.12311069228747347,0.1265004803246064,0.12311069228747347,0.1132905004893123,0.09799912606296178,0.07871540989639365,0.057256428960766804,0.03556527369143834,0.015482420337480308,-0.0014477915111131118,-0.01412798218138592,-0.022018671074884637,-0.025137566107801428,-0.024024160014903175,-0.019608024169477135,-0.013085733616184817,-0.005726736257811221,0.0013011753812607633,0.007038206816858291,0.010855477027307714,0.01248315933178856,0.012005211009068262,0.009805149887731802,0.006446336960328277,0.002607744624181485,-0.001084864753089533,-0.004073405037328031,-0.00603689840577871,-0.0067757336585719885,-0.0064219306251743396,-0.0050886443383995035,-0.0032610680167253635,-0.0010918847362976609,0.0007465565198417194,0.002431551570668268,0.003135242276391628,0.0037475240063036684,0.002970492669088027,0.002909179571989647,0.000940030114550933,0.001324731958160302,-0.0015837981969284466,0.0007168162935488041,-0.0037425007502381417,-0.003874396983162784};
#define REF_ON 0x01000008 //command to turn on internal VREF
#define X_OFFSET 3
#define Y_OFFSET 0
#define X_DRIVE 1
#define Y_DRIVE 2
#define SIZEMAT 2
float tabx[SIZEMAT] = { -100, 100 };
float taby[SIZEMAT] = { -100, 100 };
// Forward definitions
int convert_spi(int dac_val,int channel); //formats bytes for write function
inline void pwm_init();
inline void wait_for_pwm_timer();
int* fir_filterXY(int x, int y);
int main(int argc, char **argv){
int i, fd, debug=0, loop=0, user_loop=0;
int x_off=-1, y_off=-1;
int x_val=-1, y_val=-1;
int freq = -1;
unsigned int buf = REF_ON;
unsigned int dac_value = 1; // 0 to 65535 value to set dac output
unsigned int spi_bytes = 0; // spi communication bytes to send
char direction = 0; // Direction of triangle wave ramp
fd = open("/dev/spidev1.0", O_RDWR);
if(fd < 0) printf("spi failed to open\n");
iolib_init();
//Set LDAC control pin to output
iolib_setdir(9,15,1);
//Tying LDAC low will update dac channel as soon as it has new data
pin_low(9,15); //sel0
write(fd,&buf,4); //set internal vref on
// User loop
int valx = 0;
int valy = 0;
int* ass;
int assx = 0;
int assy = 0;
int i = 0;
int freqcnt = 0;
int freqi = 0;
if (freq>1000)
{
freq = 1000;
}
if (freq<1)
{
freq = 1;
}
freqcnt = (int)((1000000000/DELAY_NS)/freq - 1);
spi_bytes = convert_spi(32000, X_OFFSET);//format bytes for write function
write(fd, &spi_bytes, 4);
spi_bytes = convert_spi(32000, Y_OFFSET);//format bytes for write function
write(fd, &spi_bytes, 4);
printf("In user loop with movement frequency of:%i\n", freq);
pwm_init();
valx = 32000;
valy = 32000;
assx = 32000;
assy = 32000;
printf("starting\n");
while (1){
wait_for_pwm_timer();
spi_bytes = convert_spi(assx, X_DRIVE);//format bytes for write function
write(fd, &spi_bytes, 4);
spi_bytes = convert_spi(assy, Y_DRIVE);//format bytes for write function
write(fd, &spi_bytes, 4);
freqi++;
if(freqi >= freqcnt){
valx = (int)((tabx[i]+100) * 320);
valy = (int)((taby[i]+100) * 320);
freqi = 0;
i++;
if (i >= SIZEMAT)
i = 0;
}
ass = fir_filterXY(valx, valy);
assx = *(ass);
assy = *(ass+1);
}
return 0;
}
/* Function: convert_spi
*
* Takes a dac value (0-65535) and a dac channel (or all channels) and generates the appropriate 32bits to send to AD5666 via SPI
*
* INPUTS
* dac_val: sets the voltage output with voltage output= 2.5*(dac_val/65535)
* channel: selects which dac channel to update with dac_val. 0=DACA ,1=DACB, 2=DACC, 3=DACD, 16=all
*
* RETURNS
* spi_data: integer value to send via spi using to update channel with new dac value
*/
int convert_spi(int dac_val,int channel){
int spi_data=0;
unsigned int nibble1;
unsigned int nibble2;
unsigned int nibble3;
unsigned int nibble4;
nibble1= dac_val & 0xF000;
nibble2= dac_val & 0x0F00;
nibble3= dac_val & 0x00F0;
nibble4= dac_val & 0x000F;
spi_data |=(nibble1>>4);
spi_data |=(nibble2<<12);
spi_data |=(nibble3<<12);
spi_data |=(nibble4<<28);
spi_data |=(channel<<12);
return spi_data;
}
// Initializes the PWM timer, used to control output transitions.
// Every DELAY_NS nanoseconds, interrupt 15 will fire
inline void pwm_init(){
printf("Intereupt setup");
*PRU_INTC_GER = 1; // Enable global interrupts
printf("1");
*ECAP_APRD = DELAY_NS / 5 - 1; // Set the period in cycles of 5 ns
printf("2");
*ECAP_ECCTL2 = (1<<9) /* APWM */ | (1<<4) /* counting */;
printf("3");
*ECAP_TSCTR = 0; // Clear counter
printf("4");
*ECAP_ECEINT = 0x80; // Enable compare equal interrupt
printf("5");
*ECAP_ECCLR = 0xff; // Clear interrupt flags
printf("done\n");
}
// Wait for the PWM timer to fire.
// see TRM 15.2.4.26x
inline void wait_for_pwm_timer() {
register unsigned int __R31;
while (!(__R31 & (1 << 30))) {} // Wait for timer compare interrupt
*PRU_INTC_SICR = 15; // Clear interrupt
*ECAP_ECCLR = 0xff; // Clear interrupt flags
}
int* fir_filterXY(int x, int y){
int i = 0;
double temp = 0;
for (i = 0; i < NUMBER_OF_COEFS - 1; i++)
{
xn[i] = xn[i + 1]; //xn est au bout
}
xn[NUMBER_OF_COEFS-1] = x;
//multiplier par les coef
for (i = 0; i < NUMBER_OF_COEFS; i++)
{
temp += xn[NUMBER_OF_COEFS - i] * coefs[i];
}
xy[0] = (int)(temp+0.5);
for (i = 0; i < NUMBER_OF_COEFS - 1; i++)
{
ynn[i] = ynn[i + 1];
}
ynn[NUMBER_OF_COEFS-1] = y;
temp = 0;
for (i = 0; i < NUMBER_OF_COEFS; i++)
{
temp += ynn[NUMBER_OF_COEFS - i] * coefs[i];
}
xy[1] = (int)(temp + 0.5);
return xy;
}
A couple of recommendations:
printf() can occasionally lag in its output. To be very sure that nothing is being printed, call fflush(stdout) after the print line. This will flush the stdout buffer-- if nothing is printed after the flush, then the println() really is not being executed.
How is your program terminating? If execution does not continue past the pwm_init() function, that almost certainly means that something bad is happening with the memory locations you are writing to. Double check that your register values are correct and that your program isn't being killed due to invalid memory access.

c, obtaining a special random number

I have a algorithm problem that I need to speed up :)
I need a 32bit random number, with exact 10 bits set to 1. But in the same time, patterns like 101 (5 dec) and 11 (3 dec) to be considered illegal.
Now the MCU is a 8051 (8 bit) and I tested all this in Keil uVision. My first attempt completes, giving the solution
0x48891249
1001000100010010001001001001001 // correct, 10 bits 1, no 101 or 11
The problem is that it completes in 97 Seconds or 1165570706 CPU cycles which is ridiculous!!!
Here is my code
// returns 1 if number is not good. ie. contains at leats one 101 bit sequence
bool checkFive(unsigned long num)
{
unsigned char tmp;
do {
tmp = (unsigned char)num;
if(
(tmp & 7) == 5
|| (tmp & 3) == 3
) // illegal pattern 11 or 101
return true; // found
num >>= 1;
}while(num);
return false;
}
void main(void) {
unsigned long v,num; // count the number of bits set in v
unsigned long c; // c accumulates the total bits set in v
do {
num = (unsigned long)rand() << 16 | rand();
v = num;
// count all 1 bits, Kernigen style
for (c = 0; v; c++)
v &= v - 1; // clear the least significant bit set
}while(c != 10 || checkFive(num));
while(1);
}
The big question for a brilliant mind :)
Can be done faster? Seems that my approach is naive.
Thank you in advance,
Wow, I'm impressed, thanks all for suggestions. However, before accept, I need to test them these days.
Now with the first option (look-up) it's just not realistic, will complete blow my 4K RAM of entire 8051 micro controller :) As you can see in image bellow, I tested for all combinations in Code Blocks but there are way more than 300 and it's not finished yet until 5000 index...
The code I use to test
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
//#define bool bit
//#define true 1
//#define false 0
// returns 1 if number is not good. ie. contains at leats one 101 bit sequence
bool checkFive(uint32_t num)
{
uint8_t tmp;
do {
tmp = (unsigned char)num;
if(
(tmp & 7) == 5
|| (tmp & 3) == 3
) // illegal pattern 11 or 101
return true; // found
num >>= 1;
}while(num);
return false;
}
void main(void) {
uint32_t v,num; // count the number of bits set in v
uint32_t c, count=0; // c accumulates the total bits set in v
//printf("Program started \n");
num = 0;
printf("Program started \n");
for(num=0; num <= 0xFFFFFFFF; num++)
{
//do {
//num = (uint32_t)rand() << 16 | rand();
v = num;
// count all 1 bits, Kernigen style
for (c = 0; v; c++)
v &= v - 1; // clear the least significant bit set
//}while(c != 10 || checkFive(num));
if(c != 10 || checkFive(num))
continue;
count++;
printf("%d: %04X\n", count, num);
}
printf("Complete \n");
while(1);
}
Perhaps I can re-formulate the problem:
I need a number with:
precise (known) amount of 1 bits, 10 in my example
not having 11 or 101 patterns
remaining zeroes can be any
So somehow, shuffle only the 1 bits inside.
Or, take a 0x00000000 and add just 10 of 1 bits in random positions, except the illegal patterns.
Solution
Given a routine r(n) that returns a random integer from 0 (inclusive) to n (exclusive) with uniform distribution, the values described in the question may be generated with a uniform distribution by calls to P(10, 4) where P is:
static uint32_t P(int a, int b)
{
if (a == 0 && b == 0)
return 0;
else
return r(a+b) < a ? P(a-1, b) << 3 | 1 : P(a, b-1) << 1;
}
The required random number generator can be:
static int r(int a)
{
int q;
do
q = rand() / ((RAND_MAX+1u)/a);
while (a <= q);
return q;
}
(The purpose of dividing by (RAND_MAX+1u)/a and the do-while loop is to trim the range of rand to an even multiple of a so that bias due to a non-multiple range is eliminated.)
(The recursion in P may be converted to iteration. This is omitted as it is unnecessary to illustrate the algorithm.)
Discussion
If the number cannot contain consecutive bits 11 or 101, then the closest together two 1 bits can be is three bits apart, as in 1001. Fitting ten 1 bits in 32 bits then requires at least 28 bits, as in 1001001001001001001001001001. Therefore, to satisfy the constraints that there is no 11 or 101 and there are exactly 10 1 bits, the value must be 1001001001001001001001001001 with four 0 bits inserted in some positions (including possibly the beginning or the end).
Selecting such a value is equivalent to placing 10 instances of 001 and 4 instances of 0 in some order.1 There are 14! ways of ordering 14 items, but any of the 10! ways of rearranging the 10 001 instances with each other are identical, and any of the 4! ways of rearranging the 0 instances with each other are identical, so the number of distinct selections is 14! / 10! / 4!, also known as the number of combinations of selecting 10 things from 14. This is 1,001.
To perform such a selection with uniform distribution, we can use a recursive algorithm:
Select the first choice with probability distribution equal to the proportion of the choices in the possible orderings.
Select the remaining choices recursively.
When ordering a instances of one object and b of a second object, a/(a+b) of the potential orderings will start with the first object, and b/(a+b) will start with the second object. Thus, the design of the P routine is:
If there are no objects to put in order, return the empty bit string.
Select a random integer in [0, a+b). If it is less than a (which has probability a/(a+b)), insert the bit string 001 and then recurse to select an order for a-1 instances of 001 and b instances of 0.
Otherwise, insert the bit string 0 and then recurse to select an order for a instances of 001 and b-1 instances of 0.
(Since, once a is zero, only 0 instances are generated, if (a == 0 && b == 0) in P may be changed to if (a == 0). I left it in the former form as that shows the general form of a solution in case other strings are involved.)
Bonus
Here is a program to list all values (although not in ascending order).
#include <stdint.h>
#include <stdio.h>
static void P(uint32_t x, int a, int b)
{
if (a == 0 && b == 0)
printf("0x%x\n", x);
else
{
if (0 < a) P(x << 3 | 1, a-1, b);
if (0 < b) P(x << 1, a, b-1);
}
}
int main(void)
{
P(0, 10, 4);
}
Footnote
1 This formulation means we end up with a string starting 001… rather than 1…, but the resulting value, interpreted as binary, is equivalent, even if there are instances of 0 inserted ahead of it. So the strings with 10 001 and 4 0 are in one-to-one correspondence with the strings with 4 0 inserted into 1001001001001001001001001001.
One way to satisfy your criteria in a limited number of solutions is to utilize the fact that there can be no more that four groups of 000s within the bit population. This also means that there can one be one group of 0000 in the value. Knowing this, you can seed your value with a single 1 in bits 27-31 and then continue adding random bits checking that each bit added satisfies your 3 or 5 constraints.
When adding random bits to your value and satisfying your constraints, there can always be combinations that lead to a solution that can never satisfy all constraints. To protect against those cases, just keep an iteration count and reset/restart the value generation if iterations exceed that value. Here, if a solution is going to be found, it will be found in less than 100 iterations. And is generally found in 1-8 attempts. Meaning for each value you generate, you have on average no more than 800 iterations which will be a far cry less than "97 Seconds or 1165570706 CPU cycles" (I haven't counted cycles, but the return is almost instantaneous)
There are many ways to approach this problem, this is just one that worked in a reasonable amount of time:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#define BPOP 10
#define NBITS 32
#define LIMIT 100
/** rand_int for use with shuffle */
static int rand_int (int n)
{
int limit = RAND_MAX - RAND_MAX % n, rnd;
rnd = rand();
for (; rnd >= limit; )
rnd = rand();
return rnd % n;
}
int main (void) {
int pop = 0;
unsigned v = 0, n = NBITS;
size_t its = 1;
srand (time (NULL));
/* one of first 5 bits must be set */
v |= 1u << (NBITS - 1 - rand_int (sizeof v + 1));
pop++; /* increment pop count */
while (pop < BPOP) { /* loop until pop count 10 */
if (++its >= LIMIT) { /* check iterations */
#ifdef DEBUG
fprintf (stderr, "failed solution.\n");
#endif
pop = its = 1; /* reset for next iteration */
v = 0;
v |= 1u << (NBITS - 1 - rand_int (sizeof v + 1));
}
unsigned shift = rand_int (NBITS); /* get random shift */
if (v & (1u << shift)) /* if bit already set */
continue;
/* protect against 5 (101) */
if ((shift + 2) < NBITS && v & (1u << (shift + 2)))
continue;
if ((int)(shift - 2) >= 0 && v & (1u << (shift - 2)))
continue;
/* protect against 3 (11) */
if ((shift + 1) < NBITS && v & (1u << (shift + 1)))
continue;
if ((int)(shift - 1) >= 0 && v & (1u << (shift - 1)))
continue;
v |= 1u << shift; /* add bit at shift */
pop++; /* increment pop count */
}
printf ("\nv : 0x%08x\n", v); /* output value */
while (n--) { /* output binary confirmation */
if (n+1 < NBITS && (n+1) % 4 == 0)
putchar ('-');
putchar ((v >> n & 1) ? '1' : '0');
}
putchar ('\n');
#ifdef DEBUG
printf ("\nits: %zu\n", its);
#endif
return 0;
}
(note: you will probably want a better random source like getrandom() or reading from /dev/urandom if you intend to generate multiple random solutions within a loop -- expecially if you are calling the executable in a loop from your shell)
I have also included a DEBUG define that you can enable by adding the -DDEBUG option to your compiler string to see the number of failed solutions and number of iterations on the final.
Example Use/Output
The results for 8 successive runs:
$ ./bin/randbits
v : 0x49124889
0100-1001-0001-0010-0100-1000-1000-1001
v : 0x49124492
0100-1001-0001-0010-0100-0100-1001-0010
v : 0x48492449
0100-1000-0100-1001-0010-0100-0100-1001
v : 0x91249092
1001-0001-0010-0100-1001-0000-1001-0010
v : 0x92488921
1001-0010-0100-1000-1000-1001-0010-0001
v : 0x89092489
1000-1001-0000-1001-0010-0100-1000-1001
v : 0x82491249
1000-0010-0100-1001-0001-0010-0100-1001
v : 0x92448922
1001-0010-0100-0100-1000-1001-0010-0010
As Eric mentioned in his answer, since each 1 but must be separated by at least two 0 bits, you basically start with the 28-bit pattern 1001001001001001001001001001. It's then a matter of placing the remaining four 0 bits within this bit pattern, and there are 11 distinct places to insert each zero.
This can be accomplished by first selecting a random number from 1 to 11 to determine where to place a bit. Then you left shift all the bits above the target bit by 1. Repeat 3 more times, and you have your value.
This can be done as follows:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
void binprint(uint32_t n)
{
int i;
for (i=0;i<32;i++) {
if ( n & (1u << (31 - i))) {
putchar('1');
} else {
putchar('0');
}
}
}
// inserts a 0 bit into val after pos "1" bits are found
uint32_t insert(uint32_t val, int pos)
{
int cnt = 0;
uint32_t mask = 1u << 31;
uint32_t upper, lower;
while (cnt < pos) {
if (val & mask) { // look for a set bit and count if you find one
cnt++;
}
mask >>= 1;
}
if (mask == (1u << 31)) {
return val; // insert at the start: no change
} else if (mask == 0) {
return val << 1; // insert at the end: shift the whole thing by 1
} else {
mask = (mask << 1) - 1; // mask has all bits below the target set
lower = val & mask; // extract the lower portion
upper = val & (~mask); // extract the upper portion
return (upper << 1) | lower; // recombine with the upper portion shifted 1 bit
}
}
int main()
{
int i;
uint32_t val = 01111111111; // hey look, a good use of octal!
srand(time(NULL));
for (i=0;i<4;i++) {
int p = rand() % 11;
printf("p=%d\n", p);
val = insert(val, p);
}
binprint(val);
printf("\n");
return 0;
}
Sample output for two runs:
p=3
p=10
p=9
p=0
01001001000100100100100100100010
...
p=3
p=9
p=3
p=1
10001001000010010010010010010001
Run time is negligible.
Since you don't want a lookup table here is the way:
Basically you have this number with 28 bits set to 0 and 1 in which you need to insert 4x 0 :
0b1001001001001001001001001001
Hence you can use the following algorithm:
int special_rng_nolookup(void)
{
int secret = 0b1001001001001001001001001001;
int low_secret;
int high_secret;
unsigned int i = 28; // len of secret
unsigned int rng;
int mask = 0xffff // equivalent to all bits set in integer
while (i < 32)
{
rng = __asm__ volatile(. // Pseudo code
"rdrand"
);
rng %= (i + 1); // will generate a number between 0 and 28 where you will add a 0. Then between 0 and 29, 30, 31 for the 3 next loop.
low_secret = secret & (mask >> (i - rng)); // locate where you will add your 0 and save the lower part of your number.
high_secret = (secret ^ low_secret) << (!(!rng)); // remove the lower part to your int and shift to insert a 0 between the higher part and the lower part. edit : if rng was 0 you want to add it at the very beginning (left part) so no shift.
secret = high_secret | low_secret; // put them together.
++i;
}
return secret;
}

C Array Initialization getting error

I have tried to define a 2 dimension array in c language and initialize it with variables of float types but I have got this error:
"must be constant expression"
here is my code:
/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 1/30/2017
Author :
Company :
Comments:
Chip type : ATmega8A
Program type : Application
AVR Core Clock frequency: 8.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*******************************************************/
#include <mega8.h>
#include <stdio.h>
#include <delay.h>
#include <alcd.h>
#define A Hall_1
#define B Hall_2
#define C Hall_3
//...........................................................................................
// Declare your global variables here
float Hall_1 ,Hall_2 ,Hall_3 ;
int count=0;
//----------------------------------------------------------------------------------------------------
// Timer 0 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
count++;
}
//----------------------------------------------------------------------------------------------
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
}
//-----------------------------------------------------------------------------------------------
float adc_read(unsigned char);
float maxf(float , float , float);
float minf(float , float , float);
void commutate(unsigned char*);
//-----------------------------------------------------------------------------------------------
void main(void)
{
// Declare your local variables here
float comt_sequence[6][2]= {{B,A},{B,C},{A,C},{A,B},{C,B},{C,A}};
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000.000 kHz
TCCR1B=(0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT1=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
// ADC initialization
// ADC Clock frequency: 250.000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// Only the 8 most significant bits of
// the AD conversion result are used
ADMUX= (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) ;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
SFIOR=(0<<ACME);
// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTD Bit 0
// RD - PORTD Bit 1
// EN - PORTD Bit 2
// D4 - PORTD Bit 4
// D5 - PORTB Bit 6
// D6 - PORTB Bit 7
// D7 - PORTD Bit 5
// Characters/line: 16
lcd_init(40);
// Global enable interrupts
#asm("sei")
lcd_putsf("start");
delay_ms(500);
lcd_clear();
while (1)
{
unsigned char buffer[18] , s=0;
float m,n=0 , max_min[2];
TCCR1B=1; //start counting cycles
Hall_1 = adc_read(5);
Hall_2 = adc_read(4);
Hall_3 = adc_read(3);
m=maxf(Hall_1,Hall_2,Hall_3);
/*if(m == Hall_1)
lcd_putsf("Max= A ");
else if(m == Hall_2)
lcd_putsf("Max= B ");
else if(m == Hall_3)
lcd_putsf("Max= C ");
else
lcd_putsf("Error"); */
n=minf(Hall_1,Hall_2,Hall_3);
/*if(n == Hall_1)
lcd_putsf("Min= A");
else if(n == Hall_2)
lcd_putsf("Min= B");
else if(n == Hall_3)
lcd_putsf("Min= C");
else
lcd_putsf("Error");*/
max_min[0] = m;
max_min[1] = n;
s=count;
sprintf(buffer,"%5.4f %5.4f %d",max_min[0],max_min[1] ,TCNT1);
lcd_puts(buffer);
delay_ms(1000);
lcd_clear();
}
}
///////////////////////////////////////////////
float adc_read(unsigned char ch)
{
unsigned char lcd_buff[18];
float adc_data;
// select the corresponding channel 0~7
// ANDing with ’7' will always keep the value
// of ‘ch’ between 0 and 5 ""ATmega8 has 6 ADC channel 0-5""
ch &= 0b00000111; // AND operation with 5
ADMUX = (ADMUX & 0xF8)|ch; // clears the bottom 3 bits before ORing
// start single convertion
// write ’1' to ADSC
ADCSRA |= (1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
// Read the 8 most significant bits
// of the AD conversion result
adc_data=(ADCH * 2.56)/255;
//sprintf(lcd_buff," %5.3f ",adc_data);
//lcd_puts(lcd_buff);
//delay_ms(500);
return adc_data;
}
//------------------------------------------------------------------------------------------------
float maxf(float a , float b , float c) {
float m;
m = (a>b)?a:b;
m = (m>c)?m:c;
return m;
}
float minf(float a , float b , float c) {
float m;
m = (a<b)?a:b;
m = (m<c)?m:c;
return m;
}
//--------------------------------------------------------------------------------------
void commutate(unsigned char *max_min){
unsigned char x=0, i=0;
//unsigned char comt_pattern[6][2] = {(
for (i=0; i<6 ;i++)
if((max_min[0] == comt_sequence[i][0]) && (max_min[1] == comt_sequence[i][1])) x=i;
switch(x){
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
}
}
i add my whole code also i mention that Hall variables holds an ADC reading from a sensor and its values changes periodically what is my fault?
please help
You may not initialize arrays in C with static storage duration with non-constant initializers.
From the C Standard (6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals.
It seems your array is declared outside any function. If it is possible declare it in a function for example in main.
When creating an array like that, its size must be constant, because C doesn't allow non-constant values for the size of an array.
C99 standard section 6.7.8 (Initialization), point 4:
All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.
I did changes your code. try it.
#include <stdio.h>
#define Hall_1 10
#define Hall_2 20
#define Hall_3 30
int main()
{
float A,B,C;
A = Hall_1;
B = Hall_2;
C = Hall_3;
float commutate_sequence[6][2]= {{B,A},{B,C},{A,C},{A,B},{C,B},{C,A}};
return 0;
}
I changed code as follow and it works now:
#define A Hall_1
#define B Hall_2
#define C Hall_3
void commutate(unsigned char max_min)
{ unsigned char X=0, i=0;
float comt_sequence[6][2]= { (&Hall_2,&Hall_1) , (&Hall_2,&Hall_3),(Hall_1,&Hall_3) , (&Hall_1,&Hall_2), &Hall_3,&Hall_2) , (&Hall_3,&Hall_1) };
for (i=0; i<6 ;i++)
{ if( (max_min[0] == (*comt_sequence[i][0])) && (max_min[1] == (*comt_sequence[i][1]))) X=i;}

CRC32 calculation with CRC hash at the beginning of the message in C

I need to calculate CRC of the message and put it at the beginning of this message, so that the final CRC of the message with 'prepended' patch bytes equals 0. I was able to do this very easily with the help of few articles, but not for my specific parameters. The thing is that I have to use a given CRC32 algorithm which calculates the CRC of the memory block, but I don't have that 'reverse' algorithm that calculates those 4 patch bytes/'kind of CRC'. Parameters of the given CRC32 algorithm are:
Polynomial: 0x04C11DB7
Endianess: big-endian
Initial value: 0xFFFFFFFF
Reflected: false
XOR out with: 0L
Test stream: 0x0123, 0x4567, 0x89AB, 0xCDEF results in CRC = 0x612793C3
The code to calculate the CRC (half-byte, table-driven, I hope data type definitions are self-explanatory):
uint32 crc32tab(uint16* data, uint32 len, uint32 crc)
{
uint8 nibble;
int i;
while(len--)
{
for(i = 3; i >= 0; i--)
{
nibble = (*data >> i*4) & 0x0F;
crc = ((crc << 4) | nibble) ^ tab[crc >> 28];
}
data++;
}
return crc;
}
The table needed is (I thougth the short [16] table should contain every 16th element from the large [256] table, but this table contains actually first 16 elements, but that's how it was provided to me):
static const uint32 tab[16]=
{
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
};
I modified the code so it's not so long, but the functionality stays the same. The problem is that this forward CRC calculation looks more like backward/reverse CRC calc.
I've spent almost a week trying to find out the correct polynomial/algorithm/table combination, but with no luck. If it helps, I came up with bit-wise algorithm that corresponds to table-driven code above, although that was not so hard after all:
uint32 crc32(uint16* data, uint32 len, uint32 crc)
{
uint32 i;
while(len--)
{
for(i = 0; i < 16; i++)
{
// #define POLY 0x04C11DB7
crc = (crc << 1) ^ (((crc ^ *data) & 0x80000000) ? POLY : 0);
}
crc ^= *data++;
}
return crc;
}
Here are expected results - first 2 16-bit words make the needed unknown CRC and the rest is the known data itself (by feeding these examples to provided algorithm, the result is 0).
{0x3288, 0xD244, 0xCDEF, 0x89AB, 0x4567, 0x0123}
{0xC704, 0xDD7B, 0x0000} - append as many zeros as you like, the result is the same
{0xCEBD, 0x1ADD, 0xFFFF}
{0x81AB, 0xB932, 0xFFFF, 0xFFFF}
{0x0857, 0x0465, 0x0000, 0x0123}
{0x1583, 0xD959, 0x0123}
^ ^
| |
unknown bytes that I need to calculate
I think testing this on 0xFFFF or 0x0000 words is convenient because the direction of calculation and endianess is not important (I hope :D). So be careful to use other test bytes, because the direction of calculation is quite devious :D. Also you can see that by feeding only zeros to the algorithm (both forward and backward), the result is so-called residue (0xC704DD7B), that may be helpful.
So...I wrote at least 10 different functions (bite-wise, tables, combination of polynomials etc.) trying to solve this, but with no luck. I give you here the function in which I put my hopes into. It's 'reversed' algorithm of the table-driven one above, with different table of course. The problem is that the only correct CRC I get from that is with all 0s message and that's not so unexpected. Also I have written the reversed implementation of the bit-wise algorithm (reversed shifts, etc.), but that one returns only the first byte correctly.
Here is the table-driven one, pointer to data should point to the last element of the message and crc input should be the requested crc (0s for the whole message or you can maybe take another approach - that the last 4 bytes of message are the CRC you are looking for: Calculating CRC initial value instead of appending the CRC to payload) :
uint32 crc32tabrev(uint16* data, uint32 len, uint32 crc)
{
uint8 nibble;
int i;
while(len--)
{
for(i = 0; i < 4; i++)
{
nibble = (*data >> i*4) & 0x0F;
crc = (crc >> 4) ^ revtab[((crc ^ nibble) & 0x0F)];
}
data--;
}
return reverse(crc); //reverse() flips all bits around center (MSB <-> LSB ...)
}
The table, which I hope is 'the chosen one':
static const uint32 revtab[16]=
{
0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC,
0x76DC4190, 0x6B6B51F4, 0x4DB26158, 0x5005713C,
0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C
};
As you can see, this algorithm has some perks which make me run in circles and I think I'm maybe on the right track, but I'm missing something. I hope an extra pair of eyes will see what I can not. I'm sorry for the long post (no potato :D), but I think all of that explanation was neccessary. Thank you in advance for insight or advice.
I will answer for your CRC specification, that of a CRC-32/MPEG-2. I will have to ignore your attempts at calculating that CRC, since they are incorrect.
Anyway, to answer your question, I happen to have written a program that solves this problem. It is called spoof.c. It very rapidly computes what bits to change in a message to get a desired CRC. It does this in order log(n) time, where n is the length of the message. Here is an example:
Let's take the nine-byte message 123456789 (those digits represented in ASCII). We will prepend it with four zero bytes, which we will change to get the desired CRC at the end. The message in hex is then: 00 00 00 00 31 32 33 34 35 36 37 38 39. Now we compute the CRC-32/MPEG-2 for that message. We get 373c5870.
Now we run spoof with this input, which is the CRC length in bits, the fact that it is not reflected, the polynomial, the CRC we just computed, the length of the message in bytes, and all 32 bit locations in the first four bytes (which is what we are allowing spoof to change):
32 0 04C11DB7
373c5870 13
0 0 1 2 3 4 5 6 7
1 0 1 2 3 4 5 6 7
2 0 1 2 3 4 5 6 7
3 0 1 2 3 4 5 6 7
It gives this output with what bits in those first four bytes to set:
invert these bits in the sequence:
offset bit
0 1
0 2
0 4
0 5
0 6
1 0
1 2
1 5
1 7
2 0
2 2
2 5
2 6
2 7
3 0
3 1
3 2
3 4
3 5
3 7
We then set the first four bytes to: 76 a5 e5 b7. We then test by computing the CRC-32/MPEG-2 of the message 76 a5 e5 b7 31 32 33 34 35 36 37 38 39 and we get 00000000, the desired result.
You can adapt spoof.c to your application.
Here is an example that correctly computes the CRC-32/MPEG-2 on a stream of bytes using a bit-wise algorithm:
uint32_t crc32m(uint32_t crc, const unsigned char *buf, size_t len)
{
int k;
while (len--) {
crc ^= (uint32_t)(*buf++) << 24;
for (k = 0; k < 8; k++)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
}
return crc;
}
and with a nybble-wise algorithm using the table in the question (which is correct):
uint32_t crc_table[] = {
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
};
uint32_t crc32m_nyb(uint32_t crc, const unsigned char *buf, size_t len)
{
while (len--) {
crc ^= (uint32_t)(*buf++) << 24;
crc = (crc << 4) ^ crc_table[crc >> 28];
crc = (crc << 4) ^ crc_table[crc >> 28];
}
return crc;
}
In both cases, the initial CRC must be 0xffffffff.
Alternate approach. Assumes xorout = 0, if not, then after calculating the normal crc, then crc ^= xorout to remove it. The method here multiplies the normal crc by (1/2)%(crc polynomial) raised to (message size in bits) power % (crc polynomial) equivalent to cycling it backwards. If the message size is fixed, then the mapping is fixed and time complexity is O(1). Otherwise, it's O(log(n)).
This example code uses Visual Studio and an intrinsic for carryless multiply (PCLMULQDQ), which uses XMM (128 bit) registers. Visual Studio uses __m128i type to represent integer XMM values.
#include <stdio.h>
#include <stdlib.h>
#include <intrin.h>
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
#define POLY (0x104c11db7ull)
#define POLYM ( 0x04c11db7u)
static uint32_t crctbl[256];
static __m128i poly; /* poly */
static __m128i invpoly; /* 2^64 / POLY */
void GenMPoly(void) /* generate __m128i poly info */
{
uint64_t N = 0x100000000ull;
uint64_t Q = 0;
for(size_t i = 0; i < 33; i++){
Q <<= 1;
if(N&0x100000000ull){
Q |= 1;
N ^= POLY;
}
N <<= 1;
}
poly.m128i_u64[0] = POLY;
invpoly.m128i_u64[0] = Q;
}
void GenTbl(void) /* generate crc table */
{
uint32_t crc;
uint32_t c;
uint32_t i;
for(c = 0; c < 0x100; c++){
crc = c<<24;
for(i = 0; i < 8; i++)
/* assumes twos complement */
crc = (crc<<1)^((0-(crc>>31))&POLYM);
crctbl[c] = crc;
}
}
uint32_t GenCrc(uint8_t * bfr, size_t size) /* generate crc */
{
uint32_t crc = 0xffffffffu;
while(size--)
crc = (crc<<8)^crctbl[(crc>>24)^*bfr++];
return(crc);
}
/* carryless multiply modulo poly */
uint32_t MpyModPoly(uint32_t a, uint32_t b) /* (a*b)%poly */
{
__m128i ma, mb, mp, mt;
ma.m128i_u64[0] = a;
mb.m128i_u64[0] = b;
mp = _mm_clmulepi64_si128(ma, mb, 0x00); /* p[0] = a*b */
mt = _mm_clmulepi64_si128(mp, invpoly, 0x00); /* t[1] = (p[0]*((2^64)/POLY))>>64 */
mt = _mm_clmulepi64_si128(mt, poly, 0x01); /* t[0] = t[1]*POLY */
return mp.m128i_u32[0] ^ mt.m128i_u32[0]; /* ret = p[0] ^ t[0] */
}
/* exponentiate by repeated squaring modulo poly */
uint32_t PowModPoly(uint32_t a, uint32_t b) /* pow(a,b)%poly */
{
uint32_t prd = 0x1u; /* current product */
uint32_t sqr = a; /* current square */
while(b){
if(b&1)
prd = MpyModPoly(prd, sqr);
sqr = MpyModPoly(sqr, sqr);
b >>= 1;
}
return prd;
}
int main()
{
uint32_t inv; /* 1/2 % poly, constant */
uint32_t fix; /* fix value, constant if msg size fixed */
uint32_t crc; /* crc at end of msg */
uint32_t pre; /* prefix for msg */
uint8_t msg[13] = {0x00,0x00,0x00,0x00,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
GenMPoly(); /* generate __m128i polys */
GenTbl(); /* generate crc table */
inv = PowModPoly(2, 0xfffffffeu); /* inv = 2^(2^32-2) % Poly = 1/2 % poly */
fix = PowModPoly(inv, 8*sizeof(msg)); /* fix value */
crc = GenCrc(msg, sizeof(msg)); /* calculate normal crc */
pre = MpyModPoly(fix, crc); /* convert to prefix */
printf("crc = %08x pre = %08x ", crc, pre);
msg[0] = (uint8_t)(pre>>24); /* store prefix in msg */
msg[1] = (uint8_t)(pre>>16);
msg[2] = (uint8_t)(pre>> 8);
msg[3] = (uint8_t)(pre>> 0);
crc = GenCrc(msg, sizeof(msg)); /* check result */
if(crc == 0)
printf("passed\n");
else
printf("failed\n");
return 0;
}
Well, few hours after my question, someone whose name I don't remember posted an answer to my question which turned out to be correct. Somehow this answer got completely deleted, I don't know why or who did it, but I'd like to thank to this person and in the case you will see this, please post your answer again and I'll delete this one. But for other users, here's his answer that worked for me, thank you again, mysterious one (unfortunately, I can't replicate his notes and suggestions well enough, just the code itself):
Edit: The original answer came from user samgak, so this stays here until he'll post his answer.
The reverse CRC algorithm:
uint32 revcrc32(uint16* data, uint32 len, uint32 crc)
{
uint32 i;
data += len - 1;
while(len--)
{
crc ^= *data--;
for(i = 0; i < 16; i++)
{
uint32 crc1 = ((crc ^ POLY) >> 1) | 0x80000000;
uint32 crc2 = crc >> 1;
if(((crc1 << 1) ^ (((crc1 ^ *data) & 0x80000000) ? POLY : 0)) == crc)
crc = crc1;
else if(((crc2 << 1) ^ (((crc2 ^ *data) & 0x80000000) ? POLY : 0)) == crc)
crc = crc2;
}
}
return crc;
}
Find patch bytes:
#define CRC_OF_ZERO 0xb7647d
void bruteforcecrc32(uint32 targetcrc)
{
// compute prefixes:
uint16 j;
for(j = 0; j <= 0xffff; j++)
{
uint32 crc = revcrc32(&j, 1, targetcrc);
if((crc >> 16) == (CRC_OF_ZERO >> 16))
{
printf("prefixes: %04lX %04lX\n", (crc ^ CRC_OF_ZERO) & 0xffff, (uint32)j);
return;
}
}
}
Usage:
uint16 test[] = {0x0123, 0x4567, 0x89AB, 0xCDEF}; // prefix should be 0x0CD8236A
bruteforcecrc32(revcrc32(test, 4, 0L));

initialization function for pic microcontroller

I am trying to get a pic16 controller to run an initialization function that displays some text on an LCD only once and then goes on to display other things
The LCD output is working fine the problem is that the initialization function keeps executing. What am I doing wrong ?
/*
* File: main.c
*
* Created on Sep 1, 2013, 12:09 PM
*/
#include <pic.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "delay.h"
__CONFIG(WDTE_ON & PWRTE_ON & MCLRE_ON & BOREN_ON & FOSC_INTRCIO );
static int exec_counter = 0;
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) // bit mask macros
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define flip_bit(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define test_bit(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define E RC4 // Define the LCD Control Pins
#define RS RC5
int i; // Use Global Variables for Debug
LCDWrite(int LCDData, int RSValue)
{
PORTC = (LCDData >> 4) & 0x0F; // Get High 4 Bits for Output
RS = RSValue;
E = 1; E = 0; // Toggle the High 4 Bits Out
PORTC = LCDData & 0x0F; // Get Low 4 Bits for Output
RS = RSValue;
E = 1; E = 0; // Toggle the Low 4 Bits Out
if ((0 == (LCDData & 0xFC)) && (0 == RSValue))
DelayMs(5);
else
DelayUs(200);
} //
void writeLines(char top[],char bottom[]){
for (i = 0; top[i] != 0; i++) // Write Line 1
LCDWrite(top[i], 1);
LCDWrite(0b11000000, 0); // Move Cursor to the Second Line
for (i = 0; bottom[i] != 0; i++)// Write Line 2
LCDWrite(bottom[i], 1);
}
int countelems(char arr[]){
for (i = 0; arr[i] != 0; i++){}
return i;
}
void pad_number(char number[],char numberout[],char unit[]){
int size_n = countelems(number); // get length of number array by reference
int size_u = countelems(unit); // get length of unit array by reference
int size = size_u + size_n + 1; // calculate total size of text with 1 space between number and unit
int L_space = floor((16-size)/2)-1; // calculate space required on left side of display to center text
for (i = 0; i <= 15; i++)
numberout[i] = 0b10100000; // fill output char array with spaces
for (i = 0; i <= (size_n); i++){
numberout[i+(L_space+1)] = number[i]; // fill output char array with number
}
numberout[L_space+size_n+1] = 0b10100000; // put space in output char array between number and unit
for (i = 0; i <= size_u; i++){
numberout[i+(L_space+size_n+2)] = unit[i]; // fill output char array with unit
}
}
void pad_text(char text[],char textout[]){
int size = countelems(text); // get length of char array by reference
int L_space = floor((16-size)/2); // calculate space required on left side of display to center text
for (i = 0; i <= 15; i++)
textout[i] = 0b10100000; // fill output char array with spaces
for (i = 0; i <= 15; i++){
if( i >= L_space && i <= (L_space+size)){
textout[i] = text[i-L_space]; // fill middle of output char array with text
}
}
}
void getAnalog(int channel,char parameter[], char unit[]){
char output_parameter[16];
char output_number[16];
char number[16];
ADCON0 = channel << 2; // select channel
//set_bit(ADCON0,7); // set ADFM flag so LSB is bit 0 of ADRESL
set_bit(ADCON0,0); // switch ADC on = set ADON flag 0b00000001
sampleTime(); // wait required aquisition time
set_bit(ADCON0,1); // start conversion = set GO/DONE bit
while(test_bit(ADCON0,1)){/* wait for ADC to complete conversion */;}
int ADCresult = (ADRESL+ADRESH)/10; // get result from ADC
itoa(number,ADCresult,10); // convert ADC result to charstring
LCDWrite(0b00000001, 0); // Clear LCD
pad_text(parameter,output_parameter);
pad_number(number,output_number,unit);
writeLines(output_parameter, output_number);
}
void init(){
DelayMs(20); // Wait for LCD to Power Up
PORTC = 3; // Start Initialization Process
E = 1; E = 0; // Send Reset Command
DelayMs(5);
E = 1; E = 0; // Repeat Reset Command
DelayUs(200);
E = 1; E = 0; // Repeat Reset Command Third Time
DelayUs(200);
PORTC = 2; // Initialize LCD 4 Bit Mode
E = 1; E = 0;
DelayUs(200);
LCDWrite(0b00101000, 0); // LCD is 4 Bit I/F, 2 Line
LCDWrite(0b00000001, 0); // Clear LCD
LCDWrite(0b00000110, 0); // Move Cursor After Each Character
LCDWrite(0b00001110, 0); // Turn On LCD and Enable Cursor
// "0123456789012345"
writeLines( " INITIALIZE ",
" TEXT ");
}
void main(void) {
OPTION_REG |= 0x7; // set prescaler to 1:128 or 2.3 Seconds
OPTION_REG |= 0x8; // assign prescaler to WDT
TRISA = 0b00000101; // configure PORTA set RA0 and RA2 to analog input;
ANSEL = 0b00000101; // disable input buffers if I/O pins RA0 and RA2
TRISC = 0; // configure PORTC as output
ADCON1 = 0; // select FOSC2
if (exec_counter == 0){
exec_counter++;
init();
DelayS(4);
}
PORTC = 0;
while (1) {
getAnalog(0,"VELOCITY","KM/H");
DelayS(4);
getAnalog(2,"ACCELERATION","M/S^2");
DelayS(4);
}
return;
}
/*
* File: delay.c
*
* Created on Sep 3, 2013, 12:09 PM
*/
#include "delay.h"
#include <pic.h>
#define _XTAL_FREQ 4000000
void DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
do {
DelayUs(996);
} while(--cnt);
#endif
#if XTAL_FREQ > 2MHZ
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
} while(--i);
} while(--cnt);
#endif
}
void DelayS(unsigned int count){
for (int i=0; i<=count;i++){
NOP();
CLRWDT();
DelayMs(1000);
}
}
void sampleTime(){
// TC = – 10pF ( 1k Ω + 7k Ω + 1k Ω ) ln(0.0004885)
// = 0.686 μS
// TACQ = 5μS + 0.686μS + [ ( 50°C- 25°C ) ( 0.05μ S /°C ) ]
// = 6.936 μS /
// 1 instruction cycle = 4μS # 1 mHz
// 1 instruction cycle = 1μS # 4 mHz
// 1 instruction cycle = 500nS # 8 mHz
// 1 instruction cycle = 200nS # 20 mHz
// TACQ # 1 mHz is 6.936 μS / 4 μS or ~ 2 instruction cycles
// TACQ # 4 mHz is 6.936 μS / 1 μS or ~ 7 instruction cycles
// TACQ # 8 mHz is 6.936 μS / 0.5 μS or ~ 14 instruction cycles
// TACQ # 20 mHz is 6.936 μS / 0.2 μS or ~ 35 instruction cycles
DelayUs(8);
}
The char number[] = ""; array is very small, yet you use it in itoa(), thus overwriting random memory.

Resources