~toykeeper/flashlight-firmware/trunk

« back to all changes in this revision

Viewing changes to DrJones/luxdrv/luxdrv030.c

  • Committer: Selene Scriven
  • Date: 2015-02-16 20:18:46 UTC
  • Revision ID: ubuntu@toykeeper.net-20150216201846-a0gn20xs79193o04
Added more firmware from DrJones: luxdrv 0.30, MiniDrv, MiniMo.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// LuxDrv 0.30b    DrJones 2011++
 
3
//
 
4
// 808 bytes with ramping
 
5
//
 
6
// License: Free for private and noncommercial use for members of BudgetLightForum.com and Taschenlampenforum.de
 
7
//
 
8
// changes:
 
9
// 0.1  first version: levels,strobe,beacon,timer(136)   (638bytes)
 
10
// 0.2  ramping(200), improved timer(180), skip mode1 as next mode if already in mode 1     (898bytes)
 
11
// 0.21 changed EEPROM handling to reduce power-off-while-writing glitches -->eepsave(byte)  (874bytes)
 
12
// 0.22 bugfix in ramping; mode not stored on (very) short tap   (878bytes)
 
13
// 0.3  battery monitoring added; step down and indicator in beacon mode (994bytes)
 
14
// 0.3b improved config, const progmem, no dummy any more,  timer removed, 4 main modes as default
 
15
 
 
16
//ToDo: 
 
17
//  ? off-time checking; requires adding  diode,R,C
 
18
//  ? blink your name in morse code :)
 
19
 
 
20
 
 
21
#define F_CPU 4800000    //CPU: 4.8MHz  PWM: 9.4kHz       ####### use low fuse: 0x75  #######   
 
22
//########################################################################################### MODE/PWM SETUP 
 
23
//Special modes; comment out to disable
 
24
#define RAMPING   254  //+156
 
25
#define STROBE    253  //+50
 
26
#define BEACON    252  //+74
 
27
 
 
28
 
 
29
#define MODES      6,15,56,255,   RAMPING,  STROBE,  BEACON
 
30
 
 
31
#define RAMPMODE 5  //the number of the RAMPING mode in the MODES order; e.g. RAMPING is 5th mode -> 5
 
32
 
 
33
 
 
34
//define NOMEM         //deactivate mode memory.
 
35
#define LOCKTIME 7   //time in 1/8 s until a mode gets locked, e.g. 12/8=1.5s
 
36
#define BATTMON  125 //enable battery monitoring with this threshold
 
37
#define MINPWM   5   //needed for ramping
 
38
//###########################################################################################
 
39
 
 
40
 
 
41
#define outpin 1
 
42
 #define PWM OCR0B  //PWM-value
 
43
#define adcpin 2
 
44
 #define adcchn 1
 
45
#define portinit() do{ DDRB=(1<<outpin); PORTB=0xff-(1<<outpin)-(1<<adcpin);  }while(0)
 
46
 
 
47
#include <avr/pgmspace.h>
 
48
#define byte uint8_t
 
49
#define word uint16_t
 
50
 
 
51
PROGMEM byte modes[]={ MODES };
 
52
 
 
53
#include <avr/io.h>
 
54
#include <util/delay.h>
 
55
#include <avr/interrupt.h>
 
56
#include <avr/sleep.h>
 
57
#include <avr/eeprom.h>
 
58
 
 
59
 
 
60
 
 
61
#define WDTIME 0b01000011  //125ms
 
62
 
 
63
#define sleepinit() do{ WDTCR=WDTIME; sei(); MCUCR=(MCUCR &~0b00111000)|0b00100000; }while(0) //WDT-int and Idle-Sleep
 
64
 
 
65
#define SLEEP asm volatile ("SLEEP")
 
66
 
 
67
#define pwminit() do{ TCCR0A=0b00100001; TCCR0B=0b00000001; }while(0)  //chan A, phasePWM, clk/1  ->2.35kHz@1.2MHz
 
68
 
 
69
#define adcinit() do{ ADMUX =0b01100000|adcchn; ADCSRA=0b11000100; }while(0) //ref1.1V, left-adjust, ADC1/PB2; enable, start, clk/16
 
70
#define adcread() do{ ADCSRA|=64; while (ADCSRA&64); }while(0)
 
71
#define adcresult ADCH
 
72
 
 
73
 
 
74
#define ADCoff ADCSRA&=~(1<<7) //ADC off (enable=0);
 
75
#define ADCon  ADCSRA|=(1<<7)  //ADC on
 
76
#define ACoff  ACSR|=(1<<7)    //AC off (disable=1)
 
77
#define ACon   ACSR&=~(1<<7)   //AC on  (disable=0)
 
78
 
 
79
 
 
80
//_____________________________________________________________________________________________________________________
 
81
 
 
82
 
 
83
volatile byte mypwm=0;
 
84
volatile byte ticks=0;
 
85
volatile byte mode=0;
 
86
byte pmode=50;
 
87
 
 
88
byte eep[32];  //EEPROM buffer
 
89
byte eepos=0;
 
90
 
 
91
#ifdef RAMPING
 
92
  byte ramped=0;
 
93
#endif
 
94
 
 
95
byte lowbattcounter=0;
 
