github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_atmega1280.go (about) 1 //go:build avr && atmega1280 2 3 package machine 4 5 import ( 6 "device/avr" 7 "runtime/interrupt" 8 "runtime/volatile" 9 ) 10 11 const irq_USART0_RX = avr.IRQ_USART0_RX 12 13 const ( 14 portA Pin = iota * 8 15 portB 16 portC 17 portD 18 portE 19 portF 20 portG 21 portH 22 portJ 23 portK 24 portL 25 ) 26 27 const ( 28 PA0 = portA + 0 29 PA1 = portA + 1 30 PA2 = portA + 2 31 PA3 = portA + 3 32 PA4 = portA + 4 33 PA5 = portA + 5 34 PA6 = portA + 6 35 PA7 = portA + 7 36 PB0 = portB + 0 37 PB1 = portB + 1 38 PB2 = portB + 2 39 PB3 = portB + 3 40 PB4 = portB + 4 // peripherals: Timer2 channel A 41 PB5 = portB + 5 // peripherals: Timer1 channel A 42 PB6 = portB + 6 // peripherals: Timer1 channel B 43 PB7 = portB + 7 // peripherals: Timer0 channel A 44 PC0 = portC + 0 45 PC1 = portC + 1 46 PC2 = portC + 2 47 PC3 = portC + 3 48 PC4 = portC + 4 49 PC5 = portC + 5 50 PC6 = portC + 6 51 PC7 = portC + 7 52 PD0 = portD + 0 53 PD1 = portD + 1 54 PD2 = portD + 2 55 PD3 = portD + 3 56 PD7 = portD + 7 57 PE0 = portE + 0 58 PE1 = portE + 1 59 PE3 = portE + 3 // peripherals: Timer3 channel A 60 PE4 = portE + 4 // peripherals: Timer3 channel B 61 PE5 = portE + 5 // peripherals: Timer3 channel C 62 PE6 = portE + 6 63 PF0 = portF + 0 64 PF1 = portF + 1 65 PF2 = portF + 2 66 PF3 = portF + 3 67 PF4 = portF + 4 68 PF5 = portF + 5 69 PF6 = portF + 6 70 PF7 = portF + 7 71 PG0 = portG + 0 72 PG1 = portG + 1 73 PG2 = portG + 2 74 PG5 = portG + 5 // peripherals: Timer0 channel B 75 PH0 = portH + 0 76 PH1 = portH + 1 77 PH3 = portH + 3 // peripherals: Timer4 channel A 78 PH4 = portH + 4 // peripherals: Timer4 channel B 79 PH5 = portH + 5 // peripherals: Timer4 channel C 80 PH6 = portH + 6 // peripherals: Timer0 channel B 81 PJ0 = portJ + 0 82 PJ1 = portJ + 1 83 PK0 = portK + 0 84 PK1 = portK + 1 85 PK2 = portK + 2 86 PK3 = portK + 3 87 PK4 = portK + 4 88 PK5 = portK + 5 89 PK6 = portK + 6 90 PK7 = portK + 7 91 PL0 = portL + 0 92 PL1 = portL + 1 93 PL2 = portL + 2 94 PL3 = portL + 3 // peripherals: Timer5 channel A 95 PL4 = portL + 4 // peripherals: Timer5 channel B 96 PL5 = portL + 5 // peripherals: Timer5 channel C 97 PL6 = portL + 6 98 PL7 = portL + 7 99 ) 100 101 // getPortMask returns the PORTx register and mask for the pin. 102 func (p Pin) getPortMask() (*volatile.Register8, uint8) { 103 switch { 104 case p >= PA0 && p <= PA7: 105 return avr.PORTA, 1 << uint8(p-portA) 106 case p >= PB0 && p <= PB7: 107 return avr.PORTB, 1 << uint8(p-portB) 108 case p >= PC0 && p <= PC7: 109 return avr.PORTC, 1 << uint8(p-portC) 110 case p >= PD0 && p <= PD7: 111 return avr.PORTD, 1 << uint8(p-portD) 112 case p >= PE0 && p <= PE6: 113 return avr.PORTE, 1 << uint8(p-portE) 114 case p >= PF0 && p <= PF7: 115 return avr.PORTF, 1 << uint8(p-portF) 116 case p >= PG0 && p <= PG5: 117 return avr.PORTG, 1 << uint8(p-portG) 118 case p >= PH0 && p <= PH6: 119 return avr.PORTH, 1 << uint8(p-portH) 120 case p >= PJ0 && p <= PJ1: 121 return avr.PORTJ, 1 << uint8(p-portJ) 122 case p >= PK0 && p <= PK7: 123 return avr.PORTK, 1 << uint8(p-portK) 124 case p >= PL0 && p <= PL7: 125 return avr.PORTL, 1 << uint8(p-portL) 126 default: 127 return avr.PORTA, 255 128 } 129 } 130 131 // PWM is one PWM peripheral, which consists of a counter and two output 132 // channels (that can be connected to two fixed pins). You can set the frequency 133 // using SetPeriod, but only for all the channels in this PWM peripheral at 134 // once. 135 type PWM struct { 136 num uint8 137 } 138 139 var ( 140 Timer0 = PWM{0} // 8 bit timer for PB7 and PG5 141 Timer1 = PWM{1} // 16 bit timer for PB5 and PB6 142 Timer2 = PWM{2} // 8 bit timer for PB4 and PH6 143 Timer3 = PWM{3} // 16 bit timer for PE3, PE4 and PE5 144 Timer4 = PWM{4} // 16 bit timer for PH3, PH4 and PH5 145 Timer5 = PWM{5} // 16 bit timer for PL3, PL4 and PL5 146 ) 147 148 // Configure enables and configures this PWM. 149 // 150 // For the two 8 bit timers, there is only a limited number of periods 151 // available, namely the CPU frequency divided by 256 and again divided by 1, 8, 152 // 64, 256, or 1024. For a MCU running at 16MHz, this would be a period of 16µs, 153 // 128µs, 1024µs, 4096µs, or 16384µs. 154 func (pwm PWM) Configure(config PWMConfig) error { 155 156 switch pwm.num { 157 case 0, 2: // 8-bit timers (Timer/counter 0 and Timer/counter 2) 158 // Calculate the timer prescaler. 159 // While we could configure a flexible top, that would sacrifice one of 160 // the PWM output compare registers and thus a PWM channel. I've chosen 161 // to instead limit this timer to a fixed number of frequencies. 162 var prescaler uint8 163 switch config.Period { 164 case 0, (uint64(1e9) * 256 * 1) / uint64(CPUFrequency()): 165 prescaler = 1 166 case (uint64(1e9) * 256 * 8) / uint64(CPUFrequency()): 167 prescaler = 2 168 case (uint64(1e9) * 256 * 64) / uint64(CPUFrequency()): 169 prescaler = 3 170 case (uint64(1e9) * 256 * 256) / uint64(CPUFrequency()): 171 prescaler = 4 172 case (uint64(1e9) * 256 * 1024) / uint64(CPUFrequency()): 173 prescaler = 5 174 default: 175 return ErrPWMPeriodTooLong 176 } 177 178 if pwm.num == 0 { 179 avr.TCCR0B.Set(prescaler) 180 // Set the PWM mode to fast PWM (mode = 3). 181 avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01) 182 // monotonic timer is using the same time as PWM:0 183 // we must adust internal settings of monotonic timer when PWM:0 settings changed 184 adjustMonotonicTimer() 185 } else { 186 avr.TCCR2B.Set(prescaler) 187 // Set the PWM mode to fast PWM (mode = 3). 188 avr.TCCR2A.Set(avr.TCCR2A_WGM20 | avr.TCCR2A_WGM21) 189 } 190 case 1, 3, 4, 5: 191 // The top value is the number of PWM ticks a PWM period takes. It is 192 // initially picked assuming an unlimited counter top and no PWM 193 // prescaler. 194 var top uint64 195 if config.Period == 0 { 196 // Use a top appropriate for LEDs. Picking a relatively low period 197 // here (0xff) for consistency with the other timers. 198 top = 0xff 199 } else { 200 // The formula below calculates the following formula, optimized: 201 // top = period * (CPUFrequency() / 1e9) 202 // By dividing the CPU frequency first (an operation that is easily 203 // optimized away) the period has less chance of overflowing. 204 top = config.Period * (uint64(CPUFrequency()) / 1000000) / 1000 205 } 206 207 // The ideal PWM period may be larger than would fit in the PWM counter, 208 // which is 16 bits (see maxTop). Therefore, try to make the PWM clock 209 // speed lower with a prescaler to make the top value fit the maximum 210 // top value. 211 212 const maxTop = 0x10000 213 var prescalingTop uint8 214 switch { 215 case top <= maxTop: 216 prescalingTop = 3<<3 | 1 // no prescaling 217 case top/8 <= maxTop: 218 prescalingTop = 3<<3 | 2 // divide by 8 219 top /= 8 220 case top/64 <= maxTop: 221 prescalingTop = 3<<3 | 3 // divide by 64 222 top /= 64 223 case top/256 <= maxTop: 224 prescalingTop = 3<<3 | 4 // divide by 256 225 top /= 256 226 case top/1024 <= maxTop: 227 prescalingTop = 3<<3 | 5 // divide by 1024 228 top /= 1024 229 default: 230 return ErrPWMPeriodTooLong 231 } 232 233 // A top of 0x10000 is at 100% duty cycle. Subtract one because the 234 // counter counts from 0, not 1 (avoiding an off-by-one). 235 top -= 1 236 237 switch pwm.num { 238 case 1: 239 avr.TCCR1A.Set(avr.TCCR1A_WGM11) 240 avr.TCCR1B.Set(prescalingTop) 241 avr.ICR1H.Set(uint8(top >> 8)) 242 avr.ICR1L.Set(uint8(top)) 243 case 3: 244 avr.TCCR3A.Set(avr.TCCR3A_WGM31) 245 avr.TCCR3B.Set(prescalingTop) 246 avr.ICR3H.Set(uint8(top >> 8)) 247 avr.ICR3L.Set(uint8(top)) 248 case 4: 249 avr.TCCR4A.Set(avr.TCCR4A_WGM41) 250 avr.TCCR4B.Set(prescalingTop) 251 avr.ICR4H.Set(uint8(top >> 8)) 252 avr.ICR4L.Set(uint8(top)) 253 case 5: 254 avr.TCCR5A.Set(avr.TCCR5A_WGM51) 255 avr.TCCR5B.Set(prescalingTop) 256 avr.ICR5H.Set(uint8(top >> 8)) 257 avr.ICR5L.Set(uint8(top)) 258 } 259 } 260 return nil 261 } 262 263 // SetPeriod updates the period of this PWM peripheral. 264 // To set a particular frequency, use the following formula: 265 // 266 // period = 1e9 / frequency 267 // 268 // If you use a period of 0, a period that works well for LEDs will be picked. 269 // 270 // SetPeriod will not change the prescaler, but also won't change the current 271 // value in any of the channels. This means that you may need to update the 272 // value for the particular channel. 273 // 274 // Note that you cannot pick any arbitrary period after the PWM peripheral has 275 // been configured. If you want to switch between frequencies, pick the lowest 276 // frequency (longest period) once when calling Configure and adjust the 277 // frequency here as needed. 278 func (pwm PWM) SetPeriod(period uint64) error { 279 if pwm.num == 0 || pwm.num == 2 { 280 return ErrPWMPeriodTooLong // TODO better error message 281 } 282 283 // The top value is the number of PWM ticks a PWM period takes. It is 284 // initially picked assuming an unlimited counter top and no PWM 285 // prescaler. 286 var top uint64 287 if period == 0 { 288 // Use a top appropriate for LEDs. Picking a relatively low period 289 // here (0xff) for consistency with the other timers. 290 top = 0xff 291 } else { 292 // The formula below calculates the following formula, optimized: 293 // top = period * (CPUFrequency() / 1e9) 294 // By dividing the CPU frequency first (an operation that is easily 295 // optimized away) the period has less chance of overflowing. 296 top = period * (uint64(CPUFrequency()) / 1000000) / 1000 297 } 298 299 var prescaler uint8 300 301 switch pwm.num { 302 case 1: 303 prescaler = avr.TCCR1B.Get() & 0x7 304 case 3: 305 prescaler = avr.TCCR3B.Get() & 0x7 306 case 4: 307 prescaler = avr.TCCR4B.Get() & 0x7 308 case 5: 309 prescaler = avr.TCCR5B.Get() & 0x7 310 } 311 312 switch prescaler { 313 case 1: 314 top /= 1 315 case 2: 316 top /= 8 317 case 3: 318 top /= 64 319 case 4: 320 top /= 256 321 case 5: 322 top /= 1024 323 } 324 325 // A top of 0x10000 is at 100% duty cycle. Subtract one because the counter 326 // counts from 0, not 1 (avoiding an off-by-one). 327 top -= 1 328 329 if top > 0xffff { 330 return ErrPWMPeriodTooLong 331 } 332 333 switch pwm.num { 334 case 1: 335 // Warning: this change is not atomic! 336 avr.ICR1H.Set(uint8(top >> 8)) 337 avr.ICR1L.Set(uint8(top)) 338 339 // ... and because of that, set the counter back to zero to avoid most of 340 // the effects of this non-atomicity. 341 avr.TCNT1H.Set(0) 342 avr.TCNT1L.Set(0) 343 case 3: 344 // Warning: this change is not atomic! 345 avr.ICR3H.Set(uint8(top >> 8)) 346 avr.ICR3L.Set(uint8(top)) 347 348 // ... and because of that, set the counter back to zero to avoid most of 349 // the effects of this non-atomicity. 350 avr.TCNT3H.Set(0) 351 avr.TCNT3L.Set(0) 352 case 4: 353 // Warning: this change is not atomic! 354 avr.ICR4H.Set(uint8(top >> 8)) 355 avr.ICR4L.Set(uint8(top)) 356 357 // ... and because of that, set the counter back to zero to avoid most of 358 // the effects of this non-atomicity. 359 avr.TCNT4H.Set(0) 360 avr.TCNT4L.Set(0) 361 case 5: 362 // Warning: this change is not atomic! 363 avr.ICR5H.Set(uint8(top >> 8)) 364 avr.ICR5L.Set(uint8(top)) 365 366 // ... and because of that, set the counter back to zero to avoid most of 367 // the effects of this non-atomicity. 368 avr.TCNT5H.Set(0) 369 avr.TCNT5L.Set(0) 370 } 371 372 return nil 373 } 374 375 // Top returns the current counter top, for use in duty cycle calculation. It 376 // will only change with a call to Configure or SetPeriod, otherwise it is 377 // constant. 378 // 379 // The value returned here is hardware dependent. In general, it's best to treat 380 // it as an opaque value that can be divided by some number and passed to Set 381 // (see Set documentation for more information). 382 func (pwm PWM) Top() uint32 { 383 switch pwm.num { 384 case 1: 385 // Timer 1 has a configurable top value. 386 low := avr.ICR1L.Get() 387 high := avr.ICR1H.Get() 388 return uint32(high)<<8 | uint32(low) + 1 389 case 3: 390 // Timer 3 has a configurable top value. 391 low := avr.ICR3L.Get() 392 high := avr.ICR3H.Get() 393 return uint32(high)<<8 | uint32(low) + 1 394 case 4: 395 // Timer 4 has a configurable top value. 396 low := avr.ICR4L.Get() 397 high := avr.ICR4H.Get() 398 return uint32(high)<<8 | uint32(low) + 1 399 case 5: 400 // Timer 5 has a configurable top value. 401 low := avr.ICR5L.Get() 402 high := avr.ICR5H.Get() 403 return uint32(high)<<8 | uint32(low) + 1 404 } 405 406 // Other timers go from 0 to 0xff (0x100 or 256 in total). 407 return 256 408 } 409 410 // Counter returns the current counter value of the timer in this PWM 411 // peripheral. It may be useful for debugging. 412 func (pwm PWM) Counter() uint32 { 413 switch pwm.num { 414 case 0: 415 return uint32(avr.TCNT0.Get()) 416 case 1: 417 mask := interrupt.Disable() 418 low := avr.TCNT1L.Get() 419 high := avr.TCNT1H.Get() 420 interrupt.Restore(mask) 421 return uint32(high)<<8 | uint32(low) 422 case 2: 423 return uint32(avr.TCNT2.Get()) 424 case 3: 425 mask := interrupt.Disable() 426 low := avr.TCNT3L.Get() 427 high := avr.TCNT3H.Get() 428 interrupt.Restore(mask) 429 return uint32(high)<<8 | uint32(low) 430 case 4: 431 mask := interrupt.Disable() 432 low := avr.TCNT4L.Get() 433 high := avr.TCNT4H.Get() 434 interrupt.Restore(mask) 435 return uint32(high)<<8 | uint32(low) 436 case 5: 437 mask := interrupt.Disable() 438 low := avr.TCNT5L.Get() 439 high := avr.TCNT5H.Get() 440 interrupt.Restore(mask) 441 return uint32(high)<<8 | uint32(low) 442 } 443 444 // Unknown PWM. 445 return 0 446 } 447 448 // Period returns the used PWM period in nanoseconds. It might deviate slightly 449 // from the configured period due to rounding. 450 func (pwm PWM) Period() uint64 { 451 var prescaler uint8 452 switch pwm.num { 453 case 0: 454 prescaler = avr.TCCR0B.Get() & 0x7 455 case 1: 456 prescaler = avr.TCCR1B.Get() & 0x7 457 case 2: 458 prescaler = avr.TCCR2B.Get() & 0x7 459 case 3: 460 prescaler = avr.TCCR3B.Get() & 0x7 461 case 4: 462 prescaler = avr.TCCR4B.Get() & 0x7 463 case 5: 464 prescaler = avr.TCCR5B.Get() & 0x7 465 } 466 top := uint64(pwm.Top()) 467 switch prescaler { 468 case 1: // prescaler 1 469 return 1 * top * 1000 / uint64(CPUFrequency()/1e6) 470 case 2: // prescaler 8 471 return 8 * top * 1000 / uint64(CPUFrequency()/1e6) 472 case 3: // prescaler 64 473 return 64 * top * 1000 / uint64(CPUFrequency()/1e6) 474 case 4: // prescaler 256 475 return 256 * top * 1000 / uint64(CPUFrequency()/1e6) 476 case 5: // prescaler 1024 477 return 1024 * top * 1000 / uint64(CPUFrequency()/1e6) 478 default: // unknown clock source 479 return 0 480 } 481 } 482 483 // Channel returns a PWM channel for the given pin. 484 func (pwm PWM) Channel(pin Pin) (uint8, error) { 485 pin.Configure(PinConfig{Mode: PinOutput}) 486 pin.Low() 487 switch pwm.num { 488 case 0: 489 switch pin { 490 case PB7: // channel A 491 avr.TCCR0A.SetBits(avr.TCCR0A_COM0A1) 492 return 0, nil 493 case PG5: // channel B 494 avr.TCCR0A.SetBits(avr.TCCR0A_COM0B1) 495 return 1, nil 496 } 497 case 1: 498 switch pin { 499 case PB5: // channel A 500 avr.TCCR1A.SetBits(avr.TCCR1A_COM1A1) 501 return 0, nil 502 case PB6: // channel B 503 avr.TCCR1A.SetBits(avr.TCCR1A_COM1B1) 504 return 1, nil 505 } 506 case 2: 507 switch pin { 508 case PB4: // channel A 509 avr.TCCR2A.SetBits(avr.TCCR2A_COM2A1) 510 return 0, nil 511 case PH6: // channel B 512 avr.TCCR2A.SetBits(avr.TCCR2A_COM2B1) 513 return 1, nil 514 } 515 case 3: 516 switch pin { 517 case PE3: // channel A 518 avr.TCCR3A.SetBits(avr.TCCR3A_COM3A1) 519 return 0, nil 520 case PE4: //channel B 521 avr.TCCR3A.SetBits(avr.TCCR3A_COM3B1) 522 return 1, nil 523 case PE5: //channel C 524 avr.TCCR3A.SetBits(avr.TCCR3A_COM3C1) 525 return 2, nil 526 } 527 case 4: 528 switch pin { 529 case PH3: // channel A 530 avr.TCCR4A.SetBits(avr.TCCR4A_COM4A1) 531 return 0, nil 532 case PH4: //channel B 533 avr.TCCR4A.SetBits(avr.TCCR4A_COM4B1) 534 return 1, nil 535 case PH5: //channel C 536 avr.TCCR4A.SetBits(avr.TCCR4A_COM4C1) 537 return 2, nil 538 } 539 case 5: 540 switch pin { 541 case PL3: // channel A 542 avr.TCCR5A.SetBits(avr.TCCR5A_COM5A1) 543 return 0, nil 544 case PL4: //channel B 545 avr.TCCR5A.SetBits(avr.TCCR5A_COM5B1) 546 return 1, nil 547 case PL5: //channel C 548 avr.TCCR5A.SetBits(avr.TCCR5A_COM5C1) 549 return 2, nil 550 } 551 } 552 return 0, ErrInvalidOutputPin 553 } 554 555 // SetInverting sets whether to invert the output of this channel. 556 // Without inverting, a 25% duty cycle would mean the output is high for 25% of 557 // the time and low for the rest. Inverting flips the output as if a NOT gate 558 // was placed at the output, meaning that the output would be 25% low and 75% 559 // high with a duty cycle of 25%. 560 // 561 // Note: the invert state may not be applied on the AVR until the next call to 562 // ch.Set(). 563 func (pwm PWM) SetInverting(channel uint8, inverting bool) { 564 switch pwm.num { 565 case 0: 566 switch channel { 567 case 0: // channel A, PB7 568 if inverting { 569 avr.PORTB.SetBits(1 << 7) // PB7 high 570 avr.TCCR0A.SetBits(avr.TCCR0A_COM0A0) 571 } else { 572 avr.PORTB.ClearBits(1 << 7) // PB7 low 573 avr.TCCR0A.ClearBits(avr.TCCR0A_COM0A0) 574 } 575 case 1: // channel B, PG5 576 if inverting { 577 avr.PORTG.SetBits(1 << 5) // PG5 high 578 avr.TCCR0A.SetBits(avr.TCCR0A_COM0B0) 579 } else { 580 avr.PORTG.ClearBits(1 << 5) // PG5 low 581 avr.TCCR0A.ClearBits(avr.TCCR0A_COM0B0) 582 } 583 } 584 case 1: 585 // Note: the COM1A0/COM1B0 bit is not set with the configuration below. 586 // It will be set the following call to Set(), however. 587 switch channel { 588 case 0: // channel A, PB5 589 if inverting { 590 avr.PORTB.SetBits(1 << 5) // PB5 high 591 } else { 592 avr.PORTB.ClearBits(1 << 5) // PB5 low 593 } 594 case 1: // channel B, PB6 595 if inverting { 596 avr.PORTB.SetBits(1 << 6) // PB6 high 597 } else { 598 avr.PORTB.ClearBits(1 << 6) // PB6 low 599 } 600 } 601 case 2: 602 switch channel { 603 case 0: // channel A, PB4 604 if inverting { 605 avr.PORTB.SetBits(1 << 4) // PB4 high 606 avr.TCCR2A.SetBits(avr.TCCR2A_COM2A0) 607 } else { 608 avr.PORTB.ClearBits(1 << 4) // PB4 low 609 avr.TCCR2A.ClearBits(avr.TCCR2A_COM2A0) 610 } 611 case 1: // channel B, PH6 612 if inverting { 613 avr.PORTH.SetBits(1 << 6) // PH6 high 614 avr.TCCR2A.SetBits(avr.TCCR2A_COM2B0) 615 } else { 616 avr.PORTH.ClearBits(1 << 6) // PH6 low 617 avr.TCCR2A.ClearBits(avr.TCCR2A_COM2B0) 618 } 619 } 620 case 3: 621 // Note: the COM3A0/COM3B0 bit is not set with the configuration below. 622 // It will be set the following call to Set(), however. 623 switch channel { 624 case 0: // channel A, PE3 625 if inverting { 626 avr.PORTE.SetBits(1 << 3) // PE3 high 627 } else { 628 avr.PORTE.ClearBits(1 << 3) // PE3 low 629 } 630 case 1: // channel B, PE4 631 if inverting { 632 avr.PORTE.SetBits(1 << 4) // PE4 high 633 } else { 634 avr.PORTE.ClearBits(1 << 4) // PE4 low 635 } 636 case 2: // channel C, PE5 637 if inverting { 638 avr.PORTE.SetBits(1 << 5) // PE4 high 639 } else { 640 avr.PORTE.ClearBits(1 << 5) // PE4 low 641 } 642 } 643 case 4: 644 // Note: the COM3A0/COM3B0 bit is not set with the configuration below. 645 // It will be set the following call to Set(), however. 646 switch channel { 647 case 0: // channel A, PH3 648 if inverting { 649 avr.PORTH.SetBits(1 << 3) // PH3 high 650 } else { 651 avr.PORTH.ClearBits(1 << 3) // PH3 low 652 } 653 case 1: // channel B, PH4 654 if inverting { 655 avr.PORTH.SetBits(1 << 4) // PH4 high 656 } else { 657 avr.PORTH.ClearBits(1 << 4) // PH4 low 658 } 659 case 2: // channel C, PH5 660 if inverting { 661 avr.PORTH.SetBits(1 << 5) // PH4 high 662 } else { 663 avr.PORTH.ClearBits(1 << 5) // PH4 low 664 } 665 } 666 case 5: 667 // Note: the COM3A0/COM3B0 bit is not set with the configuration below. 668 // It will be set the following call to Set(), however. 669 switch channel { 670 case 0: // channel A, PL3 671 if inverting { 672 avr.PORTL.SetBits(1 << 3) // PL3 high 673 } else { 674 avr.PORTL.ClearBits(1 << 3) // PL3 low 675 } 676 case 1: // channel B, PL4 677 if inverting { 678 avr.PORTL.SetBits(1 << 4) // PL4 high 679 } else { 680 avr.PORTL.ClearBits(1 << 4) // PL4 low 681 } 682 case 2: // channel C, PH5 683 if inverting { 684 avr.PORTL.SetBits(1 << 5) // PL4 high 685 } else { 686 avr.PORTL.ClearBits(1 << 5) // PL4 low 687 } 688 } 689 } 690 } 691 692 // Set updates the channel value. This is used to control the channel duty 693 // cycle, in other words the fraction of time the channel output is high (or low 694 // when inverted). For example, to set it to a 25% duty cycle, use: 695 // 696 // pwm.Set(channel, pwm.Top() / 4) 697 // 698 // pwm.Set(channel, 0) will set the output to low and pwm.Set(channel, 699 // pwm.Top()) will set the output to high, assuming the output isn't inverted. 700 func (pwm PWM) Set(channel uint8, value uint32) { 701 switch pwm.num { 702 case 0: 703 value := uint16(value) 704 switch channel { 705 case 0: // channel A 706 if value == 0 { 707 avr.TCCR0A.ClearBits(avr.TCCR0A_COM0A1) 708 } else { 709 avr.OCR0A.Set(uint8(value - 1)) 710 avr.TCCR0A.SetBits(avr.TCCR0A_COM0A1) 711 } 712 case 1: // channel B 713 if value == 0 { 714 avr.TCCR0A.ClearBits(avr.TCCR0A_COM0B1) 715 } else { 716 avr.OCR0B.Set(uint8(value) - 1) 717 avr.TCCR0A.SetBits(avr.TCCR0A_COM0B1) 718 } 719 } 720 // monotonic timer is using the same time as PWM:0 721 // we must adust internal settings of monotonic timer when PWM:0 settings changed 722 adjustMonotonicTimer() 723 case 1: 724 mask := interrupt.Disable() 725 switch channel { 726 case 0: // channel A, PB5 727 if value == 0 { 728 avr.TCCR1A.ClearBits(avr.TCCR1A_COM1A1 | avr.TCCR1A_COM1A0) 729 } else { 730 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 731 avr.OCR1AH.Set(uint8(value >> 8)) 732 avr.OCR1AL.Set(uint8(value)) 733 if avr.PORTB.HasBits(1 << 5) { // is PB1 high? 734 // Yes, set the inverting bit. 735 avr.TCCR1A.SetBits(avr.TCCR1A_COM1A1 | avr.TCCR1A_COM1A0) 736 } else { 737 // No, output is non-inverting. 738 avr.TCCR1A.SetBits(avr.TCCR1A_COM1A1) 739 } 740 } 741 case 1: // channel B, PB6 742 if value == 0 { 743 avr.TCCR1A.ClearBits(avr.TCCR1A_COM1B1 | avr.TCCR1A_COM1B0) 744 } else { 745 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 746 avr.OCR1BH.Set(uint8(value >> 8)) 747 avr.OCR1BL.Set(uint8(value)) 748 if avr.PORTB.HasBits(1 << 6) { // is PB6 high? 749 // Yes, set the inverting bit. 750 avr.TCCR1A.SetBits(avr.TCCR1A_COM1B1 | avr.TCCR1A_COM1B0) 751 } else { 752 // No, output is non-inverting. 753 avr.TCCR1A.SetBits(avr.TCCR1A_COM1B1) 754 } 755 } 756 } 757 interrupt.Restore(mask) 758 case 2: 759 value := uint16(value) 760 switch channel { 761 case 0: // channel A 762 if value == 0 { 763 avr.TCCR2A.ClearBits(avr.TCCR2A_COM2A1) 764 } else { 765 avr.OCR2A.Set(uint8(value - 1)) 766 avr.TCCR2A.SetBits(avr.TCCR2A_COM2A1) 767 } 768 case 1: // channel B 769 if value == 0 { 770 avr.TCCR2A.ClearBits(avr.TCCR2A_COM2B1) 771 } else { 772 avr.OCR2B.Set(uint8(value - 1)) 773 avr.TCCR2A.SetBits(avr.TCCR2A_COM2B1) 774 } 775 } 776 case 3: 777 mask := interrupt.Disable() 778 switch channel { 779 case 0: // channel A, PE3 780 if value == 0 { 781 avr.TCCR3A.ClearBits(avr.TCCR3A_COM3A1 | avr.TCCR3A_COM3A0) 782 } else { 783 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 784 avr.OCR3AH.Set(uint8(value >> 8)) 785 avr.OCR3AL.Set(uint8(value)) 786 if avr.PORTE.HasBits(1 << 3) { // is PE3 high? 787 // Yes, set the inverting bit. 788 avr.TCCR3A.SetBits(avr.TCCR3A_COM3A1 | avr.TCCR3A_COM3A0) 789 } else { 790 // No, output is non-inverting. 791 avr.TCCR3A.SetBits(avr.TCCR3A_COM3A1) 792 } 793 } 794 case 1: // channel B, PE4 795 if value == 0 { 796 avr.TCCR3A.ClearBits(avr.TCCR3A_COM3B1 | avr.TCCR3A_COM3B0) 797 } else { 798 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 799 avr.OCR3BH.Set(uint8(value >> 8)) 800 avr.OCR3BL.Set(uint8(value)) 801 if avr.PORTE.HasBits(1 << 4) { // is PE4 high? 802 // Yes, set the inverting bit. 803 avr.TCCR3A.SetBits(avr.TCCR3A_COM3B1 | avr.TCCR3A_COM3B0) 804 } else { 805 // No, output is non-inverting. 806 avr.TCCR3A.SetBits(avr.TCCR3A_COM3B1) 807 } 808 } 809 case 2: // channel C, PE5 810 if value == 0 { 811 avr.TCCR3A.ClearBits(avr.TCCR3A_COM3C1 | avr.TCCR3A_COM3C0) 812 } else { 813 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 814 avr.OCR3CH.Set(uint8(value >> 8)) 815 avr.OCR3CL.Set(uint8(value)) 816 if avr.PORTE.HasBits(1 << 5) { // is PE5 high? 817 // Yes, set the inverting bit. 818 avr.TCCR3A.SetBits(avr.TCCR3A_COM3C1 | avr.TCCR3A_COM3C0) 819 } else { 820 // No, output is non-inverting. 821 avr.TCCR3A.SetBits(avr.TCCR3A_COM3C1) 822 } 823 } 824 } 825 interrupt.Restore(mask) 826 case 4: 827 mask := interrupt.Disable() 828 switch channel { 829 case 0: // channel A, PH3 830 if value == 0 { 831 avr.TCCR4A.ClearBits(avr.TCCR4A_COM4A1 | avr.TCCR4A_COM4A0) 832 } else { 833 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 834 avr.OCR4AH.Set(uint8(value >> 8)) 835 avr.OCR4AL.Set(uint8(value)) 836 if avr.PORTH.HasBits(1 << 3) { // is PH3 high? 837 // Yes, set the inverting bit. 838 avr.TCCR4A.SetBits(avr.TCCR4A_COM4A1 | avr.TCCR4A_COM4A0) 839 } else { 840 // No, output is non-inverting. 841 avr.TCCR4A.SetBits(avr.TCCR4A_COM4A1) 842 } 843 } 844 case 1: // channel B, PH4 845 if value == 0 { 846 avr.TCCR4A.ClearBits(avr.TCCR4A_COM4B1 | avr.TCCR4A_COM4B0) 847 } else { 848 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 849 avr.OCR4BH.Set(uint8(value >> 8)) 850 avr.OCR4BL.Set(uint8(value)) 851 if avr.PORTH.HasBits(1 << 4) { // is PH4 high? 852 // Yes, set the inverting bit. 853 avr.TCCR4A.SetBits(avr.TCCR4A_COM4B1 | avr.TCCR4A_COM4B0) 854 } else { 855 // No, output is non-inverting. 856 avr.TCCR4A.SetBits(avr.TCCR4A_COM4B1) 857 } 858 } 859 case 2: // channel C, PH5 860 if value == 0 { 861 avr.TCCR4A.ClearBits(avr.TCCR4A_COM4C1 | avr.TCCR4A_COM4C0) 862 } else { 863 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 864 avr.OCR4CH.Set(uint8(value >> 8)) 865 avr.OCR4CL.Set(uint8(value)) 866 if avr.PORTH.HasBits(1 << 5) { // is PH5 high? 867 // Yes, set the inverting bit. 868 avr.TCCR4A.SetBits(avr.TCCR4A_COM4C1 | avr.TCCR4A_COM4C0) 869 } else { 870 // No, output is non-inverting. 871 avr.TCCR4A.SetBits(avr.TCCR4A_COM4C1) 872 } 873 } 874 } 875 interrupt.Restore(mask) 876 case 5: 877 mask := interrupt.Disable() 878 switch channel { 879 case 0: // channel A, PL3 880 if value == 0 { 881 avr.TCCR5A.ClearBits(avr.TCCR5A_COM5A1 | avr.TCCR5A_COM5A0) 882 } else { 883 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 884 avr.OCR5AH.Set(uint8(value >> 8)) 885 avr.OCR5AL.Set(uint8(value)) 886 if avr.PORTL.HasBits(1 << 3) { // is PL3 high? 887 // Yes, set the inverting bit. 888 avr.TCCR5A.SetBits(avr.TCCR5A_COM5A1 | avr.TCCR5A_COM5A0) 889 } else { 890 // No, output is non-inverting. 891 avr.TCCR5A.SetBits(avr.TCCR5A_COM5A1) 892 } 893 } 894 case 1: // channel B, PL4 895 if value == 0 { 896 avr.TCCR5A.ClearBits(avr.TCCR5A_COM5B1 | avr.TCCR5A_COM5B0) 897 } else { 898 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 899 avr.OCR5BH.Set(uint8(value >> 8)) 900 avr.OCR5BL.Set(uint8(value)) 901 if avr.PORTL.HasBits(1 << 4) { // is PL4 high? 902 // Yes, set the inverting bit. 903 avr.TCCR5A.SetBits(avr.TCCR5A_COM5B1 | avr.TCCR5A_COM5B0) 904 } else { 905 // No, output is non-inverting. 906 avr.TCCR5A.SetBits(avr.TCCR5A_COM5B1) 907 } 908 } 909 case 2: // channel C, PL5 910 if value == 0 { 911 avr.TCCR5A.ClearBits(avr.TCCR5A_COM5C1 | avr.TCCR5A_COM5C0) 912 } else { 913 value := uint16(value) - 1 // yes, this is safe (it relies on underflow) 914 avr.OCR5CH.Set(uint8(value >> 8)) 915 avr.OCR5CL.Set(uint8(value)) 916 if avr.PORTL.HasBits(1 << 5) { // is PL5 high? 917 // Yes, set the inverting bit. 918 avr.TCCR5A.SetBits(avr.TCCR5A_COM5C1 | avr.TCCR5A_COM5C0) 919 } else { 920 // No, output is non-inverting. 921 avr.TCCR5A.SetBits(avr.TCCR5A_COM5C1) 922 } 923 } 924 } 925 interrupt.Restore(mask) 926 } 927 } 928 929 // SPI configuration 930 var SPI0 = SPI{ 931 spcr: avr.SPCR, 932 spdr: avr.SPDR, 933 spsr: avr.SPSR, 934 sck: PB1, 935 sdo: PB2, 936 sdi: PB3, 937 cs: PB0}