📄 main copy.c
字号:
volatile var16bit sensor_timer; // count (via TIMER0) since last actual Hall Effect detectionvolatile uint8_t line_timer = SCROLLSPEED; // counter for scrolling/line stepping; realized it only needs to be 8 bitsvolatile uint8_t cur_line = NUM_LINES-1; // the current 'top line'volatile uint8_t line_shift = 0x0f; // # of pixels extra shift we do to scroll smoothly// Sends the 4-byte LED pixel data block out// over the serial link. Front LEDs only// Sends 4 bytes + sCount extra bits over the serial link// to implement smooth scrolling. Can be used with a 0// parameter to just send out the regular 4 bytes.void clock_scroll(uint8_t sCount) { // First, send the basic 4 bytes, they go no matter what spi_transfer(fleds[0]); spi_transfer(fleds[1]); spi_transfer(fleds[2]); spi_transfer(fleds[3]); // If there is anything to do.. if (sCount != 0) { // If we have < 8 bits to transfer if (sCount < 8) { // Then that is all that we need to do spi_transfer_n(fleds[4],sCount); } else { // First latch out the full first 8 bits spi_transfer(fleds[4]); // How many bits left to do? sCount = sCount - 8; if (sCount != 0) { spi_transfer_n(fleds[5],sCount); } } } // finally, latch the bits into the LEDS LATCH_SELECT_PORT |= _BV(FRONT); NOP; NOP; NOP; NOP; LATCH_SELECT_PORT &= ~_BV(FRONT);}// TIMER0 interrupt handler. This runs about every 8ms// AFAICT. It increments the hall_debounce and sensor_timer// values until they pin.// QUESTION: what's with the setting and clearing of PORTB0?// According to the wiring diagram, it isn't connected to// 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) { // *** PORTB |= 0x1; // Let hall_debounce just wrap around. At worst it'll just // mess things up for one of the initial speedup rotations // of the blade... // if (hall_debounce != 0xFF) hall_debounce++; if (sensor_timer.bytes.high_byte != 0xFF) sensor_timer.word++; #if NUM_LINES > 0 // Increment the line timer - we only need to do this // if we are scrolling if (line_timer != 0xFF) { line_timer++; } #endif #ifdef DYNAMIC_TIME // Increment the dynamic time fractional seconds byte dynamicTimeCounter.word += DYNAMIC_TIME_CALIBRATION; if (dynamicTimeCounter.bytes.high_byte > 0x7F) { // wrap the counter dynamicTimeCounter.bytes.high_byte &= 0x7F; // Add 1 second to the time HH:MM:SS // 76-43-10 // Bytes in reverse order // Increment seconds dynamicTime[0]++; // Check for units seconds overflow - has the digit become 10? if ( dynamicTime[0] == ':' ) { // If so, reset it and increment 10's digit dynamicTime[0] = '0'; dynamicTime[1]++; // Repeat the process for the 10s seconds digit, has it become // 6? if ( dynamicTime[1] == '6' ) { // reset it and increment minutes digit dynamicTime[1] = '0'; dynamicTime[3]++; // Repeat process for minutes if ( dynamicTime[3] == ':' ) { // You should get the idea now... dynamicTime[3] = '0'; dynamicTime[4]++; if ( dynamicTime[4] == '6' ) { dynamicTime[4] = '0'; dynamicTime[6]++; // and 10s of hours if ( dynamicTime[6] == ':' ) { dynamicTime[6] = '0'; dynamicTime[7]++; } // handle special wrap #ifdef DYNAMIC_TIME_12H if ( (dynamicTime[7] == '1') && (dynamicTime[6] == '3') ) { dynamicTime[7] = '0'; dynamicTime[6] = '1'; } #else if ( (dynamicTime[7] == '2') && (dynamicTime[6] == '4') ) { dynamicTime[7] = dynamicTime[6] = '0'; } #endif } } } } } #endif // *** PORTB &= ~0x1;}// Hack - I used to copy the topChar, etc. variables into local// variables in the TIMER1 routine, but I am running out of stack space. So instead// I'm going to keep interrupts off during this routine and// use the global versions.// 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.// This code has to be fast enough to complete execution before// it gets interrupted again - and it must not make any subroutine// calls, since that'll mess up the stack and cause the entire// system to reset.volatile uint16_t topChar = 0; // top character being displayed (address in EEPROM of data)volatile uint16_t botChar = 0; // bottom character being displayedvolatile uint8_t charNum = 31; // character numbervolatile uint8_t pixelNum = 15; // pixel number#ifdef HALFSHIFT volatile uint8_t charNum2 = 31; // character number volatile uint8_t pixelNum2 = 15; // pixel number #endif#ifdef SMOOTHSCROLL volatile uint16_t scrollChar = 0; // extra scroll character #ifdef HALFSHIFT volatile uint8_t charNum3 = 31; // character number volatile uint8_t pixelNum3 = 15; // pixel number #endif#endif// 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) { // Because of the way the code's evolved, I have the vars just // defined above renamed via defines right here. Just haven't // gotten around to grepping them... #define tChar topChar #define bChar botChar #define cNum charNum #define pNum pixelNum #define sChar scrollChar #define cNum2 charNum2 #define cNum3 charNum3 #define pNum2 pixelNum2 #define pNum3 pixelNum3 // 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? ANSWER: FREQUENCY OF CPU (clocks/second) if (sensor_timer.bytes.high_byte < ( (F_CPU/NUM_PIXELS)/256 * STANDBY_TIMEOUT) / 256) { // *** PORTA |= 0x1; // If we are in normal mode, we use one shift for everyone #ifndef HALFSHIFT // 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) { // If we will wrap around to the first character, turn off the pixel // timer, clear the display, and exit. Might speed things up a bit if (cNum == 15) { TCCR1B &= ~0x7; set_all(~0x00); return; } pNum = 0; // reset to first pixel cNum = (cNum+1) & 0x0F; // 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. With the new // interleaved character sets, this becomes much easier tChar = (topLine[cNum]-32) << 1; // character offset for the top char, 0-95 // Ditto for bChar... bChar = (botLine[cNum]-32) << 1; #ifdef SMOOTHSCROLL // and if smooth scrolling, sChar sChar = (scrollLine[cNum]-32) << 1; #endif } else { // If we haven't wrapped around a character boundary, we just move // to the next 2-byte line in the character set, which will be 192 bytes // away tChar += 192; bChar += 192; #ifdef SMOOTHSCROLL sChar += 192; #endif } #else // Okay, we are doing half-shifts. So we effectively have to do the // above code once for each line // Do for the first line. Also use this to turn off the display if // we get to the end. If first line is shifted, this'll turn us off // a half-char early, so other lines can't have anything in the last // character space... pNum++; if (pNum == 16) { if (cNum == 15) { TCCR1B &= ~0x7; set_all(~0x00); return; } pNum = 0; cNum = (cNum+1) & 0x0F; tChar = (topLine[cNum]-32) << 1; // character offset for the top char, 0-95 } else { tChar += 192; } // do for second line pNum2++; if (pNum2 == 16) { pNum2 = 0; cNum2 = (cNum2+1) & 0x0F; bChar = (botLine[cNum2]-32) << 1; } else { bChar += 192; } // and scroll line #ifdef SMOOTHSCROLL pNum3++; if (pNum3 == 16) { pNum3 = 0; cNum3 = (cNum3+1) & 0x0F; sChar = (scrollLine[cNum]-32) << 1; } else { sChar += 192; } #endif #endif // 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -