// Les 3 tables ci dessous peuvent être recréée en modifiant des parametres dans l'onglet RebuildTable
// pour actualiser le contenu, decommenter la ligne sui suit et modifier les parametres utiles pour les generer
//#define REBUILD
uint8_t tabPulseSinusTotal[101] = { 2,
63,49,33,25,40,33,43,25,11,20,55,25,23,43,40,25,41,39,21, 5,
19,41,13,25, 8,23,37,25,31,20,29,25,55,47,40,25,27,21,41, 5,
39,31, 7,25,40,37,17,25,47, 4,47,25,17,37,40,25, 7,31,39, 5,
41,21,27,25,40,47,55,25,29,20,31,25,37,23, 8,25,13,41,19, 5,
21,39,41,25,40,43,23,25,55,20,11,25,43,33,40,25,33,49,63, 2
};
uint8_t tabPulseSinusOn[101] = { 0,
1, 1, 1, 1, 2, 2, 3, 2, 1, 2, 6, 3, 3, 6, 6, 4, 7, 7, 4, 1,
4, 9, 3, 6, 2, 6,10, 7, 9, 6, 9, 8,18,16,14, 9,10, 8,16, 2,
16,13, 3,11,18,17, 8,12,23, 2,24,13, 9,20,22,14, 4,18,23, 3,
25,13,17,16,26,31,37,17,20,14,22,18,27,17, 6,19,10,32,15, 4,
17,32,34,21,34,37,20,22,49,18,10,23,40,31,38,24,32,48,62, 2
};
uint64_t tabsequenceMultiSinus[101] = {0x0000000000000000,
0x0000000080000000,0x0000000001000000,0x0000000000010000,0x0000000000001000,0x0000000020000400,0x0000000001000100,0x0000000180000400,0x0000000000040040,0x0000000000000020,0x0000000000004020,
0x0000600018000300,0x0000000000060040,0x0000000000030020,0x00000018006000C0,0x0000000600180060,0x00000000000600C0,0x0000001806004030,0x0000000601804030,0x000000000000C060,0x0000000000000004,
0x0000000000006030,0x0000003030101818,0x0000000000000308,0x0000000000303018,0x0000000000000024,0x0000000000181818,0x000000060C0C0C0C,0x000000000061810C,0x000000001860830C,0x000000000003060C,
0x000000000618430C,0x000000000060C60C,0x001861861830C30C,0x000018618630C30C,0x0000006186186186,0x0000000000C610C6,0x0000000003186186,0x00000000000C60C6,0x000000C6318318C6,0x000000000000000A,
0x000000318C6318C6,0x0000000033188C66,0x0000000000000032,0x0000000000CCC266,0x000000666318C666,0x0000000CCCC46666,0x000000000000C6C6,0x0000000000CC6C66,0x0000333333266666,0x000000000000000C,
0x00004CCCCCD99999,0x0000000001339399,0x0000000000013939,0x00000013333B9999,0x000000999CE73999,0x0000000001333D99,0x000000000000004D,0x000000004CE77399,0x0000004E739CE739,0x0000000000000015,
0x00000139CE7CE739,0x0000000000139F39,0x0000000004E79E79,0x000000000139EF39,0x0000009E79E79E79,0x0000679E79CF3CF3,0x00679E79E7CF3CF3,0x00000000019F39F3,0x0000000019E7BCF3,0x00000000000CF9F3,
0x00000000679F7CF3,0x00000000019E7EF3,0x00000019F3F3F3F3,0x000000000067E7E7,0x00000000000000DB,0x0000000001CFCFE7,0x0000000000001CF7,0x000001CFCFEFE7E7,0x0000000000079FCF,0x000000000000001B,
0x00000000001F3F9F,0x00000079FE7FBFCF,0x000001E7F9FFBFCF,0x0000000001F9FF3F,0x000000F9FFE7FF9F,0x000007E7FF9FFF3F,0x00000000007CFFDF,0x0000000001F9FFBF,0x007F9FFFE7FFFCFF,0x00000000000FBFDF,
0x00000000000007DF,0x0000000001FBFFBF,0x000007FE7FFFFBFF,0x00000001FEFFFEFF,0x000000FFDFFFFBFF,0x0000000001FFEFFF,0x00000001FFFEFFFF,0x0001FFFFFEFFFFFF,0x7FFFFFFF7FFFFFFF,0x0000000000000003
};
/*
uint64_t tabsequenceMultiSinus[101] = {
0b0000000000000000000000000000000000000000000000000000000000000000, // 0x0000000000000000 // 00/02 // 000
0b0000000000000000000000000000000010000000000000000000000000000000, // 0x0000000080000000 // 01/63 // 001
0b0000000000000000000000000000000000000001000000000000000000000000, // 0x0000000001000000 // 01/49 // 002
0b0000000000000000000000000000000000000000000000010000000000000000, // 0x0000000000010000 // 01/33 // 003
0b0000000000000000000000000000000000000000000000000001000000000000, // 0x0000000000001000 // 01/25 // 004
0b0000000000000000000000000000000000100000000000000000010000000000, // 0x0000000020000400 // 02/40 // 005
0b0000000000000000000000000000000000000001000000000000000100000000, // 0x0000000001000100 // 02/33 // 006
0b0000000000000000000000000000000110000000000000000000010000000000, // 0x0000000180000400 // 03/43 // 007
0b0000000000000000000000000000000000000000000001000000000001000000, // 0x0000000000040040 // 02/25 // 008
0b0000000000000000000000000000000000000000000000000000000000100000, // 0x0000000000000020 // 01/11 // 009
0b0000000000000000000000000000000000000000000000000100000000100000, // 0x0000000000004020 // 02/20 // 010
0b0000000000000000011000000000000000011000000000000000001100000000, // 0x0000600018000300 // 06/55 // 011
0b0000000000000000000000000000000000000000000001100000000001000000, // 0x0000000000060040 // 03/25 // 012
0b0000000000000000000000000000000000000000000000110000000000100000, // 0x0000000000030020 // 03/23 // 013
0b0000000000000000000000000001100000000000011000000000000011000000, // 0x00000018006000C0 // 06/43 // 014
0b0000000000000000000000000000011000000000000110000000000001100000, // 0x0000000600180060 // 06/40 // 015
0b0000000000000000000000000000000000000000000001100000000011000000, // 0x00000000000600C0 // 04/25 // 016
0b0000000000000000000000000001100000000110000000000100000000110000, // 0x0000001806004030 // 07/41 // 017
0b0000000000000000000000000000011000000001100000000100000000110000, // 0x0000000601804030 // 07/39 // 018
0b0000000000000000000000000000000000000000000000001100000001100000, // 0x000000000000C060 // 04/21 // 019
0b0000000000000000000000000000000000000000000000000000000000000100, // 0x0000000000000004 // 01/05 // 020
0b0000000000000000000000000000000000000000000000000110000000110000, // 0x0000000000006030 // 04/19 // 021
0b0000000000000000000000000011000000110000000100000001100000011000, // 0x0000003030101818 // 09/41 // 022
0b0000000000000000000000000000000000000000000000000000001100001000, // 0x0000000000000308 // 03/13 // 023
0b0000000000000000000000000000000000000000001100000011000000011000, // 0x0000000000303018 // 06/25 // 024
0b0000000000000000000000000000000000000000000000000000000000100100, // 0x0000000000000024 // 02/08 // 025
0b0000000000000000000000000000000000000000000110000001100000011000, // 0x0000000000181818 // 06/23 // 026
0b0000000000000000000000000000011000001100000011000000110000001100, // 0x000000060C0C0C0C // 10/37 // 027
0b0000000000000000000000000000000000000000011000011000000100001100, // 0x000000000061810C // 07/25 // 028
0b0000000000000000000000000000000000011000011000001000001100001100, // 0x000000001860830C // 09/31 // 029
0b0000000000000000000000000000000000000000000000110000011000001100, // 0x000000000003060C // 06/20 // 030
0b0000000000000000000000000000000000000110000110000100001100001100, // 0x000000000618430C // 09/29 // 031
0b0000000000000000000000000000000000000000011000001100011000001100, // 0x000000000060C60C // 08/25 // 032
0b0000000000011000011000011000011000011000001100001100001100001100, // 0x001861861830C30C // 18/55 // 033
0b0000000000000000000110000110000110000110001100001100001100001100, // 0x000018618630C30C // 16/47 // 034
0b0000000000000000000000000110000110000110000110000110000110000110, // 0x0000006186186186 // 14/40 // 035
0b0000000000000000000000000000000000000000110001100001000011000110, // 0x0000000000C610C6 // 09/25 // 036
0b0000000000000000000000000000000000000011000110000110000110000110, // 0x0000000003186186 // 10/27 // 037
0b0000000000000000000000000000000000000000000011000110000011000110, // 0x00000000000C60C6 // 08/21 // 038
0b0000000000000000000000001100011000110001100000110001100011000110, // 0x000000C6318318C6 // 16/41 // 039
0b0000000000000000000000000000000000000000000000000000000000001010, // 0x000000000000000A // 02/05 // 040
0b0000000000000000000000000011000110001100011000110001100011000110, // 0x000000318C6318C6 // 16/39 // 041
0b0000000000000000000000000000000000110011000110001000110001100110, // 0x0000000033188C66 // 13/31 // 042
0b0000000000000000000000000000000000000000000000000000000000110010, // 0x0000000000000032 // 03/07 // 043
0b0000000000000000000000000000000000000000110011001100001001100110, // 0x0000000000CCC266 // 11/25 // 044
0b0000000000000000000000000110011001100011000110001100011001100110, // 0x000000666318C666 // 18/40 // 045
0b0000000000000000000000000000110011001100110001000110011001100110, // 0x0000000CCCC46666 // 17/37 // 046
0b0000000000000000000000000000000000000000000000001100011011000110, // 0x000000000000C6C6 // 08/17 // 047
0b0000000000000000000000000000000000000000110011000110110001100110, // 0x0000000000CC6C66 // 12/25 // 048
0b0000000000000000001100110011001100110011001001100110011001100110, // 0x0000333333266666 // 23/47 // 049
0b0000000000000000000000000000000000000000000000000000000000001100, // 0x000000000000000C // 02/04 // 050
0b0000000000000000010011001100110011001100110110011001100110011001, // 0x00004CCCCCD99999 // 24/47 // 051
0b0000000000000000000000000000000000000001001100111001001110011001, // 0x0000000001339399 // 13/25 // 052
0b0000000000000000000000000000000000000000000000010011100100111001, // 0x0000000000013939 // 09/17 // 053
0b0000000000000000000000000001001100110011001110111001100110011001, // 0x00000013333B9999 // 20/37 // 054
0b0000000000000000000000001001100110011100111001110011100110011001, // 0x000000999CE73999 // 22/40 // 055
0b0000000000000000000000000000000000000001001100110011110110011001, // 0x0000000001333D99 // 14/25 // 056
0b0000000000000000000000000000000000000000000000000000000001001101, // 0x000000000000004D // 04/07 // 057
0b0000000000000000000000000000000001001100111001110111001110011001, // 0x000000004CE77399 // 18/31 // 058
0b0000000000000000000000000100111001110011100111001110011100111001, // 0x0000004E739CE739 // 23/39 // 059
0b0000000000000000000000000000000000000000000000000000000000010101, // 0x0000000000000015 // 03/05 // 060
0b0000000000000000000000010011100111001110011111001110011100111001, // 0x00000139CE7CE739 // 25/41 // 061
0b0000000000000000000000000000000000000000000100111001111100111001, // 0x0000000000139F39 // 13/21 // 062
0b0000000000000000000000000000000000000100111001111001111001111001, // 0x0000000004E79E79 // 17/27 // 063
0b0000000000000000000000000000000000000001001110011110111100111001, // 0x000000000139EF39 // 16/25 // 064
0b0000000000000000000000001001111001111001111001111001111001111001, // 0x0000009E79E79E79 // 26/40 // 065
0b0000000000000000011001111001111001111001110011110011110011110011, // 0x0000679E79CF3CF3 // 31/47 // 066
0b0000000001100111100111100111100111100111110011110011110011110011, // 0x00679E79E7CF3CF3 // 37/55 // 067
0b0000000000000000000000000000000000000001100111110011100111110011, // 0x00000000019F39F3 // 17/25 // 068
0b0000000000000000000000000000000000011001111001111011110011110011, // 0x0000000019E7BCF3 // 20/29 // 069
0b0000000000000000000000000000000000000000000011001111100111110011, // 0x00000000000CF9F3 // 14/20 // 070
0b0000000000000000000000000000000001100111100111110111110011110011, // 0x00000000679F7CF3 // 22/31 // 071
0b0000000000000000000000000000000000000001100111100111111011110011, // 0x00000000019E7EF3 // 18/25 // 072
0b0000000000000000000000000001100111110011111100111111001111110011, // 0x00000019F3F3F3F3 // 27/37 // 073
0b0000000000000000000000000000000000000000011001111110011111100111, // 0x000000000067E7E7 // 17/23 // 074
0b0000000000000000000000000000000000000000000000000000000011011011, // 0x00000000000000DB // 06/08 // 075
0b0000000000000000000000000000000000000001110011111100111111100111, // 0x0000000001CFCFE7 // 19/25 // 076
0b0000000000000000000000000000000000000000000000000001110011110111, // 0x0000000000001CF7 // 10/13 // 077
0b0000000000000000000000011100111111001111111011111110011111100111, // 0x000001CFCFEFE7E7 // 32/41 // 078
0b0000000000000000000000000000000000000000000001111001111111001111, // 0x0000000000079FCF // 15/19 // 079
0b0000000000000000000000000000000000000000000000000000000000011011, // 0x000000000000001B // 04/05 // 080
0b0000000000000000000000000000000000000000000111110011111110011111, // 0x00000000001F3F9F // 17/21 // 081
0b0000000000000000000000000111100111111110011111111011111111001111, // 0x00000079FE7FBFCF // 32/39 // 082
0b0000000000000000000000011110011111111001111111111011111111001111, // 0x000001E7F9FFBFCF // 34/41 // 083
0b0000000000000000000000000000000000000001111110011111111100111111, // 0x0000000001F9FF3F // 21/25 // 084
0b0000000000000000000000001111100111111111111001111111111110011111, // 0x000000F9FFE7FF9F // 34/40 // 085
0b0000000000000000000001111110011111111111100111111111111100111111, // 0x000007E7FF9FFF3F // 37/43 // 086
0b0000000000000000000000000000000000000000011111001111111111011111, // 0x00000000007CFFDF // 20/23 // 087
0b0000000000000000000000000000000000000001111110011111111110111111, // 0x0000000001F9FFBF // 22/25 // 088
0b0000000001111111100111111111111111100111111111111111110011111111, // 0x007F9FFFE7FFFCFF // 49/55 // 089
0b0000000000000000000000000000000000000000000011111011111111011111, // 0x00000000000FBFDF // 18/20 // 090
0b0000000000000000000000000000000000000000000000000000011111011111, // 0x00000000000007DF // 10/11 // 091
0b0000000000000000000000000000000000000001111110111111111110111111, // 0x0000000001FBFFBF // 23/25 // 092
0b0000000000000000000001111111111001111111111111111111101111111111, // 0x000007FE7FFFFBFF // 40/43 // 093
0b0000000000000000000000000000000111111110111111111111111011111111, // 0x00000001FEFFFEFF // 31/33 // 094
0b0000000000000000000000001111111111011111111111111111101111111111, // 0x000000FFDFFFFBFF // 38/40 // 095
0b0000000000000000000000000000000000000001111111111110111111111111, // 0x0000000001FFEFFF // 24/25 // 096
0b0000000000000000000000000000000111111111111111101111111111111111, // 0x00000001FFFEFFFF // 32/33 // 097
0b0000000000000001111111111111111111111110111111111111111111111111, // 0x0001FFFFFEFFFFFF // 48/49 // 098
0b0111111111111111111111111111111101111111111111111111111111111111, // 0x7FFFFFFF7FFFFFFF // 62/63 // 099
0b0000000000000000000000000000000000000000000000000000000000000011 // 0x0000000000000003 // 02/02 // 100
};
*/
#define LED 2
void setup() {
Serial.begin(115200);
#ifdef REBUILD
remakeTableMultiSin();
#endif
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
delay(1000);
digitalWrite(LED, LOW);
delay(1000);
Serial.printf("Ready\n");
Serial.print("LED on gpio ");Serial.println(LED);
}
int i = 0; // index de 0 a 100
uint32_t startAt = millis();
bool bit = false;
uint8_t posit = 0;
void loop() {
if (i > 100) i = 0;
if (tabsequenceMultiSinus[i] >> posit & 0b1) digitalWrite(LED, HIGH); else digitalWrite(LED, LOW);
delay(10); // toutes les 10ms on passe au bit suivant
posit++;
if (posit > tabPulseSinusTotal[i]) posit = 0;
if (millis() - startAt > 640) { // boucle de 640 ms avant de passer a l'index suivant
Serial.println(i);
i++;
startAt = millis();
posit = 0; // demmare la sequence au debut
}
}
#ifdef REBUILD
// parametre pour construire les tables
#define RANGEMIN 2 // can't be 0 nor 1
#define RANGEMAX 64 // max 64 pour sequencage sur un uint64_t
#define BASEPRECIS 0
#define FINPRECIS 4
// #define DOUBLEMENT
// choix de ce qui est imprimé en sortie : récuperable en excel pour analyse
//#define printchoice
#define printvarsequence
//#define showSummary
//#define showdetail
//#define showtable
#define showProblem
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
uint64_t repart(uint8_t percent, uint8_t nbON, uint8_t qt) {
const uint8_t nbOFF = qt - nbON;
const uint8_t lowN = MIN(nbON, nbOFF);
const uint8_t highN = MAX(nbON, nbOFF);
const uint8_t nbSeq = (lowN == highN) ? 2 : (lowN == 2) ? 5 : (lowN % 2) ? lowN + 2 : lowN + 1;
const uint8_t startByON = percent < 50 ? 0 : 1;
const uint8_t startByOFF = startByON == 1 ? 0 : 1;
const uint8_t nbSeqON = (nbSeq + startByON) / 2;
const uint8_t nbSeqOFF = (nbSeq + startByOFF) / 2;
#ifdef showSummary
Serial.printf("id:%3d, qt:%3d, nbON:%3d, nbOFF:%3d, nbSeq:%3d, startbyON:%1d, nbSeqON:%2d, nbSeqOFF:%2d \n",percent, qt, nbON, nbOFF, nbSeq, startByON, nbSeqON, nbSeqOFF);
#endif
uint8_t seqON[nbSeqON +10] = {};
uint8_t seqOFF[nbSeqOFF +10] = {};
uint8_t sum = 0;
// premiere répartion equilibrée
int qtSeqIntern = 0;
seqON[0] = 0; // cas 0 sequence ON
for (int i = 0; i < nbSeqON; i++) {
seqON[i] = 0;
if (nbSeqON > nbSeqOFF) { // on a plus de on que de OFF, potentiellement les extremes sont /2
if (nbSeqON == 1) seqON[0] = nbON;
else if (nbSeqON == 2)
seqON[i] = nbON / 2;
else
if (i == 0 || i == (nbSeqON -1))
seqON[i] = (nbON / (nbSeqON-1)) / 2; //les extremités repartition ON sur /2
else {
seqON[i] = (nbON / (nbSeqON-1));
}
}
else {
seqON[i] = nbON / MAX(1, nbSeqON); // cas general repartition équilibrée
qtSeqIntern++;
}
sum += seqON[i];
#ifdef showdetail
Serial.printf("seqON[%d]=%d\n",i,seqON[i]);
#endif
}
#ifdef showdetail
Serial.printf("Sum ON = %d , delta = %d\n", sum, nbON - sum);
Serial.printf(" ON : qtSeqIntern = %d , delta = %d\n", qtSeqIntern, nbON - sum);
#endif
if (nbON - sum + 1 == qtSeqIntern) {
//Serial.printf(" ****Potential !!!\n"); // ça crée une situation non symetrique => augmenter tous les bit de 1 sauf celui juste supérieur milieu ...
sum = 0;
for (int i = 0; i < nbSeqON; i++) {
seqON[i]++;
sum += seqON[i];
}
seqON[nbSeqON/2]--;
sum--;
}
char Ok = 0;
if (sum != nbON) {
Ok = 0;
int gap = nbON - sum;
//if (gap != 0) Serial.printf("%d : Ecart sur le nombre de bit a ON : %d, on doit repartir sur %d positions \n", percent, gap, nbSeqON);
// si ecart, on ajuste les bits en commençant avec un position proche du centre puis alternativement on s'éloigne vers les 'bords'
for (int j = 0; j < abs(gap); j++) {
int index = 0;
int decal = 0;
int8_t idxcenter = 0;
// reflexion m = nb de modif (1 ...) , j chrono modif en cours (0 ...) , x nb pos total (>=1), d = index a modifier (0 ...)
idxcenter = nbSeqON / 2; // si nbSeqON est paire, la div par 2 donne l'index après le milieu du tableau 4/2 = 2 [0,1,<2>,3]
//idxcenter = nbSeqON / 2; // si nbSeqON est impaire, la div par 2 donne l'index milieu du tableau 5/2 = 2 [0,1,<2>,3,4]
#ifdef showdetail
Serial.printf("idxcenter %d \n", idxcenter);
#endif
if ((nbSeqON % 2) == 1) { // nombre de position total est impaire
if (abs(gap) % 2 == 1) { // nombre de modif a faire est impaire (on cible le milieu du tableau puis on alterne 1 avant , 1 après)
#ifdef showdetail
Serial.printf("NbON impaire Nbmodif impaire ");
#endif
// 1 modif (j=0) sur x position impaire => centre d = x/2 5/2=2 + [0,1,<2>,3,4] 2 est bien au centre
// 3 modif (j=0,1,2) sur x position impaire => avant centre + centre + apres centre d1=((x-1)/2)-1 d2=((x-1)/2)+0 et d3=((x-1)/2)+1 (5-1)/2-1 = 1 5/2 (5-1)/2+1=3 [0,<1>,<2>,<3>,4]
// 5 modif (j=0,1,2,3,4) sur x position impaire => 2 avant centre + avant centre + centre + apres centre + 2 après centre d1=((x-1)/2)-2 d2=((x-1)/2)-1 d3=((x-1)/2) d4=((x-1)/2)+1 d5=((x-1)/2)+2 [<0>,<1>,<2>,<3>,<4>]
// sur gap=5 j=0:decal=0; j=1:decal=-1; j=2:decal=+1; j=3:decal=-2; j=4:decal=+2
decal = (j % 2 == 0 ? 1:-1) * (j+1) / 2;
if (gap == 1 && nbSeqON >= 3 && nbSeqON % 2 == 1) { // avec nbSeqON=3, on a idxcenter=1
// a la sortie de cette boucle on fera index = idxcenter + decal;seqON[index] += (gap < 0) ? -1 : 1; donc seqOn[1] sera incrémenté
decal = 0;
seqON[idxcenter] -= 2; // en prévision du traitement qui ajoutera 1
seqON[idxcenter-1] += 1;
seqON[idxcenter+1] += 1;
}
} else { // nombre de modif a faire est pair (on cible la position avant le milieu du tableau suivi de la position après le milieu puis on alterne 1 avant , 1 après)
#ifdef showdetail
Serial.printf("NbON impaire Nbmodif paire ");
#endif
// 2 modif (j=0,1) sur x position impaire => avant centre et apres centre d1 =((x-1)/2) -1 et d2=((x-1)/2)+1 (5-1)/2-1 = 1 (5-1)/2+1=3 [0,<1>,2,<3>,4]
// 4 modif (j=0,1,2,3) sur x position impaire => 2 avant centre + avant centre + apres centre + 2 après centre d1 =((x-1)/2) -2 d2=((x-1)/2)-1 d3 =((x-1)/2) +1 d4=((x-1)/2)+2 [<0>,<1>,2,<3>,<4>]
// sur gap=4 j=0:decal=-1; j=1:decal=+1; j=2:decal=-2; j=3:decal=+2;
decal = (((j -1) + 3) / 2) * (j % 2 == 0 ? -1 : 1);
if (gap == 2 && nbSeqON > 3) decal = 0; // in this particular case add the 2 bits in the middle
}
} else { // nombre de position total est pair
if (abs(gap) % 2 == 1) { // nombre de modif a faire est impaire
#ifdef showdetail
Serial.printf("NbON paire Nbmodif impaire ");
#endif
// 1 modif sur x position paire => after centre d = x/2 4/2 = 2 [0,1,<2>,3]
// 3 modif sur x position paire => avant centre + centre + apres centre mid-1 mid+0 mid+1
// 5 modif sur x position paire => 2 avant centre + avant centre + centre + apres centre + 2 après centre mid-2 mid-1 mid+0 mid+1 mid+2
// sur gap = 5 j=0:decal=0; j=1:decal=-1; j=2:decal=+1; j=3:decal=-2; j=4:decal=+2
decal = (j % 2 == 0 ? 1:-1) * (j+1) / 2;
} else { // nombre de modif a faire est pair
#ifdef showdetail
Serial.printf("NbON paire Nbmodif paire ");
#endif
// 2 modif sur x position paire => avant centre et apres centre d1 =((x-1)/2) -1 et d2=((x-1)/2)+1 (4/2)-1 = 1 (4/2)=2 [0,<1>,<2>,3] mid-0 mid+1
// 4 modif sur x position paire => 2 avant centre + avant centre + apres centre + 2 après centre [<0>,<1>,<2>,<3>] mid-1 mid-0 mid+1 mid+2
// sur gap=4 j=0:decal=0; j=1:decal=-1; j=2:decal=+1; j=3:decal=-2; j4 +2 j5 -3
decal = ((j + 1) / 2) * (j % 2 == 0 ? 1 : -1);
}
}
index = idxcenter + decal;
#ifdef showdetail
Serial.printf("\nfor j=%d, decal index = %d\n", j, decal);
Serial.printf("Modification n° %d seqON at index : %d (on %d) \n", j+1, index, nbSeqON);
#endif
index = MAX(0,index);
index = MIN(index, nbSeqON -1);
#ifdef showdetail
Serial.printf("Change seqON[%d] from %d to %d\n", index, seqON[index], (seqON[index] + ((gap < 0) ? -1 : 1)));
#endif
seqON[index] += (gap < 0) ? -1 : 1;
Ok = 1;
}
#ifdef showProblem
if (!Ok) Serial.printf("%d : Ecart sur le nombre de bit a ON : %d, on doit repartir sur %d positions \n", percent, gap, nbSeqON);
#endif
}
sum = 0;
qtSeqIntern = 0;
seqOFF[0] = 0; // cas 0 sequence OFF
for (int i = 0; i < nbSeqOFF; i++) {
seqOFF[i] = 0;
if (nbSeqOFF > nbSeqON) { // on a plus de sequence OFF que de sequence ON
if (nbSeqOFF == 1) seqOFF[0] = nbOFF;
else if (nbSeqOFF == 2)
seqOFF[i] = nbOFF / 2;
else
if (i == 0 || i == (nbSeqOFF -1))
seqOFF[i] = (nbOFF / (nbSeqOFF-1)) / 2; //les extremités repartition ON sur /2
else {
seqOFF[i] = (nbOFF / (nbSeqOFF-1));
}
}
else {
seqOFF[i] = nbOFF / MAX(1, nbSeqOFF); // cas general repartition équilibrée
qtSeqIntern++;
}
sum += seqOFF[i];
#ifdef showdetail
Serial.printf("seqOFF[%d]=%d\n",i,seqOFF[i]);
#endif
}
#ifdef showdetail
Serial.printf("Sum OFF = %d , delta = %d\n", sum, nbOFF - sum);
Serial.printf(" OFF: qtSeqIntern = %d , delta = %d\n", qtSeqIntern, nbOFF - sum);
#endif
if (nbOFF - sum + 1 == qtSeqIntern) {
//Serial.printf(" ****Potential !!!\n"); // ça crée une situation non symetrique => augmenter tous les bit de 1 sauf celui du milieu ...
sum = 0;
for (int i = 0; i < nbSeqOFF; i++) {
seqOFF[i]++;
sum += seqOFF[i];
}
seqOFF[nbSeqOFF/2]--;
sum--;
}
if (sum != nbOFF) {
Ok = 0;
int gap = nbOFF - sum;
//if (gap != 0) Serial.printf("%d : Ecart sur le nombre de bit a OFF : %d, on doit repartir sur %d positions \n", percent, gap, nbSeqOFF);
for (int j = 0; j < abs(gap); j++) {
int index = 0;
int decal = 0;
int8_t idxcenter = 0;
// reflexion m = nb de modif (1 ...) , j chrono modif en cours (0 ...) , x nb pos total (>=1), d = index a modifier (0 ...)
idxcenter = nbSeqOFF / 2; // si nbSeqOFF est paire, la div par 2 donne l'index après le milieu du tableau 4/2 = 2 [0,1,<2>,3]
//idxcenter = nbSeqOFF / 2; // si nbSeqOFF est impaire, la div par 2 donne l'index milieu du tableau 5/2 = 2 [0,1,<2>,3,4]
#ifdef showdetail
Serial.printf("idxcenter %d \n", idxcenter);
#endif
if ((nbSeqOFF % 2) == 1) { // nombre de position total est impaire
if (abs(gap) % 2 == 1) { // nombre de modif a faire est impaire (on cible le milieu du tableau puis on alterne 1 avant , 1 après)
#ifdef showdetail
Serial.printf("NbOFF impaire Nbmodif impaire ");
#endif
// 1 modif (j=0) sur x position impaire => centre d = x/2 5/2=2 + [0,1,<2>,3,4] 2 est bien au centre
// 3 modif (j=0,1,2) sur x position impaire => avant centre + centre + apres centre d1=((x-1)/2)-1 d2=((x-1)/2)+0 et d3=((x-1)/2)+1 (5-1)/2-1 = 1 5/2 (5-1)/2+1=3 [0,<1>,<2>,<3>,4]
// 5 modif (j=0,1,2,3,4) sur x position impaire => 2 avant centre + avant centre + centre + apres centre + 2 après centre d1=((x-1)/2)-2 d2=((x-1)/2)-1 d3=((x-1)/2) d4=((x-1)/2)+1 d5=((x-1)/2)+2 [<0>,<1>,<2>,<3>,<4>]
// sur gap=5 j=0:decal=0; j=1:decal=-1; j=2:decal=+1; j=3:decal=-2; j=4:decal=+2
decal = (j % 2 == 0 ? 1:-1) * (j+1) / 2;
if (gap == 1 && nbSeqOFF >= 3 && nbSeqOFF % 2 == 1) { // avec nbSeqON=3, on a idxcenter=1
// a la sortie de cette boucle on fera index = idxcenter + decal;seqON[index] += (gap < 0) ? -1 : 1; donc seqOn[1] sera incrémenté
decal = 0;
seqOFF[idxcenter] -= 2; // en prévision du traitement qui ajoutera 1
seqOFF[idxcenter-1] += 1;
seqOFF[idxcenter+1] += 1;
}
} else { // nombre de modif a faire est pair (on cible la position avant le milieu du tableau suivi de la position après le milieu puis on alterne 1 avant , 1 après)
#ifdef showdetail
Serial.printf("NbOFF impaire Nbmodif paire ");
#endif
// 2 modif (j=0,1) sur x position impaire => avant centre et apres centre d1 =((x-1)/2) -1 et d2=((x-1)/2)+1 (5-1)/2-1 = 1 (5-1)/2+1=3 [0,<1>,2,<3>,4]
// 4 modif (j=0,1,2,3) sur x position impaire => 2 avant centre + avant centre + apres centre + 2 après centre d1 =((x-1)/2) -2 d2=((x-1)/2)-1 d3 =((x-1)/2) +1 d4=((x-1)/2)+2 [<0>,<1>,2,<3>,<4>]
// sur gap=4 j=0:decal=-1; j=1:decal=+1; j=2:decal=-2; j=3:decal=+2;
decal = (((j -1) + 3) / 2) * (j % 2 == 0 ? -1 : 1);
if (gap == 2 && nbSeqOFF > 3) decal = 0; // in this particular case add the 2 bits in the middle
}
} else { // nombre de position total est pair
if (abs(gap) % 2 == 1) { // nombre de modif a faire est impaire
#ifdef showdetail
Serial.printf("NbOFF paire Nbmodif impaire ");
#endif
// 1 modif sur x position paire => after centre d = x/2 4/2 = 2 [0,1,<2>,3]
// 3 modif sur x position paire => avant centre + centre + apres centre mid-1 mid+0 mid+1
// 5 modif sur x position paire => 2 avant centre + avant centre + centre + apres centre + 2 après centre mid-2 mid-1 mid+0 mid+1 mid+2
// sur gap = 5 j=0:decal=0; j=1:decal=-1; j=2:decal=+1; j=3:decal=-2; j=4:decal=+2
decal = (j % 2 == 0 ? 1:-1) * (j+1) / 2;
} else { // nombre de modif a faire est pair
#ifdef showdetail
Serial.printf("NbOFF paire Nbmodif paire ");
#endif
// 2 modif sur x position paire => avant centre et apres centre d1 =((x-1)/2) -1 et d2=((x-1)/2)+1 (4/2)-1 = 1 (4/2)=2 [0,<1>,<2>,3] mid-0 mid+1
// 4 modif sur x position paire => 2 avant centre + avant centre + apres centre + 2 après centre [<0>,<1>,<2>,<3>] mid-1 mid-0 mid+1 mid+2
// sur gap=4 j=0:decal=0; j=1:decal=-1; j=2:decal=+1; j=3:decal=-2; j4 +2 j5 -3
decal = ((j + 1) / 2) * (j % 2 == 0 ? 1 : -1);
}
}
index = idxcenter + decal;
#ifdef showdetail
Serial.printf("\nfor j=%d, decal index = %d\n", j, decal);
Serial.printf("Modification n° %d seqOFF at index : %d (on %d) \n", j+1, index, nbSeqOFF);
#endif
index = MAX(0,index);
index = MIN(index, nbSeqOFF -1);
#ifdef showdetail
Serial.printf("Change seqOFF[%d] from %d to %d\n", index, seqOFF[index], (seqOFF[index] + ((gap < 0) ? -1 : 1)));
#endif
seqOFF[index] += (gap < 0) ? -1 : 1;
Ok = 1;
}
#ifdef showProblem
if (!Ok) Serial.printf("%d : Ecart sur le nombre de bit a OFF : %d, on doit repartir sur %d positions \n", percent, gap, nbSeqOFF);
#endif
}
sum = 0;
uint64_t result = 0;
#ifdef showtable
Serial.printf("id * %03d * %2d * %2d * %2d **", percent, nbON, nbOFF, qt);
#endif
for (int i = 0; i < nbSeq; i++) {
uint8_t tmp = 0;
uint8_t isSeqON = 0;
#ifdef showtable
if (i == 0 && startByOFF == 1) Serial.printf(" 0 *");
#endif
if (((i + startByON) % 2) == 1) isSeqON = 1; else isSeqON = 0;
if (isSeqON == 1) tmp = seqON[i / 2]; else tmp = seqOFF[i / 2];
#ifdef showtable
Serial.printf (" %2d *", tmp);
#endif
for (int j = 0; j < tmp; j++) {
result <<= 1;
if (isSeqON == 1) {
result |= 0b1;
}
}
}
#ifdef showtable
Serial.printf("\n");
#endif
uint8_t comptON = 0;
uint8_t comptOFF = 0;
for (int i=0; i < qt; i++) {
if ((result >> i) & 0b1) comptON++; else comptOFF++;
}
#ifdef showProblem
if (comptON != nbON) Serial.printf("%03d * probleme quantité de ON (%d/%d)\n", percent,comptON, nbON);
if (comptOFF != nbOFF) Serial.printf("%03d * probleme quantité de OFF (%d/%d)\n", percent, comptOFF, nbOFF);
#endif
return result;
}
/**********************************************************************/
int remakeTableMultiSin() {
float vrai =0.0f;
float erreur = 0.0f;
float target = 0.0f;
Serial.printf("\n");
float tolerance = 0.001f;
for (int I = 0; I <= 100; I++) {
tabPulseSinusTotal[I] = 0xFF; // valeur hors plage acceptable
tabPulseSinusOn[I] = 0xFF;
target = I / 100.0f;
for (int K = BASEPRECIS; K <= FINPRECIS; K++) {
if (tabPulseSinusTotal[I] < 0xFF) break; // sort du :, on a deja une valeur avec tolerance acceptée
tolerance = 0.001f * K;
for (int T = RANGEMIN; T < RANGEMAX; T++) {
for (int N = MAX(0, (int)(T * target) - 1); N <= T; N++) {
if (T % 2 == 1 || N % 2 == 0) {
vrai = (N * 1.0f) / (T * 1.0f);
erreur = fabs(vrai - target);
if (erreur <= tolerance) {
tabPulseSinusTotal[I] = T;
tabPulseSinusOn[I] = N;
break; // sort du for N
}
}
} // for N
if (erreur <= tolerance) break; // sort du for T
} // for T
if (erreur <= tolerance) break; // sort du for K
} // for K
} // for I
// patch les 'trous' [ pour 0 , et 100 : on est toujours sur des nombres paire 0/2 2/4 et 2/2]
for (int I = 1; I < 50; I++) { // premiere moitié, si 'trou', on prend la valeur juste avant
if (tabPulseSinusTotal[I] == 0xFF) {
tabPulseSinusTotal[I] = tabPulseSinusTotal[I - 1];
tabPulseSinusOn[I] = tabPulseSinusOn[I - 1];
}
}
for (int I = 51; I <= 99; I++) { // seconde moitié, si trou, on prend la valeur juste après
if (tabPulseSinusTotal[I] == 0xFF) {
tabPulseSinusTotal[I] = tabPulseSinusTotal[I + 1];
tabPulseSinusOn[I] = tabPulseSinusOn[I + 1];
}
}
// cas particuliers 1 et 99 on force à 1/63
tabPulseSinusOn[1] = 1; tabPulseSinusTotal[1] = 63;
tabPulseSinusOn[99] = 62; tabPulseSinusTotal[99] = 63;
#ifdef DOUBLEMENT
// double la durée pour les cas impair 'court' ça devient un cas pair en contre partie, la durée de la séquence s'allonge
for (int i = 0; i <= 100; i++) {
if ((tabPulseSinusOn[i] % 2 || tabPulseSinusTotal[i] % 2) && tabPulseSinusTotal[i] <= 32) { // avec 32, en doublant, on sait encoder la séquence sur 64 bits
tabPulseSinusOn[i] *= 2;
tabPulseSinusTotal[i] *= 2;
}
}
#endif
//fait une passe complete pour traiter la repartition et afficher les information de repartition
for (int i=0; i<=100; i++) {
tabsequenceMultiSinus[i] = repart(i, tabPulseSinusOn[i], tabPulseSinusTotal[i]);
}
#ifdef printchoice
// echo des choix obtenus
for (int i = 0; i <= 100; i++) {
target = i / 100.f;
int N = tabPulseSinusOn[i];
int T = tabPulseSinusTotal[i];
Serial.printf("Choice %03d ( %5.1f ) = %03d / %03d = %8.4f Delta = %7.4f\n", i, 100.0f * target, N, T, 100.0f * N / T, (100.0f * N / T) - (100.0f * target));
}
#endif
#ifdef printvarsequence
// texte pour variable 'en dur sans refaire les calculs
Serial.printf("\nuint8_t tabPulseSinusTotal[101] = {");
for (int i = 0; i <= 100; i++) {
Serial.printf("%2d",tabPulseSinusTotal[i]);
if (i != 100) Serial.printf(","); else Serial.printf("\n};\n");
if (i % 20 == 0 && i != 100) Serial.printf("\n ");
}
Serial.printf("\nuint8_t tabPulseSinusOn[101] = {");
for (int i = 0; i <= 100; i++) {
Serial.printf("%2d",tabPulseSinusOn[i]);
if (i != 100) Serial.printf(","); else Serial.printf("\n};\n");
if (i % 20 == 0 && i != 100) Serial.printf("\n ");
}
Serial.printf("\nuint64_t tabsequenceMultiSinus[101] = {");
for (int i = 0; i <= 100; i++) {
Serial.printf("0x%016llX",tabsequenceMultiSinus[i]); // sur arduino format long long
if (i != 100) Serial.printf(","); else Serial.printf("\n};\n");
if (i % 10 == 0 && i != 100) Serial.printf("\n ");
}
char txt[16*5] = {'0'};
char ch[2] = {0};
Serial.printf("\n/*\nuint64_t tabsequenceMultiSinus[101] = {\n");
for (int k = 0; k <= 100; k++) {
txt[0]=0;
for (int i = 63; i >= 0 ; i--) {
uint64_t num = tabsequenceMultiSinus[k];
if (i < tabPulseSinusTotal[k]) sprintf(ch, "%c", (int)(num >> i) & 1?'1':'0'); else sprintf(ch,"%c", '0');
strcat(txt, ch);
}
Serial.printf(" 0b%s",txt);
if (k != 100) Serial.printf(","); else Serial.printf(" ");
Serial.printf(" // 0x%016llX // %02d/%02d // %03d\n", tabsequenceMultiSinus[k], tabPulseSinusOn[k], tabPulseSinusTotal[k], k);
if (k == 100) Serial.printf("};\n*/\n\n");
}
#endif // printvarsequence
return 0;
}
#endif // rebuild