Shop OBEX P1 Docs P2 Docs Learn Events
PropBasic ASM Tasks — Parallax Forums

PropBasic ASM Tasks

FriedVFriedV Posts: 77
edited 2011-09-21 04:25 in Propeller 1
@Bean
Was there a specific reason you didn't adopt the same calling mechanism for
cognew(@codestart, @address) as spin does?
@address would be copied into the cogs par register.
For PropBasic this would translate to cogstart taskname, @address?
The reason I'm asking this is we could use the asm parts of some spin object without
modifications (defining the right hub vars of course). But it is only a suggestion!
Fried

Comments

  • BeanBean Posts: 8,129
    edited 2011-09-21 04:11
    When starting a task "par" is set to the start of PropBasic HUB data. This is needed so TASKs can share data and hub variables.
    Can you post a simple example of what you want to do ?

    Bean
  • FriedVFriedV Posts: 77
    edited 2011-09-21 04:25
    I try to port Nico Schoemaker's SRMotorControl.spin object to PropBasic.
    The assembler part is
    DAT
    org 0

    init
    movi dira, #%11110 'Set bit 24..27 of dira to output
    movi outa,#%00000 'Set output pin 24..27 to 0

    rdlong _sliceDuration, par 'Read the clockticks of one period
    mov _r1, #100 'Set _r1 to divider of 100
    shl _r1, #15
    mov _r2, #16
    :divide 'Divide the clockticks of one period by 100 and store result into _sliceDuration
    cmpsub _sliceDuration, _r1 wc
    rcl _sliceDuration, #1
    djnz _r2, #:divide

    mov _r1, par
    add _r1, #4 'Read the Command parameter address
    mov _commandAddr, _r1 'Save Command address in _commandAddr

    mov _speedL, #0 'Set all speeds to 0
    mov _speedR, #0
    mov _curSpeedL, #0
    mov _curSpeedR, #0
    mov _command, #0
    mov _prevCommand, #0 'Set previous command to 0 = no speed, no ramp and no update

    mov _sliceCount, #100 'Preset the slicecount of one period to 100

    mov _delay, _sliceDuration 'Initialze the _delay to the end of the first period slice
    add _delay, cnt

    startPeriod
    call #getOutputMask 'Get the outputmask to control output pin 24..27
    movi outa, _outputMask 'Set output pin 24..27
    waitcnt _delay, _sliceDuration 'Wait until slice of period is ended
    djnz _sliceCount, #startPeriod '100 of period slice's are done ?
    :endPeriod
    mov _sliceCount, #100 'Set _sliceCount to 100 for new period
    call #getCommand 'Get/Check for new command and load speeds and ramp
    cmp _rampDelay, #0 wz 'Command contains ramp delay ?
    if_z jmp #startPeriod 'No ramp delay, start new period

    :ramp
    djnz _curRampDelay, #startPeriod 'Is ramp delay done ?
    mov _curRampDelay, _rampDelay 'Set new rampdelay

    cmps _curSpeedL, _speedL wc,wz 'Compare currentspeed with commandspeed of left motor
    if_c adds _curSpeedL, #1 'Currentspeed < commandspeed, add 1 to currentspeed of left motor
    if_nc_and_nz subs _curSpeedL, #1 'Currentspeed > commandspeed, sub 1 from currentspeed of left motor
    cmps _curSpeedR, _speedR wc,wz 'Compare currentspeed with commandspeed of right motor
    if_c adds _curSpeedR, #1 'Currentspeed < commandspeed, add 1 to currentspeed of right motor
    if_nc_and_nz subs _curSpeedR, #1 'Currentspeed > commandspeed, sub 1 from currentspeed of right motor

    jmp #startPeriod 'Start new period

    getOutputMask

    abs _r1, _curSpeedL wc,wz 'Get the absolute value of the leftspeed, C flag indicates backward, Z flag indicates stop
    if_z mov _outputMask, #%11000 'Stop left motor
    if_c mov _outputMask, #%11010 'Set left motor to backward, bit 24 = 1
    if_nc_and_nz mov _outputMask, #%11100 'Set left motor to forward, bit 25 = 1
    cmp _sliceCount, _r1 wc,wz 'Compare leftspeed with current slice of period
    if_nc_and_nz mov _outputMask, #%11000 '_sliceCount > leftspeed, stop left motor

    abs _r1, _curSpeedR wc,wz 'Get the absolute value of the rightspeed, C flag indicates backward, Z flag indicates stop
    if_z and _outputMask, #%00110 'Stop left motor
    if_c and _outputMask, #%10110 'Set right motor to backward, bit 27 = 1
    if_nc_and_nz and _outputMask, #%01110 'Set right motor to forward, bit 26 = 1
    cmp _sliceCount, _r1 wc,wz 'Compare leftspeed with current slice of period
    if_nc_and_nz and _outputMask, #%00110 '_sliceCount > rightspeed, stop right motor

    getOutputMask_ret
    ret

    getCommand
    rdlong _command, _commandAddr 'Read command from startPeriod memory
    test _command, #1 wz 'Command is updated ? bit 0 must be 1
    if_z jmp #getCommand_ret 'No new command present, return to caller
    cmp _command, _prevCommand wz 'Is new and previous command the same ?
    if_z jmp #:endcommand 'Command not changed, return to caller

    :setSpeed
    mov _r1, _command 'Copy command in _r1
    shr _r1, #8 'Shift leftspeed into byte 0
    mov _speedL, _r1 'Save leftspeed
    and _speedL, #$FF 'Clear byte 1..3 of leftspeed
    cmp _speedL, #101 wc 'Is leftspeed negative( > 100) ?
    if_nc muxnc _speedL, _negMask 'Create long negative
    shr _r1, #8 'Shift rightspeed into byte 0
    mov _speedR, _r1 'Save rightspeed
    and _speedR, #$FF 'Clear byte 1..3 of rightspeed
    cmp _speedR, #101 wc 'Is rightspeed negative( > 100) ?
    if_nc muxnc _speedR, _negMask 'Create long negative
    shr _r1, #8 'Shift ramp delay into byte 0
    mov _rampDelay, _r1 'Save rampdelay
    mov _curRampDelay, _rampDelay 'Set current ramp
    cmp _rampDelay, #0 wz 'Ramp delay present ?
    if_nz jmp #:endcommand 'Ramp <> 0 jump to endcommand
    mov _curSpeedL, _speedL
    mov _curSpeedR, _speedR

    :endcommand 'Reset command in startPeriod memory
    mov _prevCommand, _command 'Save the command as previous getCommand
    mov _r1, _command wz 'Copy new command into _r1, set the Z flag to 0 for muxz instruction
    muxz _r1, #1 'Reset bit 0 of the command
    wrlong _r1, _commandAddr 'Signal to object in startPeriod memory that command processing is finished
    getCommand_ret
    ret

    _negMask long $FF_FF_FF_00
    _sliceDuration res 1
    _sliceCount res 1
    _delay res 1
    _commandAddr res 1
    _command res 1
    _prevCommand res 1
    _r1 res 1
    _r2 res 1
    _speedL res 1
    _speedR res 1
    _curSpeedL res 1
    _curSpeedR res 1
    _outputMask res 1
    _rampDelay res 1
    _curRampDelay res 1

    So I simply copied this code into a
    TASK PWM
    ASM
    ...
    Nico's Code
    ...
    ENDASM
    ENDTASK

    I'm wondering if the code get the right info from the par register,
    which must point to a datastructure

    long vCog
    long vPeriodTicks
    long cCommand

    in Hub memory.

    BTW I find the "C" datastruct construct vCommand.byte[idx] very helpful, I would like to see that in PropBasic also.

    Fried
  • FriedVFriedV Posts: 77
    edited 2011-09-21 04:25
    I try to port Nico Schoemaker's SRMotorControl.spin object to PropBasic.
    The assembler part is
    DAT
    org 0

    init
    movi dira, #%11110 'Set bit 24..27 of dira to output
    movi outa,#%00000 'Set output pin 24..27 to 0

    rdlong _sliceDuration, par 'Read the clockticks of one period
    mov _r1, #100 'Set _r1 to divider of 100
    shl _r1, #15
    mov _r2, #16
    :divide 'Divide the clockticks of one period by 100 and store result into _sliceDuration
    cmpsub _sliceDuration, _r1 wc
    rcl _sliceDuration, #1
    djnz _r2, #:divide

    mov _r1, par
    add _r1, #4 'Read the Command parameter address
    mov _commandAddr, _r1 'Save Command address in _commandAddr

    mov _speedL, #0 'Set all speeds to 0
    mov _speedR, #0
    mov _curSpeedL, #0
    mov _curSpeedR, #0
    mov _command, #0
    mov _prevCommand, #0 'Set previous command to 0 = no speed, no ramp and no update

    mov _sliceCount, #100 'Preset the slicecount of one period to 100

    mov _delay, _sliceDuration 'Initialze the _delay to the end of the first period slice
    add _delay, cnt

    startPeriod
    call #getOutputMask 'Get the outputmask to control output pin 24..27
    movi outa, _outputMask 'Set output pin 24..27
    waitcnt _delay, _sliceDuration 'Wait until slice of period is ended
    djnz _sliceCount, #startPeriod '100 of period slice's are done ?
    :endPeriod
    mov _sliceCount, #100 'Set _sliceCount to 100 for new period
    call #getCommand 'Get/Check for new command and load speeds and ramp
    cmp _rampDelay, #0 wz 'Command contains ramp delay ?
    if_z jmp #startPeriod 'No ramp delay, start new period

    :ramp
    djnz _curRampDelay, #startPeriod 'Is ramp delay done ?
    mov _curRampDelay, _rampDelay 'Set new rampdelay

    cmps _curSpeedL, _speedL wc,wz 'Compare currentspeed with commandspeed of left motor
    if_c adds _curSpeedL, #1 'Currentspeed < commandspeed, add 1 to currentspeed of left motor
    if_nc_and_nz subs _curSpeedL, #1 'Currentspeed > commandspeed, sub 1 from currentspeed of left motor
    cmps _curSpeedR, _speedR wc,wz 'Compare currentspeed with commandspeed of right motor
    if_c adds _curSpeedR, #1 'Currentspeed < commandspeed, add 1 to currentspeed of right motor
    if_nc_and_nz subs _curSpeedR, #1 'Currentspeed > commandspeed, sub 1 from currentspeed of right motor

    jmp #startPeriod 'Start new period

    getOutputMask

    abs _r1, _curSpeedL wc,wz 'Get the absolute value of the leftspeed, C flag indicates backward, Z flag indicates stop
    if_z mov _outputMask, #%11000 'Stop left motor
    if_c mov _outputMask, #%11010 'Set left motor to backward, bit 24 = 1
    if_nc_and_nz mov _outputMask, #%11100 'Set left motor to forward, bit 25 = 1
    cmp _sliceCount, _r1 wc,wz 'Compare leftspeed with current slice of period
    if_nc_and_nz mov _outputMask, #%11000 '_sliceCount > leftspeed, stop left motor

    abs _r1, _curSpeedR wc,wz 'Get the absolute value of the rightspeed, C flag indicates backward, Z flag indicates stop
    if_z and _outputMask, #%00110 'Stop left motor
    if_c and _outputMask, #%10110 'Set right motor to backward, bit 27 = 1
    if_nc_and_nz and _outputMask, #%01110 'Set right motor to forward, bit 26 = 1
    cmp _sliceCount, _r1 wc,wz 'Compare leftspeed with current slice of period
    if_nc_and_nz and _outputMask, #%00110 '_sliceCount > rightspeed, stop right motor

    getOutputMask_ret
    ret

    getCommand
    rdlong _command, _commandAddr 'Read command from startPeriod memory
    test _command, #1 wz 'Command is updated ? bit 0 must be 1
    if_z jmp #getCommand_ret 'No new command present, return to caller
    cmp _command, _prevCommand wz 'Is new and previous command the same ?
    if_z jmp #:endcommand 'Command not changed, return to caller

    :setSpeed
    mov _r1, _command 'Copy command in _r1
    shr _r1, #8 'Shift leftspeed into byte 0
    mov _speedL, _r1 'Save leftspeed
    and _speedL, #$FF 'Clear byte 1..3 of leftspeed
    cmp _speedL, #101 wc 'Is leftspeed negative( > 100) ?
    if_nc muxnc _speedL, _negMask 'Create long negative
    shr _r1, #8 'Shift rightspeed into byte 0
    mov _speedR, _r1 'Save rightspeed
    and _speedR, #$FF 'Clear byte 1..3 of rightspeed
    cmp _speedR, #101 wc 'Is rightspeed negative( > 100) ?
    if_nc muxnc _speedR, _negMask 'Create long negative
    shr _r1, #8 'Shift ramp delay into byte 0
    mov _rampDelay, _r1 'Save rampdelay
    mov _curRampDelay, _rampDelay 'Set current ramp
    cmp _rampDelay, #0 wz 'Ramp delay present ?
    if_nz jmp #:endcommand 'Ramp <> 0 jump to endcommand
    mov _curSpeedL, _speedL
    mov _curSpeedR, _speedR

    :endcommand 'Reset command in startPeriod memory
    mov _prevCommand, _command 'Save the command as previous getCommand
    mov _r1, _command wz 'Copy new command into _r1, set the Z flag to 0 for muxz instruction
    muxz _r1, #1 'Reset bit 0 of the command
    wrlong _r1, _commandAddr 'Signal to object in startPeriod memory that command processing is finished
    getCommand_ret
    ret

    _negMask long $FF_FF_FF_00
    _sliceDuration res 1
    _sliceCount res 1
    _delay res 1
    _commandAddr res 1
    _command res 1
    _prevCommand res 1
    _r1 res 1
    _r2 res 1
    _speedL res 1
    _speedR res 1
    _curSpeedL res 1
    _curSpeedR res 1
    _outputMask res 1
    _rampDelay res 1
    _curRampDelay res 1

    So I simply copied this code into a
    TASK PWM
    ASM
    ...
    Nico's Code
    ...
    ENDASM
    ENDTASK

    I'm wondering if the code get the right info from the par register,
    which must point to a datastructure

    long vCog
    long vPeriodTicks
    long cCommand

    in Hub memory.

    BTW I find the "C" datastruct construct vCommand.byte[idx] very helpful, I would like to see that in PropBasic also.

    Fried
Sign In or Register to comment.