📄 spokepov.lss
字号:
// get the third line, which may wrap..
cLine++;
if (cLine == NUM_LINES) {
cLine = 0;
}
memcpy_P(scrollLine,lines+(cLine << 4),16);
// If we are doing dynamic data, set it if there
// is such data in the line.
#ifdef DYNAMIC
dCode = pgm_read_byte(dInfo+cLine);
if (dCode != 0) {
newDynamicPtr = scrollLine + (dCode & 0x0F);
dynamicType = dCode;
}
#endif
#endif
}
}
#else
// we could do this just once when the app initializes, but
// for now, let's do it here. Later we'll move it.
cur_line = line_shift = 0;
memcpy_P(topLine,lines,16);
memcpy_P(botLine,lines+16,16);
#ifdef DYNAMIC
dCode = pgm_read_byte(dInfo);
if (dCode != 0) {
newDynamicPtr = topLine + (dCode & 0x0F);
dynamicType = dCode;
}
dCode = pgm_read_byte(dInfo+1);
if (dCode != 0) {
newDynamicPtr = botLine + (dCode & 0x0F);
dynamicType = dCode;
}
#endif
#endif
// Set the character and pixel numbers so they will overflow
// on the next pixel interrupt, and cause the correct data to
// be loaded.
charNum = 31; // will wrap to 0, the first char. Not set to 15 as you might
// expect, because when it hits 15 again, the pixel output
// routine will shut down. But (31+1) mod 16 = (15+1) mod 16...
pixelNum = 15; // will wrap to 0, the first pixel
#ifdef USE_LOCAL_TIMER1
clean = 0; // flag that we changed things
#endif
// Start TIMER1 on its merry way...
TCCR1B |= _BV(CS10); // increment at clock/1
TIMSK |= _BV(OCIE1A); // enable interrupt when it matches OCR1A
} else {
// Since we don't have a valid setting for the rotation
// speed, set a couple of LEDs to let the human know we
// aren't dead yet, and turn off the timer.
set_all(~0x03);
TCCR1B &= ~_BV(CS10); // no incrementing = no interrupting
// reset the line timers so that when we get a valid spinup,
// they will start clocking the lines across the display
line_timer_l = SCROLLSPEED; // delay figure, will trigger wrap
line_shift = 0x0f; // subcharacter shift, will trigger wrap
cur_line = 0xff; // will wrap to first line
}
// Whether we're displaying or not, we reset sensor_timer so we can
// time the next revolution.
sensor_timer = 0;
}
// Finally, reset hall_debounce so we won't execute the timer reset code
// until the Hall Effect sensor hasn't bothered us for a reasonable while.
hall_debounce = 0;
// *** PORTB &= ~0x8;
}
// Initialize the IO pins on the ATMEL.
void ioinit(void) {
// Set the data direction for the PORTD and PORTB pins; see the
// circuit diagram for more information on this.
DDRD = 0x73; // input on PD2 (button), PD3 (sensor), all other output
DDRB = 0xDF; // input on MOSI/DI (for SPI), all others output
// Deselect EEPROM. Not being an EE, I'm not going to worry about
// how the ATMEL talks to the EEPROM. It's black magic.
PORTB = _BV(SPIEE_CS);
// Just above, we set PD2 and PD3 to input. If we now set those
// bits to 1, they set into pullup mode (again, not EE, claim
// ignorance), which is essential for them to work. We also set
// the SENSORPOWER bit to 1, which sends out little dribbles of
// electrons to the hall effect sensor (see circuit diagram)
//
// Finally, we write 0's to the FRONT and BACK pins, which control
// which bank of 30 LEDs we are talking to. Having both of these
// on at the same time probably causes horrible things to happen.
PORTD = (_BV(BUTTON) | _BV(SENSOR) | _BV(SENSORPOWER))
& ~_BV(FRONT) & ~_BV(BACK);
// Rather than poll to see when the hall effect sensor and
// button are pressed, we configure an interrupt handler. If you
// look at the circuit diagram, you'll see that PD3 and PD2, which
// are wired to SENSOR IN and BUTTON IN, do double-duty as INT1
// and INT0. They are both SUPPOSEDLY set to interrupt on the
// falling edge of a pulse from the devices. (Page 63)
// POSSIBLE BUG: ISC0{1,0} seems to be being set to 00, not 10
// as ISC1{1,0} is being set to. So ISC0 will trigger when
// the button interrupt line goes low. Either this is a bug,
// or the original comment was not correct (likely, IMHO)
MCUCR = _BV(ISC11) & ~_BV(ISC01) & ~_BV(ISC00) & ~_BV(ISC10);
// Activate the interrupts by setting the General Interrupt Mask
// Register (Page 63)
GIMSK = _BV(INT1) | _BV(INT0);
// The ATMEL has built-in timers that can trigger an interrupt.
// SpokePOV uses them to update the LEDs 256 times per rotation.
// Timer 0 is set to update at a rate system-clock / 256 and
// interrupt when it overflows (8 bit). This means that it
// triggers every 65536 cycles.
TCCR0A = 0; // normal, overflow (count up to 256 == num pixels)
TCCR0B = _BV(CS02); // clk/256
TIMSK |= _BV(TOIE0); // turn on overflow interrupt
// Timer 1 (T1) is the pixel timer, which is used to update the
// LEDs 256 times per rotation. It's set up as a normal timer
// as well. See Page 108&71; it is apparently being set into CTC
// mode 4. This means that the counter is compared to a 16-bit value
// and interrupts when it reaches this value.
//
// Adjusting this value is how the SpokePOV compensates for
// changes in the rotation speed of the device.
//
// Note that at this point, the timer is initialized, but not
// activated.
TCCR1A = 0;
TCCR1B = _BV(WGM12);
// Clear the debounce values, which I haven't sussed out yet.
hall_debounce = 0;
sensor_timer = 0;
}
// Delay for a specified number of milliseconds using some
// assembly code. Will this be dependant on the clock speed?
void delay_ms(unsigned char ms)
{
unsigned short delay_count = F_CPU / 4000;
unsigned short cnt;
asm volatile ("\n"
"L_dl1%=:\n\t"
"mov %A0, %A2\n\t"
"mov %B0, %B2\n"
"L_dl2%=:\n\t"
"sbiw %A0, 1\n\t"
"brne L_dl2%=\n\t"
"wdr\n\t"
"dec %1\n\t" "brne L_dl1%=\n\t":"=&w" (cnt)
:"r"(ms), "r"((unsigned short) (delay_count))
);
}
// Turn on a single LED, turning off all the other LEDs
//void set_led(uint8_t led) {
// fleds[0] = fleds[1] = fleds[2] = fleds[3] = 0xFF;
// fleds[led >> 3] = ~_BV(led & 0x7F);
// clock_scroll(0);
//}
// Set all the LEDs on a side to have the same
// repeating 8-bit value (ie: 0x00 = all on, 0xFF = all off)
// Added by RJW to permit a more comprehensive reset display
void set_all(uint8_t blockValue) {
fleds[0] = fleds[1] = fleds[2] = fleds[3] = blockValue;
156: 80 93 8c 00 sts 0x008C, r24
15a: 80 93 8b 00 sts 0x008B, r24
15e: 80 93 8a 00 sts 0x008A, r24
162: 80 93 89 00 sts 0x0089, r24
clock_scroll(0);
166: 80 e0 ldi r24, 0x00 ; 0
168: 98 df rcall .-208 ; 0x9a <clock_scroll>
16a: 08 95 ret
0000016c <__vector_4>:
16c: 1f 92 push r1
16e: 0f 92 push r0
170: 0f b6 in r0, 0x3f ; 63
172: 0f 92 push r0
174: 11 24 eor r1, r1
176: 2f 93 push r18
178: 3f 93 push r19
17a: 4f 93 push r20
17c: 5f 93 push r21
17e: 6f 93 push r22
180: 7f 93 push r23
182: 8f 93 push r24
184: 9f 93 push r25
186: af 93 push r26
188: bf 93 push r27
18a: ef 93 push r30
18c: ff 93 push r31
18e: 80 91 87 00 lds r24, 0x0087
192: 90 91 88 00 lds r25, 0x0088
196: 82 56 subi r24, 0x62 ; 98
198: 92 40 sbci r25, 0x02 ; 2
19a: 08 f0 brcs .+2 ; 0x19e <__vector_4+0x32>
19c: af c0 rjmp .+350 ; 0x2fc <__vector_4+0x190>
19e: 80 91 6a 00 lds r24, 0x006A
1a2: 8f 5f subi r24, 0xFF ; 255
1a4: 80 93 6a 00 sts 0x006A, r24
1a8: 80 91 6a 00 lds r24, 0x006A
1ac: 80 31 cpi r24, 0x10 ; 16
1ae: 09 f0 breq .+2 ; 0x1b2 <__vector_4+0x46>
1b0: 6e c0 rjmp .+220 ; 0x28e <__vector_4+0x122>
1b2: 80 91 6b 00 lds r24, 0x006B
1b6: 8f 30 cpi r24, 0x0F ; 15
1b8: 61 f0 breq .+24 ; 0x1d2 <__vector_4+0x66>
1ba: 10 92 6a 00 sts 0x006A, r1
1be: 80 91 6b 00 lds r24, 0x006B
1c2: 8f 5f subi r24, 0xFF ; 255
1c4: 8f 70 andi r24, 0x0F ; 15
1c6: 80 93 6b 00 sts 0x006B, r24
1ca: 80 91 6b 00 lds r24, 0x006B
1ce: 8f 30 cpi r24, 0x0F ; 15
1d0: 29 f4 brne .+10 ; 0x1dc <__vector_4+0x70>
1d2: 8e b5 in r24, 0x2e ; 46
1d4: 88 7f andi r24, 0xF8 ; 248
1d6: 8e bd out 0x2e, r24 ; 46
1d8: 8f ef ldi r24, 0xFF ; 255
1da: 94 c0 rjmp .+296 ; 0x304 <__vector_4+0x198>
1dc: 80 91 6b 00 lds r24, 0x006B
1e0: e8 2f mov r30, r24
1e2: ff 27 eor r31, r31
1e4: e1 57 subi r30, 0x71 ; 113
1e6: ff 4f sbci r31, 0xFF ; 255
1e8: e0 81 ld r30, Z
1ea: e0 52 subi r30, 0x20 ; 32
1ec: 8e 2f mov r24, r30
1ee: 86 95 lsr r24
1f0: 28 2f mov r18, r24
1f2: 33 27 eor r19, r19
1f4: f6 e0 ldi r31, 0x06 ; 6
1f6: 22 0f add r18, r18
1f8: 33 1f adc r19, r19
1fa: fa 95 dec r31
1fc: e1 f7 brne .-8 ; 0x1f6 <__vector_4+0x8a>
1fe: 8e 2f mov r24, r30
200: 99 27 eor r25, r25
202: 81 70 andi r24, 0x01 ; 1
204: 90 70 andi r25, 0x00 ; 0
206: 88 0f add r24, r24
208: 99 1f adc r25, r25
20a: 28 2b or r18, r24
20c: 39 2b or r19, r25
20e: 30 93 6f 00 sts 0x006F, r19
212: 20 93 6e 00 sts 0x006E, r18
216: 80 91 6b 00 lds r24, 0x006B
21a: e8 2f mov r30, r24
21c: ff 27 eor r31, r31
21e: e1 56 subi r30, 0x61 ; 97
220: ff 4f sbci r31, 0xFF ; 255
222: e0 81 ld r30, Z
224: e0 52 subi r30, 0x20 ; 32
226: 8e 2f mov r24, r30
228: 86 95 lsr r24
22a: 28 2f mov r18, r24
22c: 33 27 eor r19, r19
22e: 76 e0 ldi r23, 0x06 ; 6
230: 22 0f add r18, r18
232: 33 1f adc r19, r19
234: 7a 95 dec r23
236: e1 f7 brne .-8 ; 0x230 <__vector_4+0xc4>
238: 8e 2f mov r24, r30
23a: 99 27 eor r25, r25
23c: 81 70 andi r24, 0x01 ; 1
23e: 90 70 andi r25, 0x00 ; 0
240: 88 0f add r24, r24
242: 99 1f adc r25, r25
244: 28 2b or r18, r24
246: 39 2b or r19, r25
248: 30 93 6d 00 sts 0x006D, r19
24c: 20 93 6c 00 sts 0x006C, r18
250: 80 91 6b 00 lds r24, 0x006B
254: e8 2f mov r30, r24
256: ff 27 eor r31, r31
258: ea 58 subi r30, 0x8A ; 138
25a: ff 4f sbci r31, 0xFF ; 255
25c: e0 81 ld r30, Z
25e: e0 52 subi r30, 0x20 ; 32
260: 8e 2f mov r24, r30
262: 86 95 lsr r24
264: 28 2f mov r18, r24
266: 33 27 eor r19, r19
268: 68 94 set
26a: 15 f8 bld r1, 5
26c: 22 0f add r18, r18
26e: 33 1f adc r19, r19
270: 16 94 lsr r1
272: e1 f7 brne .-8 ; 0x26c <__vector_4+0x100>
274: 8e 2f mov r24, r30
276: 99 27 eor r25, r25
278: 81 70 andi r24, 0x01 ; 1
27a: 90 70 andi r25, 0x00 ; 0
27c: 88 0f add r24, r24
27e: 99 1f adc r25, r25
280: 28 2b or r18, r24
282: 39 2b or r19, r25
284: 30 93 69 00 sts 0x0069, r19
288: 20 93 68 00 sts 0x0068, r18
28c: 1b c0 rjmp .+54 ; 0x2c4 <__vector_4+0x158>
28e: 80 91 6e 00 lds r24, 0x006E
292: 90 91 6f 00 lds r25, 0x006F
296: 04 96 adiw r24, 0x04 ; 4
298: 90 93 6f 00 sts 0x006F, r25
29c: 80 93 6e 00 sts 0x006E, r24
2a0: 80 91 6c 00 lds r24, 0x006C
2a4: 90 91 6d 00 lds r25, 0x006D
2a8: 04 96 adiw r24, 0x04 ; 4
2aa: 90 93 6d 00 sts 0x006D, r25
2ae: 80 93 6c 00 sts 0x006C, r24
2b2: 80 91 68 00 lds r24, 0x0068
2b6: 90 91 69 00 lds r25, 0x0069
2ba: 04 96 adiw r24, 0x04 ; 4
2bc: 90 93 69 00 sts 0x0069, r25
2c0: 80 93 68 00 sts 0x0068, r24
2c4: 42 e0 ldi r20, 0x02 ; 2
2c6: 69 e8 ldi r22, 0x89 ; 137
2c8: 70 e0 ldi r23, 0x00 ; 0
2ca: 80 91 6e 00 lds r24, 0x006E
2ce: 90 91 6f 00 lds r25, 0x006F
2d2: 68 d2 rcall .+1232 ; 0x7a4 <spieeprom_read>
2d4: 42 e0 ldi r20, 0x02 ; 2
2d6: 6b e8 ldi r22, 0x8B ; 139
2d8: 70 e0 ldi r23, 0x00 ; 0
2da: 80 91 6c 00 lds r24, 0x006C
2de: 90 91 6d 00 lds r25, 0x006D
2e2: 60 d2 rcall .+1216 ; 0x7a4 <spieeprom_read>
2e4: 42 e0 ldi r20, 0x02 ; 2
2e6: 6d e8 ldi r22, 0x8D ; 141
2e8: 70 e0 ldi r23, 0x00 ; 0
2ea: 80 91 68 00 lds r24, 0x0068
2ee: 90 91 69 00 lds r25, 0x0069
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -