Skip to content

Commit

Permalink
Brightness control for pi-top.
Browse files Browse the repository at this point in the history
  • Loading branch information
sorgelig committed Feb 10, 2018
1 parent b583480 commit 1cc907c
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 0 deletions.
2 changes: 2 additions & 0 deletions MiSTer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="archie.c" />
<ClCompile Include="brightness.c" />
<ClCompile Include="cfg.c" />
<ClCompile Include="DiskImage.cpp" />
<ClCompile Include="file_io.c" />
Expand All @@ -63,6 +64,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="archie.h" />
<ClInclude Include="brightness.h" />
<ClInclude Include="cfg.h" />
<ClInclude Include="charrom.h" />
<ClInclude Include="debug.h" />
Expand Down
6 changes: 6 additions & 0 deletions MiSTer.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
<ClCompile Include="st_tos.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="brightness.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="archie.h">
Expand Down Expand Up @@ -163,6 +166,9 @@
<ClInclude Include="st_tos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="brightness.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="build.sh" />
Expand Down
252 changes: 252 additions & 0 deletions brightness.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
/*
* brightness.c
*
* Copyright 2016 rricharz
* MiSTer port. Copyright 2018 Sorgelig
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include "brightness.h"

#define MAXCOUNT 10 // maximum number of spi transfer attemps

#define LIDBITMASK 0x04
#define SCREENOFFMASK 0x02
#define PARITYMASK 0x80
#define BRIGHTNESSMASK 0x78
#define SHUTDOWNMASK 0X01

///////////////////////////////////////////////////

static uint32_t spiSpeed;
static int spiFd = -1;

static const uint8_t spiBPW = 8;
static const uint16_t spiDelay = 0;

static int spi_rw(unsigned char *data, int len)
{
struct spi_ioc_transfer spi;

memset (&spi, 0, sizeof (spi));

spi.tx_buf = (unsigned long)data;
spi.rx_buf = (unsigned long)data;
spi.len = len;
spi.delay_usecs = spiDelay;
spi.speed_hz = spiSpeed;
spi.bits_per_word = spiBPW;

return ioctl (spiFd, SPI_IOC_MESSAGE(1), &spi);
}

static int spi_open(int speed, int mode)
{
int fd ;
mode &= 3; // Mode is 0, 1, 2 or 3

if ((fd = open ("/dev/spidev32766.0", O_RDWR)) < 0)
{
printf("Unable to open SPI device: %s\n", strerror (errno));
return -1;
}

if (ioctl (fd, SPI_IOC_WR_MODE, &mode) >= 0)
{
if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) >= 0)
{
if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) >= 0)
{
spiSpeed = speed;
spiFd = fd;
return fd;
}
else
{
printf ("SPI Speed Change failure: %s\n", strerror (errno));
}
}
else
{
printf ("SPI BPW Change failure: %s\n", strerror (errno));
}
}
else
{
printf ("SPI Mode Change failure: %s\n", strerror (errno));
}

close(fd);
fd = -1;
return -1;
}

static int spi_close()
{
if(spiFd >= 0) close(spiFd);
spiFd = -1;
}

///////////////////////////////////////////////////

static int lidbit;
static int screenoffbit;
static int parity;
static int brightness = 6;
static int shutdown;

//////////////////////////////
// Calclate the parity of bits 0 - 6
static int parity7(unsigned char data)
{
int i;
int p = 0;
for (i = 0; i < 7; i++) {
if (data & 1) p = !p;
data = data >> 1;
}
return p;
}

///////////////////////////////
// analyze data byte and set global variables
// return 1 of parity is ok
// Sending: bit 8 = parity of bit 1-7
static int analyze(unsigned char data)
{
lidbit = (data & LIDBITMASK) != 0;
screenoffbit = (data & SCREENOFFMASK) != 0;
parity = (data & PARITYMASK) != 0;
brightness = (data & BRIGHTNESSMASK) >> 3;
shutdown = (data & SHUTDOWNMASK) != 0;

// printf("lid = %d, screen = %d, parity = %d, shutdown = %d, brightness = %d\n", lidbit, screenoffbit, parity, shutdown, brightness);

return (parity7(data) == parity);
}

///////////////
// Calculate data byte using global variables
// Set brightness and status parity bits
// Receiving: bit 8 = brightness parity, bit 3 = status parity
static int calculate()
{
int data = brightness << 3;
if (parity7(brightness)) data += PARITYMASK;
if (shutdown) data += SHUTDOWNMASK;
if (screenoffbit) data += SCREENOFFMASK;
if (parity7(data & 3)) data += LIDBITMASK; // parity ofthe two state bits
return data;
}

void setBrightness(int cmd, int val)
{
unsigned char data, new_data;
int count, ok;

if (spi_open(9600, 0) < 0)
{
printf("Cannot initialize spi driver\n");
return;
}

// send 0xFF and receive current status of pi-top-hub
count = 0;
data = 0xff;
printf("Brighntess sending: 0x%X\n", data);
do
{
data = 0xff;
ok = spi_rw(&data, 1);
if (ok) ok = analyze(data);
}
while ((!ok) && (count++ < MAXCOUNT));
// printf("count = %d\n", count);

if (ok)
{
printf("Brighntess receiving: 0x%X - ", data);
printf("Current brightness = %d, ", brightness);
//force to 0 as set to 1 if rebooted while in screenbitoff=0
//the state is stored on pi-top-hub, but isn't reinitialised on reboot
screenoffbit=0;
if(cmd == BRIGHTNESS_UP)
{
brightness++;
}
else if (cmd == BRIGHTNESS_DOWN)
{
brightness--;
}
else if (cmd == BRIGHTNESS_SET)
{
if(!val) screenoffbit=1;
else screenoffbit = 0;
brightness = val;
}

if (brightness < 1) brightness = 1;
if (brightness > 10) brightness = 10;

printf("Requested brightness = %d, ", brightness);
printf("Requested off = %d\n", screenoffbit);

// calculate data to send
shutdown = 0;
new_data = calculate();

// send new data until accepted
count = 0;
data = new_data;
printf("Brighntess sending: 0x%X\n", data);
do
{
data = new_data;
ok = spi_rw(&data, 1);
if (ok) ok = (data & BRIGHTNESSMASK) == (new_data & BRIGHTNESSMASK);
}
while ((!ok) && (count++ < MAXCOUNT));

// printf("count = %d\n", count);
if (ok)
{
printf("Brighntess receiving: 0x%X - ", data);
printf("New brightness = %d\n", brightness);
}
}
else printf("Reading current brightness not successful\n");

spi_close();
}

int getBrightness()
{
if (screenoffbit) return 0;
return brightness;
}
11 changes: 11 additions & 0 deletions brightness.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef __BRIGHTNESS_H__
#define __BRIGHTNESS_H__

#define BRIGHTNESS_SET 0
#define BRIGHTNESS_UP 1
#define BRIGHTNESS_DOWN 2

void setBrightness(int cmd, int val);
int getBrightness();

#endif
19 changes: 19 additions & 0 deletions user_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "minimig_boot.h"
#include "minimig_fdd.h"
#include "minimig_hdd.h"
#include "brightness.h"

#define BREAK 0x8000

Expand Down Expand Up @@ -1850,6 +1851,24 @@ void user_io_kbd(uint16_t key, int press)
}
}
else
if (key == 0xBE)
{
if (press)
{
setBrightness(BRIGHTNESS_DOWN, 0);
vol_set_timeout = GetTimer(1000);
}
}
else
if (key == 0xBF)
{
if (press)
{
setBrightness(BRIGHTNESS_UP, 0);
vol_set_timeout = GetTimer(1000);
}
}
else
if ((core_type == CORE_TYPE_MINIMIG2) ||
(core_type == CORE_TYPE_MIST) ||
(core_type == CORE_TYPE_ARCHIE) ||
Expand Down

0 comments on commit 1cc907c

Please sign in to comment.