Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Interrupt not working....

Status
Not open for further replies.
mcs51mc said:
When is an interrupt generated?
Once you know that, what is the time between 2 interrupts with the above code?

Assuming the interrupt is generated at 1sec per beat, the time between 2 interrupts will be 2secs.

Yea, i understand the meaning of:
Code:
Time_1	equ 65535[B]-10000[/B]   ;10ms interrupt assuming 12MHz xtal
Time_1	equ 65535[B]-2000[/B]   ;2ms interrupt assuming 12MHz xtal

ok... i'll try that on Excel... :)

Hmm... I thought of another easier method. That is to set the timer to run for 5 secs and count the number of pulses during that 5 secs than using the answer to multiply by 12 to get BPM. :D
 
Last edited:
S.K said:
Hmm... I thought of another easier method. That is to set the timer to run for 5 secs and count the number of pulses during that 5 secs than using the answer to multiply by 12 to get BPM. :D
That's working the wrong way!!
The time between "start timer and first pulse" and also "last pulse to stop timer" is undefined and will lead to errors!!!

You need to measure time between well defined positions in your signal. Just like you measure frequency of a sinus at maximum or zero cross or 50%amplitude.

According to previous posts, you already have the maximum of the signal correct? Why not starting the timer at peak n and stop it (or count intervals of x ms) until peak n+4 is reached?


S.K said:
Assuming the interrupt is generated at 1sec per beat, the time between 2 interrupts will be 2secs.

Yea, i understand the meaning of:
Code:
Time_1	equ 65535[B]-10000[/B]   ;10ms interrupt assuming 12MHz xtal
Time_1	equ 65535[B]-2000[/B]   ;2ms interrupt assuming 12MHz xtal
Excuse me but I think you still don't :(
You can't expect the beats to come every sec :confused:
Who will time 1sec?


S.K said:
Don't
You're in charge
The µC does what you tell him to do no more, no less
 
Last edited:
I see...

I have tried starting the timer at peak n and stopping the timer at peak n+4, but it jumps between the values of "077 BPM" and "154 BPM", sometimes even to "000 BPM"... :(
The method I'm using is counting the number of overflows between peak n and peak n+4...

You can't expect the beats to come every sec
How will time 1sec?

I don't understand... In your previous post, you said human heartbeat comes in 1 to 1.33bps... So in order to measure 1 sec accurately, i have to measure 100ms for 10 times or 10ms for 100 times?:confused:
 
Should work if :)

1) You set-up the timer to 12ms (because of you wired xtal of 2MHz :eek:)
2) Start the timer at peak n
3) Count 12ms intervals while waiting for peak n+X
4) Reload the timer must be the first instructions in the ISR of the timer!!!!
5) Stop the timer at peak n+X
6) Calculate elapsed time: ET = Overflows * 12 + ActualTimerValue - ReloadValueTimer (be sure that all terms have the same unit ms)
7) Calculate heartbeat BPM = X * 60000 / ET

Example:
Overflows = 316
Timer value at peak n+4 = 64868

Elapsed time = 316 * 12 + ((64868 - 63535) * 6 / 1000) = 3799ms
BPM = 4 * 60000 / 3799 = 63.17

Theory is ok, translate in µC now :):):)
Show us your code!

The error in the above example is +0.02 since the elapsed time should be 3800 instead of the 3799. Is this accurate enough? That is what you should evaluate in Excel!

Are you sure of your peak detection?
Connect a stable signal with known frequency to your µC to do the tests!

Do the math using one formula instead of two like in the above example!
 
Are you sure of your peak detection?
Connect a stable signal with known frequency to your µC to do the tests!

yes, I'm sure, I have tried it using a function generator and a oscilloscope... And of course, it tallies... :D

I see.... Most of the formulas is in 16-bits which im still not so sure of...
 
You better use 32 bit calculation since

BPM = 60000000 * n / ( 12000 * OFVL + 6 * TVAL - 381210)

with:
n = number of peaks
OFVL = number of 12ms overflows
TVAL = timer value at last peak

If you have 32 bit / 32 bit routines you can use the formula as is.
If you have only 32bit / 16bit routines then you must be sure that the denominator never exceeds 65535. That way you need to divide numerator & denominator by 256 for example.

That way the formula becomes
D = (12000 * OFVL + 6 * TVAL - 381210) / 256
BPM = 234375 * n / D

Again, do some evaluations for accuracy in Excel :D
 
OMG!!!! :eek: :(

I'll try.. But 1st, i have to read up on arithematic part for 8051... Thanks... :D
 
What assembler are you using?
Can you include OBJ files in your project?

I can provide you an "MATH_MOD.OBJ" file with the following routines

Add_32_Signed, Add_24_Signed, Add_16_Signed, Add_8_Signed
Sub_32_Signed, Sub_24_Signed, Sub_16_Signed, Sub_8_Signed

Add_32_Unsigned, Add_24_Unsigned, Add_16_Unsigned, Add_8_Unsigned
Sub_32_Unsigned, Sub_24_Unsigned, Sub_16_Unsigned, Sub_8_Unsigned

Mul_16x16_signed, Mul_16x16_unsigned, Mul_16x16_signed_op1
Div_32x16_signed, Div_32x16_unsigned, Div_32x16_signed_op1

That module declares the following bytes in internal RAM
MathLib_Op1, MathLib_Op2, MathLib_Res1, MathLib_Res2
all of these are 4 bytes wide.

The following bit wise result are also provided
MathLib_DivByZero, MathLib_Overflow, MathLib_Underflow
MathLib_Res1Neg, MathLib_Res2Neg


All you need to do is declare the same variables as "extern data" in your own code.
Code:
extrn code (add_32_signed, add_32_unsigned, add_24_signed, add_24_unsigned, add_16_signed, add_16_unsigned, add_8_signed, add_8_unsigned)
extrn code (sub_32_signed, sub_32_unsigned, sub_24_signed, sub_24_unsigned, sub_16_signed, sub_16_unsigned, sub_8_signed, sub_8_unsigned)
extrn code (mul_16x16_signed, mul_16x16_unsigned, mul_16x16_signed_op1)
extrn code (div_32x16_signed, div_32x16_unsigned, div_32x16_signed_op1)

extrn data (MathLib_Op1, MathLib_Op2, MathLib_Res1, MathLib_Res2)

extrn bit (MathLib_DivByZero, MathLib_Res1Neg, MathLib_Res2Neg, MathLib_Overflow, MathLib_Underflow)


Then write code like
Code:
mov  MathLib_Op1+0,MathLib_Res1+2		;Average n samples * a
mov  MathLib_Op1+1,MathLib_Res1+3
mov  MathLib_Op2+0,#043h			;a= 17255 (4366)h
mov  MathLib_Op2+1,#066h	
call mul_16x16_unsigned
mov  MathLib_Op1+0,MathLib_Res1+0		;Result + b
mov  MathLib_Op1+1,MathLib_Res1+1
mov  MathLib_Op1+2,MathLib_Res1+2
mov  MathLib_Op1+3,MathLib_Res1+3
mov  MathLib_Op2+0,#0F6h			;b= -156912265 (F6A5 B577)h
mov  MathLib_Op2+1,#0A5h
mov  MathLib_Op2+2,#0B5h
mov  MathLib_Op2+3,#077h
call add_32_signed
mov  Temperature+0,MathLib_Res1+0		;Store result
mov  Temperature+1,MathLib_Res1+1
to access the routines.

Easy :D:D:D
 
I'm using Keil assembler... I'm not sure how to include OBJ files... Is OBJ files like another file that i can call in my main program?:confused:

Btw, i have a question... Can 8051 detect pulses below/above a certain amplitude and also can it detect pulses below/above a certain frequency?:confused:

Like is there a range for the 8051 to detect the pulses?:confused:
 
Last edited:
S.K said:
I'm using Keil assembler... I'm not sure how to include OBJ files... Is OBJ files like another file that i can call in my main program?:confused:
Long time ago I used the free 2K evaluation kit from Keil. I have OBJ files in the project folder, so Keil also generate OBJ files but I don't know if you can provide an OBJ file :(

S.K said:
Btw, i have a question... Can 8051 detect pulses below/above a certain amplitude
I know some µC like the AT89C2051 have a comparator capability on specific inputs to check amplitudes.

S.K said:
and also can it detect pulses below/above a certain frequency?:confused:
Isn't that what you are doing??

Bottom line: You have to check the datasheet for your specific µC

S.K said:
Like is there a range for the 8051 to detect the pulses?:confused:
What do you mean by "range"?
 
How do provide OBJ file?:confused:

By "range", i mean, like above 5Hz, my external interrupt pin will not be able to detect the pulses. Or below 1Hz, It will not detect the pulses... Isit the same for the pulse amplitude?
 
You lost me completely :eek:
From where those 1 and 5Hz?

The pulse amplitude can be found in the ADC value somewhere in your µC (I pressume some SFR specific to your µC, check the datasheet).
Try'd to find one on the web but didn't :(
Can you post one?

You don't need any external interrupt pins!
You have 100kS/s ADC values, you need to search for a maximum in that data!
I'm convinced 100kS/s is way too much for your application, set your ADC sampling rate according to the time of the max peak in the signal. I have no idea how large that peak is so I can't suggest an appropriate sampling rate.
 
One datasheet of course!
No problem, I finally found one 136 pages!
Did you read this 136 pages?
That's a serious machine you have there!
Do you program it over JTAG?
JTAG, development kit, ... that must have cost a lot or is this some kind of school project?
 
Oh... The datasheet... Yea.. 136 pages...
Yea.. I program it over JTAG... Its a school project...
 
Last edited:
Ok fine for me :)
Can you give an overview of how far you are, both for hard- and software.
What's working what (still) not?

I know you need to measure heartbeat but can you resume how you intend to do it?

What parts of C8051F226 are you using?
You once wrote that the ADC is sampling at 100kS/s but that's the maximum speed :eek:
Do you use the ADC?
Do you use the PGA?
Do you use the comparators?
Do you use the "Window Detector"?
How are they configured?
Do you search for a peak in the ADC readings or what?
You see I did some readings in the datasheet :eek::eek:

Bottom line: I'm a little bit lost on the status of your project so please review some things :eek: :(
Schematic and code would be nice :D


Once your project is done, can you give me the develoment kit :D:D:D:D
 
Sorry for the late reply again.. its seems that i can only log in through my school computer...

Hm... Software: I can start the timer at the 1st falling edge and stop at the 4th falling edge... I'm still stuck at the 32-bit calculation... :eek: :eek:

Hardware: I use a peak detector circuit and an external reference of 2.5V.

Well, I intend to start timer at 1st falling edge and stop timer at 4th falling edge, than average it and find out the frequency than multiply by 60...:p

As for the ADC, i did use it... It was configured that the gain was 1 and conversion start with the write of "1" to ADBUSY... :)

No, i did not use comparators and window detector...:eek: :eek:

This is my code:
Code:
;*************
;-Header File-
;*************
$include (c8051f200.inc)

ORG 0000H
LJMP CONFIG
ORG 0003H
LJMP EX_INT0
ORG 002BH
LJMP T2_INT
ORG 0100H

;*************
;-Definitions-
;*************
DB0 EQU P3.0
DB1 EQU P3.1
DB2 EQU P3.2
DB3 EQU P3.3
DB4 EQU P3.4
DB5 EQU P3.5
DB6 EQU P3.6
DB7 EQU P3.7
RS EQU P2.7
RW EQU P2.5
EN EQU P2.6
DAT EQU P3
TIMER_2 EQU 65535 - 10000 
RAM_ADDR EQU 40H
ASCI_RSULT EQU 50H
OVERFLOW_COUNTER EQU 70H
START_TIMER EQU 60H
VALUE_LOW EQU 65H
VALUE_HIGH EQU 66H
;***************
;-Configuration-
;***************

CONFIG:	
;**************************************
;------------PORT I/O CONFIGURATIONS----------
;**************************************
MOV PRT0MX,#080H ; PRT0MX: T2EX routed to port pin
MOV PRT1MX,#000H ; PRT1MX: Initial Reset Value
MOV PRT2MX,#000H ; PRT2MX: Initial Reset Value
MOV P2MODE,#0FFH ; Set Port 2 as Input
MOV P0MODE,#0FFH ; Set Port 0 as Input
MOV P1MODE,#000H ; Set Port 1 as Analog Input
MOV PRT3CF,#000H ; Set Port 3 as Output
CLR RS1
CLR RS0

;**********************************************
;-----------OSCILLATOR CONFIGURATIONS----------
;**********************************************
                 MOV	OSCXCN,#067H 	; External Oscillator Control Register
                 CLR A 		; Clear value of Accumulator
                 DJNZ ACC,$ 		; Wait for
                 DJNZ ACC,$ 		; at least 1ms

OX_WAIT:  MOV A,OSCXCN	     ; Move data in OSCXCN to Accumulator 
	   JNB ACC.7,OX_WAIT         ; Poll XTLVLD
	   MOV OSCICN,#008H 	; Internal Oscillator Control Register

;**********************************************
;-----------INTERRUPT CONFIGURATIONS-----------
;**********************************************
SETB EA		 ; Enable Global Interrupts
SETB ET2	 ; Enable Timer 2 Interrupt
SETB EX0	 ; Enable External Interrupt 0
SETB PX0	 ; External Interrupt 0 High Priority

;**********************************************
;------------TIMER 0 CONFIGURATIONS------------
;**********************************************
SETB EXEN2	; Enable High to low transition causes a capture
SETB CT2	; Timer function
SETB T2CON.1	; Capture on high to low transiton on T2EX
MOV A,CKCON	; Move CKCON to Accumualtor
CLR ACC.3            ; Set system clock to divided by 12
MOV OVERFLOW_COUNTER,#00	; Move 0 to R7
MOV R7,#0                                     ; Move 4 to R3
MOV START_TIMER,#01		 ; Move 1 to R4
MOV TH2,#HIGH TIMER_2
MOV TL2,#LOW TIMER_2
 	
;***********************************************
;----------WATCHDOG TIMER CONFIGURATIONS--------
;***********************************************
CLR EA                   ; *****************
MOV WDTCN,#0DEH  ; Disable WatchDog
MOV WDTCN,#0ADH  ; Timer           
SETB EA                  ; *****************

;***************
;-Main Function-
;***************
MAIN:	ACALL INIT_LCD   ; Call subroutine "INIT_LCD"
	ACALL CLEAR_LCD  ; Call subroutine "CLEAR_LCD"
	ACALL ON_LCD     ; Call subroutine "ON_LCD"
	ACALL WAIT	; Call subroutine "WAIT

;*******************************
;-Initialization By Instruction-
;*******************************
INIT_LCD:	CLR EN
		CLR RS               ; FUNCTION SET
		MOV DAT,#30H    ; ************************
		SETB EN					
		ACALL DELAY       ; Interface is 8-bits long
		CLR EN
		ACALL DELAY       ; ************************

		CLR RS               ; FUNCTION SET
		MOV DAT,#30H    ; ************************
		SETB EN
		ACALL DELAY       ; Interface is 8-bits long
		CLR EN
		ACALL DELAY       ; ************************

		CLR RS               ; FUNCTION SET
		MOV DAT,#30H    ; ************************
		SETB EN
		ACALL DELAY       ; Interface is 8-bits long
		CLR EN
		ACALL DELAY       ; ************************
					
		CLR RS                ; FUNCTION SET
		MOV DAT,#38H	; ************************
		SETB EN              ; Set LCD to 8-bits,
		ACALL DELAY        ; 2 lines and 5x7 matrix
		CLR EN
	             ACALL DELAY        ; ************************
					
		CLR RS			; DISPLAY OFF
		MOV DAT,#08H		; ************************
		SETB EN                           ; Display Off
		ACALL DELAY	  	; Cursor Off
		CLR EN                             ; Blink of Cursor Off
		ACALL DELAY	             ; ************************

		CLR RS                              ; CLEAR DISPLAY
		MOV DAT,#01H		; ************************
		SETB EN
		ACALL DELAY                      ; Clear Display
		CLR EN
		ACALL DELAY                      ; ************************

		CLR RS          ; ENTRY MODE SET
		MOV DAT,#06H    ; ************************
		SETB EN         ; Increment Cursor Position
		ACALL DELAY     ; No Display Shift
		CLR EN
		ACALL DELAY     ; ************************

		CLR RS          ; CURSOR POSITION
		MOV DAT,#80H    ; ************************
		SETB EN
		ACALL DELAY     ; Force cursor to position 
		CLR EN          ; at 1st line 1st position
		ACALL DELAY     ; ************************
		RET

;********
;-On LCD-
;********
ON_LCD:	CLR RS          ; ON LCD
	MOV DAT,#0CH    ; *************************
	SETB EN		; Display On
	ACALL DELAY     ; Cursor On
	CLR EN          ; Blink of Cursor On
	ACALL DELAY     ; *************************
	RET

;***********
;-Clear LCD-
;***********
CLEAR_LCD:CLR RS          ; CLEAR DISPLAY
                MOV DAT,#01H    ; *************************
	   SETB EN
 	   ACALL DELAY     ; Clear Display
	   CLR EN
	   ACALL DELAY     ; *************************
	   RET

;**********************
;-Wait Until 4th Pulse-
;**********************
WAIT:	CJNE R7,#00H,WAIT  ; Wait for 4th pulses
	CLR TR2                  ; Stop Timer 0

;******
;-Math-
;******
MATH:	MOV A,OVERFLOW_COUNTER			; Stuck here... :(
	MOV B,
					

;***********************************
;-Converting Binary(Hex) to Decimal-
;***********************************
BIN_DEC_CONVRT:	MOV R0,#RAM_ADDR	; Save decimal digits in these RAM locations
		MOV A,R6
		MOV B,#10   		  ; B = 0A hex (10 dec)
		DIV AB			; Divide by 10
		MOV @R0,B		; Save lower digit
		INC R0
		MOV B,#10
		DIV AB			; Divide by 10
		MOV @R0,B		; Save the next digit
		INC R0
		MOV B,#10
		DIV AB    		; Divide by 10
		MOV @R0,B		; Save the next digit
		INC R0
		MOV @R0,A                      ; Save the last digit

;*****************************
;-Converting Decimal to ASCII-
;*****************************
DEC_ASCI_CONVRT:	MOV R0,#RAM_ADDR		; Addr of decimal data
			MOV R1,#ASCI_RSULT  ; Addr of ASCII data
			MOV R2,#4           ; Count

BACK:			MOV A,@R0	; Get decimal digit
			ORL A,#30H	; Make it an ASCII digit
			MOV @R1,A	; Save it
			INC R0		; Next digit
			INC R1		; Next
			DJNZ R2,BACK	; Repeat until last one

;*********
;-Display-
;*********
DISPLAY:  MOV A,52H         ; Move data in 52H to Accumulator
	ACALL PRINT       ; Call subroutine "PRINT"
	MOV A,51H	; Move data in 51H to Accumulator
	ACALL PRINT       ; Call subroutine "PRINT"
	MOV A,50H         ; Move data in 50H to Accumulator
	ACALL PRINT       ; Call subroutine "PRINT"
	MOV A,#' '        
	ACALL PRINT       ; Call subroutine "PRINT"
	MOV A,#'B'	; Move "B" to Accumulator
	ACALL PRINT  	; Call subroutine "PRINT"
	MOV A,#'P'	; Move "P" to Accumulator
	ACALL PRINT	; Call subroutine "PRINT"
	MOV A,#'M'	; Move "M" to Accumulator	
	ACALL PRINT	; Call subroutine "PRINT"

;******
;-Loop-
;******
LOOP:	ACALL DELAY1	      ; Call subroutine "DELAY1"
	LJMP CLEAR_LCD         ; Program will loop back to "CLEAR_LCD"

;*******
;-Print-
;*******
PRINT:     CLR EN         ; PRINT
	 SETB RS        ; *************************
	 CLR RW
	 MOV DAT,A      
	 SETB EN        ; Print out data onto LCD
	 ACALL DELAY
	 CLR EN	
	 ACALL DELAY    ; *************************
	 RET
					 
;**********************
;-External Interrupt 0-
;**********************
EX_INT0:	DJNZ START_TIMER,COUNT  ; Start timer 0 only once
	SETB TR0	      	; Start Timer 0

COUNT:	DEC R7	           	             ; Count number of pulses
	MOV VALUE_LOW,RCAP2L
	MOV VALUE_HIGH,RCAP2H
	RETI					        	

;***********************
;-Timer 2 Overflow Flag-
;***********************
T2_INT:	INC OVERFLOW_COUNTER		; Count number of overflows
	MOV TH2,#HIGH TIMER_0		;	Reloads Timer 0 with High Byte
	MOV TL2,#LOW TIMER_0		; Reloads Timer 0 with Low Byte
	RETI										

;*************
;-Delay Loops-
;*************
DELAY:	MOV R1,#004H
D1:	MOV R2,#0FFH
D2:	DJNZ R2,D2
	DJNZ R1,D1
	RET

DELAY1:	MOV R4,#0AH
D4:	MOV R5,#0FFH
D5:	MOV R6,#0FFH
D6:	DJNZ R6,D6
	DJNZ R5,D5
	DJNZ R4,D4
	RET
					 
	END           ; End of Program

As for the development kit, I'm afraid i can't give you... It belongs to the school...:D :D
 
Last edited:
Is that code really working?

You configure Timer 2 but start Timer 0 in EX_INT0
Please make up your mind Timer 0 or Timer 2 and adjust code as needed !!
(Timer 0 will be fine :))

