Created
February 13, 2024 15:23
-
-
Save ajarmst/900ddcdfcc6880065bf0e5830380275c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this demo is specifically set to run on the R1.0 ATmega328PB Proto PCB | |
// and the R1.8 'Sweet Sensor Suite' boards. | |
// demo board is using a 12MHz XTAL with the DIV8 fuse cleared, so... 12MHz | |
// to operate this demo set the bus rate for your device correctly | |
#define F_CPU 12E6 | |
// the accelerometer and i/o chip both use interrupts that this demo use | |
// accelerometer is configured to interrupt on tap (used to wakeup the OLED) | |
// i/o configured to interrupt on pin change | |
// this demo uses floating point output, so the project needs to be configured | |
// for floating point support as directed in the course notes | |
// ssd1306 library header selects 128x32 option | |
// you need to modify the SSD1306 header to option match your display size | |
// this demo is specifically setup to work with the following connections: | |
// I/O Board Atmega328PB | |
// ------------------------- | |
// SCL SCL (PC5) | |
// SDA SDA (PC4) | |
// L0 PC3 (configured as an output) | |
// AI1 PC2 (PCINT10 [PCI1], configured as an input, with interrupt) | |
// UT RXD (PD0) | |
// UR TXD (PD1) | |
// I/O Int PD2 (PCINT18 [PCI2], configured as an input, with interrupt) | |
// Buz PD6 (0C0A PWM, configured as an output) | |
// the main micro uses power from the sensor board | |
// so the USBC connection is not used on the main board | |
#include <avr/io.h> | |
#include <util/delay.h> // have to add, has delay implementation (requires F_CPU to be defined) | |
#include <avr/sleep.h> | |
#include <avr/interrupt.h> | |
#include <avr/pgmspace.h> // definitions to place items in flash | |
#include <stdio.h> | |
#include "sci.h" | |
#include "timer.h" | |
#include "I2C.h" | |
#include "LM75A.h" | |
#include "SSD1306.h" | |
#include "atd.h" | |
#include "veml7700.h" | |
#include "adxl343.h" | |
#include "MCP23008.h" | |
#include "bme280.h" | |
#include "misc.h" | |
// constants for timer output compare offset, init and ISR rearm | |
// program activities are coordinated by 100ms tick intervals | |
// and interrupts from sensors | |
const unsigned int _Timer_OC_Offset = 18750; // 1 / (12000000 / 64 / 18750) = 100ms (w/prescale 64) | |
#define _ms_per_tick 100 | |
const unsigned int C_SPLASH_SCREEN_ON_TIME = 1000 / _ms_per_tick; | |
// global isr-modified 100ms tick counter | |
// as a ulong this means the timer will wrap after 136 years, so should be OK | |
volatile unsigned long _Ticks = 0; | |
// ISR-modified flag that checks interrupt pin from accelerometer (activity) | |
volatile unsigned char _AccActivity = 0; | |
// ISR-modified flag that checks interrupt pin from port expander (pin change) | |
volatile unsigned char _PortActivity = 0; | |
// if _Ticks is higher than this value, the OLED should be off | |
// in other words, the OLEDARM value projects into the future for OLED on time | |
unsigned long _OLEDARM = 0; | |
unsigned char _OLEDState = 0; // current state of OLED (prevents redundant on/off calls in logic) | |
// toggle value to control OLED inversion to prevent pixel wear | |
unsigned char InverseCount = 0; | |
// logic to non-redundantly turn on/off OLED | |
void OLED_ONOFFControl (void); | |
// local display functions (OLED and/or USART) | |
// show A/D value on OLED | |
void ShowAD (void); | |
// show devices found on the I2C bus | |
void ShowBusScan (void); | |
// show LM75AD,118 temp on OLED | |
void ShowTemp (void); | |
// show ambient light level from VEML7700 | |
void ShowAmbientLight (int OnSCI, int OnOLED); | |
// splash screen data, placed in flash (program memory) | |
// this pattern may be generated directly with the 'OLED Edit' utility on Moodle | |
const char _SplashMap [512] PROGMEM = | |
{ | |
/* Page 0: */ | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x40, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
/* Page 1: */ | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x19, 0xf9, 0xf9, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0x7c, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, | |
0xc0, 0xe0, 0x70, 0x38, 0x18, 0x18, 0x18, 0x38, 0x70, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x70, 0x30, 0x18, | |
0x18, 0x18, 0x38, 0xf0, 0xc0, 0x00, 0x00, 0xc0, 0xe0, 0x70, 0x38, 0x18, 0x18, 0x18, 0x38, 0x70, | |
0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xf0, 0xe0, 0x00, | |
0x00, 0x00, 0xf8, 0xf8, 0x60, 0x30, 0x18, 0x18, 0x18, 0x38, 0xf0, 0xe0, 0x00, 0x00, 0xc0, 0xe0, | |
0x70, 0x38, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
/* Page 2: */ | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7f, 0x7f, 0x60, 0x60, 0x60, | |
0x00, 0x00, 0x00, 0x00, 0xc0, 0xf0, 0x3e, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x0f, 0x3f, 0x38, 0x70, 0x60, 0x60, 0x60, 0x70, 0x38, 0x1f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7f, 0x60, 0x60, 0x60, | |
0x60, 0x70, 0x38, 0x1f, 0x0f, 0x00, 0x00, 0x0f, 0x3f, 0x38, 0x70, 0x60, 0x60, 0x60, 0x70, 0x38, | |
0x1f, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x3e, 0x67, 0x63, 0x63, 0x63, 0x73, 0x33, 0x7f, 0x7f, 0x00, | |
0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x3f, | |
0x70, 0x60, 0x60, 0x60, 0x30, 0x18, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
/* Page 3: */ | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
}; | |
// one-time inits for the program, broken out to shorten main | |
void DoOneTimeInits (void) | |
{ | |
// only required for other XTAL configurations, in this version 12MHz is fine | |
// for no XTAL/16MHz hardware configurations, adjustments will be required to the code | |
// jump up to 8MHz, as 2MHz is a little slow for the OLED (works, just is not great performance) | |
// 11.11.2 ATmega328PB Full | |
//CLKPR = 0b10000000; // enable changes | |
//CLKPR = 0b00000001; // set to div by 2 (16 / 2 = 8MHz) max at 3.3V is higher (12MHz?) | |
// bring up the UART, specify clock and desired BAUD rate | |
// while vcomm and pc handle much higher rates, BAUD rate generation | |
// does not work out well above 38400 at 12MHz (actually 12MHz / 16) | |
// no fractional baud rate on this chip - 'tis but a simple UART | |
SCI0_Init(F_CPU, 38400, 0); | |
// welcome message, so we know it booted OK | |
SCI0_TxString("\x1b[2J\x1b[1;1HATmega328PB Up! Demo for I/O 1.8 + ATmega328PB Proto PCB!\x1b[0K"); | |
// informational - platform | |
//{ | |
//char buff [80] = {0}; | |
//(void)sprintf (buff, "\r\nsize of char %d", sizeof (char)); | |
//SCI0_TxString(buff); | |
//(void)sprintf (buff, "\r\nsize of short %d", sizeof (short)); | |
//SCI0_TxString(buff); | |
//(void)sprintf (buff, "\r\nsize of int %d", sizeof (int)); | |
//SCI0_TxString(buff); | |
//(void)sprintf (buff, "\r\nsize of long %d", sizeof (long)); | |
//SCI0_TxString(buff); | |
//(void)sprintf (buff, "\r\nsize of long long %d", sizeof (long long)); | |
//SCI0_TxString(buff); | |
//(void)sprintf (buff, "\r\nsize of float %d", sizeof (float)); | |
//SCI0_TxString(buff); | |
//(void)sprintf (buff, "\r\nsize of double %d", sizeof (double)); | |
//SCI0_TxString(buff); | |
//} | |
// setup GPIO pin PC2 for interrupt (for accelerometer) | |
// int10 is part of PCI1 group of pins | |
PCMSK1 |= 0b00000100; // turn on PCINT10 pin mask (enable interrupts) (12.2.7) | |
PCICR |= 0b00000010; // turn on interrupts for group 1 (12.2.4) | |
// using PC2 as AI1 (accelerometer, interrupt 1) | |
DDRC &= ~0b000000100; // make PC2 an input (default) | |
// setup GPIO pin PD2 for interrupt (for port expander) | |
// int18 is part of PCI2 group of pins | |
PCMSK2 |= 0b00000100; // turn on PCINT18 pin mask (enable interrupts) (13.2.6) | |
PCICR |= 0b00000100; // turn on interrupts for group 2 (13.2.4) | |
// using PD2 as IOI (i/o port expander interrupt) | |
DDRD &= ~0b00000100; // make PD2 an input (default) | |
// using PC3 for i/o board LED | |
DDRC |= 0b00001000; // make PC3 an output | |
// using PD6 (0C0A) as PWM output | |
DDRD |= 0b01000000; // make PD6 an output | |
// bring up the timer, requires ISR! | |
Timer_Init(Timer_Prescale_64, _Timer_OC_Offset); // 100ms intervals | |
// enable sleep mode, for idle, sort of similar to WAI on 9S12X (13.2) | |
sleep_enable(); | |
// bring up the I2C bus, at 400kHz operation | |
I2C_Init(F_CPU, I2CBus400); | |
// dump bus scan info to the SCI (helpful if the bus is connected to | |
// other devices, and you want to know what the address is) | |
ShowBusScan (); | |
// bring up the OLED module (orientation flipped) | |
SSD1306_DispInit(SSD1306_OR_UP); | |
// show splash screen test | |
for (int i = 0; i < 4; ++i) | |
{ | |
SSD1306_SetPage(i, &_SplashMap[i * 128]); | |
} | |
// render splash screen | |
SSD1306_Render(); | |
// arm the display to be on for at least 2s initially | |
_OLEDARM = _Ticks + 2000 / _ms_per_tick; | |
// while we are looking at splash screen... | |
// bring up ambient light sensor | |
if (VEML7700_Init()) | |
{ | |
SCI0_TxString("\x1b[3;1HVEML7700 Unexpected error in init!\x1b[0K"); | |
} | |
// bring up ADXL343 | |
if (!ADXL343_Init()) | |
{ | |
//SCI0_TxString("\r\nADXL343 Up!"); | |
// accelerometer can be configured to interrupt on many different conditions | |
// in this case, we want interrupt for activity, routed to interrupt output 1 | |
ADXL343_ActivityInterrupt(); | |
} | |
else | |
{ | |
SCI0_TxString("\x1b[3;1HADXL343 Unexpected error in init!\x1b[0K"); | |
} | |
// bring up the BME280 | |
{ | |
if (BME280_Init()) | |
{ | |
SCI0_TxString("\x1b[3;1HBME280 Unexpected error in init!\x1b[0K"); | |
} | |
else | |
{ | |
if (BME280_FetchCompensationValues()) | |
{ | |
SCI0_TxString("\x1b[3;1HUnable to load BME280 compensation values!\x1b[0K"); | |
} | |
else | |
{ | |
if (BME280_SetOversampling(BME280_OS_1x, BME280_OS_1x, BME280_OS_1x, BME280_ModeNormal)) | |
{ | |
SCI0_TxString("\x1b[3;1HUnable to set BME280 oversampling rates and operating mode!\x1b[0K"); | |
} | |
} | |
} | |
} | |
// set port expander input pins as weak pull-ups (except the one tied to a pull-up button) | |
MCP23008_SetWeakPullups(0b11111110); | |
// set the MCP23008 to interrupt on pin 0 (connected to a pull-up switch in test circuit) | |
MCP23008_SetInterrupt(0b00000001); | |
// bring up A/D channel 0, because why not? | |
//AtoD_Init(AtoD_Channel_0); | |
// setup PWM | |
Timer_F_PWM0(Timer_PWM_Channel_OC0A, Timer_PWM_ClockSel_Div64, Timer_PWM_Pol_NonInverting, 0); | |
// enable interrupts | |
sei(); | |
} | |
int main(void) | |
{ | |
DoOneTimeInits (); | |
// local control: is the splash screen done? default no | |
int iSplashDone = 0; | |
// the standard "don't leave me!" loop | |
while (1) | |
{ | |
// go idle! | |
// this will now fall through on: | |
// a pin interrupt (activity on the accelerometer) | |
// I/O interrupt (activity on the port expander) | |
// a timer interrupt | |
sleep_cpu(); | |
// toggle LED for proof of timer life | |
PINC = 0b00001000; | |
// check to see if the accelerometer has triggered an interrupt (activity) | |
// if so, arm the display for on time | |
if (_AccActivity) | |
{ | |
_AccActivity = 0; | |
// clear the interrupt | |
ADXL343_ReadInterruptSource(); | |
// activity detected on the accelerometer, so rearm the OLED to go on X amount of time | |
_OLEDARM = _Ticks + 5000 / _ms_per_tick; | |
{ | |
char buff [80] = {0}; | |
TimeFromMS (buff, _Ticks * _ms_per_tick); | |
SCI0_TxString ("\x1b[1;1HAccelerometer wake up detected at "); | |
SCI0_TxString (buff); | |
SCI0_TxString ("\x1b[0K"); | |
} | |
} | |
// check to see if the port expander has triggered an interrupt (pin change) | |
// if so, clear the interrupt, and write the port value to the terminal | |
if (_PortActivity) | |
{ | |
_PortActivity = 0; | |
unsigned char portval = 0; | |
MCP23008_ReadINTCap (&portval); | |
char buff[80] = {0}; | |
(void)sprintf (buff, "\x1b[2;1HPort interrupt detected : 0x%2.2X at ", portval); | |
SCI0_TxString(buff); | |
TimeFromMS (buff, _Ticks * _ms_per_tick); | |
SCI0_TxString(buff); | |
SCI0_TxString ("\x1b[0K"); | |
} | |
// only update OLED after splash screen is done (not super efficient once the timeout is done (extra checks)) | |
// if the splash timeout is done, clear the display, mark as done | |
if (!iSplashDone && _Ticks > C_SPLASH_SCREEN_ON_TIME) | |
{ | |
iSplashDone = 1; | |
SSD1306_Clear(); | |
_Ticks = 0; | |
// one-time rendering items here (to replace constant trim for output) | |
{ | |
SCI0_TxString ("\x1b[5;1HBME280"); | |
SCI0_TxString ("\x1b[6;1H------"); | |
SCI0_TxString ("\x1b[5;40HADXL343"); | |
SCI0_TxString ("\x1b[6;40H-------"); | |
SCI0_TxString ("\x1b[11;1HVEML7700"); | |
SCI0_TxString ("\x1b[12;1H--------"); | |
SCI0_TxString ("\x1b[11;40HLM75AD"); | |
SCI0_TxString ("\x1b[12;40H-----"); | |
// kill speaker chirp | |
Timer_F_PWM0(Timer_PWM_Channel_OC0A, Timer_PWM_ClockSel_STOP, Timer_PWM_Pol_NonInverting, 0); | |
} | |
} | |
// long intervals (see note below) | |
if (!(_Ticks % (60000 / _ms_per_tick)) && iSplashDone) | |
{ | |
SSD1306_SetInverse((++InverseCount) % 2); | |
} | |
// I2C bus reads here, always show on SCI | |
// only show on OLED if splash done, and state is armed | |
{ | |
// general buffer for screen/terminal output | |
char buff [100] = { 0 }; | |
int iX = 0, iY = 0, iZ = 0; | |
float gx = 0, gy = 0, gz = 0; | |
if (!ADXL343_ReadRegAccData (&iX, &iY, &iZ)) | |
{ | |
gx = iX * 0.0039; | |
gy = iY * 0.0039; | |
gz = iZ * 0.0039; | |
(void)sprintf (buff, "\x1b[7;40HX:%6.2f\x1b[0K", gx); | |
SCI0_TxString(buff); | |
(void)sprintf (buff, "\x1b[8;40HY:%6.2f\x1b[0K", gy); | |
SCI0_TxString(buff); | |
(void)sprintf (buff, "\x1b[9;40HZ:%6.2f\x1b[0K", gz); | |
SCI0_TxString(buff); | |
} | |
else | |
{ | |
SCI0_TxString("\x1b[3;1HADXL343 error..."); | |
} | |
// OLED updates, skipped if OLED is off (who will see these changes?) | |
if (iSplashDone && _OLEDState) | |
{ | |
// show runtime on OLED | |
TimeFromMS (buff, _Ticks * _ms_per_tick); | |
SSD1306_StringXY(0, 0, buff); | |
// show LM75AD,118 temp on OLED | |
ShowTemp (); | |
// show A/D value from channel 0 | |
//ShowAD (); | |
// | |
// show ambient light level | |
ShowAmbientLight (1, 1); | |
// show accelerometer data | |
{ | |
(void)sprintf (buff, "X:%6.2f Y:%6.2f", gx, gy); | |
SSD1306_StringXY (0, 3, buff); | |
(void)sprintf (buff, "Z:%6.2f", gz); | |
SSD1306_StringXY (12, 2, buff); | |
} | |
// show the data from the BME280 sensor | |
{ | |
// 0 1 2 3 4 5 6 7 | |
// PMSB PLSB PXLSB TMSB TLSB TXLSB HMSB HSLB | |
//long temp = BME_compensate_T_int32 (adcT); | |
//long temp = compensate_temperature (adcT); | |
uint32_t rawT = BME280_raw_T (); | |
int32_t compT = BME280_compensate_T_int32 (rawT); | |
uint32_t rawH = BME280_raw_H(); | |
uint32_t compH = BME280_compensate_H_int64 (rawH); | |
uint32_t rawP = BME280_raw_P (); | |
uint32_t compP = BME280_compensate_P_int32 (rawP); | |
char buff[80] = {0}; | |
(void)sprintf (buff, "\x1b[7;1HTemp = %0.2fC ", compT / 100.0f); | |
SCI0_TxString(buff); | |
(void)sprintf (buff, "\x1b[8;1HHumidity = %0.2frH ", compH / 1024.0f); | |
SCI0_TxString(buff); | |
(void)sprintf (buff, "\x1b[9;1HPressure = %0.2fhPa ", (compP + 7735) / 100.0f); | |
SCI0_TxString(buff); | |
} | |
} | |
} | |
// render any changes, turn on/off as timing indicates | |
SSD1306_Render(); | |
OLED_ONOFFControl(); | |
} | |
} | |
void ShowAmbientLight (int OnSCI, int OnOLED) | |
{ | |
char buff [80] = {0}; | |
// show ambient light level | |
{ | |
unsigned int ambientLevel = 0; | |
if (!VEML7700_ReadAmbient(&ambientLevel)) | |
{ | |
if (OnSCI) | |
{ | |
(void)sprintf(buff, "\x1b[13;1HAmbient: %4.4X (%0.1f%%) ", ambientLevel, (float)ambientLevel / 0xFFFF * 100); | |
SCI0_TxString(buff); | |
} | |
if (OnOLED) | |
{ | |
(void)sprintf (buff, "Amb L: %4.4X", ambientLevel); | |
SSD1306_StringXY (0, 2, buff); | |
} | |
} | |
else | |
{ | |
SCI0_TxString("\x1b[3;1Error reading VEML7700!"); | |
} | |
} | |
} | |
void ShowTemp (void) | |
{ | |
char buff [80] = {0}; | |
(void)sprintf (buff, "\x1b[13;40H%5.1fC ", LM75A_GetTempF()); | |
SCI0_TxString (buff); | |
// OLED: show temperature (requires LM75A to be on the I2C bus) | |
(void)sprintf (buff, "T: %5.1f\x1F", LM75A_GetTempF()); | |
SSD1306_StringXY(0, 1, buff); | |
} | |
void ShowBusScan (void) | |
{ | |
unsigned char scanresults [128] = {0}; | |
char buff [80] = {0}; | |
I2C_Scan(scanresults); | |
SCI0_TxString ("\x1b[3;1HI2C Bus Scan (7-bit addr): "); | |
for (int i = 0; i < 128; ++i) | |
{ | |
if (scanresults[i]) | |
{ | |
(void)sprintf (buff, "%2.2X, ", i); | |
SCI0_TxString(buff); | |
} | |
} | |
SCI0_TxString(" done"); | |
} | |
void ShowAD (void) | |
{ | |
char buff [80] = {0}; | |
//SCI0_TxString("\x1b[33m"); | |
unsigned char AD_low = ADCL; // must be read first | |
unsigned char AD_high = ADCH; | |
// UART: | |
//(void)sprintf (buff, " A/D Channel 0 : 0x%3.3X", AD_low + AD_high * 256); | |
//SCI0_TxString(buff); | |
//SCI0_TxString("\x1b[0m"); | |
// OLED: | |
(void)sprintf (buff, "A/D: %3.3X", AD_low + AD_high * 256); | |
SSD1306_StringXY (13, 1, buff); | |
} | |
void OLED_ONOFFControl (void) | |
{ | |
// OLED on/off logic | |
if (_OLEDARM >= _Ticks) | |
{ | |
// OLED should be ON | |
if (!_OLEDState) | |
{ | |
_OLEDState = 1; | |
SSD1306_DisplayOn(); | |
} | |
} | |
else | |
{ | |
// OLED should be OFF | |
if (_OLEDState) | |
{ | |
_OLEDState = 0; | |
SSD1306_DisplayOff(); | |
} | |
} | |
} | |
// output compare A interrupt | |
ISR(TIMER1_COMPA_vect) | |
{ | |
// rearm the output compare operation | |
OCR1A += _Timer_OC_Offset; // 100ms intervals @ prescale 64 | |
// count 100ms ticks! | |
++_Ticks; | |
} | |
//ISR (TIMER0_OVF_vect) | |
//{ | |
//OCR0A = 128; | |
//} | |
// this interrupt is hooked up to the accelerometer interrupt 1 line | |
// and will respond to any edge change (accelerometer configured to interrupt on activity) | |
ISR (PCINT1_vect) | |
{ | |
// flag is cleared automatically, so just need to take action | |
// accelerometer activity interrupt | |
// only arm if this is a rising edge of the interrupt | |
if (PINC & 0b00000100) | |
{ | |
// arm activity indicator | |
_AccActivity = 1; | |
// show on the LED that the interrupt has flagged | |
// when main loop sees the flag it will clear it | |
//PORTC |= 0b00001000; | |
} | |
} | |
// this interrupt is hooked up to the port expander interrupt line | |
ISR (PCINT2_vect) | |
{ | |
// flag is cleared automatically, so just need to take action | |
// only arm if this is a rising edge of the interrupt (not sure if this is OK) | |
//if (PIND & 0b00000100) | |
unsigned char stuff = PIND; //(is this necessary?) | |
stuff++; // suppress warning | |
{ | |
// show on the LED that the interrupt has flagged | |
// when main loop sees the flag it will clear it | |
PORTC |= 0b00001000; | |
// mark as port changed | |
_PortActivity = 1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment