typedef struct
{
uint8_t bitcnt;
uint8_t red;
uint8_t green;
uint8_t blue;
} ws_ledasm_t;
ws_ledasm_t regs;
typedef struct
{
uint8_t bitcnt;
uint8_t green;
uint8_t red;
uint8_t blue;
} ws_ledasm_t;
void WS_paint(void)
{
uint8_t lednum;
static ws_ledasm_t regs;
if (!LEDPOWER)
return;
for (lednum=0; lednum < NUM_TRICOLOR_LEDS; lednum++)
{
regs.red = ws_ledbar[lednum].color.red;
regs.green = ws_ledbar[lednum].color.green;
regs.blue = ws_ledbar[lednum].color.blue;
regs.bitcnt = 24;
asm("BANKSEL WS_paint@regs");
asm("dllp1:");
asm("bcf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **Only need to disable ints for high of pulse
asm("bsf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start high -- 0.0ns (1) / 625.0ns
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); //shift blue -- 62.5ns (1)
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+2))",1,1"); //shift red -- 125.0ns (1)
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+1))",1,1"); //shift green -- 187.5ns (1)
asm("bc llbith"); //high long -- 250.0ns (1)
asm("llbitl:");
asm("bcf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start low -- 312.5ns (1) / 625.0ns / 0.0
asm("bra llwait0"); // -- 62.5ns (0)
asm("llbith:");
asm("bra $+2"); // -- 375.0ns (1)
asm("bra llbitl"); // -- 500.0ns (1)
asm("llwait0:");
asm("bsf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **can allow ints immediately after low
asm("btfss" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 187.5ns (0)
asm("bcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 250.0ns (0)
asm("btfsc" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 312.5ns (0)
asm("bsf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 375.0ns (0)
asm("decfsz" ___mkstr(BANKMASK(WS_paint@regs))",1,1"); // -- 437.5ns (0)
asm("bra dllp1"); // -- 500.0ns (0)
}
}
I found this:@nsaspook, is the order (and contiguousness) of the bytes in the structure guaranteed by the C standard? If not, I'll probably have to pack the bytes in a uint32_t instead (for portability....ha!).
Yes and no.@nsaspook, is the order (and contiguousness) of the bytes in the structure guaranteed by the C standard? If not, I'll probably have to pack the bytes in a uint32_t instead (for portability....ha!).
As per @WBahn contiguous is not a given but is likely as a default (for 8-bit hardware, native and likely most efficient) on hardware without byte alignment restrictions but shouldn't be trusted, as even if it's possible, the compiler might default to a alignment speed optimization resulting in padding.I found this:
http://www.catb.org/esr/structure-packing/
I assume this is telling me that, since they're all single bytes, they will be contiguous and in order, regardless of platform. Correct?
Probably, but not guaranteed. All the standard dictates is, "Each non-bit-field member of a structure or union object is aligned in an implementation-defined manner appropriate to its type."I found this:
http://www.catb.org/esr/structure-packing/
I assume this is telling me that, since they're all single bytes, they will be contiguous and in order, regardless of platform. Correct?
void WS_paint(void)
{
uint8_t lednum;
static uint32_t regs;
if (!LEDPOWER)
return;
for (lednum=0; lednum < NUM_TRICOLOR_LEDS; lednum++)
{
*(((uint8_t *)®s)+0) = 24;
*(((uint8_t *)®s)+1) = ws_ledbar[lednum].color.green;
*(((uint8_t *)®s)+2) = ws_ledbar[lednum].color.red;
*(((uint8_t *)®s)+3) = ws_ledbar[lednum].color.blue;
asm("BANKSEL WS_paint@regs");
asm("dllp1:");
asm("bcf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **Only need to disable ints for high of pulse
asm("bsf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start high -- 0.0ns (1) / 625.0ns
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); //shift blue -- 62.5ns (1)
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+2))",1,1"); //shift red -- 125.0ns (1)
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+1))",1,1"); //shift green -- 187.5ns (1)
asm("bc llbith"); //high long -- 250.0ns (1)
asm("llbitl:");
asm("bcf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start low -- 312.5ns (1) / 625.0ns / 0.0
asm("bra llwait0"); // -- 62.5ns (0)
asm("llbith:");
asm("bra $+2"); // -- 375.0ns (1)
asm("bra llbitl"); // -- 500.0ns (1)
asm("llwait0:");
asm("bsf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **can allow ints immediately after low
asm("btfss" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 187.5ns (0)
asm("bcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 250.0ns (0)
asm("btfsc" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 312.5ns (0)
asm("bsf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 375.0ns (0)
asm("decfsz" ___mkstr(BANKMASK(WS_paint@regs))",1,1"); // -- 437.5ns (0)
asm("bra dllp1"); // -- 500.0ns (0)
}
}
The struct works.
So does this:
I assume, based on the discussion above, this is a better "portable" solution. Right?C:void WS_paint(void) { uint8_t lednum; static uint32_t regs; if (!LEDPOWER) return; for (lednum=0; lednum < NUM_TRICOLOR_LEDS; lednum++) { *(((uint8_t *)®s)+0) = 24; *(((uint8_t *)®s)+1) = ws_ledbar[lednum].color.green; *(((uint8_t *)®s)+2) = ws_ledbar[lednum].color.red; *(((uint8_t *)®s)+3) = ws_ledbar[lednum].color.blue; asm("BANKSEL WS_paint@regs"); asm("dllp1:"); asm("bcf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **Only need to disable ints for high of pulse asm("bsf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start high -- 0.0ns (1) / 625.0ns asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); //shift blue -- 62.5ns (1) asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+2))",1,1"); //shift red -- 125.0ns (1) asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+1))",1,1"); //shift green -- 187.5ns (1) asm("bc llbith"); //high long -- 250.0ns (1) asm("llbitl:"); asm("bcf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start low -- 312.5ns (1) / 625.0ns / 0.0 asm("bra llwait0"); // -- 62.5ns (0) asm("llbith:"); asm("bra $+2"); // -- 375.0ns (1) asm("bra llbitl"); // -- 500.0ns (1) asm("llwait0:"); asm("bsf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **can allow ints immediately after low asm("btfss" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 187.5ns (0) asm("bcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 250.0ns (0) asm("btfsc" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 312.5ns (0) asm("bsf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 375.0ns (0) asm("decfsz" ___mkstr(BANKMASK(WS_paint@regs))",1,1"); // -- 437.5ns (0) asm("bra dllp1"); // -- 500.0ns (0) } }
(I use the word "portable" loosely...)

This is not an answer to my question.Better? If it works, it's gold.
There is no actual definitive programming answer to your question. Problems happen, problems are solved, rinse, repeat until it works per specifications.This is not an answer to my question.
The original code worked. Until it didn't.
Unlike .asm, where the code always runs like I ask it to.There is no actual definitive programming answer to your question. Problems happen, problems are solved, rinse, repeat until it works per specifications.
Wake-up from that dream, it's holding you back.Unlike .asm, where the code always runs like I ask it to.
Holding me back? If I didn't know .asm as well as I do:Wake-up from that dream, it's holding you back.
Speaking as an experienced programming team lead, I can see that you are having productivity issues, the way you are tackling some of this stuff is probably costing in ways you aren't appreciating.Holding me back? If I didn't know .asm as well as I do:
1. I would not be able to complete this project with this hardware
2. I would not have been able to solve this immediate problem.
I'd say I am advancing because my dream.
I'd consider a tiny simplification too: (see "reg_ptr")The struct works.
So does this:
I assume, based on the discussion above, this is a better "portable" solution. Right?C:void WS_paint(void) { uint8_t lednum; static uint32_t regs; if (!LEDPOWER) return; for (lednum=0; lednum < NUM_TRICOLOR_LEDS; lednum++) { *(((uint8_t *)®s)+0) = 24; *(((uint8_t *)®s)+1) = ws_ledbar[lednum].color.green; *(((uint8_t *)®s)+2) = ws_ledbar[lednum].color.red; *(((uint8_t *)®s)+3) = ws_ledbar[lednum].color.blue; asm("BANKSEL WS_paint@regs"); asm("dllp1:"); asm("bcf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **Only need to disable ints for high of pulse asm("bsf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start high -- 0.0ns (1) / 625.0ns asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); //shift blue -- 62.5ns (1) asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+2))",1,1"); //shift red -- 125.0ns (1) asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+1))",1,1"); //shift green -- 187.5ns (1) asm("bc llbith"); //high long -- 250.0ns (1) asm("llbitl:"); asm("bcf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start low -- 312.5ns (1) / 625.0ns / 0.0 asm("bra llwait0"); // -- 62.5ns (0) asm("llbith:"); asm("bra $+2"); // -- 375.0ns (1) asm("bra llbitl"); // -- 500.0ns (1) asm("llwait0:"); asm("bsf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **can allow ints immediately after low asm("btfss" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 187.5ns (0) asm("bcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 250.0ns (0) asm("btfsc" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 312.5ns (0) asm("bsf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 375.0ns (0) asm("decfsz" ___mkstr(BANKMASK(WS_paint@regs))",1,1"); // -- 437.5ns (0) asm("bra dllp1"); // -- 500.0ns (0) } }
(I use the word "portable" loosely...)
void WS_paint(void)
{
uint8_t lednum;
static uint32_t regs;
uint8_t * reg_ptr = &(regs);
if (!LEDPOWER)
return;
for (lednum=0; lednum < NUM_TRICOLOR_LEDS; lednum++)
{
*(reg_ptr[0]) = 24;
*(reg_ptr[1]) = ws_ledbar[lednum].color.green;
*(reg_ptr[2]) = ws_ledbar[lednum].color.red;
*(reg_ptr[3]) = ws_ledbar[lednum].color.blue;
asm("BANKSEL WS_paint@regs");
asm("dllp1:");
asm("bcf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **Only need to disable ints for high of pulse
asm("bsf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start high -- 0.0ns (1) / 625.0ns
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); //shift blue -- 62.5ns (1)
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+2))",1,1"); //shift red -- 125.0ns (1)
asm("rlcf" ___mkstr(BANKMASK(WS_paint@regs+1))",1,1"); //shift green -- 187.5ns (1)
asm("bc llbith"); //high long -- 250.0ns (1)
asm("llbitl:");
asm("bcf" ___mkstr(BANKMASK(LATD)) ",5,0"); //start low -- 312.5ns (1) / 625.0ns / 0.0
asm("bra llwait0"); // -- 62.5ns (0)
asm("llbith:");
asm("bra $+2"); // -- 375.0ns (1)
asm("bra llbitl"); // -- 500.0ns (1)
asm("llwait0:");
asm("bsf" ___mkstr(BANKMASK(INTCON0)) "," ___mkstr(_INTCON0_GIE_POSITION) ",0"); // **can allow ints immediately after low
asm("btfss" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 187.5ns (0)
asm("bcf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 250.0ns (0)
asm("btfsc" ___mkstr(BANKMASK(STATUS)) "," ___mkstr(_STATUS_C_POSITION) ",0"); // -- 312.5ns (0)
asm("bsf" ___mkstr(BANKMASK(WS_paint@regs+3))",1,1"); // -- 375.0ns (0)
asm("decfsz" ___mkstr(BANKMASK(WS_paint@regs))",1,1"); // -- 437.5ns (0)
asm("bra dllp1"); // -- 500.0ns (0)
}
}
Sure, if you only want to code in a narrow 8-bit universe.Holding me back? If I didn't know .asm as well as I do:
1. I would not be able to complete this project with this hardware
2. I would not have been able to solve this immediate problem.
I'd say I am advancing because my dream.
Which is my goal.Sure, if you only want to code in a narrow 8-bit universe.