What's the purpose of the code lines 2 & 3
Code:
SETB T2CON.1			; Capture on high to low transiton on T2EX
MOV A,CKCON				; Move CKCON to Accumualtor
CLR ACC.3            		; Set system clock to divided by 12
MOV OVERFLOW_COUNTER,#00	; Move 0 to R7

This is the same
Code:
SETB CT2				; Timer function
SETB T2CON.1			; Capture on high to low transiton on T2EX
You must clear that bit to use internal osc, by setting that bit T2 is incrementen by high-to-low transitions at the T2 input !!

You can't use the capture mode of timer 2 since there is (propably) nothing connected to pin T2EX P0.7 !!
You need the 16-bit Counter/Timer with Auto-Reload mode.

Please review chapter 17.2 from the datasheet and adjust code as needed !!

What's the purpose of this??
Code:
;**********************
;-Wait Until 4th Pulse-
;**********************
WAIT:	CJNE R7,#00H,WAIT  ; Wait for 4th pulses
	CLR TR2                  ; Stop Timer 0

Your code should be written in such way that the main loop does nothing.
Only when other parts of the code activates some bit(s) the main loop actually do something.
Something like
Code:
EndlessLoop:

	call	ReadKeyPad	;Always check for user input

	jnb MathDone, NoMath
	clr	MathDone
	call	DoMath
	call	DisplayResult
NoMath:


	jnb JobABC,NoABC
	clr	JobABC
	call	JobABCCode
NoABC:

jmp EndlessLoop
"ReadKeyPad" has to be done all the time because you never know when the user press a key.
I know you don't have that for the moment, but next step is adding a button the start/stop measuring.
With your code the user can't stop the measuring cycle because the µC is stuck in you "Wait" loop.
"MathDone" & "JobABC" are bits set in other parts of the code.

I also miss the calculation of the TOTAL elpased time.
See my previous post with the calculations (1st August 2007 07:55 AM).

I suggest you review you code and try display the TOTAL elapsed time instead of calculated BPM.
With fixed signal that should give a stable readout!
You can the also try to change the number of pulses measured and see if the total measured time change accordingly. That way you will be sure about that part of the code and can start thinking about the math.
 
Last edited:
I see... Well, the meaning of :
Code:
MOV A,CKCON	; Move CKCON to Accumualtor
CLR ACC.3

is to make sure that my osc is divided by 12 as i did not want the osc to run too fast...

The "WAIT" loop is to wait until the 4th pulse and stop the timer...

S.K
 
S.K said:
I see... Well, the meaning of :
Code:
MOV A,CKCON	; Move CKCON to Accumualtor
CLR ACC.3

is to make sure that my osc is divided by 12 as i did not want the osc to run too fast...
Since you don't reload the acc in CKCON this has no effect on it :eek:
This is a TIMER 0 control bit (not TIMER 2).

The osc thing is not complete clear to me :(
Do you have an external osc? What frequency?
You once wrote it's 2MHz is this correct?


S.K said:
The "WAIT" loop is to wait until the 4th pulse and stop the timer...

S.K
I know what the "Wait" loop is for but holding up the µC isn't good practice :D:D
Is the "EndlessLoop" example clear to you?
What will be your next step?
 
Status
Not open for further replies.

Latest threads

Back
Top