/***********************************************************************
* Project: "Sitzmattensimulator Mazda 323"
* Homepage: http://www.kuspbv.de/projects/car/sms.html
* Version: 1.4
* State: stable
*
* Author: Michael Kammer
* Stefan Ostermann
*
**** Pin Layout *******************************************************
* _________
* 5V -| |- Ground
* Calibration test -| 12F- |- ICSP_Data
* Calibration Jumper -| 675 |- ICSP_Clock
* ICSP_VPP -|_______|- Airbag Controller
*
**** License **********************************************************
*
* Copyright (C) 2012, 2013 Stefan Ostermann
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
**********************************************************************/
#define __12f675
#include "pic12f675.h"
static unsigned int __at 0x2007 __CONFIG =
_CP_OFF &
_CPD_OFF &
_WDT_ON &
_BODEN_ON &
_PWRTE_ON &
_INTRC_OSC_NOCLKOUT &
_MCLRE_OFF;
#define GPIO_OUT GPIO2
#define GPIO_CAL GPIO4
#define GPIO_FRQ (1<<5) // GPIO5
#define clrwdt() _asm CLRWDT _endasm
#define gotoAddr(Addr) do { \
_asm PAGESEL Addr _endasm; \
_asm GOTO Addr _endasm; \
} while (0)
#define nextStep(_pass, _high, _new) do { \
clrwdt(); \
if ((pass == _pass) && (TMR1H == _high)) GPIO_OUT = _new; \
} while (0)
#define lastStep(_pass, _high, _new, _lpass, _lhigh) do { \
clrwdt(); \
if ((pass == _pass) && (TMR1H == _high)) { \
GPIO_OUT = _new; \
pass = _lpass; \
TMR1H = _lhigh; \
TMR1L = 0; \
T1IF = 0; \
if (calMode & 128) calMode++; \
} \
} while (0)
#ifdef WITH_OSCCAL
/*
* Simple SDCC workaround that puts the RETLW instruction on 0x3FF. It
* results in an 0x34FF. The correct calibration value is replaced by
* the pic programmer. Since this area is reserved GPLINK will
* complain about code outside of address range.
*/
const unsigned char __code __at 0x3FF _OSCVAL = 0xFF;
#endif
unsigned char getCalib() {
EEADR = 0x00; // 0000 0000
RD = 1;
if (EEDATA == 0xFF) gotoAddr(0x3FF); /* Does not return */
return EEDATA;
}
void saveCalib() {
do clrwdt(); while (WR);
WREN = 1;
EEADR = 0x00; // 0000 0000
EEDATA = OSCCAL;
EECON2 = 0x55; // 0101 0101
EECON2 = 0xAA; // 1010 1010
WR = 1;
}
static unsigned char pass;
static unsigned char calMode;
void main() {
/* Bank 2 */
clrwdt();
ANSEL = 0x00; // 0000 0000
TRISIO = 0x1B; // 0001 1011
WPU = 0x10; // 0001 0000
OPTION_REG = 0x07; // 0000 0111
/* Bank 1 */
clrwdt();
GPIO = 0x00; // 0000 0000
CMCON = 0x07; // 0000 0111
ADCON0 = 0x00; // 0000 0000
/* Prepare calibration */
clrwdt();
if (!GPIO_CAL) {
OSCCAL = 0;
calMode = 128;
} else {
OSCCAL = getCalib();
calMode = 0;
}
/* Init timer */
clrwdt();
TMR1L = 0;
TMR1H = 0;
T1CON = 0x31; // 0011 0001
T1IF = 0;
pass = 0;
/* Main loop */
while (1) {
if (calMode & 128) {
if (GPIO_CAL) {
calMode = 0;
saveCalib();
}
if (calMode & 4) {
calMode = 128;
OSCCAL += 8;
}
}
while (TMR1L) clrwdt();
if (T0IF) {
T0IF = 0;
GPIO ^= GPIO_FRQ;
}
if (T1IF) {
T1IF = 0;
pass++;
}
/* Sequence */
nextStep(0, 98, 0); // 1
nextStep(1, 218, 1); // 2
nextStep(2, 16, 0); // 3
nextStep(2, 43, 1); // 4
nextStep(2, 69, 0); // 5
nextStep(2, 96, 1); // 6
nextStep(2, 231, 0); // 7
nextStep(4, 93, 1); // 8
/* Loop */
lastStep(5, 105, 0, 0, 98); // 9
}
}