-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathbjorklund.h
75 lines (69 loc) · 1.8 KB
/
bjorklund.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#ifndef _BJORKLUND_H_
#define _BJORKLUND_H_
#include <inttypes.h>
/**
Implementation of the Bjorklund algorithm.
Algorithm based on SNS-NOTE-CNTRL-99
The Theory of Rep-Rate Pattern Generation in the SNS Timing System
E. Bjorklund
*/
/**
the size of the count and remainder arrays is given by:
l+1=logτ( m * sqrt(5) )−3
where τ = (1 + sqrt(5) ) / 2
(the Golden Ratio)
by logarithmic base change rule logb(x) = logc(x) / logc(b)
we have
l+1 = ln( m * sqrt(5) ) / ln( (1 + sqrt(5) ) / 2 )
for m=128, l+1 < 12
for m=32, l+1 < 9
*/
template<typename T, uint8_t BJORKLUND_ARRAY_SIZE>
class Bjorklund {
public:
T compute(int8_t slots, int8_t pulses){
bits = 0UL;
pos = 0;
if(!pulses)
return bits;
/* Figure 11 */
int8_t divisor = slots - pulses;
remainder[0] = pulses;
int8_t level = 0;
int8_t cycleLength = 1;
int8_t remLength = 1;
do {
count[level] = divisor / remainder[level];
remainder[level+1] = divisor % remainder[level];
divisor = remainder[level];
int8_t newLength = (cycleLength * count[level]) + remLength;
remLength = cycleLength;
cycleLength = newLength;
level = level + 1;
}while(remainder[level] > 1);
count[level] = divisor;
if(remainder[level] > 0)
cycleLength = (cycleLength * count[level]) + remLength;
build(level);
return bits;
}
private:
T bits;
uint8_t pos;
int8_t remainder[BJORKLUND_ARRAY_SIZE];
int8_t count[BJORKLUND_ARRAY_SIZE];
void build(int8_t level){
if(level == -1){
// pos++;
bits &= ~(1UL<<pos++);
}else if(level == -2){
bits |= 1UL<<pos++;
}else{
for(int8_t i=0; i < count[level]; i++)
build(level-1);
if(remainder[level] != 0)
build(level-2);
}
}
};
#endif /* _BJORKLUND_H_ */