I have an AP-16 that will be controlled by the SX. I looked at the Servos6digital11 program and found a communications program using port "A" in that code but it appears to be much more than what I wound need to send the basic commants to the AP-16. I was planning on using bit 7 of the "C" port I/O as a serI/O like on the Prop -1 connections but would like some example code for the SX that would do the output job at a minimum. I don't think that I'll really need any of the input information from the status or version commands. I think that the SET commands will provide everything I what to do with the AP-16
The problem with a demo for the SX is that it's like to interfere with what you're already doing. If you have other serial processes in play, or things like servos, it all gets very complicated as these processes need to be interleaved with serial control to the AP-16+.
So... what do you want your program to do, other than send messages to the AP-16+? The answer will dictate how the code is constructed.
Controlling 5 servos synched to the audio selected. There are subroutines to read and move at the most three servo's at the same time in a loop. There is a pre program delay selected by a pot read subroutine, a set of a solenoid to activate a pneumatic cylinder then servo commands interleived with the starting of the AP-16 audio, sychronized servo movements to the audio, then setting the solenoid to off. This is followed by a pot read for a post delay timer.
I need your IO map.
Out_In PIN RC
Sio PIN RC.7 ' SETUP = UP; NO ULN
Trigger PIN RC.6 ' SETUP = DN; NO ULN
PreDlayPot PIN RC.5 ' SETUP = OUT; NO ULN
PostDlayPot PIN RC.4 ' SETUP = OUT; NO ULN
GrnLED PIN RC.3 OUTPUT ' Green LED for PreDlayPot
YelLED PIN RC.2 OUTPUT ' Yellow LED for PostDlayPot
C_IO1 PIN RC.1 ' unused C_IO1
C_IO0 PIN RC.0 ' unused C_IO0
UpSol PIN RB.7 OUTPUT ' solenoid UP coil
DownSol PIN RB.6 OUTPUT ' solenoid DOWN coil
ServoCtrl PIN RB OUTPUT ' servo control pins
Servo5 PIN RB.5 ' unused P5/B_OUT5
Servo4 PIN RB.4 ' use P4
Servo3 PIN RB.3 ' use P3
Servo2 PIN RB.2 ' use P2
Servo1 PIN RB.1 ' use P1
Servo0 PIN RB.0 ' use P0
'TX PIN RA.3 OUTPUT ' to PC
'RX PIN RA.2 INPUT ' from PC
'SCL PIN RA.1 INPUT ' EE clock line (I2C)
'SDA PIN RA.0 INPUT ' EE data line (I2C)
Here's something to work with. PLEASE remember that SX code is never easy when dealing with background processes and one cannot simply cut-and-paste code from program A to program B.
For example, the last demo I wrote for you ran the interrupt at 10us but that's not fast enough for 38.4K baud comms so I had to change that to 3.33us. This means working through all the code to adjust the timing.
So... proceed carefully, but this should get you a long way down the road. Note that this is TX only code, do not use the "V" or "G" commands with the AP-16+.
' =========================================================================
'
' File......
' Purpose...
' Author....
' E-mail....
' Started...
' Updated...
'
' =========================================================================
' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
' -------------------------------------------------------------------------
' Conditional Compilation Symbols
' -------------------------------------------------------------------------
' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------
ID "Migman_2"
DEVICE SX28, OSCHS2, BOR42
FREQ 50_000_000
' -------------------------------------------------------------------------
' I/O Pins
' -------------------------------------------------------------------------
Out_In PIN RC
Sio PIN RC.7 ' SETUP = UP; NO ULN
Trigger PIN RC.6 ' SETUP = DN; NO ULN
PreDlayPot PIN RC.5 ' SETUP = OUT; NO ULN
PostDlayPot PIN RC.4 ' SETUP = OUT; NO ULN
GrnLED PIN RC.3 OUTPUT ' Green LED for PreDlayPot
YelLED PIN RC.2 OUTPUT ' Yellow LED for PostDlayPot
C_IO1 PIN RC.1 ' unused C_IO1
C_IO0 PIN RC.0 ' unused C_IO0
UpSol PIN RB.7 OUTPUT ' solenoid UP coil
DownSol PIN RB.6 OUTPUT ' solenoid DOWN coil
ServoCtrl PIN RB ' servo control pins
Servo5 PIN RB.5 OUTPUT ' use P5
Servo4 PIN RB.4 OUTPUT ' use P4
Servo3 PIN RB.3 OUTPUT ' use P3
Servo2 PIN RB.2 OUTPUT ' use P2
Servo1 PIN RB.1 OUTPUT ' use P1
Servo0 PIN RB.0 OUTPUT ' use P0
TX PIN RA.3 INPUT PULLUP ' to PC
RX PIN RA.2 INPUT PULLUP ' from PC
SCL PIN RA.1 INPUT ' EE clock line (I2C)
SDA PIN RA.0 INPUT ' EE data line (I2C)
' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------
IsOn CON 1
IsOff CON 0
Yes CON 1
No CON 0
' Bit dividers for 3.33 uS interrupt
Baud2400 CON 125
Baud38K4 CON 8
Baud1x0 CON Baud38K4 ' 1 bit period (ISR counts)
Baud1x5 CON Baud1x0 * 3 / 2 ' 1.5 bit periods
TAB CON 9
LF CON 10
FF CON 12 ' like CLS for terminals
CR CON 13
LO_LIMIT CON 60 ' to prevent servo burn-up
CENTER CON 150
HI_LIMIT CON 240
' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------
flags VAR Byte ' (keep global)
isrFlag VAR flags.0
us10Flag VAR flags.1
tmpB1 VAR Byte
tmpB2 VAR Byte
tmpB3 VAR Byte
tmpB4 VAR Byte
tmpW1 VAR Word
tmpW2 VAR Word
' define arrays after simple variables
txSerial VAR Byte (16) ' tx serial data
txBuf VAR txSerial(0) ' eight-byte buffer
txCount VAR txSerial(8) ' tx bit count
txDivide VAR txSerial(9) ' bit divisor timer
txLo VAR txSerial(10) ' holds start bit
txHi VAR txSerial(11) ' tx output reg
txHead VAR txSerial(12) ' buffer head (write to)
txTail VAR txSerial(13) ' buffer tail (read from)
txBufCnt VAR txSerial(14) ' # bytes in buffer
svoData VAR Byte (16) ' bank servo data
pos VAR svoData(0) ' position table
pos0 VAR svoData(0)
pos1 VAR svoData(1)
pos2 VAR svoData(2)
pos3 VAR svoData(3)
pos4 VAR svoData(4)
pos5 VAR svoData(5)
pos6 VAR svoData(6)
pos7 VAR svoData(7)
svoTix VAR svoData(8) ' isr divider
svoFrame_LSB VAR svoData(9) ' frame timer
svoFrame_MSB VAR svoData(10)
svoIdx VAR SvoData(11) ' active servo pointer
svoTimer VAR svoData(12) ' pulse timer
svoPin VAR svoData(13) ' active servo pin
' =========================================================================
INTERRUPT NOPRESERVE 300_000 ' (4) run every 3.33 uS
' =========================================================================
Mark_ISR:
\ SETB isrFlag ' (1)
' -------
' TX UART
' -------
'
' UART code by C. Gracey, A. Williams, et al
' -- buffer mods by Jon Williams
'
Transmit:
ASM
BANK txSerial ' (1)
TEST txCount ' (1) transmitting now?
JZ TX_Buffer ' (2/4) if txCount = 0, no
DEC txDivide ' (1) update bit timer
JNZ TX_Done ' (2/4) time for new bit?
MOV txDivide, #Baud1x0 ' (2) yes, reload timer
STC ' (1) set for stop bit
RR txHi ' (1) rotate TX char buf
RR txLo ' (1)
DEC txCount ' (1) update the bit count
MOVB TX, txLo.6 ' (4) output the bit
JMP TX_Done ' (3)
TX_Buffer:
TEST txBufCnt ' (1) anything in buffer?
JZ TX_Done ' (2/4) exit if empty
MOV W, #txBuf ' (2) point to buffer tail
ADD W, txTail ' (1)
MOV FSR, W ' (1)
MOV txHi, IND ' (2) move byte to TX reg
CLR txLo ' (1) clear for start bit
MOV txCount, #10 ' (2) start + 8 + 1 stop
INC txTail ' (1) update tail pointer
CLRB txTail.3 ' (1) keep 0..7
DEC txBufCnt ' (1) update buffer count
TX_Done:
ENDASM
' ----------------
' Servo Processing
' ----------------
'
Test_Servo_Tix:
ASM
BANK svoData ' (1)
INC svoTix ' (1) update divider
CJNE svoTix, #3, Servo_Done ' (4/6) svoTix = 3?
CLR svoTix ' (1) yes, reset for next
' Code below this point runs every 10 uS
SETB us10Flag ' (1) set every 10us
Check_Frame_Timer:
CJNE svoFrame_LSB, #2000 & 255, Inc_FrTmr ' (4/6) svoFrame = 2000 (20 ms)?
CJNE svoFrame_MSB, #2000 >> 8, Inc_FrTmr ' (4/6)
CLR svoFrame_LSB ' (1) yes, reset
CLR svoFrame_MSB ' (1)
MOV svoPin, #%0000_0001 ' (2) start servo sequence
CLR svoIdx ' (1) point to servo 0
MOV FSR, #pos ' (2)
MOV svoTimer, IND ' (2)
JMP Refesh_Servo_Outs ' (3)
Inc_FrTmr:
INC svoFrame_LSB ' (1) DEC svoFrame
ADDB svoFrame_MSB, Z ' (2)
Check_Servo_Timer:
TEST svoPin ' (1) any servos on?
SNZ ' (1)
JMP Servo_Done ' (1) no, exit
DEC svoTimer ' (1) yes, update timer
SZ ' (1) still running?
JMP Servo_Done ' (1) yes, exit
Reload_Servo_Timer:
INC svoIdx ' (1) point to next servo
MOV W, #pos ' (1) get pulse timing
ADD W, svoIdx ' (1)
MOV FSR, W ' (1)
MOV W, IND ' (1)
MOV svoTimer, W ' (1) move to timer
Select_Next_Servo:
CLC ' (1)
RL svoPin ' (1)
AND svoPin, #%0011_1111 ' (2) limit servo channels
Refesh_Servo_Outs:
AND ServoCtrl, #%1100_0000 ' (2) clear last
OR ServoCtrl, svoPin ' (2) update outputs
Servo_Done:
ENDASM
ISR_Exit:
RETURNINT ' (4)
' =========================================================================
' Subroutine / Function / Task Declarations
' =========================================================================
DELAY_MS SUB 2, 2, Word, Word ' shell for PAUSE
RD_PREPOT FUNC 1, 0 ' read on time pot
RD_POSTPOT FUNC 1, 0 ' read off time pot
TX_BYTE SUB 1 ' transmit a byte
TX_STR SUB 2, 2, Word ' transmit a string
' =========================================================================
PROGRAM Start
' =========================================================================
Start:
PUT pos, CENTER, CENTER, CENTER, CENTER, CENTER, CENTER
Main:
tmpB1 = 0
Check_Trigger:
DELAY_MS 1
INC tmpB1
IF Trigger = IsOff THEN Main
IF tmpB1 < 100 THEN Check_Trigger
Program_Code:
' SEROUT Sio, Baud, ("!AP16", %00, "PW", "WOLF", 13, 1)
TX_STR "!AP16"
TX_BYTE %00
TX_STR "PW"
TX_STR "WOLF"
TX_BYTE CR
TX_BYTE 1
DELAY_MS 5_000
GOTO Main
' -------------------------------------------------------------------------
' Subroutine / Function / Task Code
' -------------------------------------------------------------------------
' Use: DELAY_MS milliseconds
' -- replaces PAUSE
SUB DELAY_MS
'{$IFUSED DELAY_MS}
ms VAR __WPARAM12
msTix VAR __WPARAM34
DO WHILE ms > 0
msTix = 300 ' set for 1ms
DO WHILE msTix > 0 ' run 1ms timer
\ CLRB isrFlag ' clear flag
\ JNB isrFlag, @$ ' wait for next
DEC msTix ' update msTix count
LOOP
DEC ms ' update ms count
LOOP
'{$ENDIF}
ENDSUB
' -------------------------------------------------------------------------
' Use: value = RD_PREPOT
' -- duplicates BS1 POT function
' -- remove ULN influence and SETUP jumpers from pin
FUNC RD_PREPOT
'{$IFUSED RD_PREPOT}
potTix VAR __PARAM1
HIGH PreDlayPot ' charge RC circuit
DELAY_MS 10
potTix = 0 ' clear measurement
DO
LOW PreDlayPot ' discharge a little
\ CLRB us10Flag ' clear flag
\ JNB us10Flag, @$ ' wait for next
INPUT PreDlayPot ' release to check
INC potTix
IF potTix = 0 THEN EXIT ' abort if stuck
LOOP UNTIL OnPot = 0 ' wait until discharged
RETURN potTix
'{$ENDIF}
ENDFUNC
' -------------------------------------------------------------------------
' Use: value = RD_POSTPOT
' -- duplicates BS1 POT function
' -- remove ULN influence and SETUP jumpers from pin
FUNC RD_POSTPOT
'{$IFUSED RD_POSTPOT}
potTix VAR __PARAM1
HIGH PostDlayPot ' charge RC circuit
DELAY_MS 10
potTix = 0 ' clear measurement
DO
LOW PostDlayPot ' discharge a little
\ CLRB us10Flag ' clear flag
\ JNB us10Flag, @$ ' wait for next
INPUT PostDlayPot ' release to check
INC potTix
IF potTix = 0 THEN EXIT ' abort if stuck
LOOP UNTIL PostDlayPot = 0 ' wait until discharged
RETURN potTix
'{$ENDIF}
ENDFUNC
' -------------------------------------------------------------------------
' Use: TX_STR [String | Label]
' -- pass embedded string or DATA label
SUB TX_STR
'{$IFUSED TX_STR}
strAddr VAR tmpW1
sChar VAR __PARAM1
strAddr = __WPARAM12 ' get offset/base
DO
READINC strAddr, sChar ' read a character
IF sChar = 0 THEN EXIT ' if 0, string complete
TX_BYTE sChar ' send the byte
LOOP
'{$ENDIF}
ENDSUB
' -------------------------------------------------------------------------
' Use: TX_BYTE aByte
' -- moves "aByte" to 8-byte circular buffer (when space is available)
' -- will wait if buffer is presently full
' -- txBufCnt holds byte count of transmit buffer (0 to 8)
SUB TX_BYTE
'{$IFUSED TX_BYTE}
ASM
MOV FSR, #txSerial ' point to tx vars
JB txBufCnt.3, $ ' prevent buffer overrun
MOV W, #txBuf ' point to buffer head
ADD W, txHead
MOV FSR, W
MOV IND, __PARAM1 ' move byte to tx buf
INC txHead ' update head pointer
CLRB txHead.3 ' keep 0..7
INC txBufCnt ' update buffer count
MOV FSR, #__DEFAULT
ENDASM
'{$ENDIF}
ENDSUB
' -------------------------------------------------------------------------
' =========================================================================
' User Data
' =========================================================================
Jon, The code that you provided looks like what I wanted but there are a couple of things that I wanted to clear up. I made the change to the Delay_MS subroutine to make the msTix VAR a word and set it to 300 as would be needed for a 3.33 ms interrupt cycle. When I did this everyting stopped working. I tried several things and found that if the value of the msTix is greater than 255 the routine never exits. It is like the DEC command doesn't work on a word value. I tried several different combinations with word and byte values and found that it doesn't matter what I use for a word VAR anything over 255 cause the subroutine to hang. Any comments?
Second thing was that I had hoped to use bit 7 of the "C" port as the serial communications connection rather than the "A" port which I am at a lose as to what the "A" port connection is? One program that I looked at had the "A" port defined with a little more info as the DB9 connector but I still have been unable to find any definition as to which pins are which on the DB9 connector
I'm confused. This declaration promotes any value you use with DELAY_MS to a word:
DELAY_MS SUB 2, 2, Word, Word ' shell for PAUSE
And this code is setup for 300 cycles per millisecond which matches the interrupt rate.
' Use: DELAY_MS milliseconds
' -- replaces PAUSE
SUB DELAY_MS
'{$IFUSED DELAY_MS}
ms VAR __WPARAM12
msTix VAR __WPARAM34
DO WHILE ms > 0
msTix = 300 ' set for 1ms
DO WHILE msTix > 0 ' run 1ms timer
\ CLRB isrFlag ' clear flag
\ JNB isrFlag, @$ ' wait for next
DEC msTix ' update msTix count
LOOP
DEC ms ' update ms count
LOOP
'{$ENDIF}
ENDSUB
The DEC used for decrementing msTix is the SX/B version which will work with works so there should be no issue (the \ in front of an instruction is used for inline Assembly).
The transmit routine in the interrupt uses the pin defined as TX; if you change this is the pin definitions to RC.7 then it will transmit from P15 on the board. This code only has transmit capability, so do not use commands that expect a response.
Yep, I missed that subtle change to the DelayMS routine. I changed msTix from param3 to wparam34 and the preset value from 100 to 300 but missed the "\" removal from the DEC line. You the man!
Well I'm stumped. I have connected a O scope up to the TX output pin and I get nothing when I try and call a !AP16 function. I decided to see if I could get any thing by just writing directly to the TX pin. I commented out the Transmit interrupt code and programed a do loop that writes a 1 to TX (\ MOVB TX, 1) then waits 1 ms (DELAY_MS 1) then writes a 0 to TX then waits another 1 ms. The loop continues until I reset the board. Still nothing on the TX pin. I even changed the define of TX to a spare pin on the "C" port (0). I checked the pins that are being pulsed for the servos and I can see those pulses. Any Ideas?
You're using TX only code so you need to make the pin that's transmitting an output.
Since I'm using pin 7 of the "C" port for TX, should it be pulled up or pulled down or left to float. Currently it is junpered to pullup. I was able to get the commands to the AP16 to start the different sound tracks but I noticed that the very first time the routine runs after powerup that the first command to the AP16 fails. Should there be some initial setup with the txserial ?
With that code you can pull it up or let it float. The output is driven (so DO NOT request the version or status from the AP-16+). If you want to talk back and forth you need a half-duplex, open-drain driver. I have one (used in the FC-4).
I'm not sure if I should ask this here or in the AP-16 forum but I have a question about how to send the "R" of the relay command. Should that be a TX_BYTE "R" or a TX_STR "R" command for the SX. I've downloaded the new version 1.7 but the relay command as described in the AP-16 PDF file doesn't seem to activate the relay. I have the command set up as TX_STR "R".
TX_STR "!AP16"
TX_BYTE %00
TX_STR "R"
TX_BYTE 1 ' to turn it on TX_BYTE 0 'to turn it off
Does there need to be any kind od an IDLE delay between commands to the AP-16?
For single characters you would use TX_BYTE. Change the TX_STR "R" to TX_BYTE "R"
The AP-16+ has a 64-byte buffer that is checked every 50ms, so long as you don't overrun that you'll be okay without delays.