; Application for the weather data collection board.
;
; This app provides an I2C interface to read (8) parameters from various
; sensors. The intent is the I2C master will read these parameters every
; $N minutes, collecting the information the board has accumulated.
;
; READ-FROM is the only supported I2C operation. There are no registers.
; The master should simply read (8) bytes.
;
; Byte 0: temperature (== (T+20)*2.5; in Celsius)
; Byte 1: humidity (== H*2.5; in %RH)
; Byte 2: rainfall-ticks (each 0.011" seen since last-read)
; Byte 3: rainfall-seconds (since last-read; ### scale/units?)
; Byte 4: wind direction (0-15, mapping the compass from N to NNW)
; Byte 5: wind-speed-tickets (1.49 mph per tick-second)
; Byte 6: wind-speed-seconds (since last-read; ### scale/units?)
; Byte 7: light level (no units; [0..255])
;
; Use rainfall-ticks/seconds for rainfall RATE, and -ticks for an
; absolute measure of rainfall over a given period of time on the
; master device performing the reads.
;
; Use wind-speed-ticks/seconds for wind RATE. Since the -ticks
; will be relatively low, these should be averaged over a "long"
; period of collecting values. (ie. a single tick/seconds pair
; will be noisy due to a tick slipping in/out of a time frame of
; collecting values)
;
; ### TBD: gather empirical values for light levels
;
; =====
;
; Sensors used:
;
; DHT22 can be read every 2 seconds, using a 1-wire digital serial
; pin, with a pullup. This will provide both temperature and
; humidity. The values are measurement*10, so we divide by 4 (rotate
; right) which gives us measurement*2.5. Given the ranges of these
; measurements, the results fit in [0..255]. Temperature has a
; +20 to shift from [-20..80] up to [0..100] (then *10/4).
;
; Rainfall is measured as contact closures for each 0.011" of rain.
; We will observe the pin, and watch for transitions. Be wary of a
; need to debounce. Austin's heaviest rain day was 15.0 inches,
; which is 1363 closures over 24h, or less than 1 closure per second.
; https://www.sparkfun.com/products/15901
;
; Wind direction uses an ADC to measure a resistor network in the
; SEN-15901 product, determine 1 of 16 potential directions.
;
; Wind speed is measured as contact closures for rotation of the
; anemometer of the SEN-15901. Be wary of a need to debounce.
; 100 closures per second corresponds to 149.2 mph winds; thus,
; we should not see closures faster than 10 ms.
;
; Light level is determined from a CdS cell via an ADC pin.
; ### more detail
; https://www.sparkfun.com/products/9088
;
;
; NOTE: maybe? use a simple RC circuit to debounce. Should be
; simple at these contact-closure rates.
; ### how long are the contact closures? Will we see them, or
; ### should we apply RC to them, too?
; ### internet: "debounce the reed switch with a .1uf cap"
; ### internet: reed switch debounce is less than 2ms
;
; =====
;
; DHT22 sets the outer bounds on reading frequency, with a minimum
; of 2 seconds. We need to read (over time): DHT22, wind direction,
; and the light level.
;
; In between the read processing, we need to monitor the I2C bus
; (for a read-query) and the contact-closures (rainfall and wind
; speed). The contacts should be placed on PORTC along with I2C,
; so we have a single port to look at, for pin transitions.
;
; Note: if an I2C read arrives, then we simply *dump* any read
; processing that is occurring. We will simply provide the last-read
; value to upstream.
; Note: make sure to reset anything when a read is canceled.
;
; =====
;
; PIN ASSIGNMENTS
;
; RC0: DHT22 (single-wire serial)
; RC1: Rainfall (closures)
; RC2: Wind speed (closures)
; RC3: -- unused --
; RC4: SCL
; RC5: SDA
;
; RA0: Wind direction (ADC)
; RA1: Light level (ADC)
; RA2: -- unused --
; RA3: -- unused --
; RA4: -- unused --
; RA5: -- unused --
;
; NOTE: RC0 alternates between input and output. All others are
; inputs (some analog, some digital; sometimes tied to the ADC).
;
; =====
;
; OPERATION SEQUENCE
;
; Gather measurements every: 1 minute
;
; ### two ADCs at 42 µS per sample (acquisition, then process)
;
; ### DHT22 takes:
; ###   1000 µS + 40 µS + 80 µS + 80 µS + 40*(70+50 µS) + 50 µS
; ###   == 1730 µS
;
; Watch for closures, and debounce.
;
;
;
;
; =====
;
;


        list p = 16f688
        include p16f688.inc
        include ../include/handy.inc

        constant USING_I2C_SLAVE = 1
        include ../include/i2c.inc

        __config DEFAULT_CONFIG


; Define our various pins
 constant PIN_WIND_D = 0        ; PORTA
 constant PIN_LIGHT = 1         ; PORTA

 constant PIN_DHT11 = 0         ; PORTC
 constant PIN_RAIN = 1          ; PORTC
 constant PIN_WIND = 2          ; PORTC

; Define this module's variables
.gpr0   udata

; Last PORTC values we saw, to detect changes.
LAST_PORTC      res     1

; How many closures since last-read?
TICKS_RAIN      res     1
TICKS_WIND      res     1

; ### ? time since last-read



.reset: org  0x0000
        goto main


.main:  code                    ; relocatable
main:

        disable_comparators
        ; Now in Bank 0

        bank1s
        run_at_8MHz

        bank0s

        ; ### use the watchdog to ensure we don't clock-stretch
        ; ### the I2C bus for "too long" ?


busy_loop:
        ; Watch for activity on PORTC: I2C, closures
        movfw   PORTC
        xorwf   LAST_PORTC, W
        bz      busy_loop       ; nothing changed

        ; Store the changes into LAST_PORTC
        xorwf   LAST_PORTC, F

        ; W contains 1-bits for changed pins.

        ; If an I2C transaction has started (for us, or anybody),
        ; then use clock-stretching, while we do some extra work.
        ; ### need better name:
        ; assert_SCL_LOW

        ; Handle measurement ticks. Increment the TICKS on the
        ; falling-edge (it is pulled high, so the pin is active-low)
        ; ### debounce
        ; Note: we ignore transitions to HIGH
        ; Note: use the pins' state, not the changes seen in W.
        btfss   LAST_PORTC, PIN_RAIN
        incf    TICKS_RAIN, F
        btfss   LAST_PORTC, PIN_WIND
        incf    TICKS_WIND, F

        ; ### if I2C, then release the clock-stretch and begin.
        ; ### else go back for more
        ; ### TBD: periodic measurements
        goto    busy_loop

saw_i2c:
        nop


; stupid assemblers don't realize EOF means *end*
        end
