This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF51822 + custom board not quite working

Hi! My problem is that my code works on the devkit PCA10004(PCB antenna) but not on my own custom board. The devboard can be connected to and all characteristics can be read correctly. With my custom board I can program it, debug it, advertise but I can not connect to the nrf51822. In master control panel i can see the nrf51822, i get -44 to -70db depending on the proximity so the antenna(Tried 2450AT18A100E and a 31mm wire, both works about the same) + balun(2450BM14A0002T) seems to work. I get the address, name and so on but when i click service discovery I get


[11:21:57.3] Device discovery stopped
[11:21:58.4] GetDeviceInfo()
[11:21:58.7] ----------------------------
[11:21:58.7] Connected to device
[11:21:58.7] Role: 0
[11:21:58.7] PeerAddressType: 1
[11:21:58.7] PeerAddress (MSB): D86D1B8280D6
[11:21:58.7] Connection Interval: 20.0ms
[11:21:58.7] Connection Latency: 0
[11:21:58.7] Supervision Timeout: 3000ms
[11:21:58.7] Clock Accuracy: (1)
[11:21:58.7] ----------------------------
[11:21:58.7] Connected to address: D86D1B8280D6
[11:21:58.7] Starting a Read Information Request on the whole remote DB
[11:21:58.8] Lost connection to device. Reason: BTLE_CONN_FAILED_TO_BE_ESTABLISHED
[11:21:58.8] SERVER: Received packet <HciEvent: eventCode=0x0A> - <HciEvent: eventCode=0x0A>
[11:21:58.8] SERVER: Received Link Loss
[11:22:03.7] Discovering all attribute UUIDs
[11:22:03.7] Lost connection before service discovery was complete

