;RS232 Data Output for 3,5-digit LCD digital multimeters
;ATtiny13 @ 40 kHz (external clock from multimeter), lfuse=0x78, hfuse=0xFF
;This version is compatible with these multimeters:
; Manufacturer | Type | Multimeter Chip
; ----------------------+------------+-------------------
; Uni-Trend | UT70A | CJ7108F = SH7108F
;
;PORTS:
; Pin Port Function
; 1 (PB5) #RESET
; 2 (PB3) 40 kHz input
; 3 PB4 Conversion Complete input (from SH7108F Pin 39 [EOC])
; 4 GND
; 5 PB0 SPI Clock output (to SH7108F Pin 36 [CLK])
; 6 PB1 SPI Data input (from SH7108F Pin 37 [SDO])
; 7 PB2 RS232 Tx output (idle = high)
; 8 V_CC = +5V
;
;VERSIONS
; 2012-12-16 Arne Rossius
; * first version
.include "tn13def.inc"
.def temp = R16
.def temp2 = R17
.def count = R18
.def uart_space = R19
.def uart_mark = R20
.def dataL = R21
.def dataH = R22
.def dp = R23
;===============================================================================
.org 0x000
rjmp reset
.org PCI0addr
reti
;===============================================================================
reset:
;set stackpointer
ldi temp, RAMEND
out SPL, temp
;init ports
ldi temp, 0x05
out DDRB, temp
ldi temp, 0x04
out PORTB, temp
;disable analog comparator
ldi temp, 1<<ACD
out ACSR, temp
;init pin change interrupt (for wake-up on conversion complete)
ldi temp, 0x10 ;select PB4 for pin change interrupt
out PCMSK, temp
ldi temp, 1<<PCIE ;enable pin change interrupt
out GIMSK, temp
sei ;enable interrupts
;init registers
ldi uart_mark, 0x04 ;UART line idle
ldi uart_space, 0x00 ;UART line active
;===============================================================================
loop:
;sleep (power-down mode)
ldi temp, 1<<SE | 1<<SM1
out MCUCR, temp
sleep
;check if "conversion complete" is high
sbis PINB, 4
rjmp loop
;read data from SPI
ldi count, 16
spi_read:
sbi PORTB, 0
lsl dataL
rol dataH
sbic PINB, 1
ori dataL, 0x01
cbi PORTB, 0
dec count
brne spi_read
;convert and output data
mov temp, dataH
andi temp, 0x7C
cpi temp, 0x7C
breq loop ;no data yet
cpi temp, 0x70
breq overflow ;positive or negative overflow
;find dp
mov dp, dataL
andi dp, 0x03
;align data
lsr dataH
ror dataL
lsr dataH
ror dataL
;sign
ldi temp, '-'
sbrc dataH, 5
ldi temp, '+'
;first digit (MSB)
rcall putc
ldi temp, '0'
sbrc dataH, 4
ldi temp, '1'
rcall putc
;dp3
ldi temp, '.'
cpi dp, 3
brne PC+2
rcall putc
;second digit (3rd LSD)
mov temp, dataH
andi temp, 0x0F
ori temp, 0x30
rcall putc
;dp2
ldi temp, '.'
cpi dp, 2
brne PC+2
rcall putc
;third digit (2nd LSD)
mov temp, dataL
swap temp
andi temp, 0x0F
ori temp, 0x30
rcall putc
;dp1
ldi temp, '.'
cpi dp, 1
brne PC+2
rcall putc
;fourth digit (LSD)
mov temp, dataL
andi temp, 0x0F
ori temp, 0x30
rcall putc
newline:
ldi temp, 0x0d
rcall putc
ldi temp, 0x0a
rcall putc
rjmp loop
overflow:
ldi temp, 'O'
rcall putc
ldi temp, 'v'
rcall putc
ldi temp, 'e'
rcall putc
ldi temp, 'r'
rcall putc
ldi temp, 'f'
rcall putc
ldi temp, 'l'
rcall putc
ldi temp, 'o'
rcall putc
ldi temp, 'w'
rcall putc
rjmp newline
;===============================================================================
putc:
;send char via RS232 (software UART)
out PORTB, uart_space ;start bit
mov temp2, uart_mark
sbrs temp, 0
mov temp2, uart_space
out PORTB, temp2 ;bit 0
mov temp2, uart_mark
sbrs temp, 1
mov temp2, uart_space
out PORTB, temp2 ;bit 1
mov temp2, uart_mark
sbrs temp, 2
mov temp2, uart_space
out PORTB, temp2 ;bit 2
mov temp2, uart_mark
sbrs temp, 3
mov temp2, uart_space
nop
out PORTB, temp2 ;bit 3
mov temp2, uart_mark
sbrs temp, 4
mov temp2, uart_space
out PORTB, temp2 ;bit 4
mov temp2, uart_mark
sbrs temp, 5
mov temp2, uart_space
out PORTB, temp2 ;bit 5
mov temp2, uart_mark
sbrs temp, 6
mov temp2, uart_space
out PORTB, temp2 ;bit 6
mov temp2, uart_mark
sbrs temp, 7
mov temp2, uart_space
out PORTB, temp2 ;bit 7
rjmp PC+1
nop
out PORTB, uart_mark ;stop bit & idle
ret