📄 spokepov.lss
字号:
spokepov.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000077e 00000000 00000000 00000094 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000022 00800060 0000077e 00000812 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 0000000f 00800082 00800082 00000834 2**0
ALLOC
3 .noinit 00000000 00800091 00800091 00000834 2**0
CONTENTS
4 .eeprom 00000000 00810000 00810000 00000834 2**0
CONTENTS
5 .stab 00000354 00000000 00000000 00000834 2**2
CONTENTS, READONLY, DEBUGGING
6 .stabstr 00000084 00000000 00000000 00000b88 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_aranges 00000028 00000000 00000000 00000c0c 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_pubnames 000001e6 00000000 00000000 00000c34 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_info 000005dc 00000000 00000000 00000e1a 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_abbrev 000001e9 00000000 00000000 000013f6 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_line 00000737 00000000 00000000 000015df 2**0
CONTENTS, READONLY, DEBUGGING
12 .debug_str 0000024d 00000000 00000000 00001d16 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
00000000 <__vectors>:
0: 12 c0 rjmp .+36 ; 0x26 <__ctors_end>
2: 60 c0 rjmp .+192 ; 0xc4 <__vector_1>
4: f7 c0 rjmp .+494 ; 0x1f4 <__vector_2>
6: 28 c0 rjmp .+80 ; 0x58 <__bad_interrupt>
8: 55 c1 rjmp .+682 ; 0x2b4 <__vector_4>
a: 26 c0 rjmp .+76 ; 0x58 <__bad_interrupt>
c: 26 c0 rjmp .+76 ; 0x5a <__vector_6>
e: 24 c0 rjmp .+72 ; 0x58 <__bad_interrupt>
10: 23 c0 rjmp .+70 ; 0x58 <__bad_interrupt>
12: 22 c0 rjmp .+68 ; 0x58 <__bad_interrupt>
14: 21 c0 rjmp .+66 ; 0x58 <__bad_interrupt>
16: 20 c0 rjmp .+64 ; 0x58 <__bad_interrupt>
18: 1f c0 rjmp .+62 ; 0x58 <__bad_interrupt>
1a: 1e c0 rjmp .+60 ; 0x58 <__bad_interrupt>
1c: 1d c0 rjmp .+58 ; 0x58 <__bad_interrupt>
1e: 1c c0 rjmp .+56 ; 0x58 <__bad_interrupt>
20: 1b c0 rjmp .+54 ; 0x58 <__bad_interrupt>
22: 1a c0 rjmp .+52 ; 0x58 <__bad_interrupt>
24: 19 c0 rjmp .+50 ; 0x58 <__bad_interrupt>
00000026 <__ctors_end>:
26: 11 24 eor r1, r1
28: 1f be out 0x3f, r1 ; 63
2a: cf ed ldi r28, 0xDF ; 223
2c: cd bf out 0x3d, r28 ; 61
0000002e <__do_copy_data>:
2e: 10 e0 ldi r17, 0x00 ; 0
30: a0 e6 ldi r26, 0x60 ; 96
32: b0 e0 ldi r27, 0x00 ; 0
34: ee e7 ldi r30, 0x7E ; 126
36: f7 e0 ldi r31, 0x07 ; 7
38: 03 c0 rjmp .+6 ; 0x40 <.do_copy_data_start>
0000003a <.do_copy_data_loop>:
3a: c8 95 lpm
3c: 31 96 adiw r30, 0x01 ; 1
3e: 0d 92 st X+, r0
00000040 <.do_copy_data_start>:
40: a2 38 cpi r26, 0x82 ; 130
42: b1 07 cpc r27, r17
44: d1 f7 brne .-12 ; 0x3a <.do_copy_data_loop>
00000046 <__do_clear_bss>:
46: 10 e0 ldi r17, 0x00 ; 0
48: a2 e8 ldi r26, 0x82 ; 130
4a: b0 e0 ldi r27, 0x00 ; 0
4c: 01 c0 rjmp .+2 ; 0x50 <.do_clear_bss_start>
0000004e <.do_clear_bss_loop>:
4e: 1d 92 st X+, r1
00000050 <.do_clear_bss_start>:
50: a1 39 cpi r26, 0x91 ; 145
52: b1 07 cpc r27, r17
54: e1 f7 brne .-8 ; 0x4e <.do_clear_bss_loop>
56: 3a c2 rjmp .+1140 ; 0x4cc <main>
00000058 <__bad_interrupt>:
58: d3 cf rjmp .-90 ; 0x0 <__vectors>
0000005a <__vector_6>:
// anything. Is this vestigial code from when you were using
// Pin Change Interrupts? Or is it debugger code so you
// can monitor the pins and tell when something happens.
SIGNAL (SIG_TIMER0_OVF) {
5a: 1f 92 push r1
5c: 0f 92 push r0
5e: 0f b6 in r0, 0x3f ; 63
60: 0f 92 push r0
62: 11 24 eor r1, r1
64: 2f 93 push r18
66: 8f 93 push r24
68: 9f 93 push r25
PORTB |= 0x1;
6a: c0 9a sbi 0x18, 0 ; 24
if (hall_debounce != 0xFF)
6c: 80 91 8a 00 lds r24, 0x008A
70: 8f 3f cpi r24, 0xFF ; 255
72: 29 f0 breq .+10 ; 0x7e <__vector_6+0x24>
hall_debounce++;
74: 80 91 8a 00 lds r24, 0x008A
78: 8f 5f subi r24, 0xFF ; 255
7a: 80 93 8a 00 sts 0x008A, r24
if (sensor_timer != 0xFFFF)
7e: 80 91 8b 00 lds r24, 0x008B
82: 90 91 8c 00 lds r25, 0x008C
86: 8f 5f subi r24, 0xFF ; 255
88: 9f 4f sbci r25, 0xFF ; 255
8a: 49 f0 breq .+18 ; 0x9e <__vector_6+0x44>
sensor_timer++;
8c: 80 91 8b 00 lds r24, 0x008B
90: 90 91 8c 00 lds r25, 0x008C
94: 01 96 adiw r24, 0x01 ; 1
96: 90 93 8c 00 sts 0x008C, r25
9a: 80 93 8b 00 sts 0x008B, r24
PORTB &= ~0x1;
9e: c0 98 cbi 0x18, 0 ; 24
a0: 9f 91 pop r25
a2: 8f 91 pop r24
a4: 2f 91 pop r18
a6: 0f 90 pop r0
a8: 0f be out 0x3f, r0 ; 63
aa: 0f 90 pop r0
ac: 1f 90 pop r1
ae: 18 95 reti
000000b0 <delay_ms>:
}
// As we sweep around the circle, we display 256 radial pixel
// lines, once per TIMER1 interrupt. This is broken down into
// 16 16-pixel wide characters, and we have two characters
// stacked vertically. To save time, we keep track of the
// character number, pixel number (in the character), and
// pointers into the eeprom for each of the two chars being
// displayed.
volatile uint16_t topChar = 0; // top character being displayed (address in EEPROM of data)
volatile uint16_t botChar = 0; // bottom character being displayed
volatile uint8_t charNum = 0; // character number
volatile uint8_t pixelNum = 0; // pixel number
volatile uint8_t clean = 0; // have these values been changed outside TIMER1?
// This routine gets called every time the pixel timer runs down;
// in other words, once per "scan line", 256 times per revolution
// of the SpokePOV. Its purpose is to update the LEDs.
SIGNAL (SIG_TIMER1_COMPA) {
uint16_t tChar; // local copies of the values
uint16_t bChar;
uint8_t cNum;
uint8_t pNum;
uint8_t cCode; // character code to display
// When an interrupt routine is called, interrupts are disabled.
// but it's important to let other interrupts interrupt us, so
// they need to be re-enabled.
sei();
PORTB |= 0x2;
// Copy the volatile variables into their local equivalents
tChar = topChar;
bChar = botChar;
cNum = charNum;
pNum = pixelNum;
// If it has been less than STANDBY_TIMEOUT seconds since the last time we
// got a Hall Effect sensor update, then proceed as normal and
// update the LEDs.
// QUESTION: what is F_CPU?
if (sensor_timer < ((F_CPU/NUM_PIXELS)/256 * STANDBY_TIMEOUT)) {
PORTA |= 0x1;
// The first thing we do is increment our character position; this
// is done here to avoid code duplication. This means that the
// Hall Effect interrupt routine must set them up so they "wrap"
// into the first valid values.
// Move to the next pixel in the character
pNum++;
// If we have moved off the edge of the character, then
// we need to move to the next character
if (pNum == 16) {
pNum = 0; // reset to first pixel
cNum = (cNum+1) % 16; // move, with wrap, to next character position
// Now we need to reset the pointers to the correct addresses
// in the EEPROM for the characters they display. The earlier
// decision to store these in a format that makes them display
// nicely on the original SpokePOV software makes this a little
// bit difficult.
cCode = topLine[cNum]-32; // character number for the top char, 0-95
// In the character set, 2 characters are stored vertically stacked.
// So each group of 2 characters takes up 64 bytes (4x16).
tChar = ((cCode >> 1) << 6) | ( (cCode & 0x01) << 1 );
// Ditto for bChar...
cCode = botLine[cNum]-32;
bChar = ((cCode >> 1) << 6) | ( (cCode & 0x01) << 1 );
} else {
// If we haven't wrapped around a character boundary, we just move
// to the next line in the character set, which is 4 pixels offset
// in each case
tChar += 4;
bChar += 4;
}
// Unfortunately, we can't do the cute "read from the EEPROM right
// into the LEDs trick" that limor can do in SpokePOV. We have to
// read the data into the ATMEL and then write it out.
spieeprom_read(tChar,fleds,2); // the top 2 bytes
spieeprom_read(bChar,fleds+2,2); // and the bottom 2
clock_leds(); // and send them to the LEDs
// Now we increment the variables. However, we
// only do it IF haven't been touched by some other part
// of the code while we were displaying the pixels. Also, we
// turn interrupts off so that nobody else can touch them
// while we are at it
cli();
if (clean) {
topChar = tChar;
botChar = bChar;
charNum = cNum;
pixelNum = pNum;
} else {
// Since we didn't update the data, we know it was changed, and
// we know that next time, we CAN update the data. So everything
// is clean now!
clean = 1;
}
sei();
PORTA &= ~0x1;
} else {
// We have not seen the magnet in a while, so turn off the
// pixel timer...
PORTA |= 0x2;
// Turn off this pixel timer
// Question: this is different from the code in SIG_INT1. Why?
cli();
TCCR1B &= ~0x7;
sei();
// Turn off all but one LED
set_led(2);
PORTA &= ~0x2;
}
PORTB &= ~0x2;
}
// Interrupt 0 executes when the button is pressed.
// QUESTION: unlike the pixel output interrupt, this one
// doesn't sei(). Why?
SIGNAL (SIG_INT0) {
uint16_t timer;
PORTB |= 0x4;
// Twiddle our thumbs until the user releases the
// button - but measure how long he takes...
timer = 0;
while (! (BUTTON_PIN & _BV(BUTTON))) {
timer++;
delay_ms(1);
}
// A short (<500ms) press will just restart the watchdog
// timer. I think this explains the structure of the
// main() function; it doesn't have a loop to keep it
// listening for commands if it times out, but pressing
// the button will restart it.
// We do expect that the button will be down at least
// a small period of time...
if (timer > BUTTON_DEBOUNCE) {
// If a quick press...
if (timer < 500UL) {
// Re-enable the watchdog timer, then loop until
// it fires off.
WDTCSR = _BV(WDE);
while (1);
} else {
// We want to shut everything down. Setting sensor_timer
// to the pin value will cause both the communications
// loop and the regular timeout loop in the main() to
// give up, which results in the device going to sleep.
sensor_timer = 0xFFFF;
}
}
PORTB &= ~0x4;
}
// Interrupt 1 executes when the hall effect sensor fires
// QUESTION: unlike the pixel output interrupt, this one
// doesn't sei(). Why?
SIGNAL (SIG_INT1) {
PORTB |= 0x8;
// The first issue we need to deal with when the hall-effect
// sensor tells us it sees the magnet is to avoid doing any
// processing if we get an interrupt too soon after the previous
// interrupt.
// hall_debounce is incremented by TIMER0, which fires every 3ms
// or so. At the current setting of 4, this means that at least
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -