Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // TacDrv 0.1
- //
- // License: Public Domain, if DrJones approve :)
- //
- // For use in 105c type drivers
- //
- #define F_CPU 4800000 // CPU: 4.8MHz PWM: 9.4kHz ####### use low fuse: 0x75 #######
- // Mode values
- #define LO 20 // Light output, 0-255
- #define MID 120
- #define FULL 255 // Full output, no PWM
- #define STROBE 254 // Just a dummy number for id, must not be used for other modes
- #define STROBE_ON 33 // Strobe frequency should be 10-20hz, default 15hz (1000ms/15hz, 33ms on/off)
- #define STROBE_OFF 33
- // Modes, edit as you want
- #define MODES LO, MID, FULL, STROBE
- #define NOMEM // deactivate mode memory.
- #define LOCKTIME 7 // time in 1/8 s until a mode gets locked, e.g. 12/8=1.5s
- #define BATTMON 125 // enable battery monitoring with this threshold
- #define outpin 1
- #define PWM OCR0B // PWM-value
- #define adcpin 2
- #define adcchn 1
- #define portinit() do{ DDRB=(1<<outpin); PORTB=0xff-(1<<outpin)-(1<<adcpin); }while(0)
- #include <avr/pgmspace.h>
- #define byte uint8_t
- #define word uint16_t
- PROGMEM byte modes[]={ MODES };
- #include <avr/io.h>
- #include <util/delay.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- #include <avr/eeprom.h>
- #define WDTIME 0b01000011 //125ms
- #define sleepinit() do{ WDTCR=WDTIME; sei(); MCUCR=(MCUCR &~0b00111000)|0b00100000; }while(0) //WDT-int and Idle-Sleep
- #define SLEEP asm volatile ("SLEEP")
- #define pwminit() do{ TCCR0A=0b00100001; TCCR0B=0b00000001; }while(0) //chan A, phasePWM, clk/1 ->2.35kHz@1.2MHz
- #define adcinit() do{ ADMUX =0b01100000|adcchn; ADCSRA=0b11000100; }while(0) //ref1.1V, left-adjust, ADC1/PB2; enable, start, clk/16
- #define adcread() do{ ADCSRA|=64; while (ADCSRA&64); }while(0)
- #define adcresult ADCH
- #define ADCoff ADCSRA&=~(1<<7) //ADC off (enable=0);
- #define ADCon ADCSRA|=(1<<7) //ADC on
- #define ACoff ACSR|=(1<<7) //AC off (disable=1)
- #define ACon ACSR&=~(1<<7) //AC on (disable=0)
- volatile byte mypwm=0;
- volatile byte ticks=0;
- volatile byte mode=0;
- byte pmode=50;
- byte eep[32]; //EEPROM buffer
- byte eepos=0;
- byte lowbattcounter=0;
- void eepsave(byte data) { //central method for writing (with wear leveling)
- byte oldpos=eepos;
- eepos=(eepos+1)&31; //wear leveling, use next cell
- EEARL=eepos; EEDR=data; EECR=32+4; EECR=32+4+2; //WRITE //32:write only (no erase) 4:enable 2:go
- while(EECR & 2); //wait for completion
- EEARL=oldpos; EECR=16+4; EECR=16+4+2; //ERASE //16:erase only (no write) 4:enable 2:go
- }
- ISR(WDT_vect) { //WatchDogTimer interrupt
- if (ticks<255) ticks++;
- if (ticks==LOCKTIME)
- #ifdef NOMEM
- eepsave(0); //current mode locked -> next time start over, no memory.
- #else
- eepsave(mode);
- #endif
- #ifdef BATTMON //code to check voltage and ramp down
- adcread();
- if (adcresult<BATTMON) { if (++lowbattcounter>8) {mypwm=(mypwm>>1)+3;lowbattcounter=0;} }
- else lowbattcounter=0;
- #endif
- }
- inline void getmode(void) { //read current mode from EEPROM and write next mode
- eeprom_read_block(&eep, 0, 32); //read block
- while((eep[eepos]==0xff) && (eepos<32)) eepos++; //find mode byte
- if (eepos<32) mode=eep[eepos];
- else eepos=0;
- byte next=0;
- if (mode==0) next=1; //skip 1st mode if memory is 1st mode already
- if (mode & 0x80) { //last on-time was short
- mode&=0x7f; if (mode>=sizeof(modes)) mode=0;
- next=mode+1; if (next>=sizeof(modes)) next=0;
- }
- eepsave(next|0x80); //write next mode, with short-on marker
- }
- int main(void) {
- portinit();
- sleepinit();
- ACoff;
- #ifdef BATTMON
- adcinit();
- #else
- ADCoff;
- #endif
- pwminit();
- getmode(); //get current mode number from EEPROM
- byte i=0;
- pmode=pgm_read_byte(&modes[mode]); //get actual PWM value (or special mode code)
- switch(pmode){
- case STROBE: mypwm=255; while(1){ PWM=mypwm; _delay_ms(STROBE_ON); PWM=0; _delay_ms(STROBE_OFF); } break;
- default: mypwm=pmode; while(1){PWM=mypwm;SLEEP;} //all other: us as PWM value
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement