Combine 2 different 8bit ports into 1 word Var and set/reset a specific bit

Started by Ecoli-557, Jan 27, 2025, 04:28 PM

Previous topic - Next topic

trastikata

The structure you posted does not make much sense. I guess you would like to do this:

Dim OutputState As PORTF
Dim OutputStateH As PORTA
Dim wOutputStateData As OutputState.Word
Dim PortNum As Byte
Dim PortFunc As Byte

Main:
    LoadBit wOutputStateData, PortNum, PortFunc

Ecoli-557

Thank you trastikata but I am not making myself clear and I am getting frustrated over this simple task so I am stepping away for the evening to clear my head and to give you and others time to get something you need/want to get accomplished.
Thanks to all who have offered assistance so far.

RGV250

Hi,
So do you have a PC program or an app which you decide which outputs are on/off. If so are you sending just a byte in which case I do not think it will work. If you are sending a word then I do not see why you cannot just move that data to the output ports.

Bob

RGV250

Hi,
Hopefully this is something like what you are looking for. It works on an Amicus18 board receiving 2 bytes from the serial port. Combines them in to a word and then shows the outputs.
Include "Amicus18.inc"

    Dim ByteIn As Byte
    Dim Inword As Word
    Dim Carriage_Return As Byte
    TRISA = %00000000
    TRISB = %00000000
    DelayMS 100                         ' Wait for things to stabilise
    Carriage_Return = 13                ' Value to wait for

    HSerOut ["Press Return - 8-bit Value - then Return twice.",13]
    While 1 = 1                         ' Create an infinite loop
   
        HSerIn [Wait(Carriage_Return) , Dec ByteIn]   ' Read in the data for Port A
        Inword.LowByte = ByteIn                       ' Store it
        HSerIn [Wait(Carriage_Return) , Dec ByteIn]   ' Read in the data for Port B
        Inword.HighByte = ByteIn                      ' Store it
        HSerOut [Dec Inword.LowByte," . ",Dec Inword.HighByte,13] 'show the values read in.             
        PORTA = Inword.LowByte                        ' Write to the port
        PORTB = Inword.HighByte                       ' Write to the port
       
    Wend                                ' Close the loop

Stephen Moss

I think the following is similar to what you want, in the Mechanic IDE if you click on ISIS and select PIC16_ALCD it will run on that and you can see each writable pin of Ports A & C change colour as each bit is set.

Device = 16F877
Declare Xtal = 4

TRISA = $00
TRISC = $00

Dim MyWord As Word  = $00

Dim x As Word

Start:
For x = 0 To 15
SetBit MyWord, x
Print At 1,1, Bin MyWord
DelayMS 2000
PORTA = MyWord.LowByte   'Write data to the I/O port
PORTC = MyWord.HighByte  'Write data to the I/O port
Next
DelayMS 2000
MyWord = $00
GoTo Start

although that is a somewhat basic example, I think if you want to set or clear then a Procedure would be better, something like the following may work...

Dim MyWord As Word  = $00
Dim bitNum As Byte
Dim True As Bit = 1
Dim False As Bit = 0

MyWord = Set_Clear(MyWord, bitNum, True) 'used to Call the procedure to clear the bit & return the updated value of MyWord (place in code where applicable)
MyWord = Set_Clear(MyWord, bitNum, False) 'used to Call the procedure to set the bit & return the updated value of MyWord (place in code where applicable)


Proc Set_Clear(ByVal PortData As Word, ByVal bitNum As Word, ByVal ClearME As Bit), Word
If ClearMe = True Then
Result = ClearBit PortData, bitNum
Else
Result = SetBit PortData, bitNum
End If

PORTA = Result.LowByte   'Send modified data to I/O Port
PORTC = Result.HighByte  'Send modified data to I/O Port

End Proc
You could move the port data writes into the main code if you do not want it to occur immediately after the data modification it is neater here as you only need to do it once rather than after every call to the proceedure.   

top204

Remember Stephen, the ByVal directive is the default if it is not used with a parameter, so it does not need to be placed.

The mechanism can be accomplished with a procedure, but it is simpler, and clearer, to use some aliasing as trastikata has written.

For example:

    Dim bDummy_Ports  As PORTB              ' Alias the internal low byte of a Word variable to PORTB
    Dim bDummy_PortsH As PORTC              ' Alias the internal high byte of a Word variable to PORTC
    Dim Port16        As bDummy_Ports.Word  ' Combine the low and high variables into a 16-bit variable
      
    Port16 = $1234
    Port16.1 = 1
    Port16.15 = 1

Whenever "Port16" is written or read, the compiler treats it as a 16-bit variable.

The assembler code for the above code snippet is:

F1_000047 equ $ ; in [TEST_18F25K20.BAS] Port16 = $1234
    movlw 18
    movwf bDummy_PortsH,0
    movlw 52
    movwf bDummy_Ports,0
F1_000048 equ $ ; in [TEST_18F25K20.BAS] Port16.1 = 1
    bsf bDummy_Ports,1,0
F1_000049 equ $ ; in [TEST_18F25K20.BAS] Port16.15 = 1
    bsf bDummy_PortsH,7,0

And as can be seen, it is treated as a word sized variable that is actually a combination of two port SFRs:

#define bDummy_Ports PORTB
#define bDummy_PortsH PORTC
#define Port16 bDummy_Ports


I have used the above method several times when I required a 16-bit port on an 8-bit device for early 12-bit to 16-bit R2R DACs etc...

Ecoli-557

Thanks to All-
Ok OK OK,
The ethernet packet parsing now works with the desired result.
I have removed from my head more of my previous PBP cobwebs in favor of this compiler.

Current Code:
    Dim bDummy_Ports  As PORTF              ' Alias the internal low byte of a Word variable to PORTF
    Dim bDummy_PortsH As PORTA              ' Alias the internal high byte of a Word variable to PORTA
    Dim OutputState   As bDummy_Ports.Word  ' Combine the low and high variables into a 16-bit variable

The deciding Case Selection in from the ethernet port:
CaseSelection:   
    Select Case TempCase
Case80: Case 0x80 
                If PortFunc = 0x04 Then
                    Setbit OutputState, PortNum   '1 at selected port bit
                    GoSub DispPortNum
                    GoSub SendFeedBack
                    Pstat = 0         'for feedback on 7-segment display
                EndIf
                If PortFunc = 0x00 Then
                    Clearbit OutputState, PortNum   '0 at selected port bit
                    GoSub DispPortNum
                    GoSub SendFeedBack
                    Pstat = 1        'for feedback on 7-segment display
                EndIf
         End Select   

Now, for some reason, I have to send the same packet data twice to see the desired results, onward and upward - through the fog...

Thank you
trastikata
RGV250
Stephen Moss
and of course, TOP204
you have dragged me kicking and screaming into a new world.......
Regards to All,
Stephen

Stephen Moss

Quote from: top204 on Jan 28, 2025, 12:48 PMRemember Stephen, the ByVal directive is the default if it is not used with a parameter, so it does not need to be placed.
It has just become habit to use it as I do a lot of coding in Visual Basic, although I think even in that ByVal may be the assumption if you don't specify, but doing so means I (or my subsequent replacement) can be certain of how I intended the data to be passed when I come back to the code several years later.
Additionally, by including it I am potentially future proofing my code in case a subsequent change to the compiler is ever made that necessitates removing that assumption and having to subsequently specify ByVal instead.

Equally, in VB I can call a subroutine in another module with simply SubroutineName(), but I tend to use Call ModuleName.SubroutineName(), again because anyone returning to the code several years later can more easily see to which of possibly a dozen modules that make up the entire program the code is jumping to when the module name is included in the call.

top204

I know what you mean Stephen.

I have picked up many, many habits with programming that I do without even being aware that I am doing them. :-) For me, it creates a "comfort zone" with a rythmic order to them, and allows my eyes to scan a piece of code I have created without actually fully examining the syntax.

Ecoli-557

Agreed.
When I look back on code from 10 years ago I marvel at how 'clever' I was, then try to understand the flow - gets harder and harder each and every year......
My 'clever' days I suspect are gone now, although. I did get a Wiz W6100 to work with this compiler with 1 socket, now, to eventually get all 8 to be useful.
When ready, I will make my board and code available to others......

John Lawton

Quote from: Ecoli-557 on Jan 29, 2025, 01:39 PMWhen ready, I will make my board and code available to others......
That'll be interesting, using TCP/IP is non trivial but very useful connectivity.

charliecoutas

What truth you all speak. I look at code that I wrote 20+ years ago and wonder how the hell it works. I too used to be a lot cleverer than I am now. I have always insisted on good, meaningful comments on all my code, but the discreet techniques that I have used in the past almost baffle me now.

I suppose it's part of growing old.....

Charlie