A Raspberry Pi-based JJY (Japanese Standard Time) signal generator that broadcasts time-code signals compatible with radio-controlled clocks.
This Python script generates JJY time signals using PWM (Pulse Width Modulation) on a Raspberry Pi GPIO pin. The signals emulate the JJY time code standard broadcast by NICT (National Institute of Information and Communications Technology) in Japan at 40 kHz and 60 kHz.
- Raspberry Pi (any model with GPIO support)
- GPIO Pin 18 (BCM numbering) - used for PWM output
- pigpio daemon - must be running on the system
- Optional: Amplifier circuit to boost the 60 kHz carrier signal for radio transmission
- Python 3.x
pigpiolibrary- Running
pigpioddaemon
sudo apt-get install pigpio python3-pigpio
sudo systemctl enable pigpiod
sudo systemctl start pigpiod
pip install pigpioGenerates complete JJY time code frames every minute containing:
- Current minute (0-59)
- Current hour (0-23)
- Day of year (1-366)
- Year (00-99)
- Day of week (0=Sunday through 6=Saturday)
- Leap second indicators
- Parity bits for error checking
- Carrier Frequency: 60 kHz
- Duty Cycle: 50%
- Hardware PWM: Uses Raspberry Pi's hardware PWM for precise timing
- GPIO: BCM pin 18
Each minute consists of 60 time slots (0-59 seconds):
- Marker pulses (0.2s): Position markers at seconds 0, 9, 19, 29, 39, 49, 59
- Binary '1' (0.5s): Half-second carrier reduction
- Binary '0' (0.8s): 800ms carrier reduction
- Gaps: Remaining time in each second has full carrier amplitude
| Seconds | Information | Encoding |
|---|---|---|
| 1-8 | Minutes (0-59) | BCD with weights 40, 20, 10, 16, 8, 4, 2, 1 |
| 9 | Position marker P1 | - |
| 10-18 | Hours (0-23) | BCD with weights 80, 40, 20, 10, 16, 8, 4, 2, 1 |
| 19 | Position marker P2 | - |
| 20-33 | Day of year (1-366) | BCD with various weights |
| 29, 39, 49 | Position markers P3, P4, P5 | - |
| 36-37 | Parity bits | Hour and minute parity |
| 40 | Summer time flag | SU2 indicator |
| 41-48 | Year (00-99) | BCD encoding |
| 50-52 | Day of week | 0=Sunday, 6=Saturday |
| 53-54 | Leap second warning | Indicates upcoming leap second |
| 59 | Position marker P6 | Short marker (0.2s) |
- Tracks scheduled leap second insertion dates
- Provides advance warning (within one month) via bits 53-54
- Currently configured with January 1, 2017 leap second
- Automatically synchronizes to system time
- Starts transmission at the beginning of the next minute
- Continuously generates signals every 60 seconds
- Uses threading for precise timing
- PA1: Parity for hour bits (seconds 12-18)
- PA2: Parity for minute bits (seconds 1-8)
- Provides error detection for receivers
python3 adjclock.pyThe script will:
- Connect to the pigpio daemon
- Calculate delay until the next minute boundary
- Start generating JJY signals on GPIO 18
- Print debug information showing bit values and markers
- Continue running until interrupted with Ctrl+C
Starting JJY signal generator...
JJY signal will start in 23.45 seconds
Starting JJY signal for 2025-11-26 14:30
mark P0
bit 0 (weight 40)
bit 1 (weight 20)
bit 1 (weight 10)
...
mark P1
Initializes the generator with leap second data and threading controls.
Returns leap second status:
1: Positive leap second within 31 days0: No leap second scheduled-1: Negative leap second within 31 days (rare)
Generates a PWM pulse of specified duration:
- Activates 60 kHz PWM at 50% duty cycle
- Sleeps for the specified duration
- Stops PWM
- Pads with silence to complete 1 second (unless
short=True)
Generates the complete 60-second JJY time code for a given date:
- Encodes all time information into proper bit positions
- Outputs PWM signals for each bit
- Prints debug information
- Parameters:
date: datetime object for the minute to encodesummer_time: Boolean flag for summer time (DST) - currently unused in Japan
Starts the continuous JJY signal generation:
- Calculates delay to next minute boundary
- Sets up recurring 60-second timer
- Begins signal transmission
Stops signal generation:
- Sets stop flag
- Cancels scheduled timers
- Disables PWM output
PWM_GPIO = 18 # BCM pin 18
FREQ_HZ = 60000 # 60 kHz carrier
DUTY_CYCLE = 500000 # 50% (range 0-1,000,000)- Uses hardware PWM for accurate frequency generation
- Threading timers synchronized to system clock
- Sub-second precision for signal alignment
The JJY standard uses amplitude modulation of a carrier wave:
- Full amplitude: Normal carrier (binary '1' state in gaps)
- Reduced amplitude: During pulse periods (markers and bits)
- This implementation uses PWM on/off to simulate amplitude reduction
Ensure pigpiod is running:
sudo systemctl status pigpiod
sudo systemctl start pigpiod- Verify GPIO 18 is not used by other processes
- Check pigpio permissions
- Confirm PWM is enabled in Raspberry Pi configuration
- Ensure Raspberry Pi system time is accurate
- Consider using NTP for time synchronization:
sudo timedatectl set-ntp true- Does not include actual RF transmission circuitry
- Requires external amplifier and antenna for wireless transmission
- Summer time flag is hardcoded to
False(Japan does not use DST) - Leap second list must be manually updated
- No consideration for timezone
- "second" timing (aka marker) relies on software/timer, so it might be inacurate. We might need more accurate timebase, such as PPS of GPS/RTC
This is an educational implementation of the JJY time signal standard.