Pārlūkot izejas kodu

picadae_cmd.py : changed serial output to show all received data in integer format.

ctrl/main.c : write commands now send as many data bytes as received rather than just 2.
tiny/main.c : Added timer0 and PCM1 options. Added table and EEPROM reading/writing.
tiny/Makefile: Enabled 'brown-out-detection'.
master
kevin.larke 4 gadus atpakaļ
vecāks
revīzija
ffd46bf3b6
4 mainītis faili ar 434 papildinājumiem un 99 dzēšanām
  1. 8
    4
      control/app/picadae_cmd.py
  2. 31
    14
      control/ctrl/main.c
  3. 1
    1
      control/tiny/Makefile
  4. 394
    80
      control/tiny/i2c_timer_pwm.c

+ 8
- 4
control/app/picadae_cmd.py Parādīt failu

@@ -152,7 +152,7 @@ class App:
152 152
         cmdD = {
153 153
             'p':{ 'reg':0, 'n':1, 'min':0, 'max':4 },       # timer pre-scalar: sets timer tick rate
154 154
             't':{ 'reg':1, 'n':2, 'min':0, 'max':10e7 },    # microseconds
155
-            'd':{ 'reg':3, 'n':1, 'min':0, 'max':100 },    # pwm duty cylce (0-100%)
155
+            'd':{ 'reg':3, 'n':1, 'min':0, 'max':100 },     # pwm duty cylce (0-100%)
156 156
             'f':{ 'reg':4, 'n':1, 'min':1, 'max':5 },       # pwm frequency divider 1=1,2=8,3=64,4=256,5=1024
157 157
             }
158 158
 
@@ -190,6 +190,7 @@ class App:
190 190
             
191 191
             coarse = int(value/(32*254))
192 192
             fine   = int((value - coarse*32*254)/32)
193
+            print(coarse,fine)
193 194
             dataL  = [ coarse, fine ]
194 195
 
195 196
         elif opcode == 'd':
@@ -272,7 +273,6 @@ class App:
272 273
                 
273 274
             op_byteN = len(dataL)
274 275
             
275
-
276 276
         # form the command into a byte array
277 277
         cmd_bV = bytearray( [ ord(op_code), i2c_addr, reg_addr, op_byteN ] + dataL )
278 278
         
@@ -293,7 +293,7 @@ class App:
293 293
             if (i):
294 294
                 s = sys.stdin.readline().strip()
295 295
                 
296
-                if s == 'quit':
296
+                if s == 'quit' or s == 'q':
297 297
                     break
298 298
                 
299 299
                 cmd_bV,err_msg = self.parse_cmd(s)
@@ -310,7 +310,11 @@ class App:
310 310
 
311 311
                 # if a serial msg was received
312 312
                 if msg is not None and msg[0] == DATA_MSG:
313
-                    print("ser:",msg[1],int(msg[1][0]))
313
+                    str = ""
314
+                    for i in range(len(msg[1])):
315
+                        str += "{} ".format(int(msg[1][i]))
316
+                        
317
+                    print("ser:",str)
314 318
             
315 319
             
316 320
         self.serialProc.quit()

+ 31
- 14
control/ctrl/main.c Parādīt failu

@@ -20,7 +20,7 @@ volatile int  ser_buf_i_idx = 0;  // receive buffer input index
20 20
 int           ser_buf_o_idx = 0;  // receive buffer output index
21 21
 
22 22
 // Receive buffer
23
-char buf[ SER_BUF_N ];
23
+char ser_buf[ SER_BUF_N ];
24 24
 
25 25
 
26 26
 void uart_init(void)
@@ -105,7 +105,7 @@ void i2c_init()
105 105
 ISR(USART_RX_vect)
106 106
 {
107 107
   // receive the incoming byte
108
-  buf[ ser_buf_i_idx ] = uart_getchar();
108
+  ser_buf[ ser_buf_i_idx ] = uart_getchar();
109 109
 
110 110
   // advance the buffer input index
111 111
   ser_buf_i_idx = (ser_buf_i_idx + 1) % SER_BUF_N;  
@@ -141,13 +141,16 @@ int main (void)
141 141
   const uint8_t kWaitFl       = 1;
142 142
   const uint8_t kSendStopFl   = 1;
143 143
   const uint8_t kNoSendStopFl = 0;
144
+  const uint8_t data_bufN     = 0xff;
144 145
   
145 146
   char    c;
146
-  uint8_t state = kWait_for_cmd;
147
-  char    cmd;
148
-  uint8_t i2c_addr;
149
-  uint8_t dev_reg_addr;
150
-  uint8_t op_byte_cnt;
147
+  uint8_t state = kWait_for_cmd;  // parser state
148
+  char    cmd;                    // 'r' or 'w'
149
+  uint8_t i2c_addr;               // remote i2c address
150
+  uint8_t dev_reg_addr;           // remote device register address
151
+  uint8_t op_byte_cnt;            // count of data bytes to send or recv
152
+  uint8_t data_buf[ data_bufN ];  // hold data during parsing
153
+  uint8_t data_buf_idx = 0;       // next avail slot in the data buffer
151 154
   
152 155
   cli();        // mask all interupts
153 156
 
@@ -173,14 +176,14 @@ int main (void)
173 176
     if( ser_buf_o_idx != ser_buf_i_idx )
174 177
     {
175 178
       // get the waiting byte
176
-      c = buf[ser_buf_o_idx];
179
+      c = ser_buf[ser_buf_o_idx];
177 180
 
178 181
       // advance the buffer output index
179 182
       ser_buf_o_idx = (ser_buf_o_idx+1) % SER_BUF_N;
180 183
 
181 184
       //  Serial Protocol
182
-      //  'r', reg-idx, cnt,                      -> i2c_read_from()
183
-      //  'w', reg-idx, cnt, value0, ... valueN   -> i2c_xmit()
185
+      //  'r', i2c-addr, reg-idx, cnt,                      -> i2c_read_from()
186
+      //  'w', i2c-addr, reg-idx, cnt, value0, ... valueN   -> i2c_xmit()
184 187
       
185 188
       switch(state)
186 189
       {
@@ -191,7 +194,7 @@ int main (void)
191 194
             state = kWait_for_i2c;
192 195
           }
193 196
           else
194
-            uart_putchar('E');
197
+            uart_putchar('E');  // indicate a protocol error
195 198
           break;
196 199
 
197 200
         case kWait_for_i2c:
@@ -215,16 +218,30 @@ int main (void)
215 218
           else
216 219
           {
217 220
             state = kWait_for_value;
221
+            data_buf[0] = dev_reg_addr; // make 'dev_reg_addr' the first data value to write
222
+            data_buf_idx = 1;           // 
223
+            op_byte_cnt += 1;           // incr op_byte_cnt to account for 'dev_reg_addr' as first byte
224
+              
218 225
           }
219 226
           break;
220 227
             
221 228
         case kWait_for_value:
229
+          if( data_buf_idx >= data_bufN )
222 230
           {
223
-            uint8_t buf[] = { dev_reg_addr, c };
224
-                      
225
-            i2c_xmit( I2C_REMOTE_ADDR, buf, 2, kSendStopFl);
231
+            uart_putchar('F'); // indicate a buffer overrun
226 232
             state = kWait_for_cmd;
227 233
           }
234
+          else
235
+          {
236
+            data_buf[ data_buf_idx++ ] = c;
237
+          
238
+            if(data_buf_idx == op_byte_cnt )
239
+            {
240
+              
241
+              i2c_xmit( I2C_REMOTE_ADDR, data_buf, op_byte_cnt, kSendStopFl);
242
+              state = kWait_for_cmd;
243
+            }
244
+          }
228 245
           break;
229 246
             
230 247
       }            

+ 1
- 1
control/tiny/Makefile Parādīt failu

@@ -22,7 +22,7 @@ all:
22 22
 	$(OBJ2HEX) -R .eeprom -O ihex $(TARGET) $(TARGET).hex
23 23
 
24 24
 burn:
25
-	$(AVRDUDE) -p $(MCU) -P $(TTY)  -C/etc/avrdude/avrdude.conf -v -c avrisp -b 19200 -U flash:w:$(TARGET).hex -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
25
+	$(AVRDUDE) -p $(MCU) -P $(TTY)  -C/etc/avrdude/avrdude.conf -v -c avrisp -b 19200 -U flash:w:$(TARGET).hex -U lfuse:w:0xe2:m -U hfuse:w:0xdd:m -U efuse:w:0xff:m
26 26
 clean:
27 27
 	rm -f *.hex *.obj *.o
28 28
 

+ 394
- 80
control/tiny/i2c_timer_pwm.c Parādīt failu

@@ -1,3 +1,15 @@
1
+/*                                    
2
+                                    AT TINY 85
3
+                                     +--\/--+
4
+                              RESET _| 1  8 |_ +5V
5
+             ~OC1B       HOLD  DDB3 _| 2  7 |_ SCL
6
+              OC1B      ONSET  DDB4 _| 3  6 |_ DDB1 LED
7
+                                GND _| 4  5 |_ SDA
8
+                                     +------+
9
+        * = Serial and/or programming pins on Arduino as ISP
10
+*/
11
+
12
+
1 13
 // This program acts as the device (slave) for the control program i2c/a2a/c_ctl
2 14
 #define F_CPU 8000000L
3 15
 #include <stdio.h>
@@ -7,123 +19,397 @@
7 19
 
8 20
 #include "usiTwiSlave.h"
9 21
 
22
+
10 23
 #define I2C_SLAVE_ADDRESS 0x8 // the 7-bit address (remember to change this when adapting this example)
11 24
 
12 25
 
13 26
 enum
14 27
 {
15
- kCS13_10_idx     = 0,  // Timer 1 Prescalar (CS13,CS12,CS11,CS10) from Table 12-5 pg 89 (0-15)  prescaler = pow(2,val-1), 0=stop,1=1,2=2,3=4,4=8,....14=8192,15=16384  pre_scaled_hz = clock_hz/value
16
- kTmr0_Coarse_idx = 1,  // count of times timer0 count to 255 before OCR1C is set to Tmr0_Fine
17
- kTmr0_Fine_idx   = 2,  // OCR1C timer match value
18
- kPWM_Duty_idx    = 3,  //
19
- kPWM_Freq_idx    = 4,  // 1-4 = clock divider=1=1,2=8,3=64,4=256,5=1024
28
+ kTmr0_Prescale_idx =  0,  // Timer 0 clock divider: 1=1,2=8,3=64,4=256,5=1024
29
+ kTmr0_Coarse_idx   =  1,  // 
30
+ kTmr0_Fine_idx     =  2,  //
31
+ kPWM0_Duty_idx     =  3,  //
32
+ kPWM0_Freq_idx     =  4,  // 1-4 = clock divider=1=1,2=8,3=64,4=256,5=1024 
33
+ kCS13_10_idx       =  5,  // Timer 1 Prescalar (CS13,CS12,CS11,CS10) from Table 12-5 pg 89 (0-15)  prescaler = pow(2,val-1), 0=stop,1=1,2=2,3=4,4=8,....14=8192,15=16384  pre_scaled_hz = clock_hz/value
34
+ kTmr1_Coarse_idx   =  6,  // count of times timer0 count to 255 before OCR1C is set to Tmr0_Fine
35
+ kTmr1_Fine_idx     =  7,  // OCR1C timer match value
36
+ kPWM1_Duty_idx     =  8,  //
37
+ kPWM1_Freq_idx     =  9,  // 
38
+ kTable_Addr_idx    = 10,  // Next table address to read/write 
39
+ kTable_Coarse_idx  = 11,  // Next table coarse value to read/write
40
+ kTable_Fine_idx    = 12,  // Next table fine value to read/write
41
+ kMax_idx
20 42
 };
21 43
 
44
+
22 45
 volatile uint8_t ctl_regs[] =
23 46
 {
24
-   9,    // 0  9=32 us period w/ 8Mhz clock (timer tick rate) 
25
- 123,    // 1 (0-255) Tmr0_Coarse count of times timer count to 255 before loading Tmr0_Minor for final count.
26
-   8,    // 2 (0-254) Tmr0_Fine OCR1C value on final phase before triggering timer
27
- 127,    // 3 (0-255) Duty cycle
28
- 4,      // 4 (1-4)   PWM Frequency (clock pre-scaler) 
47
+   4,    //  0 (1-5)    4=32us per tick
48
+ 123,    //  1 (0-255)  Timer 0 Coarse Value 
49
+   8,    //  2 (0-255)  Timer 0 Fine Value
50
+ 127,    //  3 (0-255) Duty cycle
51
+   4,    //  4 (1-4)   PWM Frequency (clock pre-scaler)   
52
+   9,    //  5  9=32 us period w/ 8Mhz clock (timer tick rate) 
53
+ 123,    //  6 (0-255) Tmr1_Coarse count of times timer count to 255 before loading Tmr0_Minor for final count.
54
+   8,    //  7 (0-254) Tmr1_Fine OCR1C value on final phase before triggering timer
55
+ 127,    //  8 (0-255) PWM1 Duty cycle
56
+ 254,    //  9 (0-255) PWM1 Frequency  (123 hz)
57
+   0,    // 10 (0-127) Next table addr to read/write
58
+   0,    // 11 (0-255) Next table coarse value to write
59
+   0,    // 12 (0-255) Next table fine value to write
29 60
 };
30 61
 
31
-// Tracks the current register pointer position
32
-volatile uint8_t reg_position = 0;
33
-const uint8_t reg_size = sizeof(ctl_regs);
62
+#define tableN 256
63
+uint8_t table[ tableN ];
64
+ 
65
+
66
+//------------------------------------------------------------------------------
67
+//------------------------------------------------------------------------------
68
+//------------------------------------------------------------------------------
69
+//
70
+// EEPROM
71
+//
72
+
73
+void EEPROM_write(uint8_t ucAddress, uint8_t ucData)
74
+{
75
+  // Wait for completion of previous write 
76
+  while(EECR & (1<<EEPE))
77
+  {}
78
+    
79
+  EECR = (0<<EEPM1)|(0<<EEPM0); // Set Programming mode   
80
+  EEAR = ucAddress;             // Set up address and data registers 
81
+  EEDR = ucData;  
82
+  EECR |= (1<<EEMPE);           // Write logical one to EEMPE 
83
+  EECR |= (1<<EEPE);            // Start eeprom write by setting EEPE 
84
+}
85
+
86
+
87
+uint8_t EEPROM_read(uint8_t ucAddress)
88
+{
89
+  // Wait for completion of previous write 
90
+  while(EECR & (1<<EEPE))
91
+  {}
92
+    
93
+  EEAR = ucAddress;  // Set up address register 
94
+  EECR |= (1<<EERE); // Start eeprom read by writing EERE 
95
+  return EEDR;       // Return data from data register 
96
+}
97
+
98
+//------------------------------------------------------------------------------
99
+//------------------------------------------------------------------------------
100
+//------------------------------------------------------------------------------
101
+//
102
+// Read/Write table
103
+//
104
+
105
+// To write table value 42 to 127 (coarse) 64 (fine)
106
+//
107
+// w 8 kTable_Addr_idx 42
108
+// w 8 kTable_Coarse_idx 127
109
+// w 8 kTable_fine_idx 64
110
+//
111
+// TO read table value 42
112
+// w 8 kTable_Addr_idx 42
113
+// r 8 kTable_Coarse_idx -> 127
114
+// r 8 kTable_Fine_idx   ->  64
115
+
116
+
117
+#define eeprom_addr( addr ) (kMax_idx + (addr))
118
+
119
+void table_write_cur_value( void )
120
+{
121
+  uint8_t tbl_addr = ctl_regs[ kTable_Addr_idx ] * 2;
122
+  
123
+  table[ tbl_addr+0 ] = ctl_regs[ kTable_Coarse_idx ];
124
+  table[ tbl_addr+1 ] = ctl_regs[ kTable_Fine_idx ];
125
+
126
+  EEPROM_write( eeprom_addr( tbl_addr+0 ), ctl_regs[ kTable_Coarse_idx ] );
127
+  EEPROM_write( eeprom_addr( tbl_addr+1 ), ctl_regs[ kTable_Fine_idx ]); 
128
+}
129
+
130
+void table_load( void )
131
+{
132
+  uint8_t i = 0;
133
+
134
+  for(; i<128; ++i)
135
+  {
136
+    uint8_t tbl_addr  = i*2;
137
+    table[tbl_addr+0] = EEPROM_read( eeprom_addr(tbl_addr+0) );
138
+    table[tbl_addr+1] = EEPROM_read( eeprom_addr(tbl_addr+1) );
139
+  }  
140
+}
141
+
142
+void restore_memory_from_eeprom( void )
143
+{
144
+  /*
145
+  uint8_t i;
146
+  for(i=0; i<kMax_idx; ++i)
147
+  {
148
+    ctl_regs[i] = EEPROM_read( eeprom_addr( i ) );
149
+  }
150
+  */
151
+  
152
+  table_load();
153
+}
154
+
155
+
156
+//------------------------------------------------------------------------------
157
+//------------------------------------------------------------------------------
158
+//------------------------------------------------------------------------------
159
+//
160
+// Timer0
161
+//
34 162
 
35
-volatile uint8_t tmr_state        = 0;    
36
-volatile uint8_t tmr_coarse_cur   = 0;
163
+volatile uint8_t tmr0_state        = 0;    // 0=disabled 1=coarse mode, 2=fine mode 
164
+volatile uint8_t tmr0_coarse_cur   = 0;
37 165
 
38
-void tmr_reset()
166
+// Use the current tmr0 ctl_reg[] values to set the timer to the starting state.
167
+void tmr0_reset()
39 168
 {
169
+  // if a coarse count exists then go into coarse mode 
40 170
   if( ctl_regs[kTmr0_Coarse_idx] > 0 )
41 171
   {
42
-    tmr_state = 1;
43
-    OCR1C     = 254;
172
+    tmr0_state = 1;
173
+    OCR0A      = 0xff;
44 174
   }
45
-  else
175
+  else // otherwise go into fine mode
46 176
   {
47
-    tmr_state = 2;
48
-    OCR1C     = ctl_regs[kTmr0_Fine_idx];
177
+    tmr0_state = 2;
178
+    OCR0A     = ctl_regs[kTmr0_Fine_idx];
49 179
   }
50 180
   
51
-  tmr_coarse_cur = 0;  
181
+  tmr0_coarse_cur = 0;  
52 182
 }
53 183
 
54
-ISR(TIMER1_OVF_vect)
184
+ISR(TIMER0_COMPA_vect)
55 185
 {
56
-  switch( tmr_state )
186
+  switch( tmr0_state )
57 187
   {
58 188
     case 0:
189
+      // disabled
59 190
       break;
60
-      
61
-    case 1:
62
-      if( ++tmr_coarse_cur >= ctl_regs[kTmr0_Coarse_idx] )
191
+
192
+    case 1: 
193
+      // coarse mode
194
+      if( ++tmr0_coarse_cur >= ctl_regs[kTmr0_Coarse_idx] )
63 195
       {
64
-        tmr_state  = 2;
65
-        OCR1C     = ctl_regs[kTmr0_Fine_idx];        
196
+        tmr0_state  = 2;
197
+        OCR0A     = ctl_regs[kTmr0_Fine_idx];        
66 198
       }
67 199
       break;
68
-      
200
+
69 201
     case 2:
70
-      PINB = _BV(PINB4) + _BV(PINB1);  // writes to PINB toggle the pins
202
+      // fine mode
203
+      PINB = _BV(PINB4);  // writes to PINB toggle the pins
71 204
 
72
-      tmr_reset();
205
+      tmr0_reset(); // restart the timer 
73 206
       break;
74 207
   }
75
-  
76
-  
77 208
 }
78 209
 
79 210
 
80
-void timer1_init()
211
+void timer0_init()
81 212
 {
82
-  TIMSK  &= ~_BV(TOIE1);    // Disable interrupt TIMER1_OVF
83
-  OCR1A   = 255;            // Set to anything greater than OCR1C (the counter never gets here.)
84
-  TCCR1  |= _BV(CTC1);      // Reset TCNT1 to 0 when TCNT1==OCR1C 
85
-  TCCR1  |= _BV(PWM1A);     // Enable PWM A
86
-  TCCR1  |= ctl_regs[kCS13_10_idx] & 0x0f;  // 
87
-  GTCCR  |= _BV(PSR1);      // Set the pre-scaler to the selected value
213
+  TIMSK  &= ~_BV(OCIE0A);    // Disable interrupt TIMER1_OVF
214
+  TCCR0A  |=  0x02;           // CTC mode
215
+  TCCR0B  |= ctl_regs[kTmr0_Prescale_idx]; // set the prescaler
88 216
 
89
-  tmr_reset();
217
+  GTCCR  |= _BV(PSR0);      // Set the pre-scaler to the selected value
90 218
   
91
-  TIMSK  |= _BV(TOIE1);     // Enable interrupt TIMER1_OVF
219
+  tmr0_reset();              // set the timers starting state
92 220
   
221
+  TIMSK  |= _BV(OCIE0A);     // Enable interrupt TIMER1_OVF  
222
+
93 223
 }
94 224
 
225
+
226
+//------------------------------------------------------------------------------
227
+//------------------------------------------------------------------------------
228
+//------------------------------------------------------------------------------
229
+//
230
+// PWM (Timer0)
231
+//
232
+
95 233
 void pwm0_update()
96 234
 {
97
-  OCR0B   = ctl_regs[kPWM_Duty_idx];  // 50% duty cycle
98
-  TCCR0B |= ctl_regs[kPWM_Freq_idx]; // PWM frequency pre-scaler
235
+  OCR0B   = ctl_regs[kPWM0_Duty_idx];  // 50% duty cycle
236
+  TCCR0B |= ctl_regs[kPWM0_Freq_idx]; // PWM frequency pre-scaler
99 237
 }
100 238
 
101 239
 void pwm0_init()
102 240
 {
103
-  //WGM[1:0] = 3 (TOP=255)
241
+  // WGM[1:0] = 3 (TOP=255)
104 242
   // OCR0B = duty cycle (0-100%)
105 243
   // COM0A[1:0] = 2 non-inverted
106 244
   //
107 245
 
108 246
   TCCR0A |=  0x20   + 3;    // 0x20=non-inverting 3=WGM bits Fast-PWM mode (0=Bot 255=Top)
109 247
   TCCR0B |=  0x00   + 4;    //                    3=256 pre-scaler  122Hz=1Mghz/(v*256) where v=64
248
+  
249
+  GTCCR  |= _BV(PSR0);      // Set the pre-scaler to the selected value
110 250
 
111 251
   pwm0_update();
252
+
253
+  
254
+  DDRB |= _BV(DDB1);    // set direction on 
255
+}
256
+
257
+
258
+
259
+//------------------------------------------------------------------------------
260
+//------------------------------------------------------------------------------
261
+//------------------------------------------------------------------------------
262
+//
263
+// Timer1
264
+//
265
+
266
+volatile uint8_t tmr1_state        = 0;    
267
+volatile uint8_t tmr1_coarse_cur   = 0;
268
+static   uint8_t tmr1_init_fl      = 0;
269
+
270
+void tmr1_reset()
271
+{
272
+  if( ctl_regs[kTmr1_Coarse_idx] > 0 )
273
+  {
274
+    tmr1_state = 1;
275
+    OCR1C     = 254;
276
+  }
277
+  else
278
+  {
279
+    tmr1_state = 2;
280
+    OCR1C     = ctl_regs[kTmr1_Fine_idx];
281
+  }
282
+  
283
+  tmr1_coarse_cur = 0;  
284
+}
285
+
286
+ISR(TIMER1_OVF_vect)
287
+{
288
+  if( !tmr1_init_fl )
289
+  {
290
+    PORTB |= _BV(PINB3);  // set PWM pin
291
+  }
292
+  else
293
+  {
294
+    switch( tmr1_state )
295
+    {
112 296
     
113
-  DDRB |= _BV(DDB1);    
297
+      case 0:
298
+        // disabled
299
+        break;
300
+
301
+      case 1:
302
+        // coarse mode
303
+        if( ++tmr1_coarse_cur >= ctl_regs[kTmr1_Coarse_idx] )
304
+        {
305
+          tmr1_state  = 2;
306
+          OCR1C     = ctl_regs[kTmr1_Fine_idx];        
307
+        }
308
+        break;
309
+
310
+      case 2:
311
+        // fine mode
312
+        PINB = _BV(PINB4);  // writes to PINB toggle the pins
313
+
314
+        tmr1_reset();
315
+        break;
316
+    }
317
+  } 
114 318
 }
115 319
 
320
+void timer1_init()
321
+{
322
+  TIMSK  &= ~_BV(TOIE1);    // Disable interrupt TIMER1_OVF
323
+  OCR1A   = 255;            // Set to anything greater than OCR1C (the counter never gets here.)
324
+  TCCR1  |= _BV(CTC1);      // Reset TCNT1 to 0 when TCNT1==OCR1C 
325
+  TCCR1  |= _BV(PWM1A);     // Enable PWM A (to generate overflow interrupts)
326
+  TCCR1  |= ctl_regs[kCS13_10_idx] & 0x0f;  // 
327
+  GTCCR  |= _BV(PSR1);      // Set the pre-scaler to the selected value
328
+
329
+  tmr1_reset();
330
+  tmr1_init_fl = 1;
331
+  TIMSK  |= _BV(TOIE1);     // Enable interrupt TIMER1_OVF  
332
+}
116 333
 
117
-/**
118
- * This is called for each read request we receive, never put more
119
- * than one byte of data (with TinyWireS.send) to the send-buffer when
120
- * using this callback
121
- */
334
+//------------------------------------------------------------------------------
335
+//------------------------------------------------------------------------------
336
+//------------------------------------------------------------------------------
337
+//
338
+// PWM1
339
+//
340
+// PWM is optimized to use pins OC1A ,~OC1A, OC1B, ~OC1B but this code
341
+// but since these pins are not available this code uses
342
+// ISR's to redirect the output to PIN3
343
+
344
+void pwm1_update()
345
+{
346
+  OCR1B   = ctl_regs[kPWM1_Duty_idx]; // control duty cycle
347
+  OCR1C   = ctl_regs[kPWM1_Freq_idx]; // PWM frequency pre-scaler
348
+}
349
+
350
+ISR(TIMER1_COMPB_vect)
351
+{
352
+  PORTB &= ~(_BV(PINB3)); // clear PWM pin
353
+}
354
+
355
+
356
+void pwm1_init()
357
+{
358
+  TIMSK  &= ~(_BV(OCIE1B) + _BV(TOIE1));    // Disable interrupts
359
+  
360
+  DDRB   |=  _BV(DDB3);  // setup PB3 as output  
361
+
362
+  // set on TCNT1 == 0     // happens when TCNT1 matches OCR1C
363
+  // clr on OCR1B == TCNT  // happens when TCNT1 matches OCR1B
364
+  //                       // COM1B1=1 COM1B0=0 (enable output on ~OC1B)
365
+  TCCR1  |= 9;             // 32us period (256 divider) prescaler
366
+  GTCCR  |= _BV(PWM1B);    // Enable PWM B and disconnect output pins
367
+  GTCCR  |= _BV(PSR1);     // Set the pre-scaler to the selected value
368
+
369
+  pwm1_update();
370
+
371
+  TIMSK  |= _BV(OCIE1B) + _BV(TOIE1);    // Enable interrupts
372
+
373
+
374
+  
375
+}
376
+
377
+//------------------------------------------------------------------------------
378
+//------------------------------------------------------------------------------
379
+//------------------------------------------------------------------------------
380
+
381
+// Tracks the current register pointer position
382
+volatile uint8_t reg_position = 0;
383
+const uint8_t    reg_size = sizeof(ctl_regs);
384
+
385
+//
386
+// Read Request Handler
387
+//
388
+// This is called for each read request we receive, never put more
389
+// than one byte of data (with TinyWireS.send) to the send-buffer when
390
+// using this callback
391
+//
122 392
 void on_request()
123 393
 {
124
-  // read and transmit the requestd position
125
-  usiTwiTransmitByte(ctl_regs[reg_position]);
394
+  uint8_t val = 0;
395
+  
396
+  switch( reg_position )
397
+  {
398
+    case kTable_Coarse_idx:
399
+      val = table[ ctl_regs[kTable_Addr_idx]*2 + 0 ];      
400
+      break;
401
+
402
+    case kTable_Fine_idx:
403
+      val = table[ ctl_regs[kTable_Addr_idx]*2 + 1 ];
404
+      break;
405
+      
406
+    default:
407
+      // read and transmit the requestd position
408
+      val = ctl_regs[reg_position];
126 409
 
410
+  }
411
+  
412
+  usiTwiTransmitByte(val);
127 413
   
128 414
   // Increment the reg position on each read, and loop back to zero
129 415
   reg_position++;
@@ -135,14 +421,14 @@ void on_request()
135 421
 }
136 422
 
137 423
 
138
-/**
139
- * The I2C data received -handler
140
- *
141
- * This needs to complete before the next incoming transaction (start,
142
- * data, restart/stop) on the bus does so be quick, set flags for long
143
- * running tasks to be called from the mainloop instead of running
144
- * them directly,
145
- */
424
+//
425
+// The I2C data received -handler
426
+//
427
+// This needs to complete before the next incoming transaction (start,
428
+// data, restart/stop) on the bus does so be quick, set flags for long
429
+// running tasks to be called from the mainloop instead of running
430
+// them directly,
431
+//
146 432
 
147 433
 void on_receive( uint8_t byteN )
148 434
 {
@@ -174,21 +460,45 @@ void on_receive( uint8_t byteN )
174 460
     // pointer is now pointing to the first byte to write to
175 461
     while(byteN--)
176 462
     {
177
-        ctl_regs[reg_position] = usiTwiReceiveByte();
178
-
179
-        if( kCS13_10_idx <= reg_position && reg_position <= kTmr0_Fine_idx )
180
-          timer1_init();
463
+      // write the value
464
+      ctl_regs[reg_position] = usiTwiReceiveByte();
465
+
466
+      // Set timer 1
467
+      if( kTmr0_Prescale_idx <= reg_position && reg_position <= kTmr0_Fine_idx )
468
+      { timer0_init(); }
469
+      else
470
+
471
+          
472
+        // Set PWM 0
473
+        if( kPWM0_Duty_idx <= reg_position && reg_position <= kPWM0_Freq_idx )
474
+        { pwm0_update(); }
181 475
         else
182
-          if( kPWM_Duty_idx <= reg_position && reg_position <= kPWM_Freq_idx )
183
-            pwm0_update();
476
+        
477
+          // Set timer 1
478
+          if( kCS13_10_idx <= reg_position && reg_position <= kTmr1_Fine_idx )
479
+          { timer1_init(); }
480
+          else
481
+
482
+            // Set PWM 1
483
+            if( kPWM1_Duty_idx <= reg_position && reg_position <= kPWM1_Freq_idx )
484
+            { pwm1_update(); }
485
+            else
486
+          
487
+
488
+              // Write table
489
+              if( reg_position == kTable_Fine_idx )
490
+              { table_write_cur_value(); }
491
+        
492
+      reg_position++;
493
+        
494
+      if (reg_position >= reg_size)
495
+      {
496
+        reg_position = 0;
497
+      }
184 498
 
185 499
         
186
-        reg_position++;
187
-        if (reg_position >= reg_size)
188
-        {
189
-            reg_position = 0;
190
-        }
191 500
     }
501
+
192 502
   
193 503
 }
194 504
 
@@ -197,16 +507,20 @@ void on_receive( uint8_t byteN )
197 507
 int main(void)
198 508
 {
199 509
   cli();        // mask all interupts
200
-    
201
-  DDRB  |= _BV(DDB4) + _BV(DDB1);  // setup PB4 as output
202
-  PORTB &= ~(_BV(PINB4) + _BV(PINB1));
203 510
 
204
-  timer1_init();
205
-  pwm0_init();
511
+
512
+  restore_memory_from_eeprom();
513
+  
514
+  DDRB  |=   _BV(DDB4)  + _BV(DDB3)  + _BV(DDB1);  // setup PB4,PB3,PB1 as output  
515
+  PORTB &= ~(_BV(PINB4) + _BV(PINB3) + _BV(PINB1)); // clear output pins
516
+
517
+  
518
+  timer0_init();
519
+  pwm1_init();
206 520
   
207 521
   // setup i2c library
208
-  usi_onReceiverPtr = on_receive; //on_receive;
209
-  usi_onRequestPtr = on_request;
522
+  usi_onReceiverPtr = on_receive; 
523
+  usi_onRequestPtr  = on_request;
210 524
   usiTwiSlaveInit(I2C_SLAVE_ADDRESS);
211 525
   
212 526
   sei();

Notiek ielāde…
Atcelt
Saglabāt