PDA

View Full Version : Confused by Arraywrite



retepsnikrep
- 19th July 2018, 15:52
I've looked at the examples and posts on here and they are helpful but.....

OK I have a 38x25 display.
I can talk to it using hserout and have a 1ms interrupt running so want to send it 1 character every ms.
No problems so far. I can do that.

I've modded the pb3 library (using the example post) to allow a 1000 element array to store my display data (38x25 = 950)
Not sure i need to do this and might be better using a smaller array (38 elements) and line at a time... :?

So some questions.. when i write to the array using array write what happens when it gets to the end? 1000th character is sent to it.
Yes it exit's but how do you reset it and start filling it from the beginning?
Does it reset every time you do an Array write?
What happens to the overflowed characters?
Do you have to manage the length to ensure the message you are sending so it will fit in?

Some working examples might be useful if anyone has any? Thanks

mpgmike
- 19th July 2018, 18:14
The ARRAYWRITE command prepends the LOOKUP or LOOKDOWN commands.



b0 VAR BYTE
b1 VAR BYTE
Letter VAR BYTE[9]
ARRAYWRITE Letter, ["SOMETHING"]
FOR b0 = 0 TO 8
LOOKUP b0, [Letter], b1
HSEROUT b1
NEXT b0


The ARRAYWRITE command loads what you want into a Table. In the code above, the ASCii "SOMETHING" is contained in the Table. The LOOKUP command pulls the ASCii letters from the Table one at a time and makes them available to the variable b1. If you wanted to send a dynamic value you could use:



Pot VAR BYTE
b0 VAR BYTE
b1 VAR BYTE
Letter VAR BYTE[3]
ADCIN 3,Pot
ARRAYWRITE Letter, [#Pot]
FOR b0 = 0 TO 2
LOOKUP b0, [Letter], b1
HSEROUT b1
NEXT b0


In the above code an ADC value is read from AN3 to Pot then turned to ASCii ([#Pot]). If the Pot value is 133, "ARRAYWRITE Letter, [#Pot]" will load the Array "Letter" with "1", "3", and "3". The code is abbreviated to get the idea across, not intended to be plug-n-play.

As for a 1000 Byte Array, PIC pages are limited to 256 bytes. You'll probably have to create 4 separate Tables to accommodate all 1000 variables. Consider an Array that contains the alphabet and numeric characters, or whatever, or a subroutine that converts your desired output to display-compatible format.

richard
- 19th July 2018, 23:15
mikes quote here is very wrong


As for a 1000 Byte Array, PIC pages are limited to 256 bytes. You'll probably have to create 4 separate Tables to accommodate all 1000 variables.


from the manual


Arrays must fit entirely within one RAM-bank on 12-bit and 14-bit devices (PIC10, PIC12, and PIC16). Arrays may span banks on PIC18 devices. On PIC18 devices, BYTE, WORD and LONG-sized arrays are only limited in length by the amount of available memory. The compiler will assure that arrays, as well as scalar variables, will fit in memory before successfully compiling.


the inflexible way

ARRAYWRITE Letter, ["SOMETHING"]
FOR b0 = 0 TO 8
LOOKUP b0, [Letter], b1
HSEROUT b1
NEXT b0

the flexible way , use null termination method


b0=0
ARRAYWRITE Letter, ["SOMETHING",0]
while letter[b0]
LOOKUP b0, [Letter], b1
b0=b0+1
wend

Dave
- 20th July 2018, 20:10
Richard, have you actually tried your null termination method?
When trying these lines of code :

OUTARRAY VAR BYTE(80) 'serial string output array
BYTEIN VAR BYTE
character VAR BYTE

BYTEIN = 0
WHILE OUTARRAY(BYTEIN)
LOOKUP BYTEIN,[OUTARRAY],CHARACTER
' TX_BYTES2(TX_OUTPUT2) = CHARACTER
BYTEIN = BYTEIN + 1
' GOSUB SNDCHAR2 'INCREMENT BUFFER POINTERS
WEND

I get the error: Expected '['

richard
- 20th July 2018, 22:14
have you actually tried your null termination method?

not that example , the lookup line might need to be lookup2 , the lookup line is not really relevant to the null termination array processing method


OUTARRAY VAR BYTE(80) 'serial string output array
BYTEIN VAR BYTE
character VAR BYTE

BYTEIN = 0
WHILE OUTARRAY(BYTEIN)
LOOKUP2 BYTEIN,[OUTARRAY],CHARACTER
' TX_BYTES2(TX_OUTPUT2) = CHARACTER
BYTEIN = BYTEIN + 1
' GOSUB SNDCHAR2 'INCREMENT BUFFER POINTERS
WEND

Dave
- 21st July 2018, 19:17
Well Richard, Making the statement LOOKUP2 does not seem to work. I have no idea where the data is coming from but, it is not what I set the ARRAYWRITE statement with. The only thing that is correct as I can see it is the string length.

richard
- 21st July 2018, 23:54
your correct dave , I have fallen into a trap set by mike, a sram array is not a valid source for any pbp lookup command . the concept seems flawed anyway surely the lookup table source should be the translated data table and the outarray data the index. we already have b0 as a pointer to the outarray data .
my intent was just to demonstrate how to cycle through an array of variable length using a null as the end marker

mpgmike
- 22nd July 2018, 11:48
Retypesnikrep, what are you wanting to display? Is there constants like "Temperature is " along with variables like "TempC VAR BYTE"? I've used the HD44780 based LCD for several projects. A display line would look like:



ARRAYWRITE LPsiA, [#LPsi]
for b0 = 0 to 13
LOOKUP b0,["Low PSI Set = "],b1
PORTB = b1
gosub Send
next b0
if LPsi < 10 then
LPsiA[1] = LPsiA[0]
LPsiA[0] = " "
endif
PORTB = LPsiA[0]
gosub Send
PORTB = LPsiA[1]
gosub Send


Here I use ARRAYWRITE to extract the individual digits of my pressure value LPsi into ARRAY LPsiA in ASCii format.

I use LOOKUP to extract individual characters from the string "Low PSI Set = ".

retepsnikrep
- 22nd July 2018, 14:17
basically I have a 1ms interrupt going on.

I want this to check a buffer for stuff waiting to be sent to the screen, and if stuff waiting then send it via Hserout one chr at a time.

OK so far.

I want to fill my large buffer using array write as it contains text and variables... ie
So it mimics the screen, as if I was writing it straight to the screen using hserout....

arraywrite buffer, ["Temperature 1 is ",#Temp1,"C",32,"Temperature 1 is ",#Temp1,"C"]

Dave
- 22nd July 2018, 15:53
Thanks Richard, I do understand now. By the way, What's Mpgmike and Retepsniarep talking about? It seems as though this tread has been hijacked.

Dave
- 22nd July 2018, 16:08
Richard, After chatting with Charles, I decided to eliminate the "lookup2" statement and just pass the array variable to the serial buffer routine. All is working now. Nice and neat. Here is the code:

'************************************************* ********************
SERIALOUT2: 'OUTPUT SERIAL STRING TO PORT 2
'************************************************* ********************
BYTEIN = 0
WHILE OUTARRAY(BYTEIN)
TX_BYTES2(TX_OUTPUT2) = OUTARRAY(BYTEIN)
BYTEIN = BYTEIN + 1
GOSUB SNDCHAR2 'INCREMENT BUFFER POINTERS
WEND
RETURN

richard
- 23rd July 2018, 00:04
I want to fill my large buffer using array write as it contains text and variables... ie
So it mimics the screen, as if I was writing it straight to the screen using hserout....

it sounds like a ring buffer may do what you need

richard
- 23rd July 2018, 00:27
here is a rx ring buffer example I worked on with someone on one of the pbp forums some years back.
its limited to 256 bytes max buffer size.



INCLUDE "DT_INTS-18.bas"
'INCLUDE "ReEnterPBP-18.bas"


ASM ;
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX1_INT, myint, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM


DEFINE DEBUG_REG PORTB
DEFINE DEBUG_BIT 7
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 0

TRISB.7=0 ;DEBUG
LATB.7=1 ;DEBUG





index_in VAR BYTE bank0 ' Pointer - next empty location in buffer
index_out VAR BYTE bank0 ' Pointer - location of oldest character in buffer
errflag VAR BYTE bank0 ' Error flag
UartFlag VAR errflag.0
BufferFlag VAR errflag.1



buffer_size CON 256 ' Sets the size of the ring buffer
buffer VAR BYTE[buffer_size] ' Array variable for holding received characters

BufChar VAR BYTE ' Stores the character retrieved from the buffer


' trisC.6=0 ;tx1
RCSTA1 = $90 ' Enable serial port & continuous receive
' TXSTA1 = $24 ' Enable transmit, BRGH = 1
SPBRG1 = 56 ' 38400 Baud @ 48MHz, -0.16%
SPBRGH1 = 1
BAUDCON1.3 = 1 ' Enable 16 bit baudrate generator





GoTo start ' Skip around interrupt handler

Asm
myint
; Check for hardware overrun error
btfsc RCSTA1,OERR ; Check for usart overrun
bra usart_err ; jump to assembly error routine
; Test for buffer overrun
incf _index_in,W ; Increment index_in to W
subwf _index_out,W ; Subtract indexes to test for buffer overrun
btfsc STATUS,Z ; check for zero (index_in = index_out)
bra buffer_err ; jump to error routine if zero
; Increment the index_in pointer and reset it if it's outside the ring buffer
incf _index_in,F ; Increment index_in to index_in
movf _index_in,W ; Move new index_in to W
sublw _buffer_size-1; Subtract index_in from buffer_size-1
btfss STATUS, C ; If index_in => buffer_size
clrf _index_in ; Clear index_in
; Set FSR with the location of the next empty location in buffer
movlw High _buffer ;Store the High byte of buffer to FSR0H
movwf FSR0H
movlw Low _buffer ; Get the Low byte of buffer[0]
addwf _index_in,W ; Add index_in to point to next empty slot
movwf FSR0L ; Store Low byte of pointer in FSR0
; Read and store the character from the USART
movf RCREG1,W ; Read the received character
movwf INDF0 ; Put the received character in FSR0 location
BTFSC PIR1,TX1IF ;ANY MORE ?
BRA myint

finished
RST?RP
INT_RETURN

; Error routines
buffer_err ; Jump here on buffer error
bsf _errflag,1 ; Set the buffer flag
usart_err ; Jump here on USART error
bsf _errflag,0 ; Set the USART flag
movf RCREG1, W ; Trash the received character
bra finished ; Restore state and return to program
EndAsm








start:
PAUSE 3000 ' Let ME CONNECT PICKIT UART MODULE
Debug "Start",13 ,13

index_in = 0 ' Initialize ringbuffer variables
index_out = 0
GOSUB error ;CLR AND RESET EUART


@ INT_ENABLE RX_INT ; Enable USART RX Interrupts
Main:
DEBUG "Main", 13 ,13

MainLoop:

display: ' dump the buffer to the terminal
IF errflag Then GOSUB error ' Goto error routine if needed
IF index_in = index_out Then mainloop ' loop if nothing in buffer
GoSub getbuf ' Get a character from buffer
debug bufchar ' Send the character to terminal
GoTo display ' Check for more characters in buffer

' Get a character from the buffer
getbuf: ' Move the next character in buffer to bufchar
intcon = 0 ' Disable interrupts while reading buffer
index_out = index_out + 1 ' Increment index_out pointer (0 to 63)
IF index_out => buffer_size Then index_out = 0 ' Reset pointer if outside buffer
bufchar = buffer[index_out] ' Read buffer location(index_out)
INTCON = %11000000 ' Enable interrupts
Return

' Display an error
error: ' Display error message
INTCON = 0 ' Disable interrupts while in the error routine
IF errflag.1 Then ' Determine the error
debug "B!",13,13 ' Display buffer error on line-2
Else
debug "U!",13,13 ' Display usart error on line_2
EndIF
PIR1.4=0
errflag = 0 ' Reset the error flag
RCSTA1.4=0 'CREN = 0 Disable continuous receive to clear hardware error
RCSTA1.4=1 'CREN = 1 Enable continuous receive
INTCON = %11000000 ' Enable interrupts
GoTo RETURN ' repeat

;clear any rcsta error