📄 spokepov.lss
字号:
// 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) {
632: cf ed ldi r28, 0xDF ; 223
634: d0 e0 ldi r29, 0x00 ; 0
636: de bf out 0x3e, r29 ; 62
638: 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;
63a: 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;
63c: 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
63e: 8e e0 ldi r24, 0x0E ; 14
640: 81 bd out 0x21, r24 ; 33
// Initialize the various pins of the ATMEL, and set up
// the interrupts.
ioinit();
642: cf df rcall .-98 ; 0x5e2 <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)
644: 10 fd sbrc r17, 0
test_leds();
646: e8 df rcall .-48 ; 0x618 <test_leds>
// display the reason for the reset on the LEDs.
set_all(~0x01);
648: 8e ef ldi r24, 0xFE ; 254
64a: 77 dd rcall .-1298 ; 0x13a <set_all>
// enable the interrupts. I think this is not needed
// since it'll immediately be done by the loop, below.
sei();
64c: 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.
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");
64e: 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) {
650: 80 91 87 00 lds r24, 0x0087
654: 90 91 88 00 lds r25, 0x0088
658: 8f 5f subi r24, 0xFF ; 255
65a: 9f 4f sbci r25, 0xFF ; 255
65c: 79 f4 brne .+30 ; 0x67c <main+0x4a>
// Avoid pesky interruptions
cli();
65e: f8 94 cli
// Turn off all LEDs - I guess LED 0 is one of the "invisible ones"
set_all(0xFF);
660: 8f ef ldi r24, 0xFF ; 255
662: 6b dd rcall .-1322 ; 0x13a <set_all>
// Turn off power to the Hall Effect sensor.
SENSOR_PORT &= ~_BV(SENSORPOWER);
664: 96 98 cbi 0x12, 6 ; 18
// Deselect EEPROM
SPIEE_CS_PORT |= _BV(SPIEE_CS); // pull CS high to deselect
666: 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);
668: 81 b5 in r24, 0x21 ; 33
66a: 88 61 ori r24, 0x18 ; 24
66c: 81 bd out 0x21, r24 ; 33
WDTCSR = 0;
66e: 11 bc out 0x21, r1 ; 33
MCUCR |= _BV(SM1) | _BV(SM0) | _BV(SE);
670: 85 b7 in r24, 0x35 ; 53
672: 80 67 ori r24, 0x70 ; 112
674: 85 bf out 0x35, r24 ; 53
// Re-enable interrupts so we can get the wakeup!
sei();
676: 78 94 sei
// Go into sleep mode
asm("sleep");
678: 88 95 sleep
67a: e9 cf rjmp .-46 ; 0x64e <main+0x1c>
} else {
// Do we have dynamic updating to do?
#ifdef DYNAMIC
uint8_t tBytes; // Number of bytes to transfer
char *fPtr,*tPtr; // transfer pointers
// Step 1, update the dynamicPtr
if (dynamicPtr != newDynamicPtr) {
67c: 80 91 74 00 lds r24, 0x0074
680: 90 91 75 00 lds r25, 0x0075
684: 20 91 72 00 lds r18, 0x0072
688: 30 91 73 00 lds r19, 0x0073
68c: 82 17 cp r24, r18
68e: 93 07 cpc r25, r19
690: 31 f0 breq .+12 ; 0x69e <main+0x6c>
cli(); // unclear if I really need to turn off
692: f8 94 cli
dynamicPtr = (char *)newDynamicPtr; // interrupts, but I'll play it safe for
694: 30 93 75 00 sts 0x0075, r19
698: 20 93 74 00 sts 0x0074, r18
sei(); // the time being
69c: 78 94 sei
}
// If we have dynamic data to display...
if (dynamicPtr != NULL) {
69e: 20 91 74 00 lds r18, 0x0074
6a2: 30 91 75 00 lds r19, 0x0075
6a6: 21 15 cp r18, r1
6a8: 31 05 cpc r19, r1
6aa: 89 f2 breq .-94 ; 0x64e <main+0x1c>
switch (dynamicType & 0xF0) {
6ac: 80 91 71 00 lds r24, 0x0071
6b0: 99 27 eor r25, r25
6b2: 80 7f andi r24, 0xF0 ; 240
6b4: 90 70 andi r25, 0x00 ; 0
6b6: 40 97 sbiw r24, 0x10 ; 16
6b8: 21 f4 brne .+8 ; 0x6c2 <main+0x90>
case 0x10: // Rev counter
tBytes = 4; // number of bytes we'll move down below
6ba: 44 e0 ldi r20, 0x04 ; 4
fPtr = (char *)dynamicCounter;
6bc: a3 e6 ldi r26, 0x63 ; 99
6be: b0 e0 ldi r27, 0x00 ; 0
break; // gets put into dynamicBuffer in reverse order.
6c0: 03 c0 rjmp .+6 ; 0x6c8 <main+0x96>
default:
tBytes = 0;
6c2: 40 e0 ldi r20, 0x00 ; 0
fPtr = NULL; // preset the pointers to what we
6c4: a0 e0 ldi r26, 0x00 ; 0
6c6: b0 e0 ldi r27, 0x00 ; 0
}
// Now move the bytes IF newDynamicPtr hasn't changed...
// This one we do need to insulate from interrupts
tPtr = dynamicPtr; // move
6c8: f3 2f mov r31, r19
6ca: e2 2f mov r30, r18
cli();
6cc: f8 94 cli
if ( (fPtr != NULL) && (newDynamicPtr == dynamicPtr) ) {
6ce: 10 97 sbiw r26, 0x00 ; 0
6d0: 71 f0 breq .+28 ; 0x6ee <main+0xbc>
6d2: 80 91 72 00 lds r24, 0x0072
6d6: 90 91 73 00 lds r25, 0x0073
6da: 82 17 cp r24, r18
6dc: 93 07 cpc r25, r19
6de: 39 f4 brne .+14 ; 0x6ee <main+0xbc>
// Remember, dynamicPtr points to the last byte, so we
// copy bass ackwards!
for(;tBytes>0;tBytes--) {
6e0: 44 23 and r20, r20
6e2: 29 f0 breq .+10 ; 0x6ee <main+0xbc>
*tPtr-- = *fPtr++;
6e4: 8d 91 ld r24, X+
6e6: 80 83 st Z, r24
6e8: 31 97 sbiw r30, 0x01 ; 1
6ea: 41 50 subi r20, 0x01 ; 1
6ec: f9 cf rjmp .-14 ; 0x6e0 <main+0xae>
}
}
sei();
6ee: 78 94 sei
6f0: ae cf rjmp .-164 ; 0x64e <main+0x1c>
000006f2 <spi_transfer_n>:
// code space!
// Move n bits of data over the serial link
void spi_transfer_n(uint8_t c, uint8_t n) {
6f2: 96 2f mov r25, r22
// Stuff the byte to transfer into the serial data register
USIDR = c;
6f4: 8f b9 out 0x0f, r24 ; 15
// Set up the status register. On each state transition of
// the serial bus (up or down), the lower 4 bits will be
// incremented - so twice per bit. When that overflows,
// the transfer is done. So if they start out as 0, 8
// bits get moved. But if you start it out at a different
// value, you can move an arbitrary number of bits
USISR = _BV(USIOIF) | (16 - (n<<1));
6f6: 99 0f add r25, r25
6f8: 80 e1 ldi r24, 0x10 ; 16
6fa: 89 1b sub r24, r25
6fc: 80 64 ori r24, 0x40 ; 64
6fe: 8e b9 out 0x0e, r24 ; 14
// While the transfer has not finished
while ( (USISR & _BV(USIOIF)) == 0) {
// Send out another bit
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
700: 76 99 sbic 0x0e, 6 ; 14
702: 04 c0 rjmp .+8 ; 0x70c <spi_transfer_n+0x1a>
704: 8b e1 ldi r24, 0x1B ; 27
706: 8d b9 out 0x0d, r24 ; 13
708: 76 9b sbis 0x0e, 6 ; 14
70a: fd cf rjmp .-6 ; 0x706 <spi_transfer_n+0x14>
70c: 08 95 ret
0000070e <spi_transfer>:
//NOP; // slow down so that the eeprom isnt overwhelmed
}
}
// Move 4 bytes over the serial link (to the 1K/4K EEPROM or the
// LED shift registers, or both!). This code does things "blind",
// clocking 16 times, to transfer the data as fast as possible.
void spi_transfer(uint8_t c) {
USIDR = c;
70e: 8f b9 out 0x0f, r24 ; 15
USISR = _BV(USIOIF);
710: 80 e4 ldi r24, 0x40 ; 64
712: 8e b9 out 0x0e, r24 ; 14
while ( (USISR & _BV(USIOIF)) == 0) {
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
714: 76 99 sbic 0x0e, 6 ; 14
716: 04 c0 rjmp .+8 ; 0x720 <spi_transfer+0x12>
718: 8b e1 ldi r24, 0x1B ; 27
71a: 8d b9 out 0x0d, r24 ; 13
71c: 76 9b sbis 0x0e, 6 ; 14
71e: fd cf rjmp .-6 ; 0x71a <spi_transfer+0xc>
720: 08 95 ret
00000722 <spieeprom_read>:
//NOP; // slow down so that the eeprom isnt overwhelmed
}
// The byte read, if any, will be in USIDR
}
void spieeprom_read(uint16_t addr, uint8_t *buff, uint8_t len) {
722: ff 92 push r15
724: 0f 93 push r16
726: 1f 93 push r17
728: cf 93 push r28
72a: df 93 push r29
72c: 08 2f mov r16, r24
72e: 19 2f mov r17, r25
730: d7 2f mov r29, r23
732: c6 2f mov r28, r22
734: f4 2e mov r15, r20
uint8_t i;
SPIEE_CS_PORT &= ~_BV(SPIEE_CS); // pull CS low
736: c4 98 cbi 0x18, 4 ; 24
...
NOP; NOP; NOP; NOP;
spi_transfer(SPI_EEPROM_READ); // send READ command
740: 83 e0 ldi r24, 0x03 ; 3
742: e5 df rcall .-54 ; 0x70e <spi_transfer>
spi_transfer(addr >> 8); // send high addr
744: 81 2f mov r24, r17
746: 99 27 eor r25, r25
748: e2 df rcall .-60 ; 0x70e <spi_transfer>
spi_transfer(addr & 0xFF); // send low addr
74a: 80 2f mov r24, r16
74c: e0 df rcall .-64 ; 0x70e <spi_transfer>
for (i=0; i<len; i++) { // read in the right number of
74e: 00 e0 ldi r16, 0x00 ; 0
750: 0f 15 cp r16, r15
752: 30 f4 brcc .+12 ; 0x760 <spieeprom_read+0x3e>
spi_transfer(0); // bits, then move to buff[]
754: 80 e0 ldi r24, 0x00 ; 0
756: db df rcall .-74 ; 0x70e <spi_transfer>
buff[i] = USIDR;
758: 8f b1 in r24, 0x0f ; 15
75a: 89 93 st Y+, r24
75c: 0f 5f subi r16, 0xFF ; 255
75e: f8 cf rjmp .-16 ; 0x750 <spieeprom_read+0x2e>
}
SPIEE_CS_PORT |= _BV(SPIEE_CS); // pull CS high
760: c4 9a sbi 0x18, 4 ; 24
762: df 91 pop r29
764: cf 91 pop r28
766: 1f 91 pop r17
768: 0f 91 pop r16
76a: ff 90 pop r15
76c: 08 95 ret
0000076e <memcpy_P>:
76e: e6 2f mov r30, r22
770: f7 2f mov r31, r23
772: a8 2f mov r26, r24
774: b9 2f mov r27, r25
776: 03 c0 rjmp .+6 ; 0x77e <memcpy_P+0x10>
778: c8 95 lpm
77a: 31 96 adiw r30, 0x01 ; 1
77c: 0d 92 st X+, r0
77e: 41 50 subi r20, 0x01 ; 1
780: 50 40 sbci r21, 0x00 ; 0
782: d0 f7 brcc .-12 ; 0x778 <memcpy_P+0xa>
784: 08 95 ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -