📄 fftavr.c
字号:
#include <avr/io.h>
#include <avr/twi.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <inttypes.h>
#include "fftAvr.h"
#ifdef FFT_USE_INTERRUPT
uint8_t* fftAvrRecvBuffer;
volatile fftAvrResultCallback fftAvrTC = fftAvrTransmissionComplete;
volatile uint8_t fftAvrRecvCount;
volatile uint8_t fftAvrRecvIdx;
volatile uint8_t fftAvrTransComp;
// Default transmission complete callback function.
void fftAvrTransmissionComplete(uint8_t* buffer) {
fftAvrTransComp = 1;
}
// TWI interrupt service routine
SIGNAL(SIG_2WIRE_SERIAL) {
uint8_t status = TW_STATUS, data = TWDR;
if(status == TW_MR_DATA_ACK) {
*(fftAvrRecvBuffer + fftAvrRecvIdx++) = data;
if(fftAvrRecvIdx == fftAvrRecvCount-1) {
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEN);
} else {
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
}
} else if(status == TW_MR_DATA_NACK) {
*(fftAvrRecvBuffer + fftAvrRecvIdx++) = data;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
fftAvrTC(fftAvrRecvBuffer);
}
}
#endif
uint8_t twiReceive(uint8_t ack) {
uint8_t twcr = (1<<TWINT) | (1<<TWEN);
if(ack) twcr |= (1<<TWEA);
// clear interrupt to start transmission
TWCR = twcr;
// wait for transmission
while ((TWCR & (1<<TWINT)) == 0);
// return data
return TWDR;
}
uint8_t fftAvrTwiStart(void) {
// send start condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait for transmission
while ((TWCR & (1<<TWINT)) == 0);
// return status code
return TW_STATUS;
}
uint8_t fftAvrTwiTransmit(uint8_t data) {
// transmit data
TWDR = data;
// clear interrupt to start transmission
TWCR = (1<<TWINT) | (1<<TWEN);
// wait for transmission
while ((TWCR & (1<<TWINT)) == 0);
// return status code
return TW_STATUS;
}
uint8_t fftAvrInit(uint16_t fftAddr) {
uint8_t status;
// Start condition
status = fftAvrTwiStart();
if(status != TW_REP_START && status != TW_START) return 0;
// send SLA+W
status = fftAvrTwiTransmit(FFT_AVR_TWI_ADDR | TW_WRITE);
if(status != TW_MT_SLA_ACK) return 0;
// send FFT address
// high byte
status = fftAvrTwiTransmit(fftAddr >> 8);
if(status != TW_MT_DATA_ACK) return 0;
// low byte
fftAvrTwiTransmit(fftAddr & 0x00FF);
// Start condition
status = fftAvrTwiStart();
if(status != TW_REP_START && status != TW_START) return 0;
// send SLA+R
status = fftAvrTwiTransmit(FFT_AVR_TWI_ADDR | TW_READ);
if(status != TW_MR_SLA_ACK) return 0;
// FFT AVR initialization successful
return 1;
}
void fftAvrReadSpectrum(uint8_t fftMode, uint8_t* buffer) {
uint8_t ok=0, len=0;
switch(fftMode) {
case FFT_HI_RES:
ok = fftAvrInit(FFT_HI_RES_ADDR);
len = FFT_HI_RES_LEN;
break;
case FFT_HI_RES_PEAK:
ok = fftAvrInit(FFT_HI_RES_PEAK_ADDR);
len = FFT_HI_RES_LEN;
break;
case FFT_LO_RES:
ok = fftAvrInit(FFT_LO_RES_ADDR);
len = FFT_LO_RES_LEN;
break;
case FFT_LO_RES_PEAK:
ok = fftAvrInit(FFT_LO_RES_PEAK_ADDR);
len = FFT_LO_RES_LEN;
break;
case FFT_MIXED:
ok = fftAvrInit(FFT_MIXED_ADDR);
len = FFT_MIXED_LEN;
break;
case FFT_MIXED_PEAK:
ok = fftAvrInit(FFT_MIXED_PEAK_ADDR);
len = FFT_MIXED_LEN;
break;
}
if(!ok) return;
#ifndef FFT_USE_INTERRUPT
// receive data
for(uint8_t i=0; i<len; i++) {
if(i<len-1) *buffer++ = twiReceive(1);
else *buffer++ = twiReceive(0);
}
// send start condition
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
#else
fftAvrRecvBuffer = buffer;
fftAvrRecvCount = len;
fftAvrRecvIdx = 0;
fftAvrTransComp = 0;
// enable interrupts
sei();
// start transmission
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -