hpmm.pwp


//
// PicoWeb Project File for "HPMM"
//
// Demonstrates connection to external device via the PicoWeb
// serial port.  The sample device is an HP 34401A Multimeter.
// The "extra" PicoWeb RS-232 "modem control" lines are wired
// to DSR and DTR on the HP meter.
//
// This project makes use of Javascript to format the ASCII
// floating point voltage readings returned by the HP multimeter.
//
// This project can be loaded into the PicoWeb server and
// run without an actual HP multimeter present by using the
// "DUMMY_DATA" define statement.
//

#define EEPROM_IP                /* use file "ip" for IP address */
#define ENABLE_WATCHDOG
#undef DEBUGGER                 /* no debugger...we're using serial port */
#define SERIAL_BAUD_DIVISOR 51  /* serial port to 9600 baud @ 8Mhz */

#define DUMMY_DATA "1.23456E-03"   /* define to run with no meter present */

#define DSR_BIT  5         /* DSR, inverting output, DB25-11, DB9-6, PD2 */
#define DSR_PORT PORTD
#define DSR_PINS PIND
#define DSR_DDR  DDRD

#define DTR_BIT  6         /* DTR, inverting input, DB25-15, DB9-4, PD2 */
#define DTR_PORT PORTD
#define DTR_PINS PIND
#define DTR_DDR  DDRD

// HTML and images
hpmm.htm                // ii00
hpmm1.htm               // ii01
hpmm2.htm               // ii02
hpmm3.htm               // ii03
hplogo.jpg              // ii04

// CGI routines
send_cmd.cgi             // iu00

//------------------ included AVR assembly language follows ---------------
#avr_reset

    sbi DSR_DDR,DSR_BIT         ; make output
    cbi DTR_DDR,DTR_BIT         ; make input
    cbi DSR_PORT,DSR_BIT        ; "DSR" => high (inverting output)

#avr_slow

#avr_fast

#avr_asm

#define putchar_serial pmovbi putc_b,0
#define putchar_net    pmovbi putc_b,1
#define serial_binary  pser_mode 1
#define serial_normal  pser_mode 0
#define SER_TMO         60000
.dseg
old_putcok: .byte 1

;+
; **-send_cmd-send command (from GET request) and get response
;-
#define SD_ADDR     buf
#define SD_LEN      buf+2
#define SD_CHAR     buf+4
#define SD_TEMP     buf+6
#define SD_LAST     buf+8
#define SD_TMO      SD_CHAR

.cseg
send_cmd:
    ppushn putcok,1                     ; save putchar enable state
    pmovbi putcok,0xff                  ; putchar is now OK
    putchar_serial                      ; switch putchar to serial port
    serial_binary                       ; put serial port in binary mode
    pmovwi SD_ADDR,[data_addr]          ; get data address
    paddwi SD_ADDR,10                   ; GET /iuNN?xxxxxxxxxxx
                                        ; 01234567890
    pmovwi SD_LEN,[data_len]
    psubwi SD_LEN,10                    ; bias length for GET /...? part
;
; note there is not a lot of checking on the format of the URL.  the first
; occurrence of '=' is interpreted as the start of the stuff to transmit
; to the serial port, and that continues until either '&' or ' ' is
; encountered.
;
    pmovwi SD_LAST,0               ; clear last character (both bytes!)
find_equal_next:
    pr2s SD_CHAR,[SD_ADDR],1       ; scan for '=' in Ethernet packet
    pincw SD_ADDR
    pdecw SD_LEN
    pcmpbi SD_CHAR,'='
    pjumpeq serdev_next
    pcmpwi SD_LEN,0
    pjumplo serial_done
    pjumpne find_equal_next
    pjump serial_done
;
; send stuff after "=" to serial port with %XX expansion until ' '.
;
serdev_next:
    pwdr                                ; reset hardware watchdog timer
    pr2s SD_CHAR,[SD_ADDR],1            ; get next byte
    pcmpbi SD_CHAR,' '                  ; the end?
    pjumpeq serial_done                 ; yes...we found a ' '
    pcmpbi SD_CHAR,'+'                  ; map '+' -> ' '
    pjumpne not_plus
    pmovbi SD_CHAR,' '
    pjump output_next_char
not_plus:
    pcmpbi SD_CHAR,'%'                  ; check for HTTP quoting char
    pjumpne output_next_char
;
; get next two chars from request.
;
    pincw SD_ADDR                       ; skip '%'
    pr2s SD_CHAR,[SD_ADDR],2            ; get XX of %XX
    paddwi SD_ADDR,1                    ; skip past it
    psubwi SD_LEN,2                     ; discount in length
;
; hex conversion of two chars in SD_CHAR, SD_CHAR+1.
;
    pmovb SD_TEMP,SD_CHAR               ; get first char
    pandwi SD_TEMP,0xff
    psubwi SD_TEMP,'0'                  ; convert to binary (maybe)
    pcmpwi SD_TEMP,10                   ; see if valid hex digit
    pjumplo do_upper_digit              ; yep - do upper one
    pandwi SD_TEMP,0xf                  ; 1-6
    paddwi SD_TEMP,9                    ; turn 1-6 into 10-15

do_upper_digit:
    pmovb SD_CHAR,SD_CHAR+1             ; get second digit
    pandwi SD_CHAR,0xff                 ; isolate it
    psubwi SD_CHAR,'0'                  ; convert to binary (maybe)
    pcmpwi SD_CHAR,10                   ; see if valid hex digit
    pjumplo merge_digits                ; yep - merge the two
    pandwi SD_CHAR,0xf
    paddwi SD_CHAR,9

merge_digits:
    pshnw SD_TEMP,4                     ; shift top bits into place
    paddwi SD_CHAR,[SD_TEMP]            ; SD_CHAR now has char

output_next_char:
    pandwi SD_CHAR,0xff                 ; isolate it
    pcmpwi SD_CHAR,0x5c                 ; back-slash?
    pjumpeq skip_output                 ; yes...don't output

    pcmpwi SD_LAST,0x5c                 ; last character a back-slash?
    pjumpne output_char_now             ; no...proceed as normal
    pcmpwi SD_CHAR,'r'                  ; got a \r?
    pjumpne not_CR                      ; no...skip ahead
    pmovbi SD_CHAR,0x0d                 ; yes...change it to CR
not_CR:
    pcmpwi SD_CHAR,'n'                  ; got \n?
    pjumpne not_LF                      ; no...
    pmovbi SD_CHAR,0x0a                 ; yes...change to LF
not_LF:

output_char_now:
    pputcb SD_CHAR
skip_output:
    pmovbi SD_LAST,[SD_CHAR]            ; save last character
    pincw SD_ADDR                       ; adjust pointer
    pdecw SD_LEN                        ; see if we're done
    pjumplo serial_done
    pjumpne serdev_next
serial_done:
    pmovwi SD_TMO,SER_TMO               ; select the timeout period
    putchar_net                         ; switch putchar back to net
#ifdef DUMMY_DATA
    pcall send_dummy_data
#else
    pcall serdev_copynet                ; copy serial port input to net
#endif
    ppopn putcok,1                      ; restore putchar enable state
    pret
;
; loop reading chars from the serial buffer and writing to net until
; LF encountered (or timeout)
;
; SD_TMO (word) = timeout loop count.
;
.cseg
serdev_nextchar:
    pser_getc SD_CHAR                   ; get a char into buf
    pjumpeq serdev_empty                ; no more chars!
    pputcb SD_CHAR                      ; put char to the net
    pcmpbi SD_CHAR,0x0a                 ; check for LF
    pjumpeq serdev_copydone
serdev_copynet:
    pmovwi SD_TEMP,[SD_TMO]             ; reset timeout
    pwdr                                ; reset hardware watchdog timer too
    pjump serdev_nextchar               ; go get another one
serdev_empty:
    pwdr                                ; reset hardware watchdog timer
    psubwi SD_TEMP,1                    ; decrement timeout
    pjumpne serdev_nextchar             ; not yet timed out
serdev_copydone:
    pret
;
; Send dummy data in place of HP multimeter
;
.eseg
send_dummy_data:
    pprint DUMMY_DATA
    pret

Back