⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 旋转16个LED灯控制程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************Background V1.01 firmwareBackgroundPOV firmware is distributed under CC license. For more info on CC go to www.creativecommons.orgFor more info on SpokePOV go to www.ladyada.net/make/spokepovCreative Commons DeedAttribution-NonCommercial-ShareAlike 2.5You are free:    * to copy, distribute, display, and perform the work    * to make derivative worksUnder the following conditions:Attribution.   You must attribute the work in the manner specified by the    author or licensor.Noncommercial.    You may not use this work for commercial purposes.Share Alike.    If you alter, transform, or build upon this work, you may    distribute the resulting work only under a license identical to this one.    * For any reuse or distribution, you must make clear to others       the license terms of this work.    * Any of these conditions can be waived if you get permission       from the copyright holder.Your fair use and other rights are in no way affected by the above.A more detailed version of this license is available at:http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode******************************************//* Modified from charPOV 1.09 by RJW to animations and bitmaps.  Sort of	*//* full-circle from the original code										*//* Currently does not use the rotation offset or backside leds				*//* ANNOTATED by RJW - trebor@animeigo.com - to further my understanding		*//* of the code and environment before proceeding to make mods.  All page	*//* numbers refer to the ATMEL ATTiny2313 documentation located at			*//* http://www.atmel.com/dyn/resources/prod_documents/doc2543.pdf			*//* Any comments implying any ignorance were made by RJW!  The esteemed		*//* original author is by definition omniscient, and, it is feared,			*//* omnipotent as well...													*/#include <avr/io.h>#include <avr/interrupt.h>/* We now store the data that's displayed on the SpokePOV in the flash		*//* memory.  This requires using the PROGMEM routines.  For more info about	*//* them, see: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=38003 *//* IMPORTANT: read the erratta postings after the main posting, there are   *//* a couple that can bite you in the ass (esp: pgm_read_byte example)		*/#include <avr/pgmspace.h>/* The spi_ transfer routines are now in eeprom.c.  There is a define in	*//* eeprom.c as to whether they are functions or inline code					*/#include "main.h"#include "eeprom.h"/* We always need to define nothing...										*/#define NULL ((void *)0)/****************************************************************************//*                                                                          *//* IMPORTANT NOTE ABOUT VARIABLES!                                          *//*                                                                          *//* This firmware is on the ragged edge of running out of RAM for variables  *//* and stack when all the features are turned on.    						*//*                                                                          *//* If you modify it and start seeing displays where some of the characters	*//* are displayed OK but others are mangled, this is a symptom that you have *//* run out of RAM!                                                          *//*                                                                          *//* REMEMBER: function calls use up RAM as well...							*//*                                                                          *//****************************************************************************//* Cute flag that can be used to easily comment out blocks of code			*/#define DONOTCOMPILE	1/* Define the rotation direction of the SpokePOV, needed for proper bitmap	*//* display.  In my case, commented out since I rotation counterclockwise	*/// #define CLOCKWISE	1/* flag to determine whether we compile version that does smooth scrolling	*//* between lines, or the simpler jumping.  COMMENT OUT to disable!			*//* Will almost always be the same as whatever the char firmware is doing	*/#define SMOOTHSCROLL	1/* How many 8msec delays between each smooth scrolling increment.  This     *//* time * 16 is the line scroll delay time, even if not smooth scrolling	*/#define SCROLLSPEED		16/* How many lines does the display software skip when it moves between		*//* lines?  Normally 1, but 2 can be useful for special effects like			*//* changing instantly between displays.  Not really useful in the background*//* firmware, but still around for legacy reasons							*/#define LINEINC	1/* The number of "lines" in our message - how many actual different displays*//* does the background cycle through.  Each display can be a static			*//* background, a bitmap, or an animation of some sort.  If another SpokePOV *//* is running the char firmware and they start up at the same time, they	*//* will stay in rough sync.													*/#define NUM_LINES 20/* The line codes.  These define what each "line" will display, as follows: *//*																			*//* 0xFn		Display bitmap n, n = 0,4,8,A									*//*																			*//* <0x80	Code is an index into the patterns array.  This consists of 6	*//*			byte patterns that are shifted into the display.  Things start	*//*			with the first 4 bytes visible, then progress during the		*//*			SMOOTHSCROLL to display the last 4 bytes.						*/const uint8_t lines[] PROGMEM = { 0xF0,0xF0,		// RFL Logo		- over TO2006/Thanks								  0xF0,				//  and over the black line								  0,0,				// Full white	- over Peter and Nick								  90,				// shift in blk	- over blank line								  24,30,			// alternating  - over name list								  24,30,								  24,30,								  24,30,								  24,30,								  12,								  0xF8,				// always end with a smile!								  0xF8,0xF8			//								  };/* Now the patterns array, which has all the patterns we need				*//* Remember, set bits are black, clear bits are white						*/const uint8_t patterns[] PROGMEM = {	0x00,0x00,0x00,0x00,0x00,0x00,		// 000 - Full White	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,		// 006 - Full Black	0x00,0x00,0xFF,0xFF,0xFF,0xFF,		// 012 - inner white, outer black, shifting to all black	0xFF,0xFF,0x00,0x00,0x00,0x00,		// 018 - inner black, outer white, shifting to all white	0x00,0x00,0xFF,0xFF,0x00,0x00,		// 024 - inner white, outer black, scrolling in white on edges	0xFF,0xFF,0x00,0x00,0xFF,0xFF,		// 030 - inner black, outer white, scrolling in back on edges	0xFF,0x00,0xFF,0x00,0xFF,0x00,		// 036 - same as 24, denser pattern	0x00,0xFF,0x00,0xFF,0x00,0xFF,		// 042 - same as 30, denser pattern	0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,		// 048 - same as 24, even denser pattern	0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,		// 054 - same as 30, even denser pattern	0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,		// 060 - single thin line, outside rim to middle	0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,		// 066 - single thin line, middle to inside rim	0x00,0x00,0x00,0x0F,0x00,0x00,		// 072 - invert of 060, single black line	0x00,0x0F,0x00,0x00,0x00,0x00,		// 078 - invert if 066, single white line	0xFF,0xFF,0xFF,0xFF,0x00,0x00,		// 084 - all black, white shifting in	0x00,0x00,0x00,0x00,0xFF,0xFF,		// 090 - all white, black shifting in.		};	/* Array for the bitmaps we shift out to the LEDs, read in from patterns	*/uint8_t cPattern[6];			// Current pattern// How many ~3ms delays (-1) must elapse before we consider// a subsequent hall-effect sensor interrupt to be valid?#define HALL_DEBOUNCE_THRESH 4				// ~15ms// How many msecs the button must be held down before it is// considered to be an actual button press.#define BUTTON_DEBOUNCE  10// How many pixels in a full rotation of the SpokePOV#define NUM_PIXELS 256     					// max is 255 (since it is 8 bit value)// How long after the SpokePOV stops rotating will the display continue?#define STANDBY_TIMEOUT 5       			// in seconds// How long until the SpokePOV goes into sleep mode.// NOTE: not actually used, it's hard-coded instead!#define POWEROFF_TIMEOUT 2*60   			// in seconds// Internal EEPROM storage locations		// not used in this app (yet)#define EEPROM_ROTATION_OFFSET 0x00			// rotation offset to compensate for magnet position#define EEPROM_MIRROR 0x01					// flag telling whether oppposite side LEDs are mirrored#define EEPROM_ANIMATION 0x02				// animation activation flagvolatile uint8_t hall_debounce;				// count (via TIMER0) since last *used* Hall Effect detectionvolatile 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 smoothlyvolatile uint8_t cur_code = 0x06;			// current display codevolatile var16bit eeprom_addr;				// bitmap eeprom address// 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(cPattern[0]);  spi_transfer(cPattern[1]);  spi_transfer(cPattern[2]);  spi_transfer(cPattern[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(cPattern[4],sCount);           } else {          // First latch out the full first 8 bits         	  spi_transfer(cPattern[4]);  	     	  // How many bits left to do?  	     	  sCount = sCount - 8;  	     	  if (sCount != 0) {  	           spi_transfer_n(cPattern[5],sCount);           	  }  	     	}  	  }     // finally, latch the bits into the LEDS    LATCH_SELECT_PORT |= _BV(FRONT);  NOP; NOP; NOP; NOP;  LATCH_SELECT_PORT &= ~_BV(FRONT);}// 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 displayvoid set_all(uint8_t blockValue) {  spi_transfer(blockValue);  spi_transfer(blockValue);  spi_transfer(blockValue);  spi_transfer(blockValue);  // 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) {  // 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}// 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 uint8_t pixelNum = 0xFF;		// pixel number// 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) {  // 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;        // The first thing we do is increment our pixel position; for    // most of the effects, it isn't used, but it comes in handy    // for some        pixelNum++;        // Unlike the char firmware, we don't check for a wraparound and shut    // down the display, because often we're showing full on white patterns        // Update display based on the current code        if (cur_code < 0x80) {          clock_scroll(line_shift);        } else if (cur_code >= 0xF0) {          // clock out image to the LEDs            spieeprom_read(eeprom_addr,cPattern,4);      clock_scroll(0);            // either move to next line of pixels            if (pixelNum != 0xFF) {              #ifdef CLOCKWISE                  eeprom_addr.word = eeprom_addr.word + 4;              #else                  eeprom_addr.word = eeprom_addr.word - 4;              #endif              } else {              // or, if we've somehow wrapped around, reset to start of buffer                #ifdef CLOCKWISE              	  eeprom_addr.bytes.high_byte &= 0xFC;      	  eeprom_addr.bytes.low_byte = 0x00;      	      	#else      	       	  eeprom_addr.bytes.high_byte |= 0x03;      	  eeprom_addr.bytes.low_byte = 0xFC;     	#endif      	      }          } else {          set_all(0xFF);	// dummy code for now          }      }}// Interrupt 0 executes when the button is pressed.// QUESTION: unlike the pixel output interrupt, this one// doesn't sei().  Why?SIGNAL (SIG_INT0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -