mirror of
https://github.com/sinseman44/PyCNC.git
synced 2026-01-12 02:40:04 +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.
|
||||
|
||||
# Hardware
|
||||
Currently, this project supports Raspberry Pi 1-3. Tested with RPI2. But there
|
||||
is a way to add new boards. See [hal.py](./cnc/hal.py) file.
|
||||
Currently, this project supports Raspberry Pi 1-3. Tested with RPI2 and RPI3.
|
||||
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
|
||||
GPU(memory). So video output will not work with this project. Use ssh
|
||||
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._
|
||||
3.5 mm jack(PWM module), so do not use it. HDMI audio works._
|
||||
|
||||
# Usage
|
||||
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
|
||||
operating system.
|
||||
"""
|
||||
super(DMAGPIO, self).__init__(31 * 1024 * 1024, 5)
|
||||
super(DMAGPIO, self).__init__(30 * 1024 * 1024, 4)
|
||||
self.__current_address = 0
|
||||
|
||||
# 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
|
||||
|
||||
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
|
||||
|
||||
data = (
|
||||
@@ -158,7 +158,7 @@ class DMAGPIO(DMAProto):
|
||||
raise MemoryError("Out of allocated memory.")
|
||||
next1 = self._physmem.get_bus_address() + next_cb
|
||||
source = next1 - 8 # last 8 bytes are padding, use it to store data
|
||||
length = 16 * delay_us
|
||||
length = delay_us << 4 # * 16
|
||||
data = (
|
||||
self._delay_info, source, self._delay_destination, length,
|
||||
self._delay_stride, next1, 0, 0
|
||||
@@ -180,11 +180,13 @@ class DMAGPIO(DMAProto):
|
||||
"""
|
||||
# configure PWM hardware module which will clocks DMA
|
||||
self._pwm.write_int(PWM_CTL, 0)
|
||||
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
|
||||
while (self._clock.read_int(CM_CNTL) & (1 << 7)) != 0:
|
||||
self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
|
||||
while (self._clock.read_int(CM_PWM_CNTL) & CM_CNTL_BUSY) != 0:
|
||||
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_CNTL, CM_PASSWORD | CM_SRC_PLLD | CM_ENABLE)
|
||||
self._clock.write_int(CM_PWM_DIV, CM_PASSWORD | CM_DIV_VALUE(5)) # 100MHz
|
||||
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_DMAC, PWM_DMAC_ENAB
|
||||
| PWM_DMAC_PANIC(15) | PWM_DMAC_DREQ(15))
|
||||
@@ -350,7 +352,7 @@ def main():
|
||||
print("now " + hex(a))
|
||||
del cma
|
||||
dg = DMAGPIO()
|
||||
dg.add_pulse(1 << pin, 100000)
|
||||
dg.add_pulse(1 << pin, 200000)
|
||||
dg.add_delay(600000)
|
||||
dg.run(True)
|
||||
print("dmagpio is started")
|
||||
|
||||
@@ -39,6 +39,8 @@ PHYSICAL_GPIO_BUS = 0x7E000000 + GPIO_REGISTER_BASE
|
||||
|
||||
# registers and values for DMA
|
||||
DMA_BASE = 0x007000
|
||||
DMA_CS = 0x00
|
||||
DMA_CONBLK_AD = 0x04
|
||||
DMA_TI_NO_WIDE_BURSTS = 1 << 26
|
||||
DMA_TI_SRC_INC = 1 << 8
|
||||
DMA_TI_DEST_INC = 1 << 4
|
||||
@@ -79,16 +81,20 @@ def DMA_CS_PANIC_PRIORITY(x):
|
||||
|
||||
# hardware PWM controller registers
|
||||
PWM_BASE = 0x0020C000
|
||||
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
|
||||
PWM_CTL= 0x00
|
||||
PWM_DMAC = 0x08
|
||||
PWM_RNG1 = 0x10
|
||||
PWM_RNG2 = 0x20
|
||||
PWM_FIFO = 0x18
|
||||
PWM_CTL_MODE1 = 1 << 1
|
||||
PWM_CTL_MODE2 = 1 << 9
|
||||
PWM_CTL_PWEN1 = 1 << 0
|
||||
PWM_CTL_PWEN2 = 1 << 8
|
||||
PWM_CTL_CLRF = 1 << 6
|
||||
PWM_CTL_USEF1 = 1 << 5
|
||||
PWM_CTL_USEF2 = 1 << 13
|
||||
PWM_DMAC_ENAB = 1 << 31
|
||||
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
|
||||
|
||||
def PWM_DMAC_PANIC(x):
|
||||
return x << 8
|
||||
@@ -98,10 +104,13 @@ def PWM_DMAC_DREQ(x):
|
||||
|
||||
# clock manager module
|
||||
CM_BASE = 0x00101000
|
||||
CM_CNTL = 40
|
||||
CM_DIV = 41
|
||||
CM_PCM_CNTL = 0x98
|
||||
CM_PCM_DIV = 0x9C
|
||||
CM_PWM_CNTL = 0xA0
|
||||
CM_PWM_DIV = 0xA4
|
||||
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_PLLC = 5 # 1000 MHz
|
||||
CM_SRC_PLLD = 6 # 500 MHz
|
||||
@@ -218,26 +227,24 @@ class DMAProto(object):
|
||||
""" Run DMA module from created buffer.
|
||||
"""
|
||||
address = 0x100 * self._DMA_CHANNEL
|
||||
cs = self._dma.read_int(address)
|
||||
cs |= DMA_CS_END
|
||||
self._dma.write_int(address, cs)
|
||||
self._dma.write_int(address + 4, self._physmem.get_bus_address())
|
||||
self._dma.write_int(address + DMA_CS, DMA_CS_END)
|
||||
self._dma.write_int(address + DMA_CONBLK_AD, self._physmem.get_bus_address())
|
||||
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
|
||||
self._dma.write_int(address, cs)
|
||||
self._dma.write_int(address + DMA_CS, cs)
|
||||
|
||||
def _stop_dma(self):
|
||||
""" Stop DMA
|
||||
"""
|
||||
address = 0x100 * self._DMA_CHANNEL
|
||||
cs = self._dma.read_int(address)
|
||||
cs = self._dma.read_int(address + DMA_CS)
|
||||
cs |= DMA_CS_ABORT
|
||||
self._dma.write_int(address, cs)
|
||||
self._dma.write_int(address + DMA_CS, cs)
|
||||
cs &= ~DMA_CS_ACTIVE
|
||||
self._dma.write_int(address, cs)
|
||||
self._dma.write_int(address + DMA_CS, cs)
|
||||
cs |= DMA_CS_RESET
|
||||
self._dma.write_int(address, cs)
|
||||
self._dma.write_int(address + DMA_CS, cs)
|
||||
|
||||
def is_active(self):
|
||||
""" Check if DMA is working. Method can check if single sequence
|
||||
@@ -245,7 +252,7 @@ class DMAProto(object):
|
||||
:return: boolean value
|
||||
"""
|
||||
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:
|
||||
return True
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user