Při tvorbě osvětlení pro modelové kolejiště jsem narazil na problém, jak simulovat startování zářivek. Celkem zásadní problém byl jak na generátor náhodných čísel.

Snažil jsem se použít nejjednodušší dostupný procesor - PIC10F200 přece musí stačit na blikání s jednou led.

Generátor pseudonáhodných čísel je celkem jednoduchá a popsaná úloha a nemá cenu se s ní nikterak zaobírat. Já jsem pro svůj použil seed definovaný pomocí dvou konstant (ENT1 a ENT2) při nahrávání procesoru a třetí konstanty (OSCCAL) dané při výrobě. To však znamená, že světla při každém zapnutí blikají stejně.

Na fóru mne pl nasměroval na jednu užitečnou vlastnost. A to je to, že watchdog používá vlastní oscilátor, který není nikterak svázaný s oscilátorem procesoru a navíc nemá teplotní a napěťovou stabilizaci.
Čili stačí jen vymyslet metodu, jak tuto vlastnost využít.
Použil jsem úplně jednoduchou metodu - na začátku programu se rozhodnu, jestli se jedná o první reset a nebo o reset vyvolaný watchdogem (STATUS,NOT_TO). Pokud se jedná o první reset, pak program nasměřuji do zdánlivě nekonečné smyčky, která jen rotuje pseudonáhodným generátorem. Smyčka je ukončená po přetečení WDT (což má být cca 12ms, ale zdá se mi to déle). Je celkem jedno v jaké fázi dojde k přerušení, protože cílem je stejně jen "rozházet" proměnné pseudonáhodného generátoru.
Při druhém resetu pak už neinicializuju náhodný generátor, ale rovnou jej používám.

Efekt je až překvapivě dobrý. K posouzení video s efektem startování zářivky:

Zde uvádím podstatnou část kódu:
      include "p10f200.inc"
        list    st=off

        __CONFIG   _MCLRE_OFF & _CP_OFF & _WDT_ON

FXTAL           equ     D'4000000'

GP_TRIS         equ     b'00001011'             ; GP2: out led,

OPTION_INI      equ   b'10011110'   ; 10010001
                                    ; 1-------, IOC off
                                    ; -0------, weak pullups ON
                                    ; --0-----, T0CS source Fosc/4
                                    ; ---1----, T0SE edge hi>lo
                                    ; ----0---, PSA prescale TMR0
                                    ; -----001, PS prescaler 1:4 --> 128 steps = 0.512ms

#define         LED             GPIO,2                  ; LED output

        cblock  0x10
FLAGS                           ; Flags for blinking
RANDOM0                         ; Random shift register
RANDOM1
RANDOM2
RANDOM3
ENT1
ENT2
CV10
CV11
TEMP                            ; temp value

STEPS

        endc

; --- Flags
                                                ; FLAGS
#define         BLINKING        FLAGS,0
#define         LEDOUT          FLAGS,2         ; Flash phase

        movwf   OSCCAL          ;
        movwf   FLAGS           ; copy of osccal to random

        btfsc   STATUS,NOT_TO           ; After timeout worn normally
        goto    MixRandom               ; before timeout go to mix random numbers
        movlw   OPTION_INI
        option                  ;
        movlw   GP_TRIS                 ;
        tris    GPIO            ; GP3 input, all others outputs
        clrf    GPIO            ; set output latches to '0'


        call    LoadCV                  ; load CV values  {ENT1, ENT2, CV10, CV11}

        clrf    FLAGS
        clrf    COUNTPWM
        bsf             BLINKING

        movf    RANDOM0,w
        andlw   0x0F
        movwf   STEPS                   ; number of blinks
        [...]

MainLoop:
        clrwdt
        btfsc   TMR0,7          ; time to next PWM step?
        call    DoPWM                   ; yes, next step

        goto    MainLoop

; ----------------------------------------------------------------------


DoPWM:
        clrf TMR0
        [...]

; ----------------------------------------------------------------------
MixRandom
        movlw   OPTION_INI
        option                  ;
        movlw   GP_TRIS                 ;
        tris    GPIO            ; GP3 input, all others outputs
        clrf    GPIO            ; set output latches to '0'

        bsf             GPIO,2
               
        call    LoadCV                  ; load CV values {ENT1, ENT2, CV10, CV11}

        movf    ENT1,w
        movwf   RANDOM0
        movf    ENT2,w
        movwf   RANDOM1
        bsf             RANDOM0,0               ; to be sure RANDOM shift reg. is not zero
        movf    FLAGS,w         ; OSCCAL
        movwf   RANDOM2
               
RotateRand:
        swapf   RANDOM0,w               ; RANDOM shift register
        xorwf   RANDOM1,w
        movwf   TEMP
        rrf             TEMP,w
        rlf             RANDOM3,f
        rlf             RANDOM2,f
        rlf             RANDOM1,f
        rlf             RANDOM0,f
        goto    RotateRand              ; this loop look like never ending, but it is terminated by WDT timeout

; ----------------------------------------------------------------------