I measure the VDD_PA with my scope and the RF frontend gets biased for 400µs in three bursts. But the burst looks exactly the same when i click service discovery. On the devboard they are not the same. The code does not crash, the board continues to advertise and can be when i click start discovery again. The code never reaches the app_error_handler function so no function gives any error(this function contains a while(1);. The code never reaches the ble_evt_dispatch function so no connection event nor disconnection event are generated.

So my conclution is that my custom boards can not recieve anything but only transmit.

The primary crystal starts when the nrf51822 sends data and the low power crystam(32kHz) runns always.

I have attached the PCB, it is 2 layers, 1.6mm. The top plane is basicly a solid groundplane, a few other wires runns there but not close to the RF part.

The code is a modified version of the HRS example.

I have exaclty the same code running on both the devboard and the custom board and the softdevice is loaded.

Do you guys have any clue why I can not receive anything with my custom board?

The only difference I can think of to the devboard is the balun, but i can transmitt, does not that mean that i should be able to receive?

Thanks //Victor @ pluspole.

PCB.PDF

Parents
  • Code: lcd.c

    #include <stdint.h> #include <stdbool.h> #include <string.h> #include "lcd.h" #include "font_12.h" #include "font_28.h" #include "spi.h" #include "spi_master.h" #include "nrf_gpio.h" #include "app_timer.h" #include "app_error.h" #include "pwm.h"

    #define LCD_WIDTH 128 #define LCD_HEIGHT 128

    #define abs(x) ((x)<0?(-x):(x))

    static uint8_t lcdFrameBuffer[LCD_WIDTHLCD_HEIGHT/8+LCD_HEIGHT2+2]; static bool lcdPoweredUp=false; static app_timer_id_t extcomin_timer_id; //EXTCOMIN timer id

    static void lcdDrawHorizontalLine(uint32_t y, uint32_t x1, uint32_t x2); static void lcdDrawVerticalLine(uint32_t x, uint32_t y1, uint32_t y2); static void lcdToggleExtComIn(void * dummy);

    void lcdInit() { uint32_t err_code;

    spi_init(SPI0,SPI_MODE0,true);
    
    nrf_gpio_cfg_output(LCD_PIN_DISP);//DISP
    nrf_gpio_cfg_output(LCD_PIN_EXTCOMIN);//EXTCOMIN
    nrf_gpio_cfg_output(LCD_PIN_3V3_ENABLE);//3V3_Enable
    nrf_gpio_cfg_output(LCD_PIN_BL_PWM);//LCD_BL_PWM
    
    //Init timer
    err_code = app_timer_create(&amp;extcomin_timer_id, APP_TIMER_MODE_REPEATED, lcdToggleExtComIn);
    APP_ERROR_CHECK(err_code);
    
    err_code = app_timer_start(extcomin_timer_id, APP_TIMER_TICKS(500, 0) , NULL);
    APP_ERROR_CHECK(err_code);
    
    lcdPowerDown();
    lcdFrameClear();
    

    }

    void lcdSendFrameBuffer() { if(lcdPoweredUp==true) spi_tx_vector(SPI0,sizeof(lcdFrameBuffer),lcdFrameBuffer); }

    void lcdSendFrameBufferSection(uint8_t yStart, uint8_t yStop) { if(lcdPoweredUp==true) spi_tx_vector(SPI0,(yStop-yStart)((LCD_WIDTH/8)+2)+2,lcdFrameBuffer+(yStart)(LCD_WIDTH/8+2)); }

    void lcdPowerUp() { nrf_gpio_pin_set(LCD_PIN_3V3_ENABLE); nrf_gpio_pin_set(LCD_PIN_DISP); lcdSetBL(0); lcdPoweredUp=true; }

    void lcdPowerDown() { lcdPoweredUp=false; nrf_gpio_pin_clear(LCD_PIN_DISP); nrf_gpio_pin_clear(LCD_PIN_3V3_ENABLE); lcdSetBL(0); }

    void lcdSetBL(uint8_t state) { pwmChangeDuty(0,state?3:0); }

    static void lcdToggleExtComIn(void * dummy) { if(lcdPoweredUp==true) nrf_gpio_pin_toggle(LCD_PIN_EXTCOMIN); else nrf_gpio_pin_clear(LCD_PIN_EXTCOMIN); }

    void lcdFrameClear() { uint8_t y; memset(lcdFrameBuffer,0,sizeof(lcdFrameBuffer)); lcdFrameBuffer[0]=1; for(y=0;y<LCD_HEIGHT;y++) lcdFrameBuffer[1+y*(LCD_WIDTH/8+2)]=y+1; }

    void lcdSetPixel(uint32_t x, uint32_t y) { lcdFrameBuffer[2 + y * ((LCD_WIDTH>>3)+2) + (x>>3)] |= 0x01 << (x & 7); }

    void lcdResetPixel(uint32_t x, uint32_t y) { lcdFrameBuffer[2 + y * (LCD_WIDTH/8+2) + (x>>3)] &=~ (0x01 << (x & 7)); }

    void lcdInvertArea(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    uint8_t* lcdFrameBufferCopy;
    uint8_t pixelsLeft,pixelsInRow;
    if(x0&gt;x1)
    {
    	pixelsLeft=x0;
    	x0=x1&lt;0?0:x1;
    	x1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    if(y0&gt;y1)
    {
    	pixelsLeft=y0;
    	y0=y1&lt;0?0:y1;
    	y1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * (LCD_WIDTH/8+2) + (x0&gt;&gt;3);
    
    pixelsInRow=x1-x0;
    x0&amp;=7;
    for(;y0&lt;y1;y0++)
    {
    	lcdFrameBufferCopy=lcdFrameBufferOffset;
    	pixelsLeft=pixelsInRow;
    	if((8-x0)&lt;pixelsLeft)//First byte is full
    	{
    		if(x0)
    		{
    			*lcdFrameBufferCopy++^=bitsReverse[x0];
    			pixelsLeft-=8-x0;
    		}
    		while(pixelsLeft&gt;=8)
    		{
    			*lcdFrameBufferCopy++^=0xFF;
    			pixelsLeft-=8;
    		}
    		*lcdFrameBufferCopy^=bits[pixelsLeft];
    	}
    	else
    		*lcdFrameBufferCopy^=bits[pixelsLeft]&lt;&lt;x0;
    	lcdFrameBufferOffset+=(LCD_WIDTH/8+2);
    }
    

    }

    void lcdDrawCircle(int32_t x0, int32_t y0, int32_t radius) { int32_t x = radius, y = 0, xTimesWidth=radius*((LCD_WIDTH>>3)+2), yTimesWidth=0; int32_t radiusError = 1-x; uint8_t lcdFrameBufferOffset=lcdFrameBuffer+2+y0((LCD_WIDTH>>3)+2);

    while(x &gt;= y)
    {
    
    	lcdFrameBufferOffset[yTimesWidth + ((x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((x + x0) &amp; 7);
    	lcdFrameBufferOffset[xTimesWidth + ((y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((y + x0) &amp; 7);
    	lcdFrameBufferOffset[yTimesWidth + ((-x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-x + x0) &amp; 7);
    	lcdFrameBufferOffset[xTimesWidth + ((-y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-y + x0) &amp; 7);
    	lcdFrameBufferOffset[-yTimesWidth + ((-x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-x + x0) &amp; 7);
    	lcdFrameBufferOffset[-xTimesWidth + ((-y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-y + x0) &amp; 7);
    	lcdFrameBufferOffset[-yTimesWidth + ((x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((x + x0) &amp; 7);
    	lcdFrameBufferOffset[-xTimesWidth + ((y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((y + x0) &amp; 7);
    	y++;
    	yTimesWidth+=((LCD_WIDTH&gt;&gt;3)+2);
    	if(radiusError&lt;0)
    		radiusError+=2*y+1;
    	else
    	{
    		x--;
    		xTimesWidth-=((LCD_WIDTH&gt;&gt;3)+2);
    		radiusError+=2*(y-x+1);
    	}
    }
    

    }

    static uint8_t reverse(uint8_t b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; }

    void lcdDrawImage(uint8_t x0, uint8_t y0, uint8_t *image, uint8_t width, uint8_t height) { uint8_t x,y=y0; while(height--) { for(x=(x0>>3);x<((x0+width)>>3);x++) { lcdFrameBuffer[2 + y * ((LCD_WIDTH>>3)+2) + x] = reverse(*image++); } y++;

    }
    

    }

    uint8_t lcdDrawStr(uint8_t x0, uint8_t y0, int8_t *str, const FONT_INFO *fontInfo) { uint8_t offset=0;

    while (*str) {
    	if (*str == ' ')
    	{
    		offset+=fontInfo-&gt;descriptorVector[0] + 2;
    	} else if (*str == '\b') {
    		str++;
    		lcdDrawChar(x0+offset, y0, *str, fontInfo, 1);
    		offset += fontInfo-&gt;descriptorVector[ (*str - fontInfo-&gt;startChar)*2] + 2;
    	} else
    	{
    		lcdDrawChar(x0+offset, y0, *str, fontInfo, 0);
    		offset += fontInfo-&gt;descriptorVector[ (*str - fontInfo-&gt;startChar)*2] + 2;
    	}
    	str++;
    }
    return offset;
    

    }

    void lcdDrawChar(uint32_t x0, uint32_t y0, int8_t chr, const FONT_INFO *fontInfo, uint8_t inverted) { chr -= fontInfo->startChar; uint8_t fontWidth = fontInfo->descriptorVector[chr * 2]; uint8_t fontWidthBytes,writeWidthBytes; uint8_t fontHeight = fontInfo->height-1; uint32_t x, y; uint8_t *lcdFrameBufferOffset; const uint8_t *fontOffsetPtr;

    fontWidthBytes = (fontWidth &gt;&gt; 3) + ((fontWidth &amp; 7)?1:0);
    
    writeWidthBytes=fontWidth+(x0&amp;7);
    writeWidthBytes=(writeWidthBytes&gt;&gt;3)+((writeWidthBytes &amp; 7)?1:0);
    
    
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * ((LCD_WIDTH&gt;&gt;3)+2) + (x0&gt;&gt;3);
    fontOffsetPtr=fontInfo-&gt;fontBitmap+fontInfo-&gt;descriptorVector[1 + chr * 2];
    
    if (inverted) {
    	lcdDrawBlock(x0 - 1, y0 - 1, x0 + fontWidth+1, y0 + fontHeight+1);
    	x0&amp;=7;
    	for (y = 0; y &lt; fontHeight; y++)
    	{
    		*lcdFrameBufferOffset&amp;=~((*fontOffsetPtr)&lt;&lt;x0);
    		for (x = 1; x &lt; (writeWidthBytes-1); x++)
    			lcdFrameBufferOffset[x]&amp;=~(((fontOffsetPtr[x])&lt;&lt;x0) | ((fontOffsetPtr[x - 1])&gt;&gt;(8-x0)));
    		lcdFrameBufferOffset[x]&amp;=~((x&lt;fontWidthBytes?((fontOffsetPtr[x])&lt;&lt;x0):0) | ((fontOffsetPtr[x-1])&gt;&gt;(8-x0)));
    
    		lcdFrameBufferOffset+=((LCD_WIDTH&gt;&gt;3)+2);
    		fontOffsetPtr+=fontWidthBytes;
    	}
    } else {
    	x0&amp;=7;
    	for (y = 0; y &lt; fontHeight; y++)
    	{
    		*lcdFrameBufferOffset|=(*fontOffsetPtr)&lt;&lt;x0;
    		for (x = 1; x &lt; (writeWidthBytes-1); x++)
    			lcdFrameBufferOffset[x]|=((fontOffsetPtr[x])&lt;&lt;x0) | ((fontOffsetPtr[x - 1])&gt;&gt;(8-x0));
    		lcdFrameBufferOffset[x]|=(x&lt;fontWidthBytes?((fontOffsetPtr[x])&lt;&lt;x0):0) | ((fontOffsetPtr[x-1])&gt;&gt;(8-x0));
    
    		lcdFrameBufferOffset+=((LCD_WIDTH&gt;&gt;3)+2);
    		fontOffsetPtr+=fontWidthBytes;
    	}
    }
    

    } #if 0 //Which line draw lagorithm to use void lcdDrawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { if(x0==x1){lcdDrawVerticalLine(x0,y0,y1);return;} if(y0==y1){lcdDrawHorizontalLine(y0,x0,x1);return;}

    int32_t dx = abs(x1-x0), sx = x0&lt;x1 ? 1 : -1;
    int32_t dy = abs(y1-y0), sy = y0&lt;y1 ? 1 : -1;
    int32_t err = (dx&gt;dy ? dx : -dy)/2, e2;
    
    for(;;)
    {
    	lcdSetPixel(x0,y0);
    	if (x0==x1 &amp;&amp; y0==y1) break;
    	e2 = err;
    	if (e2 &gt;-dx) { err -= dy; x0 += sx; }
    	if (e2 &lt; dy) { err += dx; y0 += sy; }
    }
    

    } #else

    void lcdDrawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { if(x0==x1){lcdDrawVerticalLine(x0,y0,y1);return;} if(y0==y1){lcdDrawHorizontalLine(y0,x0,x1);return;} int32_t t, distance; int32_t xerr=0, yerr=0, delta_x, delta_y; int32_t incx, incy;

    /* compute the distances in both directions */
    delta_x=x1-x0;
    delta_y=y1-y0;
    
    /* Compute the direction of the increment,
       an increment of 0 means either a horizontal or vertical
       line.
     */
    if(delta_x&gt;0) incx=1;
    else if(delta_x==0) incx=0;
    else incx=-1;
    
    if(delta_y&gt;0) incy=1;
    else if(delta_y==0) incy=0;
    else incy=-1;
    
    /* determine which distance is greater */
    delta_x=abs(delta_x);
    delta_y=abs(delta_y);
    if(delta_x&gt;delta_y) distance=delta_x;
    else distance=delta_y;
    
    /* draw the line */
    for(t=0; t&lt;=distance+1; t++) {
    	lcdSetPixel(x0,y0);
    
    	xerr+=delta_x;
    	yerr+=delta_y;
    	if(xerr&gt;distance) {
    		xerr-=distance;
    		x0+=incx;
    	}
    	if(yerr&gt;distance) {
    		yerr-=distance;
    		y0+=incy;
    	}
    }
    

    } #endif

    static void lcdDrawHorizontalLine(uint32_t y, uint32_t x1, uint32_t x2) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    lcdFrameBufferOffset=lcdFrameBuffer+2 + y * (LCD_WIDTH/8+2) + (x1&gt;&gt;3);
    uint8_t pixelsLeft;
    if(x1&gt;x2)
    {
    	pixelsLeft=x1;
    	x1=x2;
    	x2=pixelsLeft;
    }
    pixelsLeft=x2-x1;
    x1&amp;=7;
    if((8-x1)&lt;pixelsLeft)//First byte is full
    {
    	if(x1)
    	{
    		*lcdFrameBufferOffset++|=bitsReverse[x1];
    		pixelsLeft-=8-x1;
    	}
    	while(pixelsLeft&gt;=8)
    	{
    		*lcdFrameBufferOffset++=0xFF;
    		pixelsLeft-=8;
    	}
    	*lcdFrameBufferOffset|=bits[pixelsLeft];
    }
    else
    	*lcdFrameBufferOffset|=bits[pixelsLeft]&lt;&lt;x1;
    

    }

    void lcdDrawBlock(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    uint8_t* lcdFrameBufferCopy;
    uint8_t pixelsLeft,pixelsInRow;
    if(x0&gt;x1)
    {
    	pixelsLeft=x0;
    	x0=x1&lt;0?0:x1;
    	x1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    if(y0&gt;y1)
    {
    	pixelsLeft=y0;
    	y0=y1&lt;0?0:y1;
    	y1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * (LCD_WIDTH/8+2) + (x0&gt;&gt;3);
    
    pixelsInRow=x1-x0;
    x0&amp;=7;
    for(;y0&lt;y1;y0++)
    {
    	lcdFrameBufferCopy=lcdFrameBufferOffset;
    	pixelsLeft=pixelsInRow;
    	if((8-x0)&lt;pixelsLeft)//First byte is full
    	{
    		if(x0)
    		{
    			*lcdFrameBufferCopy++|=bitsReverse[x0];
    			pixelsLeft-=8-x0;
    		}
    		while(pixelsLeft&gt;=8)
    		{
    			*lcdFrameBufferCopy++=0xFF;
    			pixelsLeft-=8;
    		}
    		*lcdFrameBufferCopy|=bits[pixelsLeft];
    	}
    	else
    		*lcdFrameBufferCopy|=bits[pixelsLeft]&lt;&lt;x0;
    	lcdFrameBufferOffset+=(LCD_WIDTH/8+2);
    }
    

    }

    void lcdClearBlock(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    uint8_t* lcdFrameBufferCopy;
    uint8_t pixelsLeft,pixelsInRow;
    if(x0&gt;x1)
    {
    	pixelsLeft=x0;
    	x0=x1&lt;0?0:x1;
    	x1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    if(y0&gt;y1)
    {
    	pixelsLeft=y0;
    	y0=y1&lt;0?0:y1;
    	y1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * (LCD_WIDTH/8+2) + (x0&gt;&gt;3);
    
    pixelsInRow=x1-x0;
    x0&amp;=7;
    for(;y0&lt;y1;y0++)
    {
    	lcdFrameBufferCopy=lcdFrameBufferOffset;
    	pixelsLeft=pixelsInRow;
    	if((8-x0)&lt;pixelsLeft)//First byte is full
    	{
    		if(x0)
    		{
    			*lcdFrameBufferCopy++&amp;=bits[x0];
    			pixelsLeft-=8-x0;
    		}
    		while(pixelsLeft&gt;=8)
    		{
    			*lcdFrameBufferCopy++=0x00;
    			pixelsLeft-=8;
    		}
    		*lcdFrameBufferCopy&amp;=bitsReverse[pixelsLeft];
    	}
    	else
    		*lcdFrameBufferCopy&amp;=bitsReverse[pixelsLeft]&lt;&lt;x0;
    	lcdFrameBufferOffset+=(LCD_WIDTH/8+2);
    }
    

    }

    static void lcdDrawVerticalLine(uint32_t x, uint32_t y1, uint32_t y2) { const uint8_t bits[]={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; uint8_t byteToWrite; uint8_t *offsetPtr; if(y1>y2) { byteToWrite=y1; y1=y2; y2=byteToWrite; } byteToWrite=bits[x&7]; offsetPtr=(uint8_t *)(lcdFrameBuffer+2+(x>>3)+y1 * (LCD_WIDTH/8+2)); y1=y2-y1; while(y1) { *offsetPtr|=byteToWrite; offsetPtr+=LCD_WIDTH/8+2; y1--; } }

    spi.c: #include "spi_master.h" #include <stdint.h> #include <stdbool.h> #include "ble.h" #include "ble_srv_common.h" #include "spi.h"

    void spi_init(SPIModuleNumber module_number, SPIMode mode, bool lsb_first) { spi_master_init(module_number,mode,lsb_first); }

    bool spi_tx_vector(SPIModuleNumber module_number, uint16_t transfer_size, const uint8_t *tx_data) { NRF_SPI_Type *spi_base_address = (SPI0 == module_number)? NRF_SPI0 : (NRF_SPI_Type *)NRF_SPI1; return spi_master_tx((uint32_t *)spi_base_address,transfer_size,tx_data); }

    spi_master_config.h #ifndef SPI_MASTER_CONFIG_H #define SPI_MASTER_CONFIG_H

    /* SPI0 / #define SPI_PSELSCK0 30 /!< GPIO pin number for SPI clock (note that setting this to 31 will only work for loopback purposes as it not connected to a pin) / #define SPI_PSELMOSI0 00 /!< GPIO pin number for Master Out Slave In / #define SPI_PSELMISO0 0xFFFFFFFF /!< GPIO pin number for Master In Slave Out / #define SPI_PSELSS0 01 /!< GPIO pin number for Slave Select */

    /* SPI1 / #define SPI_PSELSCK1 29 /!< GPIO pin number for SPI clock / #define SPI_PSELMOSI1 21 /!< GPIO pin number for Master Out Slave In / #define SPI_PSELMISO1 23 /!< GPIO pin number for Master In Slave Out / #define SPI_PSELSS1 28 /!< GPIO pin number for Slave Select */

    #define SPI_OPERATING_FREQUENCY ( 0x02000000UL << (uint32_t)Freq_500Kbps ) /*!< Master clock frequency. / #define TIMEOUT_COUNTER 0x300000UL /!< timeout for getting rx bytes from slave */

    #endif

    and H file fpr spi and lcd are elementary

Reply
  • Code: lcd.c

    #include <stdint.h> #include <stdbool.h> #include <string.h> #include "lcd.h" #include "font_12.h" #include "font_28.h" #include "spi.h" #include "spi_master.h" #include "nrf_gpio.h" #include "app_timer.h" #include "app_error.h" #include "pwm.h"

    #define LCD_WIDTH 128 #define LCD_HEIGHT 128

    #define abs(x) ((x)<0?(-x):(x))

    static uint8_t lcdFrameBuffer[LCD_WIDTHLCD_HEIGHT/8+LCD_HEIGHT2+2]; static bool lcdPoweredUp=false; static app_timer_id_t extcomin_timer_id; //EXTCOMIN timer id

    static void lcdDrawHorizontalLine(uint32_t y, uint32_t x1, uint32_t x2); static void lcdDrawVerticalLine(uint32_t x, uint32_t y1, uint32_t y2); static void lcdToggleExtComIn(void * dummy);

    void lcdInit() { uint32_t err_code;

    spi_init(SPI0,SPI_MODE0,true);
    
    nrf_gpio_cfg_output(LCD_PIN_DISP);//DISP
    nrf_gpio_cfg_output(LCD_PIN_EXTCOMIN);//EXTCOMIN
    nrf_gpio_cfg_output(LCD_PIN_3V3_ENABLE);//3V3_Enable
    nrf_gpio_cfg_output(LCD_PIN_BL_PWM);//LCD_BL_PWM
    
    //Init timer
    err_code = app_timer_create(&amp;extcomin_timer_id, APP_TIMER_MODE_REPEATED, lcdToggleExtComIn);
    APP_ERROR_CHECK(err_code);
    
    err_code = app_timer_start(extcomin_timer_id, APP_TIMER_TICKS(500, 0) , NULL);
    APP_ERROR_CHECK(err_code);
    
    lcdPowerDown();
    lcdFrameClear();
    

    }

    void lcdSendFrameBuffer() { if(lcdPoweredUp==true) spi_tx_vector(SPI0,sizeof(lcdFrameBuffer),lcdFrameBuffer); }

    void lcdSendFrameBufferSection(uint8_t yStart, uint8_t yStop) { if(lcdPoweredUp==true) spi_tx_vector(SPI0,(yStop-yStart)((LCD_WIDTH/8)+2)+2,lcdFrameBuffer+(yStart)(LCD_WIDTH/8+2)); }

    void lcdPowerUp() { nrf_gpio_pin_set(LCD_PIN_3V3_ENABLE); nrf_gpio_pin_set(LCD_PIN_DISP); lcdSetBL(0); lcdPoweredUp=true; }

    void lcdPowerDown() { lcdPoweredUp=false; nrf_gpio_pin_clear(LCD_PIN_DISP); nrf_gpio_pin_clear(LCD_PIN_3V3_ENABLE); lcdSetBL(0); }

    void lcdSetBL(uint8_t state) { pwmChangeDuty(0,state?3:0); }

    static void lcdToggleExtComIn(void * dummy) { if(lcdPoweredUp==true) nrf_gpio_pin_toggle(LCD_PIN_EXTCOMIN); else nrf_gpio_pin_clear(LCD_PIN_EXTCOMIN); }

    void lcdFrameClear() { uint8_t y; memset(lcdFrameBuffer,0,sizeof(lcdFrameBuffer)); lcdFrameBuffer[0]=1; for(y=0;y<LCD_HEIGHT;y++) lcdFrameBuffer[1+y*(LCD_WIDTH/8+2)]=y+1; }

    void lcdSetPixel(uint32_t x, uint32_t y) { lcdFrameBuffer[2 + y * ((LCD_WIDTH>>3)+2) + (x>>3)] |= 0x01 << (x & 7); }

    void lcdResetPixel(uint32_t x, uint32_t y) { lcdFrameBuffer[2 + y * (LCD_WIDTH/8+2) + (x>>3)] &=~ (0x01 << (x & 7)); }

    void lcdInvertArea(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    uint8_t* lcdFrameBufferCopy;
    uint8_t pixelsLeft,pixelsInRow;
    if(x0&gt;x1)
    {
    	pixelsLeft=x0;
    	x0=x1&lt;0?0:x1;
    	x1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    if(y0&gt;y1)
    {
    	pixelsLeft=y0;
    	y0=y1&lt;0?0:y1;
    	y1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * (LCD_WIDTH/8+2) + (x0&gt;&gt;3);
    
    pixelsInRow=x1-x0;
    x0&amp;=7;
    for(;y0&lt;y1;y0++)
    {
    	lcdFrameBufferCopy=lcdFrameBufferOffset;
    	pixelsLeft=pixelsInRow;
    	if((8-x0)&lt;pixelsLeft)//First byte is full
    	{
    		if(x0)
    		{
    			*lcdFrameBufferCopy++^=bitsReverse[x0];
    			pixelsLeft-=8-x0;
    		}
    		while(pixelsLeft&gt;=8)
    		{
    			*lcdFrameBufferCopy++^=0xFF;
    			pixelsLeft-=8;
    		}
    		*lcdFrameBufferCopy^=bits[pixelsLeft];
    	}
    	else
    		*lcdFrameBufferCopy^=bits[pixelsLeft]&lt;&lt;x0;
    	lcdFrameBufferOffset+=(LCD_WIDTH/8+2);
    }
    

    }

    void lcdDrawCircle(int32_t x0, int32_t y0, int32_t radius) { int32_t x = radius, y = 0, xTimesWidth=radius*((LCD_WIDTH>>3)+2), yTimesWidth=0; int32_t radiusError = 1-x; uint8_t lcdFrameBufferOffset=lcdFrameBuffer+2+y0((LCD_WIDTH>>3)+2);

    while(x &gt;= y)
    {
    
    	lcdFrameBufferOffset[yTimesWidth + ((x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((x + x0) &amp; 7);
    	lcdFrameBufferOffset[xTimesWidth + ((y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((y + x0) &amp; 7);
    	lcdFrameBufferOffset[yTimesWidth + ((-x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-x + x0) &amp; 7);
    	lcdFrameBufferOffset[xTimesWidth + ((-y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-y + x0) &amp; 7);
    	lcdFrameBufferOffset[-yTimesWidth + ((-x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-x + x0) &amp; 7);
    	lcdFrameBufferOffset[-xTimesWidth + ((-y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((-y + x0) &amp; 7);
    	lcdFrameBufferOffset[-yTimesWidth + ((x+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((x + x0) &amp; 7);
    	lcdFrameBufferOffset[-xTimesWidth + ((y+x0)&gt;&gt;3)] |= 0x01 &lt;&lt; ((y + x0) &amp; 7);
    	y++;
    	yTimesWidth+=((LCD_WIDTH&gt;&gt;3)+2);
    	if(radiusError&lt;0)
    		radiusError+=2*y+1;
    	else
    	{
    		x--;
    		xTimesWidth-=((LCD_WIDTH&gt;&gt;3)+2);
    		radiusError+=2*(y-x+1);
    	}
    }
    

    }

    static uint8_t reverse(uint8_t b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; }

    void lcdDrawImage(uint8_t x0, uint8_t y0, uint8_t *image, uint8_t width, uint8_t height) { uint8_t x,y=y0; while(height--) { for(x=(x0>>3);x<((x0+width)>>3);x++) { lcdFrameBuffer[2 + y * ((LCD_WIDTH>>3)+2) + x] = reverse(*image++); } y++;

    }
    

    }

    uint8_t lcdDrawStr(uint8_t x0, uint8_t y0, int8_t *str, const FONT_INFO *fontInfo) { uint8_t offset=0;

    while (*str) {
    	if (*str == ' ')
    	{
    		offset+=fontInfo-&gt;descriptorVector[0] + 2;
    	} else if (*str == '\b') {
    		str++;
    		lcdDrawChar(x0+offset, y0, *str, fontInfo, 1);
    		offset += fontInfo-&gt;descriptorVector[ (*str - fontInfo-&gt;startChar)*2] + 2;
    	} else
    	{
    		lcdDrawChar(x0+offset, y0, *str, fontInfo, 0);
    		offset += fontInfo-&gt;descriptorVector[ (*str - fontInfo-&gt;startChar)*2] + 2;
    	}
    	str++;
    }
    return offset;
    

    }

    void lcdDrawChar(uint32_t x0, uint32_t y0, int8_t chr, const FONT_INFO *fontInfo, uint8_t inverted) { chr -= fontInfo->startChar; uint8_t fontWidth = fontInfo->descriptorVector[chr * 2]; uint8_t fontWidthBytes,writeWidthBytes; uint8_t fontHeight = fontInfo->height-1; uint32_t x, y; uint8_t *lcdFrameBufferOffset; const uint8_t *fontOffsetPtr;

    fontWidthBytes = (fontWidth &gt;&gt; 3) + ((fontWidth &amp; 7)?1:0);
    
    writeWidthBytes=fontWidth+(x0&amp;7);
    writeWidthBytes=(writeWidthBytes&gt;&gt;3)+((writeWidthBytes &amp; 7)?1:0);
    
    
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * ((LCD_WIDTH&gt;&gt;3)+2) + (x0&gt;&gt;3);
    fontOffsetPtr=fontInfo-&gt;fontBitmap+fontInfo-&gt;descriptorVector[1 + chr * 2];
    
    if (inverted) {
    	lcdDrawBlock(x0 - 1, y0 - 1, x0 + fontWidth+1, y0 + fontHeight+1);
    	x0&amp;=7;
    	for (y = 0; y &lt; fontHeight; y++)
    	{
    		*lcdFrameBufferOffset&amp;=~((*fontOffsetPtr)&lt;&lt;x0);
    		for (x = 1; x &lt; (writeWidthBytes-1); x++)
    			lcdFrameBufferOffset[x]&amp;=~(((fontOffsetPtr[x])&lt;&lt;x0) | ((fontOffsetPtr[x - 1])&gt;&gt;(8-x0)));
    		lcdFrameBufferOffset[x]&amp;=~((x&lt;fontWidthBytes?((fontOffsetPtr[x])&lt;&lt;x0):0) | ((fontOffsetPtr[x-1])&gt;&gt;(8-x0)));
    
    		lcdFrameBufferOffset+=((LCD_WIDTH&gt;&gt;3)+2);
    		fontOffsetPtr+=fontWidthBytes;
    	}
    } else {
    	x0&amp;=7;
    	for (y = 0; y &lt; fontHeight; y++)
    	{
    		*lcdFrameBufferOffset|=(*fontOffsetPtr)&lt;&lt;x0;
    		for (x = 1; x &lt; (writeWidthBytes-1); x++)
    			lcdFrameBufferOffset[x]|=((fontOffsetPtr[x])&lt;&lt;x0) | ((fontOffsetPtr[x - 1])&gt;&gt;(8-x0));
    		lcdFrameBufferOffset[x]|=(x&lt;fontWidthBytes?((fontOffsetPtr[x])&lt;&lt;x0):0) | ((fontOffsetPtr[x-1])&gt;&gt;(8-x0));
    
    		lcdFrameBufferOffset+=((LCD_WIDTH&gt;&gt;3)+2);
    		fontOffsetPtr+=fontWidthBytes;
    	}
    }
    

    } #if 0 //Which line draw lagorithm to use void lcdDrawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { if(x0==x1){lcdDrawVerticalLine(x0,y0,y1);return;} if(y0==y1){lcdDrawHorizontalLine(y0,x0,x1);return;}

    int32_t dx = abs(x1-x0), sx = x0&lt;x1 ? 1 : -1;
    int32_t dy = abs(y1-y0), sy = y0&lt;y1 ? 1 : -1;
    int32_t err = (dx&gt;dy ? dx : -dy)/2, e2;
    
    for(;;)
    {
    	lcdSetPixel(x0,y0);
    	if (x0==x1 &amp;&amp; y0==y1) break;
    	e2 = err;
    	if (e2 &gt;-dx) { err -= dy; x0 += sx; }
    	if (e2 &lt; dy) { err += dx; y0 += sy; }
    }
    

    } #else

    void lcdDrawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { if(x0==x1){lcdDrawVerticalLine(x0,y0,y1);return;} if(y0==y1){lcdDrawHorizontalLine(y0,x0,x1);return;} int32_t t, distance; int32_t xerr=0, yerr=0, delta_x, delta_y; int32_t incx, incy;

    /* compute the distances in both directions */
    delta_x=x1-x0;
    delta_y=y1-y0;
    
    /* Compute the direction of the increment,
       an increment of 0 means either a horizontal or vertical
       line.
     */
    if(delta_x&gt;0) incx=1;
    else if(delta_x==0) incx=0;
    else incx=-1;
    
    if(delta_y&gt;0) incy=1;
    else if(delta_y==0) incy=0;
    else incy=-1;
    
    /* determine which distance is greater */
    delta_x=abs(delta_x);
    delta_y=abs(delta_y);
    if(delta_x&gt;delta_y) distance=delta_x;
    else distance=delta_y;
    
    /* draw the line */
    for(t=0; t&lt;=distance+1; t++) {
    	lcdSetPixel(x0,y0);
    
    	xerr+=delta_x;
    	yerr+=delta_y;
    	if(xerr&gt;distance) {
    		xerr-=distance;
    		x0+=incx;
    	}
    	if(yerr&gt;distance) {
    		yerr-=distance;
    		y0+=incy;
    	}
    }
    

    } #endif

    static void lcdDrawHorizontalLine(uint32_t y, uint32_t x1, uint32_t x2) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    lcdFrameBufferOffset=lcdFrameBuffer+2 + y * (LCD_WIDTH/8+2) + (x1&gt;&gt;3);
    uint8_t pixelsLeft;
    if(x1&gt;x2)
    {
    	pixelsLeft=x1;
    	x1=x2;
    	x2=pixelsLeft;
    }
    pixelsLeft=x2-x1;
    x1&amp;=7;
    if((8-x1)&lt;pixelsLeft)//First byte is full
    {
    	if(x1)
    	{
    		*lcdFrameBufferOffset++|=bitsReverse[x1];
    		pixelsLeft-=8-x1;
    	}
    	while(pixelsLeft&gt;=8)
    	{
    		*lcdFrameBufferOffset++=0xFF;
    		pixelsLeft-=8;
    	}
    	*lcdFrameBufferOffset|=bits[pixelsLeft];
    }
    else
    	*lcdFrameBufferOffset|=bits[pixelsLeft]&lt;&lt;x1;
    

    }

    void lcdDrawBlock(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    uint8_t* lcdFrameBufferCopy;
    uint8_t pixelsLeft,pixelsInRow;
    if(x0&gt;x1)
    {
    	pixelsLeft=x0;
    	x0=x1&lt;0?0:x1;
    	x1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    if(y0&gt;y1)
    {
    	pixelsLeft=y0;
    	y0=y1&lt;0?0:y1;
    	y1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * (LCD_WIDTH/8+2) + (x0&gt;&gt;3);
    
    pixelsInRow=x1-x0;
    x0&amp;=7;
    for(;y0&lt;y1;y0++)
    {
    	lcdFrameBufferCopy=lcdFrameBufferOffset;
    	pixelsLeft=pixelsInRow;
    	if((8-x0)&lt;pixelsLeft)//First byte is full
    	{
    		if(x0)
    		{
    			*lcdFrameBufferCopy++|=bitsReverse[x0];
    			pixelsLeft-=8-x0;
    		}
    		while(pixelsLeft&gt;=8)
    		{
    			*lcdFrameBufferCopy++=0xFF;
    			pixelsLeft-=8;
    		}
    		*lcdFrameBufferCopy|=bits[pixelsLeft];
    	}
    	else
    		*lcdFrameBufferCopy|=bits[pixelsLeft]&lt;&lt;x0;
    	lcdFrameBufferOffset+=(LCD_WIDTH/8+2);
    }
    

    }

    void lcdClearBlock(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { const uint8_t bits[]={0x00, 0x01,0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; const uint8_t bitsReverse[]={0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};

    uint8_t* lcdFrameBufferOffset;
    uint8_t* lcdFrameBufferCopy;
    uint8_t pixelsLeft,pixelsInRow;
    if(x0&gt;x1)
    {
    	pixelsLeft=x0;
    	x0=x1&lt;0?0:x1;
    	x1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    if(y0&gt;y1)
    {
    	pixelsLeft=y0;
    	y0=y1&lt;0?0:y1;
    	y1=pixelsLeft&gt;=LCD_WIDTH?(LCD_WIDTH-1):pixelsLeft;
    }
    lcdFrameBufferOffset=lcdFrameBuffer + 2 + y0 * (LCD_WIDTH/8+2) + (x0&gt;&gt;3);
    
    pixelsInRow=x1-x0;
    x0&amp;=7;
    for(;y0&lt;y1;y0++)
    {
    	lcdFrameBufferCopy=lcdFrameBufferOffset;
    	pixelsLeft=pixelsInRow;
    	if((8-x0)&lt;pixelsLeft)//First byte is full
    	{
    		if(x0)
    		{
    			*lcdFrameBufferCopy++&amp;=bits[x0];
    			pixelsLeft-=8-x0;
    		}
    		while(pixelsLeft&gt;=8)
    		{
    			*lcdFrameBufferCopy++=0x00;
    			pixelsLeft-=8;
    		}
    		*lcdFrameBufferCopy&amp;=bitsReverse[pixelsLeft];
    	}
    	else
    		*lcdFrameBufferCopy&amp;=bitsReverse[pixelsLeft]&lt;&lt;x0;
    	lcdFrameBufferOffset+=(LCD_WIDTH/8+2);
    }
    

    }

    static void lcdDrawVerticalLine(uint32_t x, uint32_t y1, uint32_t y2) { const uint8_t bits[]={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; uint8_t byteToWrite; uint8_t *offsetPtr; if(y1>y2) { byteToWrite=y1; y1=y2; y2=byteToWrite; } byteToWrite=bits[x&7]; offsetPtr=(uint8_t *)(lcdFrameBuffer+2+(x>>3)+y1 * (LCD_WIDTH/8+2)); y1=y2-y1; while(y1) { *offsetPtr|=byteToWrite; offsetPtr+=LCD_WIDTH/8+2; y1--; } }

    spi.c: #include "spi_master.h" #include <stdint.h> #include <stdbool.h> #include "ble.h" #include "ble_srv_common.h" #include "spi.h"

    void spi_init(SPIModuleNumber module_number, SPIMode mode, bool lsb_first) { spi_master_init(module_number,mode,lsb_first); }

    bool spi_tx_vector(SPIModuleNumber module_number, uint16_t transfer_size, const uint8_t *tx_data) { NRF_SPI_Type *spi_base_address = (SPI0 == module_number)? NRF_SPI0 : (NRF_SPI_Type *)NRF_SPI1; return spi_master_tx((uint32_t *)spi_base_address,transfer_size,tx_data); }

    spi_master_config.h #ifndef SPI_MASTER_CONFIG_H #define SPI_MASTER_CONFIG_H

    /* SPI0 / #define SPI_PSELSCK0 30 /!< GPIO pin number for SPI clock (note that setting this to 31 will only work for loopback purposes as it not connected to a pin) / #define SPI_PSELMOSI0 00 /!< GPIO pin number for Master Out Slave In / #define SPI_PSELMISO0 0xFFFFFFFF /!< GPIO pin number for Master In Slave Out / #define SPI_PSELSS0 01 /!< GPIO pin number for Slave Select */

    /* SPI1 / #define SPI_PSELSCK1 29 /!< GPIO pin number for SPI clock / #define SPI_PSELMOSI1 21 /!< GPIO pin number for Master Out Slave In / #define SPI_PSELMISO1 23 /!< GPIO pin number for Master In Slave Out / #define SPI_PSELSS1 28 /!< GPIO pin number for Slave Select */

    #define SPI_OPERATING_FREQUENCY ( 0x02000000UL << (uint32_t)Freq_500Kbps ) /*!< Master clock frequency. / #define TIMEOUT_COUNTER 0x300000UL /!< timeout for getting rx bytes from slave */

    #endif

    and H file fpr spi and lcd are elementary

Children
No Data
Related