One of my early day’s Assembly (ASM-51) codes!!!

  1 
  2 ;-------=========-------=========-------=========-------=========-------=========-------=========-------=========-------
  3 ;       Data definitions
  4 ;-------=========-------=========-------=========-------=========-------=========-------=========-------=========-------
  5     ;------======------======------======------======------======------======------======------======------
  6     ;       Variable definitions
  7     ;------======------======------======------======------======------======------======------======------     
  8         IR_BUF          EQU     0x80        ; Buffer for sample store
  9         IR_DR_L         EQU     0x7E        ; Buffer Low for storing the smallest bit duration
 10         IR_DR_H         EQU     0x7F        ; Buffer High for storing the smallest bit duration
 11         IR_GEN_BUF      EQU     0x7D        ; General purpose buffer, _NOT_STATIC_
 12         IR_ERR          EQU     0x7C        ; IR input error counter
 13         
 14     ;------======------======------======------======------======------======------======------======------
 15     ;       Value definitions
 16     ;------======------======------======------======------======------======------======------======------     
 17         IR_CTR          EQU     0x40        ; Count for sample store
 18         CRLF_CTR        EQU     0x10        ; Count for sending a CRLF
 19         TMR_SMPL_1      EQU     0xA2        ; Timer reload value (approx. 100uS)
 20         TMR_SMPL        EQU     0x47        ; Timer reload value (approx. 200uS)
 21         
 22     ;------======------======------======------======------======------======------======------======------
 23     ;       Pin & Register definitions
 24     ;------======------======------======------======------======------======------======------======------     
 25         IR_IN           EQU     P3.2        ; IR signal input pin
 26         
 27 ;-------=========-------=========-------=========-------=========-------=========-------=========-------=========-------
 28 
 29 
 30 
 31 ;-------=========-------=========-------=========-------=========-------=========-------=========-------=========-------
 32 ;       Code starts here
 33 ;-------=========-------=========-------=========-------=========-------=========-------=========-------=========-------
 34         org     0000h
 35         jmp     reset_rtn
 36         
 37         org     0003h
 38         jmp     ie0_rtn
 39 ;-------=========-------=========-------=========-------=========-------=========-------=========-------=========-------
 40 
 41     ;------======------======------======------======------======------======------======------======------
 42     ;       Macro definitions perticular to this file
 43     ;------======------======------======------======------======------======------======------======------
 44     MACRO   @RST_TMR0_00
 45         clr     TR0                     ; Stop the Timer 0
 46         mov     TH0,#0x00               ; Reset high byte of Timer 0
 47         mov     TL0,#0x04               ; Compensate the cycles
 48         setb    TR0                     ; Kick timer 0 off again
 49     ENDMAC
 50     
 51     MACRO   @RESET_TR0_TO
 52         clr     TR0                     ; Stop the Timer 0
 53         mov     TH0,|1                  ; Reset high byte of Timer 0
 54         mov     A,#0x06                 ; Compensate the cycles
 55         add     A,|2                    ; Add it to the TL0 value
 56         mov     TL0,A                   ; Move it to TL0 and 
 57         setb    TR0                     ; Kick timer 0 off again
 58     ENDMAC
 59     
 60     MACRO   @SEND_CHAR
 61         jnb     TI,$                    ; Wait for the last transmission is over
 62         clr     TI                      ; For new transmission
 63         mov     SBUF,|1
 64     ENDMAC
 65 
 66 ;===============================================================================================================
 67 ;       External Interrupt handling routine, IR signal is fed here
 68 ;===============================================================================================================
 69 ie0_rtn:
 70         push    ACC
 71         clr     EX0                     ; Disable EX0 first
 72     ;------======------======------======------======------======------======------======------======------
 73     ;       Enter external interrupt 0 service routine
 74     ;------======------======------======------======------======------======------======------======------
 75         clr     TR0                     ; Stop the Timer 0
 76         mov     TH0,#0x00               ; Reset high byte of Timer 0
 77         mov     TL0,#0x03               ; Reset low byte of Timer 0
 78         setb    TR0                     ; Kick timer 0 off
 79 
 80         mov     R0,#IR_BUF              ; Pointer for sample store buffer
 81         mov     R1,#IR_BUF              ; Pointer for sample send buffer
 82         mov     R3,#IR_CTR              ; Counter for sample store buffer
 83         mov     R4,#0x02                ; Counter for sample send buffer        
 84         mov     R5,#CRLF_CTR            ; Counter for sending a '\n' during dump
 85         
 86     ;------======------======------======------======------======------======------======------======------
 87     ;       Sample and store the incoming start bit
 88     ;------======------======------======------======------======------======------======------======------
 89         jnb     IR_IN,$                 ; Start sampling - Bit 0
 90         clr     TR0                     ; Stop timer 0 to note values
 91         mov     @R0,TH0                 ; Store high byte first
 92         inc     R0                      ; Point to next buffer slot
 93         mov     @R0,TL0                 ; Store low byte next
 94         inc     R0                      ; Point to next buffer slot
 95         clr     TF0                     ; Clear to make sure only timeout triggers error
 96         dec     R3                      ; For writes above
 97         dec     R3                      ; For writes above
 98         @RST_TMR0_00                    ; Reset the timer to 0x0000 before continueing      
 99 smpl_sync:  
100         jb      TF0,smpl_exit           ; Error, jump to handle the error
101         jnb     IR_IN,smpl_sync         ; If the line is low for a while, timeout occurs
102         clr     A                       ; To measure the in bit
103 
104     ;------======------======------======------======------======------======------======------======------
105     ;       Sampling loop, iterates once for every bit
106     ;------======------======------======------======------======------======------======------======------
107 smpl_lp:
108         inc     A                       ; Continue measuring the duration
109         jc      smpl_exit               ; If overflow occurs, exit the measuring loop
110         nop                             ;
111         nop                             ;
112         nop                             ;
113         nop                             ;
114         nop                             ; For reducing the count
115         jb      IR_IN,smpl_lp           ; Continue measuring the duration
116         mov     @R0,A                   ; Store the count
117         inc     R0                      ; Point to the next byte in buffer
118         inc     R4                      ; Increment bytes to send
119 smpl_chk_tmout: 
120         inc     A
121         jc      smpl_err                ; If overflow occurs, Error
122         nop                             ;
123         nop                             ;
124         nop                             ;
125         nop                             ;
126         nop                             ; For reducing the count
127         jnb     IR_IN,smpl_chk_tmout    ; Continue measuring the duration
128         clr     A                       ; Make sure to measure from 0x00
129         djnz    R3,smpl_lp              ; Check for buffer over flow
130         
131     ;------======------======------======------======------======------======------======------======------
132     ;       Exit sampling loop, start sending the byte values over UART @ (1,19200,N,1,NoFlow)
133     ;------======------======------======------======------======------======------======------======------ 
134 smpl_exit:
135         clr     TF0                     ; Ensure overflow occurs only after timeout
136         @RESET_TR0_TO   #0x20,#0x00     ; For a little sleep
137         jnb     TF0,$                   ; Delay for the duration (not calculated)
138         clr     TR0                     ; Stop the timer
139         clr     TF0                     ; Clear the timer overflow flag
140         clr     IE0                     ; Just in case another interrupt is pending on IE0
141     ;   setb    EX0                     ; Re enable the external 0 interrupt (May this idea work!!!)
142         pop     ACC                     ;
143         reti
144 
145 smpl_err:   
146         @SEND_CHAR  #'R'                ; Indicate error to monitor
147         dec     IR_ERR                  ; Increment the IR Error counter
148         pop     ACC                     ;
149         reti
150         
151 ;------======------======------======------======------======------======------======------======------======------
152 ;                       Exit external interrupt 0 ISR
153 ;------======------======------======------======------======------======------======------======------======------
154 
155 
156 ;------======------======------======------======------======------======------======------======------======------
157 ;                       Enter the reset routine and main loop
158 ;------======------======------======------======------======------======------======------======------======------
159 reset_rtn:
160     ;------======------======------======------======------======------======------======------======------
161     ;       Peripheral initialization routines
162     ;------======------======------======------======------======------======------======------======------
163         mov     SP,#0xE0                ; Allocating 32 bytes for stack
164         orl     PCON,#0x80              ; Set SMOD of PCON, Enable double baud rate
165         anl     TMOD,#0xAF              ; Clear C/T, M0 for Timer1 of TMOD
166         mov     TMOD,#0x21              ; Set M1 for Timers 0 & 1 of TMOD
167                                         ; Set Timer 1 to Mode 2 (8-bit auto reload) for Baud Rate Generation
168                                         ; Timer 0 is in Mode 1 (16 bit timer mode)
169         mov     TH1,#0xFD               ; Set Baud Rate to 9600 bps
170         clr     SM0                     ; Clear SM0 of SCON
171         setb    SM1                     ; Set SM1 of SCON
172                                         ; Set UART to Mode 1 (8-bit UART)
173         setb    REN                     ; Set REN of SCON to Enable UART Receive
174         setb    TR1                     ; Set TR1 of TCON to Start Timer1
175         setb    TI                      ; Set TI of SCON to Get Ready to Send
176         clr     RI                      ; Clear RI of SCON to Get Ready to Receive
177         
178         setb    IT0                     ; Make interrupt edge triggered     
179 ;//     setb    EX0                     ; Enable external interrupt0
180         setb    EA                      ; Enable all interrupts
181         mov     R7,#0x14                ; Implement a 1 sec delay during start up
182 sec_delay:  
183         clr     TR0                     ; Stop timer 0
184         mov     TH0,#0x3C               ; Set timer 0 for 20mS delay (not accurate)
185         mov     TL0,#0xB3               ; Compensate for load cycles (4)
186         setb    TR0                     ; Kick timer off for running
187         jnb     TF0,$                   ; Wait for timer overflow
188         clr     TF0                     ; Clear the timer interrupt
189         djnz    R7,sec_delay            ; If not 20 times, continue the dealy loop
190 
191         setb        EX0                 ; Ensure EX0 enabled before entering main loop
192     ;------======------======------======------======------======------======------======------======------
193     ;       Main loop starts here, infinite loop
194     ;------======------======------======------======------======------======------======------======------
195 main_lp:
196         jnb     RI,ir_rx_chk            ; For PC control, through serial port
197         clr     RI                      ; If received a control byte, echo it first
198         jnb     TI,$                    ; Is a tranmit in progress?
199         clr     TI                      ; To indicate next transmission
200         mov     A,SBUF                  ; Load the serial in byte in here
201         mov     SBUF,A                  ; Echo back
202         cjne    A,#'m',ir_rx_chk        ; If asking for a memory dump
203         call    mem_dump                ; Dump the memory to the serial terminal
204 ir_rx_chk:
205         jb      EX0,main_lp             ; Wait for the IR signal to be decoded
206 
207 
208     ;------======------======------======------======------======------======------======------======------
209     ;   //\\//\\ Debug Section Send bytes: for debug printing only 17th to 20th byte //\\//\\
210     ;------======------======------======------======------======------======------======------======------
211 ;       mov     A,R1                    ; Load the current send buffer pointer
212 ;       add     A,#0x26                 ; Offset by 38 to start with 38th byte
213 ;       mov     R1,A                    ; Set the buffer pointer to 17th byte
214 ;       mov     R4,#0x04                ; Set counter for sending only 4 bytes
215     ;------======------======------======------======------======------======------======------======------
216     ;   //\\//\\ End Section Send bytes: for debug printing only 17th to 20th byte //\\//\\
217     ;------======------======------======------======------======------======------======------======------
218 
219     ;------======------======------======------======------======------======------======------======------
220     ;       Send a CR/LF feed before start
221     ;------======------======------======------======------======------======------======------======------
222         jnb     TI,$                    ; Wait for the last tranmission over
223         clr     TI                      ; Clear the transmit flag
224         mov     SBUF,#0x0D              ; Send a carriage return
225         jnb     TI,$                    ; Wait for the last tranmission over
226         clr     TI                      ; Clear the transmit flag
227         mov     SBUF,#0x0A              ; Send a line feed
228 
229 send_lp:
230         mov     A,@R1                   ; Load byte from buffer
231         call    hex_to_uart             ; Send the hex value of the byte on serial port
232         mov     @R1,#0xFF               ; Reset the location
233         inc     R1                      ; Increment the send pointer
234         djnz    R4,send_lp              ; Decrement the send counter (<<)
235  ;\\        djnz        R5,send_continue        ; Decrement the '\n' counter (>>)
236     ;------======------======------======------======------======------======------======------======------
237     ;       Send a line feed after All digits (previously (12x3) digits (>>))
238     ;------======------======------======------======------======------======------======------======------
239         jnb     TI,$                    ; Wait for the last tranmission over
240         clr     TI                      ; Clear the transmit flag
241         mov     SBUF,#0x0D              ; Send a carriage return
242         jnb     TI,$                    ; Wait for the last tranmission over
243         clr     TI                      ; Clear the transmit flag
244         mov     SBUF,#0x0A              ; Send a line feed
245         jnb     TI,$                    ; Wait for the last tranmission over
246         clr     TI                      ; Clear the transmit flag
247         mov     SBUF,#0x0A              ; Send another line feed
248         
249 ;\\         mov     R5,#CRLF_CTR        ; Reset line feed counter (>>)
250 ;\\send_continue:                       ; (>>)
251 ;\\     djnz        R4,send_lp          ; Decrement the send counter(>>)
252         
253     ;------======------======------======------======------======------======------======------======------
254     ;       Sent all bytes, continue from beginning
255     ;------======------======------======------======------======------======------======------======------
256         setb    EX0                     ; Start the next receive cycle
257         jmp     main_lp                 ; Continue forever
258         
259 ;------======------======------======------======------======------======------======------======------======------
260 ;                   (Never)Exit the reset routine and main loop
261 ;------======------======------======------======------======------======------======------======------======------
262 
263 ;------======------======------======------======------======------======------======------======------======------
264 ;                   Put hex value on serial port
265 ;------======------======------======------======------======------======------======------======------======------
266 hex_to_uart:
267     ;------======------======------======------======------======------======------======------======------
268     ;       Send High byte in ASCII first
269     ;------======------======------======------======------======------======------======------======------
270         mov     IR_GEN_BUF,A            ; Store the byte temporarily in buffer
271         swap    A                       ; Take the high byte
272         anl     A,#0x0F                 ; Mask the low byte
273         cjne    A,#0x0A,high_is_char    ; If hex digit is less than 0xA
274   high_is_char:
275         jc      high_dont_add           ; skip adding 7 to make it ASCII alphabet
276         add     A,#0x07                 ; Make it ASCII alphabet
277   high_dont_add:
278         add     A,#0x30                 ; Convert to ASCII
279         jnb     TI,$                    ; Wait till the last transmission is over
280         clr     TI                      ; Clear the transmission flag
281         mov     SBUF,A                  ; Send it
282  
283     ;------======------======------======------======------======------======------======------======------
284     ;       Send Low byte in ASCII next
285     ;------======------======------======------======------======------======------======------======------
286         mov     A,IR_GEN_BUF            ; Restore the byte from buffer
287         anl     A,#0x0f                 ; Mask the high byte
288         cjne    A,#0x0A,low_is_char     ; If hex digit is less than 0xA
289   low_is_char:
290         jc      low_dont_add            ; skip adding 7 to make it ASCII alphabet
291         add     A,#0x07                 ; Make it ASCII alphabet
292   low_dont_add:
293         add     A,#0x30                 ; Convert to ASCII
294         jnb     TI,$                    ; Wait till the last transmission is over
295         clr     TI                      ; Clear the transmission flag
296         mov     SBUF,A                  ; Send it
297   
298     ;------======------======------======------======------======------======------======------======------
299     ;       Send a space after each digit
300     ;------======------======------======------======------======------======------======------======------
301         jnb     TI,$                    ; Wait for the last tranmission over
302         clr     TI                      ; Clear the transmit flag
303         mov     SBUF,#0x20              ; Send a white space charecter
304         ret
305 
306 ;------======------======------======------======------======------======------======------======------======------
307 ;               Dump memory to UART in hex
308 ;------======------======------======------======------======------======------======------======------======------
309 mem_dump:
310     ;------======------======------======------======------======------======------======------======------
311     ;       Loop till all bytes sent
312     ;------======------======------======------======------======------======------======------======------
313         clr     EA                      ; Disable all interrupts
314         mov     IR_BUF,R1               ; Save the pointer's contents
315         mov     R1,#0xFF                ; Start with location 0xFF
316 mem_dump_loop:
317         mov     A,@R1                   ; Load the contents into A
318         call    hex_to_uart             ; And send the hex value
319         djnz    R1,mem_dump_loop        ; Continue till all bytes sent
320         mov     A,@R1                   ; For location 0x00
321         call    hex_to_uart             ; Send it
322         mov     R1,IR_BUF               ; Save the pointer's contents
323         setb    EA                      ; Enable all interrupts
324         ret

A Battery Health Check (HW)

battery_monitorThe goal is to develop a battery health-check system in 40 hours or less. This includes learning a couple of new skills, defining the target design, designing hardware, software and test it.

So far, I learned KiCAD. Prototyped the analog on breadboard, came up with this design and created this schematic in the KiCAD. It took 16 ~ 18 hours of work till now. I had to create schematic library packages for the PIC16F883 microcontroller, BTW.

I used to draw schematics and create PCBs in CirCAD. Since it is commercial package, costly and really costly ($$$$), I needed an alternate package for the moment. I explored a few options and found KiCAD doing the job, at least for now.

The Goal:

I wanted to come up with a battery monitoring system to collect a battery’s charge discharge data for measuring and plotting it’s performance. The system should charge the battery at a defined current – normally fixed by the charger. Then goes over a discharge cycle with a predetermined load (e.g 0.1C), collecting the performance characteristics such as rate of voltage drop, actual current delivered, discharge cycle time and total cycle time. Then the cycle is repeated with different loads (e.g. 0.2C load, 0.3C,…,2C). The number of steps (load cycles and load values) should be selectable in software. The results should be logged to a permanent storage for import. The imported data can be used to measure, plot and graph the battery characteristics, thus giving the performance and life expectancy under different load conditions.

About the Circuit:

It consists of four modules: the analog frontend, the charge/discharge controller, the microcontroller and the display. The long term storage (using EN25F80) is still pending.

The analog frontend takes three lines from battery – the battery’s +ve & -ve terminals directly and a third lead that connects the battery to load or charger. The charge/discharge controller is built around IC ULN2003 with a total of five relays – one for charger and four for load. Each realy on the load will carry a specific load attached to it – I chose 16Amps, 8Amps, 4Amps & 2Amps. This allows me to discharge the battery under test (BUT or DUT) at a rate anywhere from 2A to 30A in 2A steps.

More to come soon…

Note: All the work shared on this page is free for use under following terms: all shares/distributions including derived works should refer a link to this page and you use this information at your own risk. I am not responsible for any results including success and/or damages.

Why should Hard Disks have only one set of R/W Heads – Arm?

I just started wondering, why should hard disks have only one arm for R/W heads. I did not try doing much research yet, but I think the technology today is mature enough to have more than one arm, thus improving the disk response.

One obvious challenge is the chances of disk crash will be doubled if we have two arms. Probably, the life expectancy also is cut in to half. But can the technology today take care of these challenges? Is it worth it? I am still trying to dig.
More to come…

%d bloggers like this: