Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/machine/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package machine
import "errors"

var (
ErrTimeoutRNG = errors.New("machine: RNG Timeout")
ErrInvalidInputPin = errors.New("machine: invalid input pin")
ErrInvalidOutputPin = errors.New("machine: invalid output pin")
ErrInvalidClockPin = errors.New("machine: invalid clock pin")
ErrInvalidDataPin = errors.New("machine: invalid data pin")
ErrNoPinChangeChannel = errors.New("machine: no channel available for pin interrupt")
ErrTimeoutRNG = errors.New("machine: RNG Timeout")
ErrInvalidInputPin = errors.New("machine: invalid input pin")
ErrInvalidOutputPin = errors.New("machine: invalid output pin")
ErrInvalidClockPin = errors.New("machine: invalid clock pin")
ErrInvalidDataPin = errors.New("machine: invalid data pin")
ErrNoPinChangeChannel = errors.New("machine: no channel available for pin interrupt")
ErrFeatureNotImplemented = errors.New("machine: this feature is not yet implemented")
)

// Device is the running program's chip name, such as "ATSAMD51J19A" or
Expand Down
73 changes: 73 additions & 0 deletions src/machine/machine_atmega328p.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ package machine

import (
"device/avr"
"errors"
"runtime/interrupt"
"runtime/volatile"
)

var (
ErrCallbackAlreadyDefined = errors.New("machine: callback already defined")
)

const irq_USART0_RX = avr.IRQ_USART_RX

// getPortMask returns the PORTx register and mask for the pin.
Expand Down Expand Up @@ -467,3 +472,71 @@ var SPI0 = SPI{
sdo: PB3,
sdi: PB4,
cs: PB2}

// Pin Change Interrupts
var (
pinCallbacks [3][8]func(Pin)
)

func handlePCINTInterrupts(intr uint8, port *volatile.Register8) {
current := port.Get()
for i := uint8(0); i < 8; i++ {
if (current>>i)&0x01 == 0x01 && pinCallbacks[intr][i] != nil {
pinCallbacks[intr][i](Pin(i * (intr + 1)))
}
}
}

func handlePCINT0Interrupts(intr interrupt.Interrupt) {
handlePCINTInterrupts(avr.IRQ_PCINT0-avr.IRQ_PCINT0, avr.PINB)
}

func handlePCINT1Interrupts(intr interrupt.Interrupt) {
handlePCINTInterrupts(avr.IRQ_PCINT1-avr.IRQ_PCINT0, avr.PINC)
}

func handlePCINT2Interrupts(intr interrupt.Interrupt) {
handlePCINTInterrupts(avr.IRQ_PCINT2-avr.IRQ_PCINT0, avr.PIND)
}

type PinChange uint8

// Pin change interrupt constants for SetInterrupt.
const (
PinToggle PinChange = 1
)

func (pin Pin) SetInterrupt(pinChange PinChange, callback func(Pin)) (err error) {
if callback == nil {
// Disable this pin interrupt
return ErrFeatureNotImplemented
}

switch {
case pin >= PB0 && pin <= PB7:
// PCMSK0 - PCINT0-7
pinIndex := pin - PD0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pinIndex := pin - PD0
pinIndex := pin - PB0

pinCallbacks[0][pinIndex] = callback
avr.PCMSK0.SetBits(1 << pinIndex)
avr.PCICR.SetBits(avr.PCICR_PCIE0)
interrupt.New(avr.IRQ_PCINT0, handlePCINT0Interrupts)
case pin >= PC0 && pin <= PC7:
// PCMSK1 - PCINT8-14
pinIndex := pin - PC0
pinCallbacks[1][pinIndex] = callback
avr.PCMSK1.SetBits(1 << pinIndex)
avr.PCICR.SetBits(avr.PCICR_PCIE1)
interrupt.New(avr.IRQ_PCINT1, handlePCINT1Interrupts)
case pin >= PD0 && pin <= PD7:
// PCMSK2 - PCINT16-23
pinIndex := pin - PD0
pinCallbacks[2][pinIndex] = callback
avr.PCMSK2.SetBits(1 << pinIndex)
avr.PCICR.SetBits(avr.PCICR_PCIE2)
interrupt.New(avr.IRQ_PCINT2, handlePCINT2Interrupts)
default:
return ErrInvalidInputPin
}

return nil
}