Hi Guys.
I would like to know how can I find information to program the 28 pin BasicAtomm for C / C++:?: I use BB2.
You can program in C / C++:?: it appears in the IDE option.
Thanks.
Hi Guys.
I would like to know how can I find information to program the 28 pin BasicAtomm for C / C++:?: I use BB2.
You can program in C / C++:?: it appears in the IDE option.
Thanks.
Yes, the Basic Atom Pro IDE does support C or C++ which is downloaded as part of the IDE. This is a standard GNU release of the language. You can go up to the GNU websistes to find documention on their implementation of the language. The help menu of the IDE opens up the H8/3694 hardware manual, where you can find out a lot about the underlying chips and it’s subsystems. The data sheets for the BAP or the pin out section of the Atom Pro manual shows you which underlying pins of the H8 connect up to which pins of the BAP
I have only played with this some as you more or less have to start off from scratch, except for the standard libraries. There are no hardware specific libraries that make it easy for you to do things like servos or the like.
As for how to do it: You go to the Projects menu and do a new project. Choose the C/C++ option and the appropriate directory and the like and it will create a new set of files for that project. You then can do build and download to either simply build the project or to build and download.
Good Luck
Kurt
I know that you asked the same question on the Basic Micro websiste as well as asked for a sample program. So I thought I would answer it all in one place.
Awhile ago I played with the C compiler. The one note is that I downloaded a set of header files from the Renesas website. As I believe this stuff may be copyrighted I am not sure I can include the content of it in this post. I like using their header files as it breaks down the definitions of the IO structures into easy to use fields, that also make it more obvious if you should switch to a different Renesas chip, when for example the Atom Pro Plus… comes out. This file is part of a zip file named: include_h8_070420.zip
You can find this file up on their website: america.renesas.com/request?LANGUAGE_CD=EN&SCREEN_ID=ViewGRSDownloadSearch&EXECUTE_ACTION=search&LOCATION=GLOBAL&LAYER_ID=&DISP_PAGE=&FrameOtherProductDraftSubmit=search#
In the search field, you can type in: include_h8
which should get you to the right file.
But I created a project called HelloWorld, which in my case I built up to use I2C with a SRF08 or SRF10 sensor to do a ping. I then used the 3 LEDS on the BB2 board for status. I think one led just toggeled when I was doing a ping and the other two blinked the range. One blinked the 10s and the other the 1s… Again I am not saying this code is perfect. I also did some preliminary work on being able to output stuff to S_OUT at 9600 baud. A quick look through the I2C code looks like I was starting also to play with the Async version of I2C with interrupts. I don’t remember at all if this part was functional or not…
It has been awhile, since I looked at the code, not sure if it all works… But here are the contents of most of the files:
HelloWorld.cpp
[code]#include <signal.h>
extern “C” {
#include “3694s.h”
};
#include “i2c.h”
#include “serio.h”
volatile unsigned long g_lWTimerOverflowCount;
extern void itoa(int n, char *psz);
extern bool TXRX(unsigned char bIn, unsigned char *pbOut, bool fWaitforAck);
extern bool PS2InputOutputStrings(unsigned char *pbOut, unsigned char *pbIn, unsigned char cbIn, bool fPause, unsigned char bRetryCount);
/*
ms_sleep() - delay for specified number of milliseconds
*/
void ms_sleep(unsigned int ms)
{
// Ok lets play with the actual timer. First lets try the long long integer…
unsigned long ulCountEnd;
unsigned long ulTicEnd;
// calculate the end time based on there are 2 tics per uS so there would be 2*1024 tics per ms
// We will set up two different values for a 48 bit clock which is in .5uS increments.
ulTicEnd = ((unsigned long int)ms * 2048) + TW.TCNT; // convert mS to clock tics to wait
ulCountEnd = g_lWTimerOverflowCount + (ulTicEnd >> 16);
ulTicEnd &= 0xffff;
for (;
{
if ((ulCountEnd < g_lWTimerOverflowCount) ||
((ulCountEnd == g_lWTimerOverflowCount) && ((unsigned int)ulTicEnd <= TW.TCNT)))
break;
}
}
/*
#pragma interrupt(TIMERW)
void TIMERW() // for TimerW 16mhz/8 = 2cl/uS. So 210241024/65536) -> called 32 times per second.
{
g_lWTimerOverflowCount++;
if (g_wI2CCountDown)
{
g_wI2CCountDown--;
IO.PDR8.BIT.B6 = 0x1; // start off in some known state
}
else
IO.PDR8.BIT.B6 = 0x0; // start off in some known state
TW.TSRW.BIT.OVF = 0;
}
//
// initialize timer 0 to generate an interrupt every millisecond.
//
void init_timer(void)
{
g_lWTimerOverflowCount = 0; // initialize the count
g_wI2CCountDown = 0;
TW.TCRW.BIT.CKS = 0x3; // set clock to use system clock/8 as increment. so about 1/2 Us per increment overflow every or 128uS
TW.TSRW.BIT.OVF = 0; // make sure the overflow is cleared
TW.TMRW.BIT.CTS = 1; // starts the timer counting
TW.TIERW.BIT.OVIE = 1; // enable interrupt on overflow
#if TIMERA
TA.TMA.BYTE=4; //increments on clock/256
IRR1.BIT.IRRTA = 0; // Make sure the interrupt happened flag is clear
IENR1.BIT.IENTA = 1; // ENABLE TIMERAINT
#endif
}
int main(void)
{
int iError;
init_timer();
unsigned char bBuff[10];
unsigned short iVal;
unsigned char abRegs[2];
TW.TIOR1.BIT.IOD = 0; // Make sure P84 is an IO pin...
IO.PCR8 = 0x70; // make sure it is write
IO.PDR8.BIT.B6 = 0x1; // start off in some known state
IO.PDR8.BIT.B5 = 0x1;
IO.PDR8.BIT.B4 = 0x1;
IO.PMR5.BYTE |= 0xc0;
IO.PCR5 = 0;
// BUGBUG: not used, simply here to see calling sequences.
PS2InputOutputStrings(bBuff, abRegs, 4, true, 3);
while (1) {
ms_sleep(512); /* wait 0.5 seconds */
IO.PDR8.BIT.B4 = 0x0; /* toggle LED */
ms_sleep(512);
IO.PDR8.BIT.B4 = 0x1; /* toggle LED */
// Now lets try to do a ping with our I2c code
iError = I2C_WriteRegister(0xe0, 0, 80);
switch (iError)
{
case I2C_ERROR_TIMEOUT_BBSY:
IO.PDR8.BIT.B5 = 0x0; /* toggle LED */
IO.PDR8.BIT.B6 = 0x1; /* toggle LED */
break;
case I2C_ERROR_TIMEOUT_IRIC1:
IO.PDR8.BIT.B5 = 0x1; /* toggle LED */
IO.PDR8.BIT.B6 = 0x0; /* toggle LED */
break;
case I2C_ERROR_TIMEOUT_IRIC2:
IO.PDR8.BIT.B5 = 0x0; /* toggle LED */
IO.PDR8.BIT.B6 = 0x0; /* toggle LED */
break;
}
if (iError == 0)
{
ms_sleep(100);
//I2C_ReadRegister(0xe0, 2, &bVal);
iError = I2C_ReadMultiplRegisters(0xe0, 2, 2, abRegs);
if (iError == 0)
{
char szLine[20];
iVal = (((unsigned short)abRegs[0])<< 8) + abRegs[1];
// try to output this to the debug terminal
WriteSOutString((char*)"Ping: ");
itoa(iVal, szLine);
WriteSOutString((char *)szLine);
WriteSOutString((char*)"\n\r");
while (iVal >= 10)
{
IO.PDR8.BIT.B6 = 0x0; /* toggle LED */
ms_sleep(150);
IO.PDR8.BIT.B6 = 0x1; /* toggle LED */
ms_sleep(150);
iVal -= 10;
}
while (iVal-- > 0)
{
IO.PDR8.BIT.B5 = 0x0; /* toggle LED */
ms_sleep(150);
IO.PDR8.BIT.B5 = 0x1; /* toggle LED */
ms_sleep(150);
}
}
}
}
}
//==============================================================================================
// Quick and dirty itoa function
//
void itoa(int n, char *psz)
{
char *pszT;
char cT;
if (n < 0)
{
*psz++ = '-';
n = -n;
}
pszT = psz;
while (n >= 10)
{
*pszT++ = '0' + n%10;
n = n/10;
}
*pszT++ = '0' + n%10; // output last character of number
*pszT-- = '\0'; // output a trailing null character
// now we need to swap the characters to make the correct number
while (psz < pszT)
{
cT = *pszT;
*pszT-- = *psz;
*psz++ = cT;
}
}
bool TXRX(unsigned char bIn, unsigned char *pbOut, bool fWaitforAck)
{
int i;
int j;
unsigned char bOut;
bOut = 0;
for (i= 0; i < 8;i++)
{
IO.PDR8.BIT.B5 = (bIn & 0x1);
bIn = bIn >> 1;
IO.PDR8.BIT.B7 = 0; // set clock low
for (j=0; j < 10; j++)
;
IO.PDR8.BIT.B7 = 1; // set clock back high
bOut = (bOut >> 1) | (IO.PDR8.BIT.B4) >> 7;
}
if (pbOut)
*pbOut = bOut;
return true;
}
bool PS2InputOutputStrings(unsigned char *pbOut, unsigned char *pbIn, unsigned char cbIn, bool fPause, unsigned char bRetryCount)
{
unsigned char cbOut;
unsigned char *pbOutT;
unsigned char bMode;
unsigned char bTimeout;
bTimeout = false;
if (bRetryCount == 0)
bRetryCount = 1; // At least once...
while (bRetryCount > 0)
{
pbOutT = pbOut;
cbOut = *pbOutT++;
if (fPause)
ms_sleep(1);
// output header
if (!TXRX(*pbOutT++, 0, true))
goto TimeoutHeader;
if (!TXRX(*pbOutT++, &bMode, true))
goto TimeoutHeader;
TimeoutHeader:
bTimeout = true;
}
return bTimeout;
}
[/code]
HelloWorld.h
Yep above file was empty:
I2C.cpp
[code]/* ------------------------------------------------------------------------------------------ /
/ ------------------------------------------------------------------------------------------ /
/ I2C helper function ---------------------------------------------------------------------- /
/ ------------------------------------------------------------------------------------------ /
/ ------------------------------------------------------------------------------------------ */
extern “C” {
#include “3694s.h”
};
#include “i2c.h”
extern volatile short int ms_count;
volatile unsigned int g_wI2CCountDown;
// variables for async functions
// Now define some state information for the Async functions…
// We will need to save things away for the interrupt handler to us.
// BUGBUG:: will move this info back into the source file. No one else will need this info.
enum AI2CS { AI2CS_IDLE, AI2CS_INIT, AI2CS_WSTARTPULSE, AI2CS_WADDRSTRANSMIT, AI2CS_TDATA,
AI2CS_TWAITLASTBYTE, AI2CS_NOACK, AI2CS_WSTOP, AI2CS_INITRDATA, AI2CS_RDATA, AI2CS_REND, AI2CS_WRECVSTOP};
AI2CS g_ai2cs=AI2CS_IDLE;
unsigned char g_bAddrAI2C; // need the device address
unsigned char g_cbAI2C; // Need to know how many more bytes to read or write
unsigned char *g_pbAI2C; // Need to save away buffer to read or write to
bool g_fInterrupt; // if set we will user a user interrupt to signal we are done, else they will have to poll.
bool g_fTransmitAI2C; // Are we transmitting or or we receiving?
int g_iErrorAI2C; // setup an error code…
extern int AI2C_Process(void);
//=============================================================================================
// I2C Startup through send device address.
//=============================================================================================
int I2C_StartAddr(unsigned char bAddr)
{
int iReturn = 0;
IIC2.ICCR1.BIT.ICE = 1; // First set some address make sure ICE is not set.
IIC2.ICMR.BIT.MLS = 0; // Should be zero for I2c Format…
IIC2.ICMR.BIT.WAIT = 1;
IIC2.ICMR.BIT.BC = 0; // I2c format 9 bits…
IIC2.ICIER.BIT.ACKE = 1; // enable acks
IIC2.ICCR1.BIT.CKS = 0xf; // set to initial state.
g_wI2CCountDown = 100;
while (IIC2.ICCR2.BIT.BBSY != 0)
{
if (g_wI2CCountDown == 0)
{
iReturn = I2C_ERROR_TIMEOUT_BBSY;
goto Exit;
}
}
// Now lets Set our self into the Master Write mode
IIC2.ICCR1.BIT.MST = 1;
IIC2.ICCR1.BIT.TRS = 1;
// Issue a start condition
//IIC2.ICCR1.BIT.BBSY = 1;
//IIC2.ICCR1.BIT.SCP = 0;
// Must be set at same time or start condition may not happen correctly...
IIC2.ICCR2.BYTE = (IIC2.ICCR2.BYTE | 0x80) & 0xbf; // set BBSY and clear SCP.
// wait until IRIC bit goes high
g_wI2CCountDown = 100;
while (IIC2.ICSR.BIT.TDRE == 0)
{
if (g_wI2CCountDown == 0)
{
iReturn = I2C_ERROR_TIMEOUT_IRIC1;
goto Exit;
}
}
// Now output the address into the data register.
IIC2.ICDRT = bAddr;
// Wait until the byte transfer is complete - Again add timeouts
g_wI2CCountDown = 100;
while (IIC2.ICSR.BIT.TEND == 0)
{
if (g_wI2CCountDown == 0)
{
iReturn = I2C_ERROR_TIMEOUT_IRIC2;
goto Exit;
}
}
// See if we got an ack
if (IIC2.ICIER.BIT.ACKBR)
iReturn = I2C_ERROR_NOACK;
Exit:
return iReturn;
}
//=============================================================================================
// Master Write
//=============================================================================================
int I2C_MasterWriteBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb)
{
int iReturn;
//See if we can start up communications
iReturn = I2C_StartAddr(bAddr);
if (iReturn == I2C_ERROR_OK)
{
while (cb > 1)
{
// Now output the next byte from our buffer.
cb--; // decrement
IIC2.ICDRT = *pbBuff++;
// Wait until the byte transfer is complete - Again add timeouts
g_wI2CCountDown = 100;
while (!IIC2.ICSR.BIT.TDRE)
{
if (g_wI2CCountDown == 0)
{
iReturn = I2C_ERROR_TIMEOUT_WRITE;
goto Exit;
}
}
}
// fOR the last byte we wait for transfer end, not just transfer data register empty...
// make sure we were not passed in 0...
if (cb)
{
IIC2.ICDRT = *pbBuff;
// See if we got an ack
while (!IIC2.ICSR.BIT.TEND)
{
if (g_wI2CCountDown == 0)
{
iReturn = I2C_ERROR_TIMEOUT_WRITE;
goto Exit;
}
}
}
}
IIC2.ICSR.BIT.TEND = 0;
IIC2.ICSR.BIT.STOP = 0;
IIC2.ICCR2.BYTE &= 0x3f; // cleart BBSY and clear SCP.
// wait until stop happens...
while (!IIC2.ICSR.BIT.STOP)
{
if (g_wI2CCountDown == 0)
{
iReturn = I2C_ERROR_TIMEOUT_WRITE;
goto Exit;
}
}
IIC2.ICCR1.BIT.MST = 1;
IIC2.ICCR1.BIT.TRS = 0; // clear the transmit status
IIC2.ICSR.BIT.TDRE = 0;
Exit:
return iReturn;
}
//=============================================================================================
// Master Read
//=============================================================================================
int I2C_MasterReadBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb)
{
int iReturn;
unsigned char bRecv;
//See if we can start up communications
iReturn = I2C_StartAddr(bAddr|0x01); // tell them we are trying to do a read
if (iReturn == I2C_ERROR_OK)
{
// Select Receive mode
IIC2.ICSR.BIT.TEND = 0;
IIC2.ICCR1.BIT.TRS = 0;
IIC2.ICSR.BIT.TDRE = 0;
IIC2.ICIER.BIT.ACKBT = 0;
// Start receiving. First read is a dummy.
bRecv = IIC2.ICDRR;
while (cb-- > 0)
{
// if this is our last byte let the system know before reading it...
if (cb == 0)
IIC2.ICCR1.BIT.RCVD = 1;
// wait for the next byte to come available.
while (!IIC2.ICSR.BIT.RDRF)
; // BUGBUG - again should have timeouts...
// Now put the next byte into our buffer.
*pbBuff++ = IIC2.ICDRR;
}
// Now acknowledge data for the last reception
IIC2.ICIER.BIT.ACKBT = 1;
// Clear IRIC to end the wait insertion
bRecv = IIC2.ICDRR;
while (!IIC2.ICSR.BIT.RDRF)
; // BUGBUG - again should have timeouts...
}
IIC2.ICSR.BIT.STOP = 0;
IIC2.ICCR2.BYTE &= 0x3f; // cleart BBSY and clear SCP. // outputs a stop
// wait until stop happens...
while (!IIC2.ICSR.BIT.STOP)
;
bRecv = IIC2.ICDRR;
IIC2.ICCR1.BIT.RCVD = 0;
IIC2.ICCR1.BIT.MST = 0;
return iReturn;
}
//=============================================================================================
// Write Register
//=============================================================================================
int I2C_WriteRegister(unsigned char bAddr, unsigned char bReg, unsigned char bVal)
{
unsigned char abBuff[2];
abBuff[0] = bReg;
abBuff[1] = bVal;
return I2C_MasterWriteBuffer(bAddr, abBuff, 2);
}
//=============================================================================================
// Read Register
//=============================================================================================
int I2C_ReadRegister(unsigned char bAddr, unsigned char bReg, unsigned char *pbVal)
{
int iReturn;
iReturn = I2C_MasterWriteBuffer(bAddr, &bReg, 1);
if (iReturn == I2C_ERROR_OK)
iReturn = I2C_MasterReadBuffer(bAddr, pbVal, 1);
return iReturn;
}
//=============================================================================================
// read Multiple Registers
//=============================================================================================
int I2C_ReadMultiplRegisters(unsigned char bAddr, unsigned char bReg, unsigned char cb, unsigned char *pb)
{
int iReturn;
iReturn = I2C_MasterWriteBuffer(bAddr, &bReg, 1);
if (iReturn == I2C_ERROR_OK)
iReturn = I2C_MasterReadBuffer(bAddr, pb, cb);
return iReturn;
}
//===============================================================================================
// Async versions of the I2C functions - allows the caller to do other things then just spin in
// wait loops. Uses the I2C Interrupt facitility
//===============================================================================================
//=============================================================================================
// I2C Async Interrupt handler
//=============================================================================================
extern “C” void AIIC_INTHANDLER();
#pragma interrupt(AIIC_INTHANDLER)
void AIIC_INTHANDLER()
{
// BUGBUG:: should put code in here to make sure we are getting the correct interrupt for the
// state we are in.
AI2C_Process();
}
//=============================================================================================
// Main Async Process function. Will take current states and try to process and transistion to the
// next state.
//=============================================================================================
int AI2C_Process(void)
{
int iReturn = 0;
unsigned char bRecv; // used for dummy reads.
ProcessNewState:
switch (g_ai2cs)
{
case AI2CS_IDLE:
// bugbug:: why did we get here???
break;
case AI2CS_INIT:
IIC2.ICCR1.BIT.ICE = 1; // First set some address make sure ICE is not set.
IIC2.ICMR.BIT.MLS = 0; // Should be zero for I2c Format...
IIC2.ICMR.BIT.WAIT = 1;
IIC2.ICMR.BIT.BC = 0; // I2c format 9 bits...
IIC2.ICIER.BIT.ACKE = 1; // enable acks
IIC2.ICCR1.BIT.CKS = 0xf; // set to initial state.
g_wI2CCountDown = 100;
while (IIC2.ICCR2.BIT.BBSY != 0)
{
if (g_wI2CCountDown == 0)
{
g_iErrorAI2C = I2C_ERROR_TIMEOUT_BBSY; // let caller know we could not unbusy the I2c
return I2C_ERROR_TIMEOUT_BBSY;
}
}
// Now lets Set our self into the Master Write mode
IIC2.ICCR1.BIT.MST = 1;
IIC2.ICCR1.BIT.TRS = 1;
// Tell interrupt system we are wanting to be interrupted on TDRE
IIC2.ICIER.BIT.TIE = 1;
g_wI2CCountDown = 100; // set a timeout time
g_ai2cs = AI2CS_WSTARTPULSE; // set new state for waiting for start pulse.
// Issue a start condition
//IIC2.ICCR1.BIT.BBSY = 1;
//IIC2.ICCR1.BIT.SCP = 0;
// Must be set at same time or start condition may not happen correctly...
IIC2.ICCR2.BYTE = (IIC2.ICCR2.BYTE | 0x80) & 0xbf; // set BBSY and clear SCP.
break; // wait until we get the start pulse.
case AI2CS_WSTARTPULSE:
IIC2.ICIER.BIT.TIE = 0; // don't interrupt on TDRE
IIC2.ICIER.BIT.TEIE = 1; // do intrrupt on TEND
g_ai2cs = AI2CS_WADDRSTRANSMIT; // set new state for waiting for start pulse.
g_wI2CCountDown = 100;
// Now output the address into the data register.
IIC2.ICDRT = g_bAddrAI2C;
break;
case AI2CS_WADDRSTRANSMIT:
// See if we got an ack
if (IIC2.ICIER.BIT.ACKBR)
g_ai2cs = AI2CS_NOACK;
// see if we are in transmit or receive mode:
else if (g_fTransmitAI2C)
g_ai2cs = AI2CS_TDATA;
else
g_ai2cs = AI2CS_INITRDATA;
goto ProcessNewState; // I hate gotos, but this is easier
case AI2CS_TDATA:
// BUGBUG:: assume that we are not called with CB = 0...
// Now output the next byte from our buffer.
g_cbAI2C--; // decrement
g_wI2CCountDown = 100;
if (g_cbAI2C)
{
IIC2.ICIER.BIT.TIE = 1;
}
else
{
IIC2.ICIER.BIT.TIE = 0;
IIC2.ICIER.BIT.TEIE = 1; // wait for end transmit
g_ai2cs = AI2CS_TWAITLASTBYTE; // different state for last byte
}
IIC2.ICDRT = *g_pbAI2C++; // now put the byte out into the buffer...
break;
case AI2CS_NOACK: // If we get no nack also come here. to basicaly issue the stop...
g_iErrorAI2C = I2C_ERROR_NOACK; // let caller know we did not get an ack...
case AI2CS_TWAITLASTBYTE:
IIC2.ICSR.BIT.TEND = 0;
IIC2.ICSR.BIT.STOP = 0;
IIC2.ICCR2.BYTE &= 0x3f; // cleart BBSY and clear SCP.
IIC2.ICIER.BIT.STIE = 1; // wait for a STOP condition
g_ai2cs = AI2CS_WSTOP;
break;
case AI2CS_WSTOP:
IIC2.ICCR1.BIT.MST = 1;
IIC2.ICCR1.BIT.TRS = 0; // clear the transmit status
IIC2.ICSR.BIT.TDRE = 0;
IIC2.ICIER.BIT.STIE = 0; // done waiting...
g_ai2cs = AI2CS_IDLE;
break;
// now some of the receive processing code.
case AI2CS_INITRDATA:
// Select Receive mode
IIC2.ICSR.BIT.TEND = 0;
IIC2.ICCR1.BIT.TRS = 0;
IIC2.ICSR.BIT.TDRE = 0;
IIC2.ICIER.BIT.ACKBT = 0;
g_ai2cs = AI2CS_RDATA;
// Start receiving. First read is a dummy.
bRecv = IIC2.ICDRR;
IIC2.ICIER.BIT.RIE = 1; // now enable interrupt for receive
if (g_cbAI2C == 1)
IIC2.ICCR1.BIT.RCVD = 1;
break;
// We received some data...
case AI2CS_RDATA:
// Now put the next byte into our buffer.
*g_pbAI2C++ = IIC2.ICDRR;
g_cbAI2C--;
// if we are about to wait for the last byte then tell system
if (g_cbAI2C == 1)
IIC2.ICCR1.BIT.RCVD = 1;
// if we still have more bytes to go, break out and wait for the next interrupt...
if (g_cbAI2C)
break;
// Now acknowledge data for the last reception
IIC2.ICIER.BIT.ACKBT = 1;
// Clear IRIC to end the wait insertion
bRecv = IIC2.ICDRR;
g_ai2cs = AI2CS_REND;
break;
case AI2CS_REND:
IIC2.ICSR.BIT.STOP = 0;
IIC2.ICCR2.BYTE &= 0x3f; // cleart BBSY and clear SCP. // outputs a stop
IIC2.ICIER.BIT.STIE = 1; // wait for a STOP condition
g_ai2cs = AI2CS_WRECVSTOP;
break; // wait for our stop condition...
case AI2CS_WRECVSTOP:
bRecv = IIC2.ICDRR;
IIC2.ICCR1.BIT.RCVD = 0;
IIC2.ICCR1.BIT.MST = 0;
IIC2.ICIER.BIT.STIE = 0; // done waiting...
g_ai2cs = AI2CS_IDLE;
break;
}
return iReturn;
}
//=============================================================================================
// Master Write
//=============================================================================================
int AI2C_MasterWriteBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb)
{
g_bAddrAI2C = bAddr;
g_pbAI2C = pbBuff;
g_cbAI2C = cb;
g_fTransmitAI2C = 1;
g_ai2cs = AI2CS_INIT;
g_iErrorAI2C = 0; // assume no error.
return AI2C_Process();
}
//=============================================================================================
// Master Read
//=============================================================================================
int AI2C_MasterReadBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb)
{
g_bAddrAI2C = bAddr;
g_pbAI2C = pbBuff;
g_cbAI2C = cb;
g_fTransmitAI2C = 0;
g_ai2cs = AI2CS_INIT;
g_iErrorAI2C = 0; // assume no error.
return AI2C_Process();
}
//=============================================================================================
// Write Register
//=============================================================================================
int AI2C_WriteRegister(unsigned char bAddr, unsigned char bReg, unsigned char bVal)
{
unsigned char abBuff[2];
if (g_ai2cs != AI2CS_IDLE)
return g_ai2cs;
abBuff[0] = bReg;
abBuff[1] = bVal;
return AI2C_MasterWriteBuffer(bAddr, abBuff, 2);
}
//=============================================================================================
// Read Register
//=============================================================================================
int AI2C_ReadRegister(unsigned char bAddr, unsigned char bReg, unsigned char *pbVal)
{
int iReturn;
if (g_ai2cs != AI2CS_IDLE)
return g_ai2cs;
iReturn = AI2C_MasterWriteBuffer(bAddr, &bReg, 1);
if (iReturn == I2C_ERROR_OK)
iReturn = AI2C_MasterReadBuffer(bAddr, pbVal, 1);
return iReturn;
}
//=============================================================================================
// read Multiple Registers
//=============================================================================================
int AI2C_ReadMultiplRegisters(unsigned char bAddr, unsigned char bReg, unsigned char cb, unsigned char *pb)
{
int iReturn;
if (g_ai2cs != AI2CS_IDLE)
return g_ai2cs;
iReturn = AI2C_MasterWriteBuffer(bAddr, &bReg, 1);
if (iReturn == I2C_ERROR_OK)
iReturn = AI2C_MasterReadBuffer(bAddr, pb, cb);
return iReturn;
}
[/code]
I2C.H
[code]//-------------------------------------------------------------------------------------
// I2c.H
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
// Error Definition
//-------------------------------------------------------------------------------------
#define I2C_ERROR_OK 0x0000
#define I2C_ERROR_NOACK 0x0001
#define g_ai2cCurrentState 0x0002
#define I2C_ERROR_TIMEOUT_BBSY 0x8001
#define I2C_ERROR_TIMEOUT_IRIC1 0x8002
#define I2C_ERROR_TIMEOUT_IRIC2 0x8003
#define I2C_ERROR_TIMEOUT_WRITE 0x8004
#define I2C_ERROR_TIMEOUT_READ 0x8005
//-------------------------------------------------------------------------------------
// external variables…
//-------------------------------------------------------------------------------------
#define SETI2CTIMEOUTVALUE(x) g_wI2CCountDown = x
#define I2CTIMEOUT (g_wI2CCountDown == 0)
extern volatile unsigned int g_wI2CCountDown;
//-------------------------------------------------------------------------------------
// function definitions
//-------------------------------------------------------------------------------------
extern int I2C_StartAddr(unsigned char bAddr);
extern int I2C_MasterWriteBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb);
extern int I2C_MasterReadBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb);
// Now define functions to read and write registers…
extern int I2C_WriteRegister(unsigned char bAddr, unsigned char bReg, unsigned char bVal);
extern int I2C_ReadRegister(unsigned char bAddr, unsigned char bReg, unsigned char *pbVal);
extern int I2C_ReadMultiplRegisters(unsigned char bAddr, unsigned char bReg, unsigned char cb, unsigned char *pb);
// And the Async versions of these…
extern int AI2C_StartAddr(unsigned char bAddr);
extern int AI2C_MasterWriteBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb);
extern int AI2C_MasterReadBuffer(unsigned char bAddr, unsigned char *pbBuff, int cb);
// Now define functions to read and write registers…
extern int AI2C_WriteRegister(unsigned char bAddr, unsigned char bReg, unsigned char bVal);
extern int AI2C_ReadRegister(unsigned char bAddr, unsigned char bReg, unsigned char *pbVal);
extern int AI2C_ReadMultiplRegisters(unsigned char bAddr, unsigned char bReg, unsigned char cb, unsigned char *pb);
[/code]
Then the real primitive serial IO.
SERIO.CPP
[code]/* Serial IO output to the S_OUT of the atom Pro. This is on P14 on the 3694 IO chip…
*
#include “SerIO.h”
extern “C” {
#include “3694s.h”
};
/* writes a character at the current location, updates
current location to next space (to right) */
#ifndef F_CPU
#define F_CPU 16000000L
#endif
// Roughly calculate the number of times to go in our loop. The main loop in the delay takes maybe 8 clocks per cycle…
#define DELAY_LOOP_COUNT ((((unsigned short)(F_CPU/9600))-75)/8)
void _Delay(unsigned int us)
{
while ( us ) { us–; } /* 6 cpu cycles per loop */
}
void WriteSOutCh(char ch)
{
#define ASYNC_HIGH 1
#define ASYNC_LOW 0
// first initialize the P14 to be output and standard IO.
IO.PMR1.BIT.IRQ0 = 0; // Standard IO pin
IO.PCR1 |=0x10; // make sure the pin is set to Output.
// Here is the workhorse.
int i;
// Need to first output the Start Bit
IO.PDR1.BIT.B4 = ASYNC_LOW;
_Delay(DELAY_LOOP_COUNT); // try to convert to number of loops to wait. 35 approx cycles used elsewhere...
for (i=0;i<8;i++)
{
// Output each bit
if (ch & 1)
IO.PDR1.BIT.B4 = ASYNC_HIGH;
else
IO.PDR1.BIT.B4 = ASYNC_LOW;
ch = ch >> 1;
_Delay(DELAY_LOOP_COUNT); // try to convert to number of loops to wait. 35 approx cycles used elsewhere...
}
// Now output Stop Bit
IO.PDR1.BIT.B4 = ASYNC_HIGH;
_Delay(DELAY_LOOP_COUNT); // try to convert to number of loops to wait. 35 approx cycles used elsewhere...
}
void WriteSOutString(char *psz)
{
// bugbug should validate address
while (*psz)
{
WriteSOutCh(*psz++);
}
}
[/code]
and its header file: serio.h
[code]/* SerIO.h
*
//#pragma once
extern void WriteSOutCh(char ch);
extern void WriteSOutString(char *psz);
[/code]
To have multiple files under the project you can use the Add File to Project under the project menu. Again I am sorry I did not post the main header file.
Also I make no guarantees of the code, this is simply a snapshot of code from maybe 6 months to a year ago… Maybe if there is some interest, some of us could convert some of this into a tutorial, or an appendix to the manual or wiki…
Kurt
Note: I updated the above post, with a link that should help you download the zip file that contains all of the IO definitions for the different H8 famility of processors.
Also I forgot a few things above:
You need to update the file vects.c
to setup the interrupt vectors for any intterupts you are using.
Like:
[code]void start(void); /* Startup code (in start.s) */
asm (" .section .vects");
asm("jmp @_start"); //_RESET
asm("jmp @_start"); //_NMI
asm("jmp @_start"); //_TRAP0
asm("jmp @_start"); //_TRAP1
asm("jmp @_start"); //_TRAP2
asm("jmp @_start"); //_TRAP3
asm("jmp @_start"); //_BREAK
asm("jmp @_start"); //_DIRECT
asm("jmp @_start"); //_IRQ0:
asm("jmp @_start"); //_IRQ1:
asm("jmp @_start"); //_IRQ2:
asm("jmp @_start"); //_IRQ3:
asm("jmp @_start"); //_WKP:
asm("jmp @_start"); //_TIMERAV:
asm("jmp @_TIMERW"); //_TIMERW:
asm("jmp @_start"); //_TIMERV:
asm("jmp @_start"); //_SCI3:
asm("jmp @_AIIC_INTHANDLER"); //_IIC:
asm("jmp @_start"); //_ADCONV:
asm("jmp @_start"); //_USER1:
asm("jmp @_start"); //_USER2:
asm("jmp @_start"); //_USER3:
asm("jmp @_start"); //_USER4:
asm("jmp @_start"); //_USER5:
asm("jmp @_start"); //_USER6:
asm("jmp @_start"); //_USER7:
asm("jmp @_start"); //_USER8:
asm("jmp @_start"); //_USER9:
asm("jmp @_start"); //_USER10:
asm("jmp @_start"); //_USER11:
asm("jmp @_start"); //_USER12:
asm("jmp @_start"); //_USER13:
asm("jmp @_start"); //_USER14:
asm("jmp @_start"); //_USER15:
asm("jmp @_start"); //_USER16:
asm("jmp @_start"); //_USER17:
asm("jmp @_start"); //_USER18:
asm("jmp @_start"); //_USER19:
asm("jmp @_start"); //_USER20:
asm("jmp @_start"); //_USER21:
asm("jmp @_start"); //_USER22:
asm("jmp @_start"); //_USER23:
asm("jmp @_start"); //_USER24:
asm("jmp @_start"); //_USER25:
asm("jmp @_start"); //_USER26:
asm("jmp @_start"); //_USER27:
asm("jmp @_start"); //_USER28:
asm("jmp @_start"); //_USER29:
asm("jmp @_start"); //_USER30:
asm("jmp @_start"); //_USER31:
asm("jmp @_start"); //_USER32:
asm("jmp @_start"); //_USER33:
asm("jmp @_start"); //_USER34:
asm("jmp @_start"); //_USER35:
asm("jmp @_start"); //_USER36:
asm("jmp @_start"); //_USER37:
asm("jmp @_start"); //_USER38:
asm("jmp @_start"); //_USER39:
asm("jmp @_start"); //_USER40:
asm("jmp @_start"); //_USER41:
asm("jmp @_start"); //_USER42:
asm("jmp @_start"); //_USER43:
asm("jmp @_start"); //_USER44:
asm("jmp @_start"); //_USER45:
asm("jmp @_start"); //_USER46:
asm("jmp @_start"); //_USER47:
asm("jmp @_start"); //_USER48:
asm("jmp @_start"); //_USER49:
asm("jmp @_start"); //_USER50:
asm("jmp @_start"); //_USER51:
asm("jmp @_start"); //_USER52:
asm("jmp @_start"); //_USER53:
asm("jmp @_start"); //_USER54:
asm("jmp @_start"); //_USER55:
asm("jmp @_start"); //_USER56:
asm("jmp @_start"); //_USER57:
asm("jmp @_start"); //_USER58:
asm("jmp @_start"); //_USER59:
asm("jmp @_start"); //_USER60:
asm("jmp @_start"); //_USER61:
asm("jmp @_start"); //_USER62:
asm("jmp @_start"); //_USER63:
asm("jmp @_start"); //_USER64:
asm("jmp @_start"); //_USER65:
asm("jmp @_start"); //_USER66:
asm("jmp @_start"); //_USER67:
asm("jmp @_start"); //_USER68:
asm("jmp @_start"); //_USER69:
asm("jmp @_start"); //_USER70:
asm("jmp @_start"); //_USER71:
asm("jmp @_start"); //_USER72:
asm("jmp @_start"); //_USER73:
asm("jmp @_start"); //_USER74:
asm("jmp @_start"); //_USER75:
asm("jmp @_start"); //_USER76:
asm("jmp @_start"); //_USER77:
asm("jmp @_start"); //_USER78:
asm("jmp @_start"); //_USER79:
asm("jmp @_start"); //_USER80:
asm("jmp @_start"); //_USER81:
asm("jmp @_start"); //_USER82:
asm("jmp @_start"); //_USER83:
asm("jmp @_start"); //_USER84:
asm("jmp @_start"); //_USER85:
asm("jmp @_start"); //_USER86:
asm("jmp @_start"); //_USER87:
asm("jmp @_start"); //_USER88:
asm("jmp @_start"); //_USER89:
asm("jmp @_start"); //_USER90:
asm("jmp @_start"); //_USER91:
asm("jmp @_start"); //_USER92:
asm("jmp @_start"); //_USER93:
asm("jmp @_start"); //_USER94:
asm("jmp @_start"); //_USER95:
asm("jmp @_start"); //_USER96:
asm("jmp @_start"); //_USER97:
asm("jmp @_start"); //_USER98:
asm("jmp @_start"); //_USER99:
asm("jmp @_start"); //_USER100:
asm("jmp @_start"); //_USER101:
asm("jmp @_start"); //_USER102:
[/code]
This for example included our handler of the wtimer interrupt as well as the I2C interupt.
ok, thank you very much!