• AVR Freaks

Helpful ReplyHot!mixed C and assembly port manipulation

Page: < 123 > Showing page 2 of 3
Author
ric
Super Member
  • Total Posts : 24593
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 17:32:40 (permalink)
0
Even nicer, although you could have added some comments to let the OP know what's going on. ;)
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#21
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3338
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 18:06:27 (permalink)
-1 (1)
My logic would be to get a chip that can meet the task.
 
Give this a shot:
char bitmask = 0x80;
loop:
    [led logic here]
    bitmask = bitmask >> 1;
    if(bitmask) goto loop;

 

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#22
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3338
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 18:08:44 (permalink)
-1 (1)
Just realised I have had headphones on for half an hour with no music playing.

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#23
ric
Super Member
  • Total Posts : 24593
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 18:18:16 (permalink)
0
1and0
Nice!  I'll see you and raise you:

I'll raise you again (ultimate speed, at the cost of some more code space)
void sendByte(volatile unsigned char byte)
{   //parameter will arrive in WREG
    asm("banksel LATA         ");
    asm("btfsc   WREG,7       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");

    asm("btfsc   WREG,6       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");

    asm("btfsc   WREG,5       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");

    asm("btfsc   WREG,4       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");

    asm("btfsc   WREG,3       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");

    asm("btfsc   WREG,2       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");

    asm("btfsc   WREG,1       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");

    asm("btfsc   WREG,0       ");
    asm("bsf     LATA & 0x7F,0");
    asm("nop                  ");
    asm("bsf     LATA & 0x7F,0");
    asm("bcf     LATA & 0x7F,0");
}
 


I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#24
dan1138
Super Member
  • Total Posts : 3287
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 18:52:01 (permalink)
0
Just thinking
;
; For the neopixels the PIC16F1512 instruction clock needs a
; period of 0.30us and system oscillator period of 0.075us,
; about 13.3 MHz.
;
; The a system oscillator of 16MHz will likely work, but
; tweaks in the send loop may be needed.
;
    banksel ByteCount
    movlw   D'3'
    movwf   ByteCount

    movlw   LOW(BytesToSend)
    movwf   FSRL
    movlw   HIGH(BytesToSend)
    movwf   FSRH
    banksel LATA
    bcf     LATA,0
;
; delay for more than 50 microseconds
; to reset the neopixel data line.
;
SendNext:
    banksel LATA
    rlf     INDF,W
    bsf     WREG,0   ;  Output bit is: 0  1
SendLoop:            ; ---------------------
    btfsc   STATUS,C ; cycle: 0 LATA0: 0  0
    bsf     LATA,0   ; cycle: 1 LATA0: 0  1
    bsf     LATA,0   ; cycle: 2 LATA0: 1  1
    bcf     LATA,0   ; cycle: 3 LATA0: 0  0
    addwf   WREG,F   ; cycle: 4 LATA0: 0  0
    btfss   STATUS,Z ; cycle: 5 LATA0: 0  0
    bra     SendLoop ; cycle: 6 LATA0: 0  0
                     ; cycle: 7 LATA0: 0  0
    incf    FSRL
    btfsc   STATUS,Z
    incf    FSRH
    banksel ByteCount
    decfsz  ByteCount,F
    bra     SendNext



post edited by dan1138 - 2019/10/15 15:22:55
#25
Mysil
Super Member
  • Total Posts : 3476
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 19:10:50 (permalink)
+1 (1)
Hi,
Make sure it doesn't get too fast.
 
There is some differences between specifications for different devices,
and some differences between characteristics observations in documents referred in previous messages,
but there is minimum time needed between bit transfer,
or minimum time needed for LOW period.
 
Josh.com:
"There is a minimum time the level must stay low between consecutive bits (TxL), which ensures that the chip sees  separate bits rather than one long bit."
 
or Tim's blog:
T_period_in. When the period time of the input signal was much shorter than 1250 ns, the WS2812 started to reject input pulses. As can be seen for 333 ns, only about every fifth input pulse is replicated in the output pulses. The shortest pulse period time where all input pulses appeared on the data output was 1063 ns."
 
This is time consomed by loop control and other overhead in code suggested in previous messages.
 
    Mysil
#26
ric
Super Member
  • Total Posts : 24593
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 19:25:09 (permalink)
+1 (1)
The OP's PIC (PIC16F1512) is running at 16MHz, so 250ns per instruction.
My "unrolled" code is a constant 5 instructions per bit => 1250ns per bit, so well over the 1063ns threshold.
It would be a different story if the PIC was running at 32MHz.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#27
1and0
Access is Denied
  • Total Posts : 9989
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 19:38:05 (permalink)
+2 (2)
ric
Even nicer, although you could have added some comments to let the OP know what's going on. ;)

Comment is added as requested. ;)
 
ric
I'll raise you again (ultimate speed, at the cost of some more code space)

Smaller file size and cleaner as an assembly file sendByte.as ;)
#include <xc.inc>
global _sendByte
psect   sendByte,local,class=CODE,delta=2
_sendByte:
        banksel LATA
    IRP bit,7,6,5,4,3,2,1,0
        btfsc   WREG,bit
        bsf     LATA0
        nop
        bsf     LATA0
        bcf     LATA0
    ENDM
        return

 
Edit: Make sure you have a prototype for the assembly routine:
void sendByte(uint8_t byte);

 
 
post edited by 1and0 - 2019/10/14 19:46:18
#28
ric
Super Member
  • Total Posts : 24593
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 19:52:23 (permalink)
0
1and0
Smaller file size and cleaner as an assembly file sendByte.as ;)

Very impressive!
I've never tried the IRP macro before. That's very elegant.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#29
bitdoctor
Starting Member
  • Total Posts : 26
  • Reward points : 0
  • Joined: 2019/10/11 06:10:09
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 20:01:29 (permalink)
0
Mysil
Hi,
Make sure it doesn't get too fast.
[...]
This is time consomed by loop control and other overhead in code suggested in previous messages.
 
    Mysil

Yes, my reasoning is that when working in multiples of 250 ns., the inter-bit time should exceed the longest of T0L and T1L which is 650ns. The next clock step after that is 3 cycles, or 750ns. With my lazy code, I don't have to sweat that, as you said. Everything (the scoped LED strip) always worked using 1 cycle for T0H, 3 for T1H, minimum 3 for T0L or T0H, minimum 200 (50us*4) cycles for a reset (latch op). Also comfortably within spec. You could get more fine grained with a higher clock speed.
 
I think the main confusion about the whole timing thing is that all the manufacturer spec minimums are true, but apparently not all the maximums.
post edited by bitdoctor - 2019/10/14 20:29:54
#30
ric
Super Member
  • Total Posts : 24593
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 20:16:00 (permalink)
0
I just happen to have a board with a PIC16F1829 at home connected to a string of SK6812RGBW LEDs.
I may try slowing it down to 16MHz and see if the post#28 code works.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#31
1and0
Access is Denied
  • Total Posts : 9989
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 20:27:23 (permalink)
0
ric
 
I've never tried the IRP macro before. That's very elegant.

Yeah, too bad the asm() form of in-line assembly statement does not accept it.
#32
ric
Super Member
  • Total Posts : 24593
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/14 20:45:18 (permalink)
0
The asm() form seems horribly limited.
You could do much more in the #asm/#endasm form in XC8 v1.xx that just is not possible now.

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#33
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3338
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/15 01:57:28 (permalink)
-1 (1)
In 16bit IRP becomes:
 
.irpc   reg, 02468
    push.d  w\reg
.endr
 

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#34
ric
Super Member
  • Total Posts : 24593
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/15 02:29:22 (permalink)
0 (2)
Marty, why do you keep offering 16 bit solutions in 8 bit forums?

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#35
dan1138
Super Member
  • Total Posts : 3287
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/15 14:29:57 (permalink)
0 (2)
ric
Marty, why do you keep offering 16 bit solutions in 8 bit forums?

When all your problems look like nails your tools look like hammers.
#36
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3338
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/15 16:12:04 (permalink)
-1 (1)
That was not a solution, you did not even bother to read the post.
 
 

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#37
dan1138
Super Member
  • Total Posts : 3287
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/15 16:20:16 (permalink)
0
After looking at a bunch of the neopixel data sheets it seems that the T0L and T1L time is not that critical.

When the next bit low to high edge occurs before the data reset time out (50 microsecond) and long enough after the high to low edge of the bit cell start to not look like a false start event then it should work.

Here is a complete application that may work:
/*
 * File:   main.c
 * Author: dan1138
 * Target: PIC16F1512
 *
 * Created on October 15, 2019, 2:42 PM
 *
 *                             PIC16F1512
 *                  +-------------:_:-------------+
 *        VPP ->  1 : RE3/MCLR/VPP        PGD/RB7 : 28 <> PGD
 *   Neopixel <-  2 : RA0/AN0             PGC/RB6 : 27 <> PGC
 *            <>  3 : RA1/AN1        T1G/AN13/RB5 : 26 <>
 *            <>  4 : RA2/AN2            AN11/RB4 : 25 <>
 *            <>  5 : RA3/AN3             AN9/RB3 : 24 <>
 *            <>  6 : RA4/T0CKI           AN8/RB2 : 23 <>
 *            <>  7 : RA5/AN4            AN10/RB1 : 22 <>
 *        GND ->  8 : VSS            INT/AN12/RB0 : 21 <>
 *            <>  9 : RA7/OSC1                VDD : 20 <- 5v0
 *            <> 10 : RA6/OSC2                VSS : 19 <- GND
 *            <> 11 : RC0/SOSCO      RXD/AN19/RC7 : 18 <>
 *            <> 12 : RC1/SOSCI/CCP2 TXD/AN18/RC6 : 17 <>
 *            <> 13 : RC2/AN14/CCP1  SDO/AN17/RC5 : 16 <>
 *            <> 14 : RC3/AN15/SCK   SDI/AN16/RC4 : 15 <>
 *                  +-----------------------------:
 *                              DIP-28
 *
 * Description:
 *
 *  Demo code that "may" write to a string of 27 neopixels.
 *
 *  Note: Tested only with the MPLABX simulator, and you know what that means.
 */
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config VCAPEN = OFF     // Voltage Regulator Capacitor Enable bit (VCAP pin function disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

#include <xc.h>
#include <stdint.h>

#define _XTAL_FREQ (16000000ul)
/*
 * Initialize this PIC
 */
void PIC_Init(void)
{
    INTCON = 0;
    OSCCON = 0b01111010;    /* Select internal 16MHz oscillator */
    
    ANSELA = 0b11111110;    /* Make RA0 a digital output */
    TRISA  = 0b11111110;
    LATA   = 0b11111111;
}
/*
 * Update pixels
 */
void SendNeopixels(void *pPixels, uint8_t Bytes)
{
    FSR0 = (volatile unsigned short)pPixels;
    LATAbits.LATA0 = 0;
    __delay_us(50);
    do {
    __asm("  banksel LATA    ");
    __asm("  rlf     INDF0,W ");
    __asm("  bsf     WREG,0  ");
    __asm("SendLoop:         ");
    __asm("  btfsc   STATUS,0");
    __asm("  bsf     PORTA,0 "); /* Don't whine it is using the LATA register */
    __asm("  bsf     PORTA,0 ");
    __asm("  bcf     PORTA,0 ");
    __asm("  addwf   WREG,W  ");
    __asm("  btfss   STATUS,2");
    __asm("  bra     SendLoop");
    __asm("  addfsr  0,1     ");
    } while (--Bytes);
}
/*
 * Pixel structure
 */
struct {
    uint8_t Red;   /* The order may be different with your neopixel */
    uint8_t Blue;
    uint8_t Green;
} Buffer[27];
/*
 * Application loop
 */
void main(void)
{
    uint8_t Index;
    
    PIC_Init();
    
    for(Index = 0; Index < sizeof(Buffer)/sizeof(*Buffer); Index++)
    {
        Buffer[Index].Red   = 127; /* Who know what color this might be */
        Buffer[Index].Blue  = 63;  /* should be red-bluish green. */
        Buffer[Index].Green = 31;
    }
    for(;;)
    {
        SendNeopixels(Buffer, sizeof(Buffer));
        NOP();
    }
}

post edited by dan1138 - 2019/10/16 00:25:34
#38
trossin
New Member
  • Total Posts : 26
  • Reward points : 0
  • Joined: 2006/06/02 11:31:50
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/15 18:23:58 (permalink)
+1 (1)
Those Neopixels are picky. If you just want to drive one pixel it is not bad. Driving a string requires very repeatable timing or you will get random color changes. I was able to drive a long string with an 18F1330 all in C code using the free XC8 compiler by extracting each color byte before wiggling the port using 24 statements like:

If(red & 0x02) SendOne(); else SendZero();

The 24 lines are in a loop per pixel
#39
trossin
New Member
  • Total Posts : 26
  • Reward points : 0
  • Joined: 2006/06/02 11:31:50
  • Location: 0
  • Status: offline
Re: mixed C and assembly port manipulation 2019/10/15 18:23:59 (permalink)
0
Sorry double posted
#40
Page: < 123 > Showing page 2 of 3
Jump to:
© 2019 APG vNext Commercial Version 4.5