Page 1 of 1

38kHz modulation with GPIO output??

Posted: Thu Jan 24, 2013 3:21 pm
by redhawk
I would like to turn my Pi into a remote control controller this would enable access to several devices with only 1 IR LED with the possibility of cgi scripts.

As I understand the signals are encoded with a 38kHz modulation just how accurate this has to be I don't really know but is the Pi up to the job??

If I coded in C would I be able to generate a good enough 38kHz signal to fool my remote controlled equipment??

Has anyone actually written such a program yet??

Richard S.

Re: 38kHz modulation with GPIO output??

Posted: Thu Jan 24, 2013 9:58 pm
by Hi-Z
I can't figure out if you're trying to make a 38kHz clock signal or a modulated 38kHz signal, so I don't know if this will help.

The DS1307 Real Time Clock (RTC) has an programmable output square wave which can be configured for 1 Hz, 4.096 kHz, 8.192 kHz and 32.768 kHz

Note: If you have the RTC integrated into your kernel already then the i2c bus will tell you it can't be accessed. Power up the Pi with the power to the RTC disconnected and once it's booted you can reconnect the power and the RTC will be available on the bus.

Re: 38kHz modulation with GPIO output??

Posted: Fri Jan 25, 2013 5:43 pm
by M33P

There is a caveat with this: you have to use a debug function of the VC firmware that outputs a divided clock to GPCLK1 on the GPIO header. In theory it should be divided from the actual crystal clock (19.2MHz). ... 4&p=211575

You can then gate this clock with another GPIO (via 2-input NAND gate) to give a 38kHz modulated signal.

Re: 38kHz modulation with GPIO output??

Posted: Fri Jan 25, 2013 6:08 pm
by tbowmo
You could just use what others have done already :)

using the LIRC package, an IR diode on a gpio (with a transistor to beef up current to the diode), and voila..

/ Thomas

Re: 38kHz modulation with GPIO output??

Posted: Mon Jun 17, 2013 11:56 am
by Hoagie

I've got IR transmitting working - on a revision 2 Pi only though. I use the PCM output, which can send a data stream at much higher frequencies than 38 kHz. I also record the signals using the PCM input. I'm in the process of writing up the project and will post a link when I've finished.


Re: 38kHz modulation with GPIO output??

Posted: Sat Nov 04, 2017 1:05 am
by radneran
Hi Geoff

Any chance you could share how you did the modulation. Is there any specific library you used? Really new to raspberry pi here so no idea how to go about the modulation.


Re: 38kHz modulation with GPIO output??

Posted: Sun Nov 05, 2017 8:47 am
by Hoagie
i’ll probably regret trying to post this from an ipad, but here goes.

Code: Select all

gcc -o play playcode.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

#define CLK_BASE        0x20101000
#define CLK_LEN         0xA8
#define PCMCLK_CNTL     0x98 / 4
#define PCMCLK_DIV      0x9c / 4

#define PCM_BASE        0x20203000
#define PCM_LEN         0x24
#define PCM_CS_A        (0x00/4)
#define PCM_FIFO_A      (0x04/4)
#define PCM_MODE_A      (0x08/4)
#define PCM_RXC_A       (0x0c/4)
#define PCM_TXC_A       (0x10/4)
#define PCM_DREQ_A      (0x14/4)
#define PCM_INTEN_A     (0x18/4)
#define PCM_INT_STC_A   (0x1c/4)
#define PCM_GRAY        (0x20/4)

#define GPIO_BASE       0x20200000
#define GPIO_LEN        0x100
#define GPIO_GPFSEL3    (0x0c/4)
#define GPIO_GPFSEL2    (0x08/4)
// 5-3 = pin 21

static volatile uint32_t *pcm_reg;
static volatile uint32_t *clk_reg;
static volatile uint32_t *gpio_reg;

// Peripherals memory mapping
static void* map_peripheral(uint32_t base, uint32_t len)
    void* vaddr;

    int fd = open("/dev/mem", O_RDWR);
    if (fd < 0)
        printf("Failed to open /dev/mem: %m\n");
        return NULL;

    vaddr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, base);
    if (vaddr == MAP_FAILED) 
        printf("Failed to map peripheral at 0x%08x: %m\n", base);
        return NULL;


    return vaddr;

void delay(int us)
    struct timespec ts = { 0, us * 1000 };
    nanosleep(&ts, NULL);

int main(int argc, char **argv)
        if (argc != 2)
                printf("Should be run as play outfile\n");
                return -1;
        FILE* fp;
        uint32_t samples[4000];
        fp = fopen(argv[1],"r");
        if (!fp)
                printf("Can't open file %s\n",argv[1]);
                return -2;
	int samplecount = 0;

	while (!feof(fp))

	printf("samples: %d\n",samplecount);


	int count = 0;
	// setup PCM input
	pcm_reg = map_peripheral(PCM_BASE, PCM_LEN);
	clk_reg = map_peripheral(CLK_BASE, CLK_LEN);
	gpio_reg= map_peripheral(GPIO_BASE, GPIO_LEN);

        if (pcm_reg && clk_reg && gpio_reg)
                printf("got pointers  %x %x and %x\n",pcm_reg,clk_reg,gpio_reg);

                gpio_reg[GPIO_GPFSEL3] = (gpio_reg[GPIO_GPFSEL3] & 0xffffffC0) | 0x36;

		pcm_reg[PCM_CS_A] = 1<<25 | 1;                // Disable Rx+Tx, Enable PCM block

		// setup the clock
                clk_reg[PCMCLK_CNTL] = 0x5A000000 | (clk_reg[PCMCLK_CNTL] & 0x15); // disable the clock
                clk_reg[PCMCLK_CNTL] = 0x5A000000 | 1; //  pwd | src = oscillator = 19.2Mhz
                clk_reg[PCMCLK_DIV] = 0x5A000000 | 100<<12; // 100 khz clock rate
                clk_reg[PCMCLK_CNTL] = 0x5A000000 | 1<<4 | 1; // pwd | enable | src = oscillator = 19.2Mhz

		pcm_reg[PCM_MODE_A] = 31<<10 | 15;    // FLEN 31, FSLEN 1
		pcm_reg[PCM_RXC_A] = 1<<31 | 0<<30 | 8<<16;  // ch1wex !ch1en ch1wid=8
		pcm_reg[PCM_TXC_A] =  1<<31 | 1<<30 | 8<<16;  // ch1wex ch1en ch1wid=8
		pcm_reg[PCM_CS_A] |= (1<<3 | 1<<4 );		// flush tx and rx buffers
		pcm_reg[PCM_CS_A] |= (1<<2);		// set TXON

		// output 10000 words
		uint32_t txd = 1<<19;

		int repeat;
		for(count = 0 ; count < samplecount ; count++)
			// wait for it to ask for data
			while (( pcm_reg[PCM_CS_A] & txd) == 0)

			// give it some data

			pcm_reg[PCM_FIFO_A] = samples[count];

		// wait for tx queue to empty
		uint32_t txe = 1<<21;
		while (( pcm_reg[PCM_CS_A] & txe) == 0) 

		// close PCM
                pcm_reg[PCM_CS_A] = 1;                // Disable Rx+Tx, Enable pcm block
		pcm_reg[PCM_CS_A] = 0;			// power down PCM block.

	return 0;
i had a similar program to receive the data and save it to a file. i really cant remember how this all works, but i know you can basically output 32 bits serially pretty quickly and its buffered so the software had no issues with speed and timing. Some of the documentation for the PCM stuff was hard to find, ill see if i have aany information about where i got it.
It has to be run as root because of the memory access.