📄 spokepov.lss
字号:
set_all(0x00);
61a: 80 e0 ldi r24, 0x00 ; 0
61c: 9c dd rcall .-1224 ; 0x156 <set_all>
delay_ms(255);
61e: 8f ef ldi r24, 0xFF ; 255
620: 83 de rcall .-762 ; 0x328 <delay_ms>
622: 08 95 ret
00000624 <main>:
// likely the 1-second reset timer will go off before
// this ends. But no biggy, since if it does, it'll
// reset the LEDs..
}
int main(void) {
624: cf ed ldi r28, 0xDF ; 223
626: d0 e0 ldi r29, 0x00 ; 0
628: de bf out 0x3e, r29 ; 62
62a: cd bf out 0x3d, r28 ; 61
uint8_t cmd; // the reason we reset
// MCUSR is the MCU Status Register (page 40). It tells us
// why we reset, and a reset is the only way to get here.
cmd = MCUSR;
62c: 14 b7 in r17, 0x34 ; 52
// The first order of business is to tell the chip that
// we've got things under control.
MCUSR = 0;
62e: 14 be out 0x34, r1 ; 52
// Turn on watchdog timer immediately, this protects against
// a 'stuck' system by resetting it.
// WDTCSR is the Watchdog Timer Control Register (page 45).
// We set it so that it'll generate a watchdog interrupt
// every second. The idea is that if things mess up,
// the watchdog will kickstart us.
WDTCSR = _BV(WDE) | _BV(WDP2) | _BV(WDP1); // 1 second
630: 8e e0 ldi r24, 0x0E ; 14
632: 81 bd out 0x21, r24 ; 33
// Initialize the various pins of the ATMEL, and set up
// the interrupts.
ioinit();
634: cf df rcall .-98 ; 0x5d4 <ioinit>
// test the copy from our PROGMEM string
// We saved the reason for the reset of the chip. If
// it's a power-on, then we run a test pattern through
// the LEDs. Note that because we've set a 1-second
// watchdog timer (in ioinit), if this test sequence
// takes more than a second, the chip will reset. But
// since we'll know it isn't a power-on, the test
// sequence won't run...
if ((cmd & _BV(PORF)) != 0)
636: 10 fd sbrc r17, 0
test_leds();
638: e8 df rcall .-48 ; 0x60a <test_leds>
// display the reason for the reset on the LEDs.
set_all(~0x01);
63a: 8e ef ldi r24, 0xFE ; 254
63c: 8c dd rcall .-1256 ; 0x156 <set_all>
// enable the interrupts. I think this is not needed
// since it'll immediately be done by the loop, below.
sei();
63e: 78 94 sei
// Loop until we timeout, at which point the ATMEL is
// put to sleep. If the communications routine timed
// out, or the user pressed the button for >500ms,
// then sensor_timer will be 0xFFFF and we'll immediately
// sleep.
// Change to for (;;) to see if it makes any difference
while (1) {
// Reset the watchdog Timer.
//
// QUESTION: What's with toggling the PD0 output line here?
// it doesn't seem to be connected to anything according to
// the circuit diagram...
// *** PORTD |= 0x1;
asm("wdr");
640: a8 95 wdr
// *** PORTD &= ~0x1;
// If the sensor_timer (incremented by TIMER0) maxes out
// (in about 3 minutes), then sleep everything.
if (sensor_timer == 0xFFFF) {
642: 80 91 87 00 lds r24, 0x0087
646: 90 91 88 00 lds r25, 0x0088
64a: 8f 5f subi r24, 0xFF ; 255
64c: 9f 4f sbci r25, 0xFF ; 255
64e: 79 f4 brne .+30 ; 0x66e <main+0x4a>
// Avoid pesky interruptions
cli();
650: f8 94 cli
// Turn off all LEDs - I guess LED 0 is one of the "invisible ones"
set_all(0xFF);
652: 8f ef ldi r24, 0xFF ; 255
654: 80 dd rcall .-1280 ; 0x156 <set_all>
// Turn off power to the Hall Effect sensor.
SENSOR_PORT &= ~_BV(SENSORPOWER);
656: 96 98 cbi 0x12, 6 ; 18
// Deselect EEPROM
SPIEE_CS_PORT |= _BV(SPIEE_CS); // pull CS high to deselect
658: c4 9a sbi 0x18, 4 ; 24
// Turn off Watchdog (must be restarted when we get the wakeup)
// Wakeup will be via the button interrupt.
WDTCSR |= _BV(WDCE) | _BV(WDE);
65a: 81 b5 in r24, 0x21 ; 33
65c: 88 61 ori r24, 0x18 ; 24
65e: 81 bd out 0x21, r24 ; 33
WDTCSR = 0;
660: 11 bc out 0x21, r1 ; 33
MCUCR |= _BV(SM1) | _BV(SM0) | _BV(SE);
662: 85 b7 in r24, 0x35 ; 53
664: 80 67 ori r24, 0x70 ; 112
666: 85 bf out 0x35, r24 ; 53
// Re-enable interrupts so we can get the wakeup!
sei();
668: 78 94 sei
// Go into sleep mode
asm("sleep");
66a: 88 95 sleep
66c: e9 cf rjmp .-46 ; 0x640 <main+0x1c>
} else {
// Do we have dynamic updating to do?
#ifdef DYNAMIC
uint8_t tBytes; // Number of bytes to transfer
// Use unions to overlay variables and save some space
union {
char *fPtr; // from pointer
uint16_t divisor; // the divisor for RPM
} a;
union {
char *tPtr; // to pointer
char *divTable; // divisor table
} b;
// Step 1, update the dynamicPtr
if (dynamicPtr != newDynamicPtr) {
66e: 80 91 74 00 lds r24, 0x0074
672: 90 91 75 00 lds r25, 0x0075
676: 20 91 72 00 lds r18, 0x0072
67a: 30 91 73 00 lds r19, 0x0073
67e: 82 17 cp r24, r18
680: 93 07 cpc r25, r19
682: 31 f0 breq .+12 ; 0x690 <main+0x6c>
cli(); // unclear if I really need to turn off
684: f8 94 cli
dynamicPtr = (char *)newDynamicPtr; // interrupts, but I'll play it safe for
686: 30 93 75 00 sts 0x0075, r19
68a: 20 93 74 00 sts 0x0074, r18
sei(); // the time being
68e: 78 94 sei
}
// If we have dynamic data to display...
if (dynamicPtr != NULL) {
690: 80 91 74 00 lds r24, 0x0074
694: 90 91 75 00 lds r25, 0x0075
698: 89 2b or r24, r25
69a: 91 f2 breq .-92 ; 0x640 <main+0x1c>
switch (dynamicType & 0xF0) {
69c: 80 91 71 00 lds r24, 0x0071
6a0: 99 27 eor r25, r25
6a2: 80 7f andi r24, 0xF0 ; 240
6a4: 90 70 andi r25, 0x00 ; 0
6a6: 80 97 sbiw r24, 0x20 ; 32
6a8: 09 f0 breq .+2 ; 0x6ac <main+0x88>
6aa: 61 c0 rjmp .+194 ; 0x76e <main+0x14a>
#ifdef DYNAMIC_REVCOUNT // Rev counter compiled in?
case 0x10: // Rev counter
tBytes = 4; // number of bytes we'll move down below
a.fPtr = (char *)dynamicCounter;
break; // gets put into dynamicBuffer in reverse order.
#endif
#ifdef DYNAMIC_RPM // RPM counter compiled in?
case 0x20:
// Initialize the RPM counter to 0
dynamicCounter[0]=dynamicCounter[1]=dynamicCounter[2] = '0';
6ac: 80 e3 ldi r24, 0x30 ; 48
6ae: 80 93 65 00 sts 0x0065, r24
6b2: 80 91 65 00 lds r24, 0x0065
6b6: 80 93 64 00 sts 0x0064, r24
6ba: 80 91 64 00 lds r24, 0x0064
6be: 80 93 63 00 sts 0x0063, r24
// Get a copy of the TIMER1 value that we need to divide 732 by
a.divisor = OCR1A;
6c2: 8a b5 in r24, 0x2a ; 42
6c4: 9b b5 in r25, 0x2b ; 43
// Start out pointing to the SECOND element of the div732 array.
// We need to set to the second one because the min value of the
// OCR1A hibyte (max speed) is 01, and we'll do at most 7 shifts
// before we see a bit. But there are 8 bits after that that
// might get looked at, so the div732 table must be 8 entries long.
// We also add 2 so that we are pointing at the last byte of each
// entry.
b.divTable = (char *)(div732+5); // 3 bytes per entry
6c6: ab e2 ldi r26, 0x2B ; 43
6c8: b0 e0 ldi r27, 0x00 ; 0
// Shift the divisor to the left and the divtable pointer to the
// right until the high bit of the divisor is set
while ( (a.divisor & 0x80) == 0) {
a.divisor = a.divisor << 1;
b.divTable = b.divTable + 3;
6ca: 87 fd sbrc r24, 7
6cc: 04 c0 rjmp .+8 ; 0x6d6 <main+0xb2>
6ce: 88 0f add r24, r24
6d0: 99 1f adc r25, r25
6d2: 13 96 adiw r26, 0x03 ; 3
6d4: fa cf rjmp .-12 ; 0x6ca <main+0xa6>
}
// Now we go back through the div732 array, adding in the digits
// whenever we have a set bit in the divisor, until we've run out
// of significant bits
while (b.divTable > div732) {
// Add in the least significant bit. Keep in mind we are adding
// ASCII to ASCII (so must subtract 48...)
dynamicCounter[0] = dynamicCounter[0] + pgm_read_byte(*b.divTable--) - 48;
if (dynamicCounter[0] > '9') {
dynamicCounter[0] = dynamicCounter[0] - 10;
dynamicCounter[1]++;
}
// repeat for second byte...
dynamicCounter[1] = dynamicCounter[1] + pgm_read_byte(*b.divTable--) - 48;
if (dynamicCounter[1] > '9') {
dynamicCounter[1] = dynamicCounter[1] - 10;
dynamicCounter[2]++;
}
// and for third, but no carry needed this time
dynamicCounter[1] = dynamicCounter[1] + pgm_read_byte(*b.divTable--) - 48;
// finally, shift back in the table
b.divTable = b.divTable - 3;
// and get the next bit of the divisor
a.divisor = a.divisor << 1;
6d6: 80 e0 ldi r24, 0x00 ; 0
6d8: a6 32 cpi r26, 0x26 ; 38
6da: b8 07 cpc r27, r24
6dc: 09 f0 breq .+2 ; 0x6e0 <main+0xbc>
6de: 08 f4 brcc .+2 ; 0x6e2 <main+0xbe>
6e0: 46 c0 rjmp .+140 ; 0x76e <main+0x14a>
6e2: 8c 91 ld r24, X
6e4: e8 2f mov r30, r24
6e6: ff 27 eor r31, r31
6e8: 11 97 sbiw r26, 0x01 ; 1
6ea: c8 95 lpm
6ec: 90 2d mov r25, r0
6ee: 80 91 63 00 lds r24, 0x0063
6f2: 89 0f add r24, r25
6f4: 80 53 subi r24, 0x30 ; 48
6f6: 80 93 63 00 sts 0x0063, r24
6fa: 80 91 63 00 lds r24, 0x0063
6fe: 8a 33 cpi r24, 0x3A ; 58
700: 50 f0 brcs .+20 ; 0x716 <main+0xf2>
702: 80 91 63 00 lds r24, 0x0063
706: 8a 50 subi r24, 0x0A ; 10
708: 80 93 63 00 sts 0x0063, r24
70c: 80 91 64 00 lds r24, 0x0064
710: 8f 5f subi r24, 0xFF ; 255
712: 80 93 64 00 sts 0x0064, r24
716: 8c 91 ld r24, X
718: e8 2f mov r30, r24
71a: ff 27 eor r31, r31
71c: 11 97 sbiw r26, 0x01 ; 1
71e: c8 95 lpm
720: 90 2d mov r25, r0
722: 80 91 64 00 lds r24, 0x0064
726: 89 0f add r24, r25
728: 80 53 subi r24, 0x30 ; 48
72a: 80 93 64 00 sts 0x0064, r24
72e: 80 91 64 00 lds r24, 0x0064
732: 8a 33 cpi r24, 0x3A ; 58
734: 50 f0 brcs .+20 ; 0x74a <main+0x126>
736: 80 91 64 00 lds r24, 0x0064
73a: 8a 50 subi r24, 0x0A ; 10
73c: 80 93 64 00 sts 0x0064, r24
740: 80 91 65 00 lds r24, 0x0065
744: 8f 5f subi r24, 0xFF ; 255
746: 80 93 65 00 sts 0x0065, r24
74a: 8c 91 ld r24, X
74c: e8 2f mov r30, r24
74e: ff 27 eor r31, r31
750: c8 95 lpm
752: 90 2d mov r25, r0
754: 80 91 64 00 lds r24, 0x0064
758: 89 0f add r24, r25
75a: 80 53 subi r24, 0x30 ; 48
75c: 80 93 64 00 sts 0x0064, r24
760: 14 97 sbiw r26, 0x04 ; 4
762: 20 e0 ldi r18, 0x00 ; 0
764: a6 32 cpi r26, 0x26 ; 38
766: b2 07 cpc r27, r18
768: 11 f0 breq .+4 ; 0x76e <main+0x14a>
76a: 08 f0 brcs .+2 ; 0x76e <main+0x14a>
76c: ba cf rjmp .-140 ; 0x6e2 <main+0xbe>
}
// And when that's all done, we just set up for the move
tBytes = 3;
a.fPtr = (char *)dynamicCounter;
#endif
default:
tBytes = 0;
a.fPtr = NULL; // preset the pointers to what we
}
// Now move the bytes IF newDynamicPtr hasn't changed...
// This one we do need to insulate from interrupts
b.tPtr = dynamicPtr; // move
cli();
76e: f8 94 cli
if ( (a.fPtr != NULL) && (newDynamicPtr == dynamicPtr) ) {
// Remember, dynamicPtr points to the last byte, so we
// copy bass ackwards!
for(;tBytes>0;tBytes--) {
*b.tPtr-- =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -