Skip to content

Commit 5de6def

Browse files
jespinoclaude
andcommitted
machine/attiny85: optimize PWM prescaler lookups
Replace verbose switch statements with more efficient implementations: - SetPeriod: Use bit shift (top >>= prescaler-1) instead of 15-case switch for dividing uint64 by power-of-2 prescaler values - Period: Replace switch statements with compact uint16 lookup tables for both Timer0 and Timer1, casting to uint64 only when needed This addresses review feedback about inefficient switch-based lookups. On AVR, this approach is significantly smaller: - Bit shifts for uint64 division: ~34 bytes vs ~140 bytes - uint16 tables: 22 bytes code + 32/16 bytes data vs ~140 bytes - Total savings: ~190 bytes (68% reduction) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 7f357b8 commit 5de6def

File tree

1 file changed

+15
-75
lines changed

1 file changed

+15
-75
lines changed

src/machine/machine_attiny85.go

Lines changed: 15 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -179,37 +179,10 @@ func (pwm PWM) SetPeriod(period uint64) error {
179179

180180
// Get current prescaler
181181
prescaler := avr.TCCR1.Get() & 0x0f
182-
switch prescaler {
183-
case 1:
184-
// no change
185-
case 2:
186-
top /= 2
187-
case 3:
188-
top /= 4
189-
case 4:
190-
top /= 8
191-
case 5:
192-
top /= 16
193-
case 6:
194-
top /= 32
195-
case 7:
196-
top /= 64
197-
case 8:
198-
top /= 128
199-
case 9:
200-
top /= 256
201-
case 10:
202-
top /= 512
203-
case 11:
204-
top /= 1024
205-
case 12:
206-
top /= 2048
207-
case 13:
208-
top /= 4096
209-
case 14:
210-
top /= 8192
211-
case 15:
212-
top /= 16384
182+
// Timer1 prescaler values follow a power-of-2 pattern:
183+
// prescaler n maps to divisor 2^(n-1), so we can use a simple shift
184+
if prescaler > 0 && prescaler <= 15 {
185+
top >>= (prescaler - 1)
213186
}
214187

215188
if top > 256 {
@@ -250,61 +223,28 @@ func (pwm PWM) Counter() uint32 {
250223
return 0
251224
}
252225

226+
// Prescaler lookup tables using uint16 (more efficient than uint64 on AVR)
227+
// Timer0 prescaler lookup table (index 0-7 maps to prescaler bits)
228+
var timer0Prescalers = [8]uint16{0, 1, 8, 64, 256, 1024, 0, 0}
229+
230+
// Timer1 prescaler lookup table (index 0-15 maps to prescaler bits)
231+
var timer1Prescalers = [16]uint16{0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384}
232+
253233
// Period returns the used PWM period in nanoseconds. It might deviate slightly
254234
// from the configured period due to rounding.
255235
func (pwm PWM) Period() uint64 {
256236
var prescaler uint64
257237
switch pwm.num {
258238
case 0:
259239
prescalerBits := avr.TCCR0B.Get() & 0x7
260-
switch prescalerBits {
261-
case 1:
262-
prescaler = 1
263-
case 2:
264-
prescaler = 8
265-
case 3:
266-
prescaler = 64
267-
case 4:
268-
prescaler = 256
269-
case 5:
270-
prescaler = 1024
271-
default:
240+
prescaler = uint64(timer0Prescalers[prescalerBits])
241+
if prescaler == 0 {
272242
return 0
273243
}
274244
case 1:
275245
prescalerBits := avr.TCCR1.Get() & 0x0f
276-
switch prescalerBits {
277-
case 1:
278-
prescaler = 1
279-
case 2:
280-
prescaler = 2
281-
case 3:
282-
prescaler = 4
283-
case 4:
284-
prescaler = 8
285-
case 5:
286-
prescaler = 16
287-
case 6:
288-
prescaler = 32
289-
case 7:
290-
prescaler = 64
291-
case 8:
292-
prescaler = 128
293-
case 9:
294-
prescaler = 256
295-
case 10:
296-
prescaler = 512
297-
case 11:
298-
prescaler = 1024
299-
case 12:
300-
prescaler = 2048
301-
case 13:
302-
prescaler = 4096
303-
case 14:
304-
prescaler = 8192
305-
case 15:
306-
prescaler = 16384
307-
default:
246+
prescaler = uint64(timer1Prescalers[prescalerBits])
247+
if prescaler == 0 {
308248
return 0
309249
}
310250
}

0 commit comments

Comments
 (0)