Permalink
Browse files

Totally new implementation for the software PWM generator.

  • Loading branch information...
Lassi Useri
Lassi Useri committed Sep 23, 2012
1 parent 8586682 commit 83348b5ee8b3799f57c1fe9b278176936538b6e4
Showing with 145 additions and 150 deletions.
  1. +145 −96 driver/AirCore_4_spwm/AirCore_4_spwm.ino
  2. +0 −54 driver/AirCore_4_spwm/Sin4096.h
@@ -1,85 +1,121 @@
-#define I2C_SLAVE_ADDR 0x4 // the 7-bit address (remember to change this)
#include <Wire.h>
-
-#include "Sin4096.h"
-
-enum { MotorCount = 8 }; // 1 2 3 4 5 6 7 8
-const uint8_t meterPinX[MotorCount] = { 0, 2, 4, 6, 8, 10, A0, A2, };
-const uint8_t meterPinY[MotorCount] = { 1, 3, 5, 7, 9, 11, A1, A3, };
-
-volatile uint8_t meterValue[MotorCount] = { 0 }; // angle = 0..255
-
-
-const uint32_t MicrosecondInTicks = 16;
-const uint32_t MillisecondInTicks = 16000;
-const uint32_t SecondInTicks = 16000000;
-const uint8_t pwmPreScaler = 8; // 0..8?
-
-volatile bool demo = true; // Demo mode
-
-
-volatile uint32_t tick_counter_overflow = 0; // Incremented 244,140625 times per second
-ISR(TIMER1_OVF_vect) { // interrupt service routine that wraps a user defined function supplied by attachInterrupt
- ++tick_counter_overflow;
-}
-
-inline uint32_t getTickCount() {
- cli();
- uint16_t timer = TCNT1; // (1a) Read HW timer
- if (TIFR1 & (1 << TOV1)) {
- timer = TCNT1; // (1b) Overflow occured concurrently, read timer again to get new value after overflow
- ++tick_counter_overflow; // Handle it here, instead of the interrupt handler
- TIFR1 = (1 << TOV1); // Clear the pending flag and
- }
+// This is ATmega328P specific implementation!
+const uint8_t I2CSlaveAddress = 0x04; // The 7-bit address, remember to change this!
+
+volatile bool demoMode = true; // Starts in Demo mode where timer2 interrupt will automatically increment the gauge values
+
+const uint8_t PwmFrequencySelector = 13; // 0..13..21
+// Selector Resolution Frequency Notes
+// 0 2 16 MHz Too fast, doesn't even generate valid PWM
+// 1 4 8 MHz
+// 2 8 2 MHz Too fast still, but the aircore already moving, very jerky
+// 3 16 1 MHz
+// 4 32 500 kHz
+// 5 64 250 kHz
+// 6 128 125 kHz
+// 7 256 63 kHz
+// 8 512 31 kHz Aircore moves, but still jerky
+// 9 1024 16 kHz
+// 10 2048 7812 Hz
+// 11 4096 3906 Hz Aircore moves fine, some noise
+// 12 8192 1953 Hz Aircore moves smoothly, but noise is very irritating
+// 13 16386 976 Hz Optimal?
+// 14 32768 488 Hz Optimal?
+// 15 65536 244 Hz Aircore needle starts to vibrate a little bit at the quadrants. This could be minimized by tweaking the sine table -> TODO
+// 16 16368 122 Hz
+// 17 32768 61 Hz Too slow for aircores!
+// 18 65536 31 Hz
+// 19 16384 15 Hz
+// 20 32768 7.7 Hz
+// 21 65536 3.8 Hz Jeah, right, om nom nom
+
+const uint8_t PwmTimerPrescaler[22] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, };
+const uint16_t PwmTimerDuration[22] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 8, 64, 64, 64, };
+const uint32_t PwmPulseWidth[22] = { 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 16368, 32768, 65536, 16384, 32768, 65536, };
+
+// There are two pins per gauge, and they are allocated from ports D, C and B. I2C mode assumed!
+const uint8_t GaugeCountPortD = 4;
+const uint8_t GaugePinSinPortD[GaugeCountPortD] = { B00000001, B00000100, B00010000, B01000000, };
+const uint8_t GaugePinCosPortD[GaugeCountPortD] = { B00000010, B00001000, B00100000, B10000000, };
+const uint8_t PortMaskD = B11111111;
- uint32_t ticks = uint32_t(tick_counter_overflow << 16) | timer; // (2) Read volatile overflow counter
- sei();
-
- return ticks;
+const uint8_t GaugeCountPortC = 2;
+const uint8_t GaugePinSinPortC[GaugeCountPortC] = { B00000001, B00000100 };
+const uint8_t GaugePinCosPortC[GaugeCountPortC] = { B00000010, B00001000 };
+const uint8_t PortMaskC = B00001111;
+
+const uint8_t GaugeCountPortB = 2;
+const uint8_t GaugePinSinPortB[GaugeCountPortB] = { B00000001, B00000100 };
+const uint8_t GaugePinCosPortB[GaugeCountPortB] = { B00000010, B00001000 };
+const uint8_t PortMaskB = B00001111;
+
+const uint8_t GaugeCount = GaugeCountPortD + GaugeCountPortC + GaugeCountPortB; // Should be 8!
+
+// The actual gauge values. As bytes they can be read or write with interrups enabled. For read-modify-write disable interrupts!
+volatile uint8_t gaugeValue[GaugeCount] = { 0 }; // angle = 0..255
+
+// This takes 1024 bytes of RAM
+uint16_t sin256Table[256] = { 0 };
+
+// Timer2 interrupt, called 244.140625 times per second
+ISR(TIMER2_OVF_vect) {
+ if (demoMode) {
+ for (uint8_t i = 0; i < GaugeCount; ++i) {
+ ++gaugeValue[i];
+ }
+ }
}
void setup() {
-
-
pinMode(13, OUTPUT); // Status LED
-
- // Set Timer1 to 16 MHz
- cli();
- // 15.11.1 TCCR1A – Timer/Counter1 Control Register A
- TCCR1A = 0; // No PWM is used.So set this to zero.
-
- // 15.11.2 TCCR1B – Timer/Counter1 Control Register B
- TCCR1B = 0 << CS12 | 0 << CS11 | 1 << CS10; // Input clock is set to clk_io/1 (No prescaling)
-
- // 15.11.3 TCCR1C – Timer/Counter1 Control Register C
-
- // 15.11.8 TIMSK1 – Timer/Counter1 Interrupt Mask Register
- TIMSK1 = 1 << TOIE1; // Bit 0 – TOIE1: Timer/Counter1, Overflow Interrupt Enable
-
- // 15.11.4 TCNT1H and TCNT1L – Timer/Counter1
- TCNT1 = 0x0000;
- sei();
+ cli(); {
+ // Set Timer1 to X MHz
+ TCCR1A = 0; // No PWM is used. So set this to zero. - 15.11.1 TCCR1A – Timer/Counter1 Control Register A
+ TCCR1B = PwmTimerPrescaler[PwmFrequencySelector]; // See 15.11.2 TCCR1B – Timer/Counter1 Control Register B
+ TIMSK1 = 0 << TOIE1; // Bit 0 – TOIE1: Timer/Counter1, Overflow Interrupt Enable - // 15.11.8 TIMSK1 – Timer/Counter1 Interrupt Mask Register
+ TCNT1 = 0x0000; // Reset the conuter - 15.11.4 TCNT1H and TCNT1L – Timer/Counter1
+ // Now TCNT1 wraps around 244.140625 times per second and can count maximum of 4.095 ms durations
+ } sei();
+
+ cli(); {
+ // Set Timer2 to X MHz
+ TCCR2A = 0; // Normal mode, no PWM
+ TCCR2B = B00000111; // 16000000 Hz / 1024 = 15625 Hz / 256 = ~61 Hz overflow
+ TIMSK2 = B00000001; // Overflow Interrupt Enable
+ TCNT2 = 0x00; // Reset the counter
+ } sei();
+
+ // Set I2C
+ Wire.begin(I2CSlaveAddress); // Join i2c bus with address #I2C_SLAVE_ADDR
+ Wire.onReceive(receiveEvent); // Register event handler
+ digitalWrite(A4, HIGH); // Enable the pull-up for SDA
+ digitalWrite(A5, HIGH); // Enable the pull-up for SCL
+
+ // Generate initial values with difference phase
+ if (demoMode) {
+ for (uint8_t i = 0; i < GaugeCount; ++i) {
+ gaugeValue[i] = 13*i;
+ }
+ }
-
-
// Enable driving pins
- for (uint8_t i = 0; i < MotorCount; ++i) {
- pinMode(meterPinX[i], OUTPUT);
- pinMode(meterPinY[i], OUTPUT);
- }
-
+ DDRD |= PortMaskD;
+ DDRC |= PortMaskC;
+ DDRB |= PortMaskB;
+
+ // Precalculate sine table
+ for (uint16_t i = 0; i < 256; ++i) {
+ const float scalehalf = float(PwmPulseWidth[PwmFrequencySelector] - 1)*0.5f; // 255 => 127.5, 4095 => 2047.5
+ float sinehalf = sin(2*M_PI * ((float)i)/256);
+ sin256Table[i] = (int16_t)(scalehalf * (1.0f*sinehalf) + scalehalf + 0.5);
+ }
- Wire.begin(I2C_SLAVE_ADDR); // join i2c bus with address #I2C_SLAVE_ADDR
- Wire.onReceive(receiveEvent); // register event
- // Enable the pull-ups
- digitalWrite(A4, HIGH);
- digitalWrite(A5, HIGH);
// Status ok
digitalWrite(13, HIGH);
@@ -88,49 +124,62 @@ void setup() {
// TODO: Check that we have at least two bytes before going on and supposing first one is register...
void receiveEvent(int howMany)
{
- if (howMany < 2)
- {
- // We're only interested when we know we can suppose the first byte is register address
- return;
+ if (howMany < 2) {
+ return; // We're only interested when we know we can suppose the first byte is register address
}
- byte reg_addr = Wire.read();
- byte max_reg = reg_addr + howMany - 1;
+
+ demoMode = false;
+ TIMSK2 = B00000000; // Stop timer2 interrupts for demo mode
+
+ uint8_t reg_addr = Wire.read();
+ uint8_t max_reg = reg_addr + howMany - 1;
- for (byte i = reg_addr; i < max_reg; i++)
- {
- meterValue[i] = Wire.read();
+ for (uint8_t i = reg_addr; i < max_reg; ++i) {
+ if (i < GaugeCount) gaugeValue[i] = Wire.read();
}
- demo = false;
+
}
void loop() {
- uint32_t time = getTickCount();
-
-
-
- uint8_t pwmTime = uint8_t((time >> pwmPreScaler) & 0xff); // 0 = 62.5 kHz, 7 = 488 Hz
+ cli(); {
+ // Read current time
+ uint16_t pwmTime = TCNT1 % PwmPulseWidth[PwmFrequencySelector];
- // fill dummy values
- if (demo) {
- uint32_t position = time / (MillisecondInTicks*16);
+ uint8_t portBitsD = 0; //PORTD & ~PortMaskD;
+ uint8_t portBitsC = 0; //PORTC & ~PortMaskC;
+ uint8_t portBitsB = 0; //PORTB & ~PortMaskB;
- for (uint8_t i = 0; i < MotorCount; ++i) {
- meterValue[i] = position; //(i + 3);
+ uint8_t gauge = 0;
+
+ // Generate PWM-signals with different phase shift on each gauges
+ for (uint8_t i = 0; i < GaugeCountPortD; ++i) {
+ uint8_t angle = gaugeValue[gauge++];
+ if (sin256Table[uint8_t(angle + 0)] < pwmTime) { portBitsD |= GaugePinSinPortD[i]; }
+ if (sin256Table[uint8_t(angle + 64)] < pwmTime) { portBitsD |= GaugePinCosPortD[i]; }
}
- }
+
+ for (uint8_t i = 0; i < GaugeCountPortC; ++i) {
+ uint8_t angle = gaugeValue[gauge++];
+ if (sin256Table[uint8_t(angle + 0)] < pwmTime) { portBitsC |= GaugePinSinPortC[i]; }
+ if (sin256Table[uint8_t(angle + 64)] < pwmTime) { portBitsC |= GaugePinCosPortC[i]; }
+ }
+
+ for (uint8_t i = 0; i < GaugeCountPortB; ++i) {
+ uint8_t angle = gaugeValue[gauge++];
+ if (sin256Table[uint8_t(angle + 0)] < pwmTime) { portBitsB |= GaugePinSinPortB[i]; }
+ if (sin256Table[uint8_t(angle + 64)] < pwmTime) { portBitsB |= GaugePinCosPortB[i]; }
+ }
+
+ // Write patterns
+ PORTD = portBitsD;
+ PORTC = portBitsC;
+ PORTB = portBitsB;
- // Generate PWM-signals
- for (uint8_t i = 0; i < MotorCount; ++i) {
- cli();
- uint16_t value = meterValue[i] << 4;
- digitalWrite(meterPinX[i], (sine4096(value + 0) < pwmTime));
- digitalWrite(meterPinY[i], (sine4096(value + 1024) < pwmTime));
- sei();
- }
+ }; sei();
}
@@ -1,54 +0,0 @@
-#include <avr/pgmspace.h>
-
-/**
- * We get truly weird compile erors if this table is bigger than 3354 values... (using full 4k table would make things a lot simpler...)
- */
-//prog_uchar sinq11024Table[3354] PROGMEM = {};
-prog_uchar sinq11024Table[1024] PROGMEM =
-{
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86,
- 0x86, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c,
- 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
- 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98,
- 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
- 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xab, 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0,
- 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb6, 0xb6,
- 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
- 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1,
- 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
- 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
- 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
- 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5,
- 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
- 0xda4, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
- 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2,
- 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
- 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
- 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
- 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
- 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
- 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
- 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
- 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
- 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd,
- 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
-
-inline uint8_t sine4096(uint16_t val) {
- val = val & 0xfff; // 0..4096
- if (val < 1024) {
- return pgm_read_byte_near(sinq11024Table + val);
- } else if (val < 2048) {
- return pgm_read_byte_near(sinq11024Table + (1023 - (val - 1024)));
- } else if (val < 3072) {
- return 255 - pgm_read_byte_near(sinq11024Table + (val - 2048));
- } else {
- return 255 - pgm_read_byte_near(sinq11024Table + (1023 - (val - 3072)));
- }
-}

0 comments on commit 83348b5

Please sign in to comment.