2017-01-24 1 views
0
#include <avr/pgmspace.h> 

//max errror ~0.017452 [91*4=364 bytes] 
static const float PROGMEM SineTable[91] = { 
0.0, 0.017452, 0.034899, 0.052336, 0.069756, 0.087156, 
0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809, 
0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372, 
0.309017, 0.325568, 0.34202, 0.358368, 0.374607, 0.390731, 
0.406737, 0.422618, 0.438371, 0.45399, 0.469472, 0.48481, 
0.5, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576, 
0.587785, 0.601815, 0.615661, 0.62932, 0.642788, 0.656059, 
0.669131, 0.681998, 0.694658, 0.707107, 0.71934, 0.731354, 
0.743145, 0.75471, 0.766044, 0.777146, 0.788011, 0.798636, 
0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167, 
0.866025, 0.87462, 0.882948, 0.891007, 0.898794, 0.906308, 
0.913545, 0.920505, 0.927184, 0.93358, 0.939693, 0.945519, 
0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.97437, 
0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546, 
0.994522, 0.996195, 0.997564, 0.99863, 0.999391, 0.999848, 1.0 
}; 

float _Sine(uint16_t angle) { 
    float tmp; 

asm (
    //validate angle >= 0 && angle <= 90 
"cpi %A1, 90+1 \n" 
"cpc %B1, __zero_reg__ \n" 
"brcc _NaN  \n" //out of range 

//calculate table index 
"lsl %A1  \n" //float is 4 bytes wide 
"rol %B1  \n" //index = angle * 4 
"lsl %A1  \n" 
"rol %B1  \n" 

//add index to start of SineTable 
"add r30, %A1 \n" 
"adc r31, %B1 \n" 

//get sine value (4-bytes) 
"lpm %A0, Z+ \n" 
"lpm %B0, Z+ \n" 
"lpm %C0, Z+ \n" 
"lpm %D0, Z \n" 
"ret   \n" //exit 

//return NAN 
"_NaN:    \n" 
"ldi %A0, lo8(%3) \n" //NAN = 0x7fc00000 
"ldi %B0, hi8(%3) \n" 
"ldi %C0, hlo8(%3) \n" 
"ldi %D0, hhi8(%3) \n" 
: "=r" (tmp) : "r" (angle), "z" (SineTable), "F" (NAN) : 
); 

return tmp; 
} 

int main() { 
    uint16_t a = 40; 
    float temp = _Sine(a); 
    Serial.begin(9600); 
    Serial.println(temp); 
} 

이 코드는 avr 어셈블리에서 천사의 죄를 계산하는 코드입니다. 하지만 arduino에서 코딩하고 arduino IDE에서 어셈블리를 작성하고 있습니다. 내가 이것을 위해 얻는 오류는 다음과 같습니다. 15 이상의 레지스터 번호가 필요합니다. 하지만 15 이하의 레지스터를 사용하지 않고 무엇이이 코드에 문제가 있는지 전혀 모릅니다.arduino에서 어셈블리에서 죄를 계산하는 중 오류가 발생했습니다.

+1

코드 작성자에게 문의 할 수 있습니까? 당신은 그 사람처럼 보이지 않습니다. – SergeyA

+1

나는 AVR을 말하지 않지만, "15 이상의 레지스터 번호"가 오류라면, 아마도 'r30'을 사용해서는 안되는가? –

+0

r30이 15보다 높습니까? – hodhod96

답변

3

ldi에 15보다 큰 레지스터가 필요하지만 일반 레지스터 제약 r을 사용하면 컴파일러에서 해당 피연산자에 대해 낮은 레지스터를 선택할 수 있습니다. tmp에 대해 d 제약 조건으로 전환 할 수 있습니다.

또한 컴파일러에 알리지 않고 Z을 삭제합니다.

모두 내가 말했듯이 어셈블리를 사용하여이 작업을 수행하는 데는 아무런 문제가 없습니다. 컴파일러는 배열을 인덱싱 완벽하게 할 수있다, 당신은 기본적으로 그냥 필요

return angle <= 90 ? SineTable[angle] : NAN; 

사실 거의 동일한 어셈블리 코드를 생성 내 테스트에 따라.

+2

그 외 : 사인 또는 코사인을 찾는 데 필요한 0.90도 사인의 찾아보기 테이블이 있으므로 범위를 벗어 났을 때 'NAN'대신 적절한 사분면을 계산할 수 있습니다. –

+0

감사합니다. 나는 이것을 바꿨으나 지금은 오류가 발생하지 않는다. 그러나 나는 아직도 왜 Serial.print (temp)를 얻을 수 없다. 아, 그리고 어셈블리를 사용하면 숙제입니다. 나는 이것에 어떤 점도 확실히 보이지 않는다. – hodhod96

+0

_ 여전히 여전히 Serial.print (temp) _의 의미가 무엇인지 알 수 없습니다. – Jester

관련 문제