github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/runtime_atmega.go (about)

     1  //go:build avr && (atmega || atmega32u4)
     2  
     3  package runtime
     4  
     5  import (
     6  	"device/avr"
     7  	"machine"
     8  )
     9  
    10  func initUART() {
    11  	machine.InitSerial()
    12  }
    13  
    14  func putchar(c byte) {
    15  	machine.Serial.WriteByte(c)
    16  }
    17  
    18  func getchar() byte {
    19  	for machine.Serial.Buffered() == 0 {
    20  		Gosched()
    21  	}
    22  	v, _ := machine.Serial.ReadByte()
    23  	return v
    24  }
    25  
    26  func buffered() int {
    27  	return machine.Serial.Buffered()
    28  }
    29  
    30  // Sleep for a given period. The period is defined by the WDT peripheral, and is
    31  // on most chips (at least) 3 bits wide, in powers of two from 16ms to 2s
    32  // (0=16ms, 1=32ms, 2=64ms...). Note that the WDT is not very accurate: it can
    33  // be off by a large margin depending on temperature and supply voltage.
    34  //
    35  // TODO: disable more peripherals etc. to reduce sleep current.
    36  func sleepWDT(period uint8) {
    37  	// Configure WDT
    38  	avr.Asm("cli")
    39  	avr.Asm("wdr")
    40  	// Start timed sequence.
    41  	avr.WDTCSR.SetBits(avr.WDTCSR_WDCE | avr.WDTCSR_WDE)
    42  	// Enable WDT and set new timeout
    43  	avr.WDTCSR.SetBits(avr.WDTCSR_WDIE | period)
    44  	avr.Asm("sei")
    45  
    46  	// Set sleep mode to idle and enable sleep mode.
    47  	// Note: when using something other than idle, the UART won't work
    48  	// correctly. This needs to be fixed, though, so we can truly sleep.
    49  	avr.SMCR.Set((0 << 1) | avr.SMCR_SE)
    50  
    51  	// go to sleep
    52  	avr.Asm("sleep")
    53  
    54  	// disable sleep
    55  	avr.SMCR.Set(0)
    56  }