<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Grove Ultrasonic Ranger Example
This example shows how to use the 
Grove ultrasonic_ranger
on the board. The Ultrasonic sensor has a maximal range of 400 cm, 
a minimal range of 3 cm and resolution of 1 cm.
If no obstacle is seen by the sensor, 500 cm will be returned 
by default.
In this notebook, we only show how to control the grove ultrasonic ranger 
using the Pmod interface. A PYNQ Pmod Grove adapter is required in this 
notebook. With proper changes in this notebook, users can also control 
the ultrasonic ranger using the Arduino shield.
Step1:  1. Use Microblaze to control the ultrasonic ranger
The following program assumes that the ultrasonic sensor is attached to the 
G1 connector of the Pmod Grove adapter, and the adapter is connected to PMODA.
For the timer controller, the control registers are shown as follows
Step2:  2. Do one-time distance measurement
Remember to put some obstacles in front of the sensor, otherwise the default
value will be returned.
<ASSISTANT_TASK:>
Python Code:
from pynq.overlays.base import BaseOverlay
base = BaseOverlay("base.bit")
Explanation: Grove Ultrasonic Ranger Example
This example shows how to use the 
Grove ultrasonic_ranger
on the board. The Ultrasonic sensor has a maximal range of 400 cm, 
a minimal range of 3 cm and resolution of 1 cm.
If no obstacle is seen by the sensor, 500 cm will be returned 
by default.
In this notebook, we only show how to control the grove ultrasonic ranger 
using the Pmod interface. A PYNQ Pmod Grove adapter is required in this 
notebook. With proper changes in this notebook, users can also control 
the ultrasonic ranger using the Arduino shield.
End of explanation
%%microblaze base.PMODA
#include "xparameters.h"
#include "xtmrctr.h"
#include "gpio.h"
#include "timer.h"
#include <pmod_grove.h>
#define TCSR0 0x00
#define TLR0 0x04
#define TCR0 0x08
#define TCSR1 0x10
#define TLR1 0x14
#define TCR1 0x18
#define MAX_COUNT 0xFFFFFFFF
void create_10us_pulse(gpio usranger){
    gpio_set_direction(usranger, GPIO_OUT);
    gpio_write(usranger, 0);
    delay_us(2);
    gpio_write(usranger, 1);
    delay_us(10);
    gpio_write(usranger, 0);
}
void configure_as_input(gpio usranger){
    gpio_set_direction(usranger, GPIO_IN);
}
unsigned int capture_duration(gpio usranger){
    unsigned int count1, count2;
    count1=0;
    count2=0;
    XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TLR0, 0x0);
    XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x190);
    while(!gpio_read(usranger));
    count1=XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCR0);
    while(gpio_read(usranger));
    count2=XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCR0);
    if(count2 > count1) {
        return (count2 - count1);
    } else {
        return((MAX_COUNT - count1) + count2);  
    }
}
unsigned int read_raw(){
    gpio usranger;
    usranger = gpio_open(PMOD_G1_A);
    create_10us_pulse(usranger);
    configure_as_input(usranger);
    return capture_duration(usranger);
}
Explanation: 1. Use Microblaze to control the ultrasonic ranger
The following program assumes that the ultrasonic sensor is attached to the 
G1 connector of the Pmod Grove adapter, and the adapter is connected to PMODA.
For the timer controller, the control registers are shown as follows:
|Register name |Register functionality               |Register value |
|:-------------|:------------------------------------|:----------------|
|TCSR0         |Timer 0 Control and Status Register  |0x00             |
|TLR0          |Timer 0 Load Register                |0x04             |
|TCR0          |Timer 0 Counter Register             |0x08             |
|TCSR1         |Timer 1 Control and Status Register  |0x10             |
|TLR1          |Timer 1 Load Register                |0x14             |
|TCR1          |Timer 1 Counter Register             |0x18             |
End of explanation
from pynq import Clocks
def read_distance_cm():
    raw_value = read_raw()
    clk_period_ns = int(1000 / Clocks.fclk0_mhz)
    num_microseconds = raw_value * clk_period_ns * 0.001
    if num_microseconds * 0.001 > 30:
        return 500
    else:
        return num_microseconds/58
read_distance_cm()
Explanation: 2. Do one-time distance measurement
Remember to put some obstacles in front of the sensor, otherwise the default
value will be returned.
End of explanation
<END_TASK>