mirror of
https://github.com/sinseman44/PyCNC.git
synced 2026-07-16 08:37:09 +00:00
fix PWM usage
This commit is contained in:
@@ -33,13 +33,10 @@ So having Raspberry Pi connected this way, there is no need to configure
|
|||||||
pin map for project.
|
pin map for project.
|
||||||
|
|
||||||
# Hardware
|
# Hardware
|
||||||
Currently, this project supports Raspberry Pi 1-3. Tested with RPI2. But there
|
Currently, this project supports Raspberry Pi 1-3. Tested with RPI2 and RPI3.
|
||||||
is a way to add new boards. See [hal.py](./cnc/hal.py) file.
|
But there is a way to add new boards. See [hal.py](./cnc/hal.py) file.
|
||||||
_Note: Current Raspberry Pi implementation uses the same resources as on board
|
_Note: Current Raspberry Pi implementation uses the same resources as on board
|
||||||
GPU(memory). So video output will not work with this project. Use ssh
|
3.5 mm jack(PWM module), so do not use it. HDMI audio works._
|
||||||
connection to board. And do not connect HDMI cable, otherwise project would not
|
|
||||||
run. Probably, increasing of GPU dedicated memory(at least to 64 MB) could solve
|
|
||||||
it and allow to work project and GPU together, but it was never tested._
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
Just clone this repo and run `./pycnc` from repo root. It will start in
|
Just clone this repo and run `./pycnc` from repo root. It will start in
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class DMAGPIO(DMAProto):
|
|||||||
otherwise memory will be unlocked and it could be overwritten by
|
otherwise memory will be unlocked and it could be overwritten by
|
||||||
operating system.
|
operating system.
|
||||||
"""
|
"""
|
||||||
super(DMAGPIO, self).__init__(31 * 1024 * 1024, 5)
|
super(DMAGPIO, self).__init__(30 * 1024 * 1024, 4)
|
||||||
self.__current_address = 0
|
self.__current_address = 0
|
||||||
|
|
||||||
# get helpers registers, this class uses PWM module to create precise
|
# get helpers registers, this class uses PWM module to create precise
|
||||||
@@ -133,7 +133,7 @@ class DMAGPIO(DMAProto):
|
|||||||
next1 = next2 - self._DMA_CONTROL_BLOCK_SIZE
|
next1 = next2 - self._DMA_CONTROL_BLOCK_SIZE
|
||||||
|
|
||||||
source1 = next1 - 8 # last 8 bytes are padding, use it to store data
|
source1 = next1 - 8 # last 8 bytes are padding, use it to store data
|
||||||
length2 = 16 * length_us
|
length2 = length_us << 4 # * 16
|
||||||
source3 = next3 - 8
|
source3 = next3 - 8
|
||||||
|
|
||||||
data = (
|
data = (
|
||||||
@@ -158,7 +158,7 @@ class DMAGPIO(DMAProto):
|
|||||||
raise MemoryError("Out of allocated memory.")
|
raise MemoryError("Out of allocated memory.")
|
||||||
next1 = self._physmem.get_bus_address() + next_cb
|
next1 = self._physmem.get_bus_address() + next_cb
|
||||||
source = next1 - 8 # last 8 bytes are padding, use it to store data
|
source = next1 - 8 # last 8 bytes are padding, use it to store data
|
||||||
length = 16 * delay_us
|
length = delay_us << 4 # * 16
|
||||||
data = (
|
data = (
|
||||||
self._delay_info, source, self._delay_destination, length,
|
self._delay_info, source, self._delay_destination, length,
|
||||||
self._delay_stride, next1, 0, 0
|
self._delay_stride, next1, 0, 0
|
||||||
@@ -180,11 +180,13 @@ class DMAGPIO(DMAProto):
|
|||||||
"""
|
"""
|
||||||
# configure PWM hardware module which will clocks DMA
|
# configure PWM hardware module which will clocks DMA
|
||||||
self._pwm.write_int(PWM_CTL, 0)
|
self._pwm.write_int(PWM_CTL, 0)
|
||||||
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
|
self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
|
||||||
while (self._clock.read_int(CM_CNTL) & (1 << 7)) != 0:
|
while (self._clock.read_int(CM_PWM_CNTL) & CM_CNTL_BUSY) != 0:
|
||||||
time.sleep(0.00001) # 10 us, wait until BUSY bit is clear
|
time.sleep(0.00001) # 10 us, wait until BUSY bit is clear
|
||||||
self._clock.write_int(CM_DIV, CM_PASSWORD | CM_DIV_VALUE(50)) # 10MHz
|
self._clock.write_int(CM_PWM_DIV, CM_PASSWORD | CM_DIV_VALUE(5)) # 100MHz
|
||||||
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD | CM_ENABLE)
|
self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD |
|
||||||
|
CM_CNTL_ENABLE)
|
||||||
|
|
||||||
self._pwm.write_int(PWM_RNG1, 100)
|
self._pwm.write_int(PWM_RNG1, 100)
|
||||||
self._pwm.write_int(PWM_DMAC, PWM_DMAC_ENAB
|
self._pwm.write_int(PWM_DMAC, PWM_DMAC_ENAB
|
||||||
| PWM_DMAC_PANIC(15) | PWM_DMAC_DREQ(15))
|
| PWM_DMAC_PANIC(15) | PWM_DMAC_DREQ(15))
|
||||||
@@ -350,7 +352,7 @@ def main():
|
|||||||
print("now " + hex(a))
|
print("now " + hex(a))
|
||||||
del cma
|
del cma
|
||||||
dg = DMAGPIO()
|
dg = DMAGPIO()
|
||||||
dg.add_pulse(1 << pin, 100000)
|
dg.add_pulse(1 << pin, 200000)
|
||||||
dg.add_delay(600000)
|
dg.add_delay(600000)
|
||||||
dg.run(True)
|
dg.run(True)
|
||||||
print("dmagpio is started")
|
print("dmagpio is started")
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ PHYSICAL_GPIO_BUS = 0x7E000000 + GPIO_REGISTER_BASE
|
|||||||
|
|
||||||
# registers and values for DMA
|
# registers and values for DMA
|
||||||
DMA_BASE = 0x007000
|
DMA_BASE = 0x007000
|
||||||
|
DMA_CS = 0x00
|
||||||
|
DMA_CONBLK_AD = 0x04
|
||||||
DMA_TI_NO_WIDE_BURSTS = 1 << 26
|
DMA_TI_NO_WIDE_BURSTS = 1 << 26
|
||||||
DMA_TI_SRC_INC = 1 << 8
|
DMA_TI_SRC_INC = 1 << 8
|
||||||
DMA_TI_DEST_INC = 1 << 4
|
DMA_TI_DEST_INC = 1 << 4
|
||||||
@@ -79,16 +81,20 @@ def DMA_CS_PANIC_PRIORITY(x):
|
|||||||
|
|
||||||
# hardware PWM controller registers
|
# hardware PWM controller registers
|
||||||
PWM_BASE = 0x0020C000
|
PWM_BASE = 0x0020C000
|
||||||
|
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
|
||||||
PWM_CTL= 0x00
|
PWM_CTL= 0x00
|
||||||
PWM_DMAC = 0x08
|
PWM_DMAC = 0x08
|
||||||
PWM_RNG1 = 0x10
|
PWM_RNG1 = 0x10
|
||||||
|
PWM_RNG2 = 0x20
|
||||||
PWM_FIFO = 0x18
|
PWM_FIFO = 0x18
|
||||||
PWM_CTL_MODE1 = 1 << 1
|
PWM_CTL_MODE1 = 1 << 1
|
||||||
|
PWM_CTL_MODE2 = 1 << 9
|
||||||
PWM_CTL_PWEN1 = 1 << 0
|
PWM_CTL_PWEN1 = 1 << 0
|
||||||
|
PWM_CTL_PWEN2 = 1 << 8
|
||||||
PWM_CTL_CLRF = 1 << 6
|
PWM_CTL_CLRF = 1 << 6
|
||||||
PWM_CTL_USEF1 = 1 << 5
|
PWM_CTL_USEF1 = 1 << 5
|
||||||
|
PWM_CTL_USEF2 = 1 << 13
|
||||||
PWM_DMAC_ENAB = 1 << 31
|
PWM_DMAC_ENAB = 1 << 31
|
||||||
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
|
|
||||||
|
|
||||||
def PWM_DMAC_PANIC(x):
|
def PWM_DMAC_PANIC(x):
|
||||||
return x << 8
|
return x << 8
|
||||||
@@ -98,10 +104,13 @@ def PWM_DMAC_DREQ(x):
|
|||||||
|
|
||||||
# clock manager module
|
# clock manager module
|
||||||
CM_BASE = 0x00101000
|
CM_BASE = 0x00101000
|
||||||
CM_CNTL = 40
|
CM_PCM_CNTL = 0x98
|
||||||
CM_DIV = 41
|
CM_PCM_DIV = 0x9C
|
||||||
|
CM_PWM_CNTL = 0xA0
|
||||||
|
CM_PWM_DIV = 0xA4
|
||||||
CM_PASSWORD = 0x5A << 24
|
CM_PASSWORD = 0x5A << 24
|
||||||
CM_ENABLE = 1 << 4
|
CM_CNTL_ENABLE = 1 << 4
|
||||||
|
CM_CNTL_BUSY = 1 << 7
|
||||||
CM_SRC_OSC = 1 # 19.2 MHz
|
CM_SRC_OSC = 1 # 19.2 MHz
|
||||||
CM_SRC_PLLC = 5 # 1000 MHz
|
CM_SRC_PLLC = 5 # 1000 MHz
|
||||||
CM_SRC_PLLD = 6 # 500 MHz
|
CM_SRC_PLLD = 6 # 500 MHz
|
||||||
@@ -218,26 +227,24 @@ class DMAProto(object):
|
|||||||
""" Run DMA module from created buffer.
|
""" Run DMA module from created buffer.
|
||||||
"""
|
"""
|
||||||
address = 0x100 * self._DMA_CHANNEL
|
address = 0x100 * self._DMA_CHANNEL
|
||||||
cs = self._dma.read_int(address)
|
self._dma.write_int(address + DMA_CS, DMA_CS_END)
|
||||||
cs |= DMA_CS_END
|
self._dma.write_int(address + DMA_CONBLK_AD, self._physmem.get_bus_address())
|
||||||
self._dma.write_int(address, cs)
|
|
||||||
self._dma.write_int(address + 4, self._physmem.get_bus_address())
|
|
||||||
cs = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG
|
cs = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG
|
||||||
self._dma.write_int(address, cs)
|
self._dma.write_int(address + DMA_CS, cs)
|
||||||
cs |= DMA_CS_ACTIVE
|
cs |= DMA_CS_ACTIVE
|
||||||
self._dma.write_int(address, cs)
|
self._dma.write_int(address + DMA_CS, cs)
|
||||||
|
|
||||||
def _stop_dma(self):
|
def _stop_dma(self):
|
||||||
""" Stop DMA
|
""" Stop DMA
|
||||||
"""
|
"""
|
||||||
address = 0x100 * self._DMA_CHANNEL
|
address = 0x100 * self._DMA_CHANNEL
|
||||||
cs = self._dma.read_int(address)
|
cs = self._dma.read_int(address + DMA_CS)
|
||||||
cs |= DMA_CS_ABORT
|
cs |= DMA_CS_ABORT
|
||||||
self._dma.write_int(address, cs)
|
self._dma.write_int(address + DMA_CS, cs)
|
||||||
cs &= ~DMA_CS_ACTIVE
|
cs &= ~DMA_CS_ACTIVE
|
||||||
self._dma.write_int(address, cs)
|
self._dma.write_int(address + DMA_CS, cs)
|
||||||
cs |= DMA_CS_RESET
|
cs |= DMA_CS_RESET
|
||||||
self._dma.write_int(address, cs)
|
self._dma.write_int(address + DMA_CS, cs)
|
||||||
|
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
""" Check if DMA is working. Method can check if single sequence
|
""" Check if DMA is working. Method can check if single sequence
|
||||||
@@ -245,7 +252,7 @@ class DMAProto(object):
|
|||||||
:return: boolean value
|
:return: boolean value
|
||||||
"""
|
"""
|
||||||
address = 0x100 * self._DMA_CHANNEL
|
address = 0x100 * self._DMA_CHANNEL
|
||||||
cs = self._dma.read_int(address)
|
cs = self._dma.read_int(address + DMA_CS)
|
||||||
if cs & DMA_CS_ACTIVE == DMA_CS_ACTIVE:
|
if cs & DMA_CS_ACTIVE == DMA_CS_ACTIVE:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|||||||
Reference in New Issue
Block a user