96
 
 
97
 
 
98
 
 
99
void eepsave(byte data) {  //central method for writing (with wear leveling)
 
100
  byte oldpos=eepos;
 
101
  eepos=(eepos+1)&31;  //wear leveling, use next cell
 
102
  EEARL=eepos; EEDR=data; EECR=32+4; EECR=32+4+2;  //WRITE  //32:write only (no erase)  4:enable  2:go
 
103
  while(EECR & 2); //wait for completion
 
104
  EEARL=oldpos;           EECR=16+4; EECR=16+4+2;  //ERASE  //16:erase only (no write)  4:enable  2:go
 
105
}
 
106
 
 
107
 
 
108
 
 
109
 
 
110
ISR(WDT_vect) {  //WatchDogTimer interrupt
 
111
  if (ticks<255) ticks++;
 
112
  if (ticks==LOCKTIME)
 
113
  #ifdef NOMEM
 
114
    eepsave(0);  //current mode locked -> next time start over, no memory.
 
115
  #else 
 
116
    eepsave(mode);
 
117
  #endif
 
118
 
 
119
 
 
120
  #ifdef BATTMON //code to check voltage and ramp down
 
121
   adcread(); 
 
122
   if (adcresult<BATTMON) { if (++lowbattcounter>8) {mypwm=(mypwm>>1)+3;lowbattcounter=0;} } 
 
123
   else lowbattcounter=0;
 
124
  #endif
 
125
}
 
126
 
 
127
 
 
128
 
 
129
 
 
130
inline void getmode(void) {  //read current mode from EEPROM and write next mode
 
131
 
 
132
  eeprom_read_block(&eep, 0, 32);                     //read block 
 
133
  while((eep[eepos]==0xff) && (eepos<32)) eepos++;    //find mode byte
 
134
  if (eepos<32) mode=eep[eepos];
 
135
  else eepos=0;
 
136
 
 
137
  byte next=0;
 
138
  if (mode==0) next=1; //skip 1st mode if memory is 1st mode already
 
139
 
 
140
  #ifdef RAMPING  
 
141
   if (mode & 0x40) {   //RAMPING
 
142
     ramped=1;
 
143
     if (mode & 0x80)  { next=RAMPMODE; mode&=0x7f; } //mode: for savemode
 
144
   }else              //ENDRAMPING
 
145
  #endif
 
146
 
 
147
  if (mode & 0x80) {  //last on-time was short
 
148
    mode&=0x7f;   if (mode>=sizeof(modes)) mode=0;
 
149
    next=mode+1;  if (next>=sizeof(modes)) next=0; 
 
150
  } 
 
151
 
 
152
  eepsave(next|0x80); //write next mode, with short-on marker
 
153
}
 
154
 
 
155
 
 
156
 
 
157
 
 
158
 
 
159
int main(void) {
 
160
 
 
161
  portinit();
 
162
  sleepinit();
 
163
  ACoff;
 
164
  #ifdef BATTMON
 
165
    adcinit();
 
166
  #else
 
167
    ADCoff;
 
168
  #endif
 
169
  pwminit();
 
170
 
 
171
 
 
172
  getmode();  //get current mode number from EEPROM
 
173
 
 
174
  byte i=0;
 
175
 
 
176
  #ifdef RAMPING
 
177
   byte p,j=0,dn=1;  //for ramping
 
178
   if (ramped) {  //use the ramped mode
 
179
      pmode=255; i=30-MINPWM-(mode&0x3f); while(i--){pmode=pmode-(pmode>>3)-1;}  //get PWM value  //never gives 250..254
 
180
   } else
 
181
  #endif
 
182
 
 
183
  pmode=pgm_read_byte(&modes[mode]);  //get actual PWM value (or special mode code)
 
184
 
 
185
 
 
186
  switch(pmode){
 
187
 
 
188
    #ifdef RAMPING
 
189
    case RAMPING: 
 
190
      ticks=100; //crude way to deactivate the 2s-lock       //RAMPING
 
191
      while(EECR & 2); //wait for completion of getmode's write
 
192
      while(1){ p=255; i=30-MINPWM-j; while(i--){p=p-(p>>3)-1;}   //ramp up
 
193
                PWM=p;
 
194
                eepsave(192+j);    
 
195
                SLEEP;
 
196
                if (dn) {if (j          ) j--; else {dn=0;SLEEP;SLEEP;} } 
 
197
                else    {if (j<30-MINPWM) j++; else {dn=1;SLEEP;SLEEP;} }
 
198
      } break;
 
199
    #endif
 
200
 
 
201
    #ifdef STROBE
 
202
    case STROBE:  mypwm=255; while(1){ PWM=mypwm; _delay_ms(20); PWM=0; _delay_ms(60); } break; //strobe 12.5Hz  //+48
 
203
    #endif
 
204
 
 
205
    #ifdef BEACON
 
206
    case BEACON:  
 
207
      #ifdef BATTMON    
 
208
        adcread(); i=adcresult; while (i>BATTMON) {PWM=8; SLEEP;SLEEP; PWM=0; SLEEP; i-=5;}   SLEEP;SLEEP;SLEEP;
 
209
      #endif    
 
210
      mypwm=255; while(1){ PWM=mypwm; _delay_ms(20); PWM=0; i=70;do{SLEEP;}while(--i);  } break;  //beacon 10s //+48
 
211
    #endif
 
212
 
 
213
 
 
214
    default:   mypwm=pmode; while(1){PWM=mypwm;SLEEP;}  //all other: us as PWM value
 
215
 
 
216
  }//switch
 
217
  return 0;
 
218
}//main
 
219