瀏覽代碼

Drop in libraries (not configured yet)

kbere 2 年之前
父節點
當前提交
8f1f59be6e
共有 15 個文件被更改,包括 899 次插入17 次删除
  1. 23 0
      LICENSE.txt
  2. 1 0
      PCB/.gitignore
  3. 二進制
      PCB/01/GPST.PcbDoc
  4. 16 16
      PCB/01/GPStracker.PrjPcb
  5. 131 0
      soft/1wire.c
  6. 43 0
      soft/1wire.h
  7. 176 0
      soft/HD44780.c
  8. 100 0
      soft/HD44780.h
  9. 192 0
      soft/I2C.c
  10. 28 0
      soft/I2C.h
  11. 1 1
      soft/Makefile
  12. 68 0
      soft/ds18b20.c
  13. 16 0
      soft/ds18b20.h
  14. 51 0
      soft/expander.c
  15. 53 0
      soft/expander.h

+ 23 - 0
LICENSE.txt

@@ -0,0 +1,23 @@
+Copyright (c) k4be
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDi
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 1 - 0
PCB/.gitignore

@@ -0,0 +1 @@
+**/History/

二進制
PCB/01/GPST.PcbDoc


+ 16 - 16
PCB/01/GPStracker.PrjPcb

@@ -31,7 +31,7 @@ ReportSuppressedErrorsInMessages=0
 FSMCodingStyle=eFMSDropDownList_OneProcess
 FSMEncodingStyle=eFMSDropDownList_OneHot
 IsProjectConflictPreventionWarningsEnabled=0
-OutputPath=
+OutputPath=Project Outputs for GPStracker
 LogFolderPath=
 ManagedProjectGUID=
 IncludeDesignInRelease=0
@@ -241,7 +241,7 @@ SCH_HasExpandLogicalToPhysicalSheets=-1
 SaveSettingsToOutJob=0
 
 [Generic_EDE]
-OutputDir=
+OutputDir=Project Outputs for GPStracker
 
 [OutputGroup1]
 Name=Netlist Outputs
@@ -1188,31 +1188,31 @@ ComparisonOptions5=Kind=Structure Class|MinPercent=75|MinMatch=3|ShowMatch=0|Use
 [SmartPDF]
 PageOptions=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=A4|PaperIndex=9
 Configuration_Name1=OutputConfigurationParameter1
-Configuration_Item1=DesignatorDisplayMode=Physical|PrintArea=DesignExtent|PrintAreaLowerLeftCornerX=0|PrintAreaLowerLeftCornerY=0|PrintAreaUpperRightCornerX=0|PrintAreaUpperRightCornerY=0|Record=PcbPrintView|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item1=DesignatorDisplayMode=Physical|PrintArea=DesignExtent|PrintAreaLowerLeftCornerX=0|PrintAreaLowerLeftCornerY=0|PrintAreaUpperRightCornerX=0|PrintAreaUpperRightCornerY=0|Record=PcbPrintView|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name2=OutputConfigurationParameter2
-Configuration_Item2=IncludeBoardCutouts=False|IncludeBottomLayerComponents=True|IncludeMultiLayerComponents=True|IncludeTopLayerComponents=True|IncludeViewports=True|Index=0|Mirror=False|Name=Multilayer Composite Print|PadNumberFontSize=14|Record=PcbPrintOut|ShowHoles=False|ShowPadNets=False|ShowPadNumbers=False|SubstituteFonts=False|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item2=IncludeBoardCutouts=False|IncludeBottomLayerComponents=True|IncludeMultiLayerComponents=True|IncludeTopLayerComponents=True|IncludeViewports=True|Index=0|Mirror=False|Name=Multilayer Composite Print|PadNumberFontSize=14|Record=PcbPrintOut|ShowHoles=False|ShowPadNets=False|ShowPadNumbers=False|SubstituteFonts=False|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name3=OutputConfigurationParameter3
-Configuration_Item3=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=TopOverlay|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item3=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=TopOverlay|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name4=OutputConfigurationParameter4
-Configuration_Item4=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=TopLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item4=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=TopLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name5=OutputConfigurationParameter5
-Configuration_Item5=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=BottomLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item5=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=BottomLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name6=OutputConfigurationParameter6
-Configuration_Item6=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=MultiLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item6=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=MultiLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name7=OutputConfigurationParameter7
-Configuration_Item7=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=BottomOverlay|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item7=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=BottomOverlay|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name8=OutputConfigurationParameter8
-Configuration_Item8=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=KeepOutLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item8=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=KeepOutLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name9=OutputConfigurationParameter9
-Configuration_Item9=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical1|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item9=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical1|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name10=OutputConfigurationParameter10
-Configuration_Item10=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical2|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item10=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical2|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name11=OutputConfigurationParameter11
-Configuration_Item11=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical10|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item11=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical10|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name12=OutputConfigurationParameter12
-Configuration_Item12=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical11|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item12=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical11|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name13=OutputConfigurationParameter13
-Configuration_Item13=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical12|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item13=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical12|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 Configuration_Name14=OutputConfigurationParameter14
-Configuration_Item14=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical15|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\altium-projects\GPStracker\GPST.PcbDoc
+Configuration_Item14=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical15|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=D:\Projects\moje\GPStracker\PCB\01\GPST.PcbDoc
 

+ 131 - 0
soft/1wire.c

@@ -0,0 +1,131 @@
+/*
+ * 1wire.c
+ * k4be 2019
+ * License: BSD
+ */ 
+
+#include "1wire.h"
+#include <util/delay.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+
+#ifdef SEARCHROM
+#ifdef INITST
+unsigned char initst;
+#endif
+#endif
+
+unsigned char _1WireInit(void){
+	unsigned char out=0;
+	_1WPORT &= ~_1WL;
+	_1WLOW();
+	_delay_us(480);
+	cli();
+	_1WHIGH();
+	_delay_us(70);
+	if(!_1WISHIGH()) out++;
+	sei();
+	_delay_us(410);
+	if(!_1WISHIGH()) out++;
+	return out; // 0 - short; 1 - ok; 2 - open/no slaves
+}
+
+void _1WireWriteByte(unsigned char data){
+	register unsigned char i;
+	for(i=0;i<8;i++){
+		_1WireWriteSlot(data&1,0);
+		data >>= 1;
+	}
+}
+
+void _1WireWriteBytePR(unsigned char data){ // enable strong pullup right after the command
+	register unsigned char i;
+	for(i=0;i<7;i++){
+		_1WireWriteSlot(data&1,0);
+		data >>= 1;
+	}
+	_1WireWriteSlot(data,1);
+	_1WPORT |= _1WL;
+	_1WDDR |= _1WL;
+	sei();
+	if(!_1WISHIGH()) _1WirePoweroff();
+}
+
+
+void _1WireWriteSlot(unsigned char x, unsigned char pr){
+	cli();
+	_1WLOW();
+	if(x) _delay_us(6); else _delay_us(60);
+	_1WHIGH();
+	if(x) _delay_us(64); else _delay_us(10);
+	if(!pr) sei();
+	_delay_us(1);
+}
+
+unsigned char _1WireReadByte(void){
+	register unsigned char i=1;
+	unsigned char data=0;
+	while(i){
+		if(_1WireReadSlot()) data |= i;
+		i <<= 1;
+	}
+	return data;
+}
+
+unsigned char _1WireReadSlot(void){
+	unsigned char out=0;
+	cli();
+	_1WLOW();
+	_delay_us(6);
+	_1WHIGH();
+	_delay_us(9);
+	if(_1WISHIGH()) out=1;
+	sei();
+	_delay_us(55);
+	return out;
+}
+/*
+void _1WirePoweroff(void){ // turn off power
+	_1WDDR &= ~_1WL;
+	_1WPORT &= ~_1WL;
+}*/
+
+#ifdef SEARCHROM
+
+unsigned char _1WireSearch(unsigned char rv, unsigned char *buf){
+	unsigned char i,a,b,mask=1,lz=0;
+#ifdef INITST
+	if((initst = _1WireInit())!=1) return 0xff;
+#else
+	if(_1WireInit()!=1) return 0xff;
+#endif
+	_1WireWriteByte(0xf0);
+	for(i=1;i<65;i++){
+		a = _1WireReadSlot();
+		b = _1WireReadSlot();
+		if(a && b) return 0xff;
+		if(a==b) {
+			if(i>rv) a = 0;
+			else if(i==rv) a = 1;
+			else a = !!((*buf)&mask);
+			if(!a) lz=i;
+		}
+		_1WireWriteSlot(a,0);
+		if(a) (*buf)|=mask; else (*buf)&=~mask;
+		mask<<=1;
+		if(!mask){
+			mask = 1;
+			buf++;
+		}
+	}
+	rv=lz;
+	return rv;
+}
+
+void _1WireSendRom(unsigned char *rom){
+	register unsigned char i;
+	for(i=0;i<8;i++){
+		_1WireWriteByte(rom[i]);
+	}
+}
+#endif

+ 43 - 0
soft/1wire.h

@@ -0,0 +1,43 @@
+/*
+ * 1wire.h
+ * k4be 2019
+ * License: BSD
+ */ 
+
+
+#ifndef OWIRE_H_
+#define OWIRE_H_
+
+#undef SEARCHROM
+#undef INITST
+
+#ifdef INITST
+extern unsigned char initst;
+#endif
+
+#include <avr/io.h>
+
+#define _1WPORT PORTB
+#define _1WDDR DDRB
+#define _1WPIN PINB
+#define _1WL _BV(PB0)
+
+unsigned char _1WireInit(void);
+void _1WireWriteSlot(unsigned char bit, unsigned char pr);
+unsigned char _1WireReadSlot(void);
+void _1WireWriteByte(unsigned char dana);
+void _1WireWriteBytePR(unsigned char dana);
+unsigned char _1WireReadByte(void);
+void _1WirePoweroff(void);
+void _1WireSendRom(unsigned char *rom);
+unsigned char _1WireSearch(unsigned char rv, unsigned char *buf);
+
+#define _1WLOW() _1WDDR |= _1WL;
+#define _1WHIGH() _1WDDR &= ~_1WL;
+#define _1WISHIGH() (_1WPIN & _1WL)
+
+#define _1WirePoweroff() { _1WDDR &= ~_1WL; _1WPORT &= ~_1WL; }
+
+
+
+#endif /* OWIRE_H_ */

+ 176 - 0
soft/HD44780.c

@@ -0,0 +1,176 @@
+//-------------------------------------------------------------------------------------------------
+// Wyświetlacz alfanumeryczny ze sterownikiem HD44780
+// Sterowanie w trybie 8-bitowym z odczytem flagi zajętości
+// Plik : HD44780.c	
+// Mikrokontroler : Atmel AVR
+// Kompilator : avr-gcc
+// Autor : Radosław Kwiecień
+// Źródło : http://radzio.dxp.pl/hd44780/
+// Data : 24.03.2007
+//-------------------------------------------------------------------------------------------------
+
+#include "HD44780.h"
+#include <avr/pgmspace.h>
+
+
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja zapisu bajtu do wyświetacza (bez rozróżnienia instrukcja/dane).
+//
+//-------------------------------------------------------------------------------------------------
+void _LCD_Write(unsigned char dataToWrite)
+{
+LCD_DATA_DIR = 0xFF;
+
+LCD_RW_PORT &= ~LCD_RW;
+LCD_E_PORT |= LCD_E;
+LCD_DATA_PORT = dataToWrite;
+LCD_E_PORT &= ~LCD_E;
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja odczytu bajtu z wyświetacza (bez rozróżnienia instrukcja/dane).
+//
+//-------------------------------------------------------------------------------------------------
+
+unsigned char _LCD_Read(void)
+{
+unsigned char tmp = 0;
+
+LCD_DATA_DIR = 0x00;
+
+LCD_RW_PORT |= LCD_RW;
+LCD_E_PORT |= LCD_E;
+_delay_us(1); //tu zmieniłem
+tmp = LCD_DATA_PIN;
+LCD_E_PORT &= ~LCD_E;
+return tmp;
+}
+
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja zapisu rozkazu do wyświetlacza
+//
+//-------------------------------------------------------------------------------------------------
+void LCD_WriteCommand(unsigned char commandToWrite)
+{
+LCD_RS_PORT &= ~LCD_RS;
+_LCD_Write(commandToWrite);
+while(LCD_ReadStatus()&0x80);
+}
+
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja odczytu bajtu statusowego
+//
+//-------------------------------------------------------------------------------------------------
+unsigned char LCD_ReadStatus(void)
+{
+LCD_RS_PORT &= ~LCD_RS;
+return _LCD_Read();
+return 0;
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja zapisu danych do pamięci wyświetlacza
+//
+//-------------------------------------------------------------------------------------------------
+void LCD_WriteData(unsigned char dataToWrite)
+{
+LCD_RS_PORT |= LCD_RS;
+_LCD_Write(dataToWrite);
+while(LCD_ReadStatus()&0x80);
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja odczytu danych z pamięci wyświetlacza
+//
+//-------------------------------------------------------------------------------------------------
+unsigned char LCD_ReadData(void)
+{
+LCD_RS_PORT |= LCD_RS;
+return _LCD_Read();
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja wyświetlenia napisu na wyswietlaczu.
+//
+//-------------------------------------------------------------------------------------------------
+void LCD_WriteText(const char * text)
+{
+while(*text)
+  LCD_WriteData(*text++);
+}
+
+void LCD_WriteTextP(const char *text)
+{
+char a;
+while((a = pgm_read_byte(text++)))
+  LCD_WriteData(a);
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja ustawienia współrzędnych ekranowych
+//
+//-------------------------------------------------------------------------------------------------
+void LCD_GoTo(unsigned char x, unsigned char y)
+{
+LCD_WriteCommand(HD44780_DDRAM_SET | (x + (0x40 * y)));
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja czyszczenia ekranu wyświetlacza.
+//
+//-------------------------------------------------------------------------------------------------
+void LCD_Clear(void)
+{
+LCD_WriteCommand(HD44780_CLEAR);
+_delay_ms(2);
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Funkcja przywrócenia początkowych współrzędnych wyświetlacza.
+//
+//-------------------------------------------------------------------------------------------------
+void LCD_Home(void)
+{
+LCD_WriteCommand(HD44780_HOME);
+_delay_ms(2);
+}
+//-------------------------------------------------------------------------------------------------
+//
+// Procedura inicjalizacji kontrolera HD44780.
+//
+//-------------------------------------------------------------------------------------------------
+void LCD_Initalize(void)
+{
+unsigned char i;
+LCD_DATA_DIR = 0xFF;
+LCD_E_DIR 	|= LCD_E;   //
+LCD_RS_DIR 	|= LCD_RS;  //
+LCD_RW_DIR	|= LCD_RW;
+LCD_RS_PORT &= ~LCD_RS; // wyzerowanie linii RS
+LCD_E_PORT &= ~LCD_E;  // wyzerowanie linii E
+LCD_RW_PORT  &= ~LCD_RW;
+_delay_ms(100); // oczekiwanie na ustalibizowanie się napiecia zasilajacego
+
+for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
+  {
+  LCD_E_PORT |= LCD_E;
+  LCD_DATA_PORT = 0x3F;
+  LCD_E_PORT &= ~LCD_E;
+  _delay_ms(5); // czekaj 5ms
+  }
+
+LCD_WriteCommand(HD44780_FUNCTION_SET | HD44780_FONT5x7 | HD44780_TWO_LINE | HD44780_8_BIT); // interfejs 4-bity, 2-linie, znak 5x7
+LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF); // wyłączenie wyswietlacza
+//LCD_WriteCommand(HD44780_CLEAR); // czyszczenie zawartosći pamieci DDRAM
+LCD_WriteCommand(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);// inkrementaja adresu i przesuwanie kursora
+LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK); // włącz LCD, bez kursora i mrugania
+}
+
+//-------------------------------------------------------------------------------------------------
+//
+// Koniec pliku HD44780.c
+//
+//-------------------------------------------------------------------------------------------------

+ 100 - 0
soft/HD44780.h

@@ -0,0 +1,100 @@
+//-------------------------------------------------------------------------------------------------
+// Wyœwietlacz alfanumeryczny ze sterownikiem HD44780
+// Sterowanie w trybie 8-bitowym z odczytem flagi zajêtoœci
+// Plik : HD44780.h	
+// Mikrokontroler : Atmel AVR
+// Kompilator : avr-gcc
+// Autor : Rados³aw Kwiecieñ
+// �ród³o : http://radzio.dxp.pl/hd44780/
+// Data : 24.03.2007
+//-------------------------------------------------------------------------------------------------
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+//-------------------------------------------------------------------------------------------------
+//
+// Konfiguracja sygna³ów steruj¹cych wyœwietlaczem.
+// Mo¿na zmieniæ stosownie do potrzeb.
+//
+//-------------------------------------------------------------------------------------------------
+#define LCD_RS_DIR		DDRA
+#define LCD_RS_PORT 	PORTA
+#define LCD_RS			(1 << PA2)
+
+#define LCD_RW_DIR		DDRA
+#define LCD_RW_PORT		PORTA
+#define LCD_RW			(1 << PA1)
+
+#define LCD_E_DIR		DDRA
+#define LCD_E_PORT		PORTA
+#define LCD_E			(1 << PA0)
+
+#define LCD_DATA_DIR	DDRB
+#define LCD_DATA_PORT	PORTB
+#define LCD_DATA_PIN	PINB
+
+//-------------------------------------------------------------------------------------------------
+//
+// Instrukcje kontrolera Hitachi HD44780
+//
+//-------------------------------------------------------------------------------------------------
+
+#define HD44780_CLEAR					0x01
+
+#define HD44780_HOME					0x02
+
+#define HD44780_ENTRY_MODE				0x04
+	#define HD44780_EM_SHIFT_CURSOR		0
+	#define HD44780_EM_SHIFT_DISPLAY	1
+	#define HD44780_EM_DECREMENT		0
+	#define HD44780_EM_INCREMENT		2
+
+#define HD44780_DISPLAY_ONOFF			0x08
+	#define HD44780_DISPLAY_OFF			0
+	#define HD44780_DISPLAY_ON			4
+	#define HD44780_CURSOR_OFF			0
+	#define HD44780_CURSOR_ON			2
+	#define HD44780_CURSOR_NOBLINK		0
+	#define HD44780_CURSOR_BLINK		1
+
+#define HD44780_DISPLAY_CURSOR_SHIFT	0x10
+	#define HD44780_SHIFT_CURSOR		0
+	#define HD44780_SHIFT_DISPLAY		8
+	#define HD44780_SHIFT_LEFT			0
+	#define HD44780_SHIFT_RIGHT			4
+
+#define HD44780_FUNCTION_SET			0x20
+	#define HD44780_FONT5x7				0
+	#define HD44780_FONT5x10			4
+	#define HD44780_ONE_LINE			0
+	#define HD44780_TWO_LINE			8
+	#define HD44780_4_BIT				0
+	#define HD44780_8_BIT				16
+
+#define HD44780_CGRAM_SET				0x40
+
+#define HD44780_DDRAM_SET				0x80
+
+//-------------------------------------------------------------------------------------------------
+//
+// Deklaracje funkcji
+//
+//-------------------------------------------------------------------------------------------------
+
+void LCD_WriteCommand(unsigned char);
+unsigned char LCD_ReadStatus(void);
+void LCD_WriteData(unsigned char);
+unsigned char LCD_ReadData(void);
+void LCD_WriteText(const char *);
+void LCD_GoTo(unsigned char, unsigned char);
+void LCD_Clear(void);
+void LCD_Home(void);
+void LCD_Initalize(void);
+void LCD_WriteTextP(const char *);
+
+//-------------------------------------------------------------------------------------------------
+//
+// Koniec pliku HD44780.h
+//
+//-------------------------------------------------------------------------------------------------

+ 192 - 0
soft/I2C.c

@@ -0,0 +1,192 @@
+/*
+ * I2C.c
+ * k4be 2022
+ * License: BSD
+ */ 
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include "I2C.h"
+#include "main.h"
+
+void I2C_init(void){
+	TWBR = 18;
+	TWSR |= 0;
+}
+
+/* two byte command (or command + value) */
+unsigned int I2C_SendCommand(unsigned char address, unsigned char command, unsigned char data_byte)
+{
+	unsigned int error = ERROR_I2C;
+	for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
+	{
+		error = 0;
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
+		error |= I2C_WaitForTWInt();
+		
+		error |= I2C_SendOneCommandByte(address << 1);
+		error |= I2C_SendOneCommandByte(command);
+		error |= I2C_SendOneCommandByte(data_byte);
+		
+		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
+	}
+	
+	return error;
+}
+
+/* three byte command (or command + 2 values) */
+unsigned int I2C_SendCommand3byte(unsigned char address,unsigned char command,unsigned char data0, unsigned char data1)
+{
+	unsigned int error = ERROR_I2C;
+	for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
+	{
+		error = 0;
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
+		error |= I2C_WaitForTWInt();
+		
+		error |= I2C_SendOneCommandByte(address << 1);
+		error |= I2C_SendOneCommandByte(command);
+		error |= I2C_SendOneCommandByte(data0);
+		error |= I2C_SendOneCommandByte(data1);
+		
+		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
+	}
+
+	return error;
+}
+
+/* read single byte */
+unsigned int I2C_ReceiveCommand(unsigned char address, unsigned char command, unsigned char *data_byte)
+{
+	unsigned int error = ERROR_I2C;
+	unsigned char _unused;
+	for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
+	{
+		error = 0;
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
+		error |= I2C_WaitForTWInt();
+		
+		error |= I2C_SendOneCommandByte(address << 1);
+		error |= I2C_SendOneCommandByte(command);
+		error |= I2C_SendOneCommandByte((address << 1) | 1);
+
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+		error |= I2C_WaitForTWInt();
+
+		error |= I2C_ReceiveOneCommandByte(&_unused, 0);
+		error |= I2C_ReceiveOneCommandByte(data_byte, 0);
+
+		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+	}
+	
+	return error;
+}
+
+/* send command + any byte count */
+unsigned int I2C_Send_n_bytes(unsigned char address,unsigned char command, const unsigned char *data, unsigned int length)
+{
+	unsigned int error = ERROR_I2C;
+	unsigned int i;
+	
+	for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
+	{
+		error = 0;
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
+		error |= I2C_WaitForTWInt();
+		
+		error |= I2C_SendOneCommandByte(address << 1);
+		error |= I2C_SendOneCommandByte(command);
+		for(i=0;i<length;i++){
+			error |= I2C_SendOneCommandByte(data[i]);
+		}
+		
+		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+	}
+
+	return error;
+}
+
+/* read any byte count */
+unsigned int I2C_Receive_n_bytes(unsigned char address, unsigned char command, unsigned char *data, unsigned int length)
+{
+	unsigned int i;
+	unsigned int error = ERROR_I2C;
+	for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
+	{
+		error = 0;
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
+		error |= I2C_WaitForTWInt();
+		
+		error |= I2C_SendOneCommandByte(address << 1);
+		error |= I2C_SendOneCommandByte(command);
+		
+		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+		_delay_us(1);
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+		error |= I2C_WaitForTWInt();
+		
+		error |= I2C_SendOneCommandByte((address << 1) | 1);
+
+		for(i=0; i<length; i++){
+			error |= I2C_ReceiveOneCommandByte(&data[i], i != length-1);
+		}
+
+		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+	}
+	
+	return error;
+}
+
+/* read 2 bytes */
+unsigned int I2C_ReceiveCommand3byte(unsigned char address, unsigned char command, unsigned char *data0, unsigned char *data1)
+{
+	unsigned int error = ERROR_I2C;
+	unsigned char addressTrash;
+	for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
+	{
+		error = 0;
+		TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);//Send START condition
+		error |= I2C_WaitForTWInt();
+		
+		error |= I2C_SendOneCommandByte(address << 1);
+		error |= I2C_SendOneCommandByte(command);
+		error |= I2C_SendOneCommandByte((address << 1) | 1);
+		
+		TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+		error |= I2C_WaitForTWInt();
+
+		error |= I2C_ReceiveOneCommandByte(&addressTrash, 0);
+		error |= I2C_ReceiveOneCommandByte(data0, 0);
+		error |= I2C_ReceiveOneCommandByte(data1, 0);
+		
+		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+	}
+	
+	return error;
+}
+
+unsigned int I2C_SendOneCommandByte(unsigned char command)
+{
+	TWDR = command;
+	TWCR = (1<<TWINT) | (1<<TWEN);
+	return I2C_WaitForTWInt();
+}
+
+unsigned int I2C_ReceiveOneCommandByte(unsigned char *command, unsigned char ack)
+{
+	TWCR = (1<<TWINT) | (1<<TWEN) | (ack?_BV(TWEA):0);
+	unsigned int error = I2C_WaitForTWInt();
+	*command = TWDR;
+	return error;
+}
+
+unsigned int I2C_WaitForTWInt(void){
+	unsigned char count = 20;
+	while (count && !(TWCR & (1<<TWINT))){
+		count--;
+		_delay_us(10);
+	}
+	if(count == 0) return ERROR_I2C_TIMEOUT;
+
+	return ERROR_NO;
+}

+ 28 - 0
soft/I2C.h

@@ -0,0 +1,28 @@
+/*
+ * I2C.h
+ * k4be 2022
+ * License: BSD
+ */ 
+
+#ifndef I2C_H_
+#define I2C_H_
+
+#define MAX_REPEAT_I2C		3
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include "I2C.h"
+#include "main.h"
+
+void I2C_init(void);
+unsigned int I2C_SendCommand(unsigned char address, unsigned char command, unsigned char data);
+unsigned int I2C_SendCommand3byte(unsigned char address,unsigned char command, unsigned char data0, unsigned char data1);
+unsigned int I2C_ReceiveCommand(unsigned char address,unsigned char command, unsigned char *data);
+unsigned int I2C_ReceiveCommand3byte(unsigned char address, unsigned char command, unsigned char *data0, unsigned char *data1);
+unsigned int I2C_SendOneCommandByte(unsigned char command);
+unsigned int I2C_ReceiveOneCommandByte(unsigned char *command, unsigned char ack);
+unsigned int I2C_WaitForTWInt(void);
+unsigned int I2C_Receive_n_bytes(unsigned char address, unsigned char command, unsigned char *data, unsigned int length);
+unsigned int I2C_Send_n_bytes(unsigned char address,unsigned char command, unsigned char *data, unsigned int length);
+
+#endif /* I2C_H_ */

+ 1 - 1
soft/Makefile

@@ -2,7 +2,7 @@
 PROJECT	= glg
 
 ### Source files and search directory
-CSRC    = main.c uart0.c uart1.c ff.c mmc.c
+CSRC    = main.c uart0.c uart1.c ff.c mmc.c 1wire.c ds18b20.c expander.c HD44780-I2C.c I2C.c
 ASRC    = xitoa.S stime.S
 VPATH   =
 

+ 68 - 0
soft/ds18b20.c

@@ -0,0 +1,68 @@
+/*
+ * ds18b20.c
+ * k4be 2019
+ * License: BSD
+ */ 
+
+#include <string.h>
+#include <util/crc16.h>
+#include <util/delay.h>
+#include "main.h"
+#include "ds18b20.h"
+#include "1wire.h"
+
+union {
+	signed int t;
+	unsigned char owbuffer[9];
+} t;
+
+#define MAX_ERRORS 5
+
+unsigned char temp_ok;
+float hs_temp;
+
+void gettemp(void){
+	unsigned char i, crc=0, tmp;
+	static unsigned char error_cnt;
+	unsigned char temp_ok_out = 0;
+
+	if(System.timers.owire) return;
+
+	_delay_ms(1);
+
+
+	if(_1WireInit() != 1){
+		return;
+	}
+
+	_1WireWriteByte(0xcc);
+	_1WireWriteByte(0xbe);
+
+	for(i=0;i<9;i++){
+		tmp = _1WireReadByte();
+		t.owbuffer[i] = tmp;
+		crc = _crc_ibutton_update(crc, tmp);
+	}
+	if(!crc){
+		if(t.owbuffer[0] != 0x50 || t.owbuffer[1] != 0x05 || t.owbuffer[5] != 0xff || t.owbuffer[7] != 0x10){
+			hs_temp = (float)t.t * 0.0625;
+			temp_ok_out = 1;
+		}
+	}
+
+	if(!temp_ok_out){
+		if(error_cnt > MAX_ERRORS){
+			temp_ok = 0;
+		} else {
+			error_cnt++;
+		}
+	} else {
+		error_cnt = 0;
+		temp_ok = 1;
+	}
+	
+	_1WireInit();
+	_1WireWriteByte(0xcc);
+	_1WireWriteByte(0x44);
+	atomic_set_uint(&System.timers.owire, ms(4000));
+}

+ 16 - 0
soft/ds18b20.h

@@ -0,0 +1,16 @@
+/*
+ * ds18b20.h
+ * k4be 2019
+ * License: BSD
+ */ 
+
+
+#ifndef DS18B20_H_
+#define DS18B20_H_
+
+extern unsigned char temp_ok;
+extern float hs_temp;
+
+void gettemp(void);
+
+#endif /* DS18B20_H_ */

+ 51 - 0
soft/expander.c

@@ -0,0 +1,51 @@
+/*
+ * expander.c
+ * k4be 2022
+ * License: BSD
+ *
+ * PCA9539/TCA9539 GPIO expander driver
+ */ 
+
+#include "main.h"
+#include "I2C.h"
+#include "expander.h"
+#include <avr/io.h>
+
+unsigned char exp_output[EXPANDER_COUNT*2];
+
+void expander_init(unsigned char addr, unsigned char p1in, unsigned char p2in){
+	addr += EXPANDER_ADDR;
+	expander_write_all();
+	System.global_error |= I2C_SendCommand3byte(addr, CMD_PORT0_CONFIG, p1in, p2in);
+}
+
+unsigned int expander_read(unsigned char addr){
+	unsigned char low, high;
+	System.global_error |= I2C_ReceiveCommand(addr, CMD_PORT0_INPUT, &low);
+	System.global_error |= I2C_ReceiveCommand(addr, CMD_PORT1_INPUT, &high);
+	return (unsigned int)low | (((unsigned int) high)<<8);
+}
+
+void expander_write(unsigned char expaddr){
+	unsigned char addr = EXPANDER_ADDR + expaddr;
+	System.global_error |= I2C_SendCommand3byte(addr, CMD_PORT0_OUTPUT, exp_output[expaddr*2], exp_output[expaddr*2 + 1]);
+}
+
+void expander_write_all(void){
+	unsigned char i;
+	for(i=0; i<EXPANDER_COUNT; i++)	
+		expander_write(i);
+}
+
+void expander_set_bit(unsigned char port, unsigned char val, unsigned char on){
+	if(on){
+		exp_output[port] |= val;
+	} else {
+		exp_output[port] &= ~val;
+	}
+/*	if(SREG & _BV(SREG_I)){
+		System.expander_pending = 1;
+	} else {*/
+		expander_write(port / 2);
+//	}
+}

+ 53 - 0
soft/expander.h

@@ -0,0 +1,53 @@
+/*
+ * expander.h
+ * k4be 2022
+ * License: BSD
+ *
+ * PCA9539/TCA9539 GPIO expander driver
+ */ 
+
+
+#ifndef EXPANDER_H_
+#define EXPANDER_H_
+
+#define P00	0
+#define P01	1
+#define P02	2
+#define P03	3
+#define P04	4
+#define P05 5
+#define P06 6
+#define P07 7
+
+#define P10 0
+#define P11 1
+#define P12 2
+#define P13 3
+#define P14 4
+#define P15 5
+#define P16 6
+#define P17 7
+
+#define EXP_PORT0	(128|0)
+#define EXP_PORT1	(128|1)
+
+#define CMD_PORT0_INPUT 0
+#define CMD_PORT1_INPUT 1
+#define CMD_PORT0_OUTPUT 2
+#define CMD_PORT1_OUTPUT 3
+#define CMD_PORT0_INV 4
+#define CMD_PORT1_INV 5
+#define CMD_PORT0_CONFIG 6
+#define CMD_PORT1_CONFIG 7
+
+#define EXPANDER_ADDR 0b1110100 // first address
+
+#define EXPANDER_COUNT 1 // number of expanders (contiguous addresses)
+
+void expander_init(unsigned char addr, unsigned char p1in, unsigned char p2in);
+unsigned int expander_read(unsigned char addr);
+void expander_write(unsigned char addr);
+void expander_write_all(void);
+void expander_set_bit(unsigned char port, unsigned char val, unsigned char on);
+
+#endif /* EXPANDER_H_ */