SPI Communication Problem Between STM32F-Discovery and MAX31856 - stm32f4discovery

I was trying to communicate my STM discovery board with MAX31856 using SPI communication. According to datasheet, I should send address byte first, then data bytes following. I am currently able to write to registers but when i try to read the data i wrote to registers, I couldn't read data unless I only send read command.
For example:
http://puu.sh/E2gJD.png
With this code, I am able to read default register values.
http://puu.sh/E2gLC.png
With this code, I am able to write new values to CR0 and CR1 registers. The first 0x80 value is register CR0's address byte. The next values are new register values 0x80 and 0x37.
http://puu.sh/E2gNK.png
I stopped the previous program and changed my code to this one. Then I started debugging. As you can see from this picture, the CR0 and CR1 register values are changed to what we wrote before.
Finally;
http://puu.sh/E2gRw.png
When I try to combine these two operations, writing and reading, I wasn't able to read what I wrote to registers. Need some help about solving this problem.
uint8_t spiTXData[17],spiRXData[17],spiTXDataR[17], spiRXDataR[17];
/* USER CODE END 0 */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DAC_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
// HAL_Delay ( 1 ) ;
//
// HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
// spiTXDataR[0] = 0x00;
// HAL_SPI_TransmitReceive(&hspi1, spiTXDataR, spiRXDataR, 3, 50);
// HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
// HAL_Delay ( 1 ) ;
spiTXData[0] = 0x80;
spiTXData[1] = 0x80;
spiTXData[2] = 0x37;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, spiTXData, spiRXData, 3, 50);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
spiTXDataR[0] = 0x00;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, spiTXDataR, spiRXDataR, 17, 50);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
I need to be able to read the commands I write to CR0 and CR1 registers later. How can I do that? I hope you understand my problem and able to help me.
Thanks.

As far as I know there is no CR0 and CR1 but I assume what you are locking for is CR1 and CR2. You can read these values by either setting a pointer to the address of the register and reding the dereferenced pointer value like so:
uint32_t *ptr = REGISTER_ADDRESS;
variable = *ptr;
now variable should contain the registers value assuming that the regsiter you are looking for is a 32 bit register.
Another way is to use the premade "defines" true studio provides to read those values for example:
SPI1->CR1
In my case it is SPI1 but it depends on the how many SPIs your mcu has and which one you are using.
Usualy the Reference Manual and/or the Data Sheet that are provided by ST on their Website (specific one for each MCU or at least MCU family) are a pretty got help in figuring out the names of the registers and/or their addresses.

Related

Reading YUY2 data from an IMFSample that appears to have improper data on Windows 10

I am developing an application that using IMFSourceReader to read data from video files. I am using DXVA for improved performance. I am having trouble with one specific full-HD H.264 encoded AVI file. Based on my investigation this far, I believe that the IMFSample contains incorrect data. My workflow is below:
Create a source reader with a D3D manager to enable hardware acceleration.
Set the current media type to YUY2 as DXVA does not
decode to any RGB colorspace.
Call ReadSample to get an IMFSample. Works fine.
Use the VideoProcessorBlt to perform YUY2 to BGRA32
conversion. For this specific file it errors out with an
E_INVALIDARGS error code. Decided to do the conversion myself.
Used IMFSample::ConvertToContiguousBuffer to receive an IMFMediaBuffer. When locking this buffer, the pitch is reported as 1280 bytes. This I believe is incorrect, because for a full HD video, the pitch should be (1920 + 960 + 960 = 3840 bytes).
I dumped the raw memory and extracted the Y, U and V components based on my understanding of the YUY2 layout. You can find it below. So, the data is there but I do not believe it is laid out as YUY2. Need some help in interpreting the data.
My code for reading is below:
// Direct3D surface that stores the result of the YUV2RGB conversion
CComPtr<IDirect3DSurface9> _pTargetSurface;
IDirectXVideoAccelerationService* vidAccelService;
initVidAccelerator(&vidAccelService); // Omitting the code for this.
// Create a new surface for doing the color conversion, set it up to store X8R8G8B8 data.
hr = vidAccelService->CreateSurface( static_cast<UINT>( 1920 ),
static_cast<UINT>( 1080 ),
0, // no back buffers
D3DFMT_X8R8G8B8, // data format
D3DPOOL_DEFAULT, // default memory pool
0, // reserved
DXVA2_VideoProcessorRenderTarget, // to use with the Blit operation
&_pTargetSurface, // surface used to store frame
NULL);
GUID processorGUID;
DXVA2_VideoDesc videoDescriptor;
D3DFORMAT processorFmt;
UINT numSubStreams;
IDirectXVideoProcessor* _vpd;
initVideoProcessor(&vpd); // Omitting the code for this
// We get the videoProcessor parameters on creation, and fill up the videoProcessBltParams accordingly.
_vpd->GetCreationParameters(&processorGUID, &videoDescriptor, &processorFmt, &numSubStreams);
RECT targetRECT; // { 0, 0, width, height } as left, top, right, bottom
targetRECT.left = 0;
targetRECT.right = videoDescriptor.SampleWidth;
targetRECT.top = 0;
targetRECT.bottom = videoDescriptor.SampleHeight;
SIZE targetSIZE; // { width, height }
targetSIZE.cx = videoDescriptor.SampleWidth;
targetSIZE.cy = videoDescriptor.SampleHeight;
// Parameters that are required to use the video processor to perform
// YUV2RGB and other video processing operations
DXVA2_VideoProcessBltParams _frameBltParams;
_frameBltParams.TargetRect = targetRECT;
_frameBltParams.ConstrictionSize = targetSIZE;
_frameBltParams.StreamingFlags = 0; // reserved.
_frameBltParams.BackgroundColor.Y = 0x0000;
_frameBltParams.BackgroundColor.Cb = 0x0000;
_frameBltParams.BackgroundColor.Cr = 0x0000;
_frameBltParams.BackgroundColor.Alpha = 0xFFFF;
// copy attributes from videoDescriptor obtained above.
_frameBltParams.DestFormat.VideoChromaSubsampling = videoDescriptor.SampleFormat.VideoChromaSubsampling;
_frameBltParams.DestFormat.NominalRange = videoDescriptor.SampleFormat.NominalRange;
_frameBltParams.DestFormat.VideoTransferMatrix = videoDescriptor.SampleFormat.VideoTransferMatrix;
_frameBltParams.DestFormat.VideoLighting = videoDescriptor.SampleFormat.VideoLighting;
_frameBltParams.DestFormat.VideoPrimaries = videoDescriptor.SampleFormat.VideoPrimaries;
_frameBltParams.DestFormat.VideoTransferFunction = videoDescriptor.SampleFormat.VideoTransferFunction;
_frameBltParams.DestFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
// The default values are used for all these parameters.
DXVA2_ValueRange pRangePABrightness;
_vpd->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &pRangePABrightness);
DXVA2_ValueRange pRangePAContrast;
_vpd->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &pRangePAContrast);
DXVA2_ValueRange pRangePAHue;
_vpd->GetProcAmpRange(DXVA2_ProcAmp_Hue, &pRangePAHue);
DXVA2_ValueRange pRangePASaturation;
_vpd->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &pRangePASaturation);
_frameBltParams.ProcAmpValues = { pRangePABrightness.DefaultValue, pRangePAContrast.DefaultValue,
pRangePAHue.DefaultValue, pRangePASaturation.DefaultValue };
_frameBltParams.Alpha = DXVA2_Fixed32OpaqueAlpha();
_frameBltParams.DestData = DXVA2_SampleData_TFF;
// Input video sample for the Blt operation
DXVA2_VideoSample _frameVideoSample;
_frameVideoSample.SampleFormat.VideoChromaSubsampling = videoDescriptor.SampleFormat.VideoChromaSubsampling;
_frameVideoSample.SampleFormat.NominalRange = videoDescriptor.SampleFormat.NominalRange;
_frameVideoSample.SampleFormat.VideoTransferMatrix = videoDescriptor.SampleFormat.VideoTransferMatrix;
_frameVideoSample.SampleFormat.VideoLighting = videoDescriptor.SampleFormat.VideoLighting;
_frameVideoSample.SampleFormat.VideoPrimaries = videoDescriptor.SampleFormat.VideoPrimaries;
_frameVideoSample.SampleFormat.VideoTransferFunction = videoDescriptor.SampleFormat.VideoTransferFunction;
_frameVideoSample.SrcRect = targetRECT;
_frameVideoSample.DstRect = targetRECT;
_frameVideoSample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();
_frameVideoSample.SampleData = DXVA2_SampleData_TFF;
CComPtr<IMFSample> sample; // Assume that this was read in from a call to ReadSample
CComPtr<IMFMediaBuffer> buffer;
HRESULT hr = sample->GetBufferByIndex(0, &buffer);
CComPtr<IDirect3DSurface9> pSrcSurface;
// From the MediaBuffer, we get the Source Surface using MFGetService
hr = MFGetService( buffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), (void**)&pSrcSurface );
// Update the videoProcessBltParams with frame specific values.
LONGLONG sampleStartTime;
sample->GetSampleTime(&sampleStartTime);
_frameBltParams.TargetFrame = sampleStartTime;
LONGLONG sampleDuration;
sample->GetSampleDuration(&sampleDuration);
_frameVideoSample.Start = sampleStartTime;
_frameVideoSample.End = sampleStartTime + sampleDuration;
_frameVideoSample.SrcSurface = pSrcSurface;
// Run videoProcessBlt using the parameters setup (this is used for color conversion)
// The returned code is E_INVALIDARGS
hr = _vpd->VideoProcessBlt( _pTargetSurface, // target surface
&_frameBltParams, // parameters
&_frameVideoSample, // video sample structure
1, // one sample
NULL); // reserved
After a call to ReadSample of IMFSourceReader or inside OnReadSample callback function of the IMFSourceReaderCallback implementation, you might receive the MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED flag. It means that the current media type has changed for one or more streams. To get the current media type call the IMFSourceReader::GetCurrentMediaType method.
In your case you need to query (again) the IMFMediaType's MF_MT_FRAME_SIZE attribute for the video stream, in order to obtain the new correct video resolution. You should use the new video resolution to set the "width" and "height" values of the VideoProcessorBlt parameters' source and destination rectangles.

GCC produces unaligned function address on Cortex M3

I just placed a function to a specific address using a section and then I output the address of that function and the result is the chosen section address + 1.
This is what I did:
void __attribute__((section (".my_fct_address"))) Fct_Ptr_Test (void)
{
...
}
and
void (*fct_ptr) (void);
fct_ptr = Fct_Ptr_Test;
printf ("0X%X\r\n", (uint32_t)(fct_ptr));
fct_ptr ();
in ld-file:
.my_fct_address 0x800F000 :
{
KEEP(*(.my_fct_address)) /* keep my variable even if not referenced */
} > FLASH
The above printf statement outputs 0x800F001 and Fct_Ptr_Test is called properly
If I set
fct_ptr = 0x800F000;
the system crashes.
If I set
fct_ptr = 0x800F001;
everything is fine again.
If I don't place Fct_Ptr_Test in its own section , ie let the linker place it anywhere I also get an odd address.
Now I wonder how 0x800F001 can be a proper address on a 32 bit controller (ARM cortex M3) and what is stored in 0x800F000.
Even more strange: map-file always shows the even addresses
Can anybody help?
Thanks
Martin
Linker sets the least-significant bit of Thumb functions to 1 to facilitate interworking (see docs). Perhaps that's your case?

Can't find my mistake in the implementation of the counter

I'm implementing the counter from chap. 3. Here is my code:
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/03/a/PC.hdl
/**
* A 16-bit counter with load and reset control bits.
* if (reset[t] == 1) out[t+1] = 0
* else if (load[t] == 1) out[t+1] = in[t]
* else if (inc[t] == 1) out[t+1] = out[t] + 1 (integer addition)
* else out[t+1] = out[t]
*/
CHIP PC {
IN in[16], load, inc, reset;
OUT out[16];
//sel=0; a;sel=1;b
PARTS:
//reset
Not16(in=true, out=resetted);
//inc
Inc16(in=t, out=incremented);
//Choose input between reset and out[t]
Mux16(a=t,b=resetted,sel=reset,out=o1);
//Choose input between o1 and in[t](load)
Mux16(a=o1, b=in,sel=load,out=o2);
//Choose input between o2 and inc
Mux16(a=o2,b=incremented, sel=inc, out=o3);
Register(in=o3, load=load, out=t, out=out);
}
It's seems to fail at this test:
set in -32123,
tick,
output
This is line 5, I can't find my mistake(s). Any help is appreciated
Hint (because this is a learning exercise, after all):
You are doing a cascade of muxes to generate your new value, but under what circumstances are you updating the Register?
Suggestions:
Go back to Chapter 2 and notice that they had you implement a Mux4Way16 component. Using it will make your life a lot easier.
Also, you can use false as an input and it will automatically become as wide as needed. So you don't need to run true through a Not16 to get false[16].

BOBJ SDK Add Group MemberOf Parent Group

All,
I add a group to be a child of the parent group but, it is not becoming a member of the parent group. I have to go in and set it manually.
Anyone know how this works?
I had to play with it and do a little research on the BOB Forum but I figured it out, though its non-intuitive.
I'm going to assume you know how to get the parent group IUserGroup object.
// get the plugin manager
IPluginMgr pluginMgr = store.getPluginMgr();
// Retrieve the User plugin.
IPluginInfo groupPlugin = pluginMgr.getPluginInfo("CrystalEnterprise.UserGroup");
// Create a new InfoObjects collection.
IInfoObjects newInfoObjects = store.newInfoObjectCollection();
// Add the User plugin to the collection.
newInfoObjects.add (groupPlugin);
// Retrieve the newly created user object.
IUserGroup newUserGroup = (IUserGroup)newInfoObjects.get(0);
// build the new group
String newGroupName = "My Test Group";
newUserGroup.setTitle(newGroupName);
newUserGroup.setDescription("Just for sample test code");
store.commit(newInfoObjects);
// now that things commited associate the parent group
if(parentGroup != null)
{
parentGroup.getSubGroups().add(new Integer(newUserGroup.getID()));
store.commit(parGroupObjs);
}
The big stumper is that you you would expect to just use the setParentID() method. Word of warning this this was only tested under BO XI R2, not R3, so it may not be 100% correct for the current version.

Binary SMS in Symbian

I wonder if anyone has managed to create a working code for sending out binary messages (to configure Symbian phones) and have also some binary data sample.
So far all the samples I have found fail to leave the Outbox or never return.
// Current entry is the Draft folder.
iSmsMtm->SwitchCurrentEntryL( KMsvDraftEntryId );
// Create a new SMS message entry as a child of the current context.
iSmsMtm->CreateMessageL( KUidMsgTypeSMS.iUid );
CMsvEntry& serverEntry = iSmsMtm->Entry();
TMsvEntry entry( serverEntry.Entry() );
/* Send Binary SMS */
CSmsHeader &hdr = iSmsMtm->SmsHeader();
CSmsMessage &msg = hdr.Message();
CSmsPDU &pdu = msg.SmsPDU();
CSmsUserData &userdata = pdu.UserData();
// Set the DCS byte
pdu.SetBits7To4(TSmsDataCodingScheme::ESmsDCSTextUncompressedWithNoClassInfo);
pdu.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
pdu.SetClass(ETrue, TSmsDataCodingScheme::ESmsClass2);
char buf[]= {...}; //my binary data, 247 bytes long
// Construct a dummy message
HBufC8 * iMessage = HBufC8::NewL(300);
TPtr8 TempUDHBufDesc((TUint8*)buf,247,247);
iMessage->Des().Copy(TempUDHBufDesc);
_LOGFENTRY1(_L("mess length %d"),iMessage->Des().Length());
userdata.SetBodyL(*iMessage);
delete iMessage;
// Message will be sent immediately.
entry.SetSendingState( KMsvSendStateWaiting );
entry.iDate.UniversalTime(); // insert current time //Solution for HomeTime()
// Set the SMS message settings for the message.
CSmsHeader& header = iSmsMtm->SmsHeader();
CSmsSettings* settings = CSmsSettings::NewL();
CleanupStack::PushL( settings );
settings->CopyL( iSmsMtm->ServiceSettings() ); // restore settings
settings->SetDelivery( ESmsDeliveryImmediately ); // to be delivered immediately
settings->SetDeliveryReport(EFalse);
settings->SetCharacterSet(TSmsDataCodingScheme::ESmsAlphabet8Bit); // IMPORTANT! For sending binary SMS
header.SetSmsSettingsL( *settings ); // new settings
// Let's check if there is a service center address.
if ( header.Message().ServiceCenterAddress().Length() == 0 )
{
// No, there isn't. We assume there is at least one service center
// number set and use the default service center number.
CSmsSettings* serviceSettings = &( iSmsMtm->ServiceSettings() );
// Check if number of service center addresses in the list is null.
if ( !serviceSettings->ServiceCenterCount() )
{ _LOGENTRY("No SC");
return ; // quit creating the message
}
else
{
CSmsNumber* smsCenter= CSmsNumber::NewL();
CleanupStack::PushL(smsCenter);
smsCenter->SetAddressL((serviceSettings->GetServiceCenter( serviceSettings->DefaultServiceCenter())).Address());
header.Message().SetServiceCenterAddressL( smsCenter->Address() );
CleanupStack::PopAndDestroy(smsCenter);
}
}
CleanupStack::PopAndDestroy( settings );
// Recipient number is displayed also as the recipient alias.
entry.iDetails.Set( _L("+3725038xxx") );
iSmsMtm->AddAddresseeL( _L("+3725038xxx") , entry.iDetails );
// Validate message.
if ( !ValidateL() )
{ _LOGENTRY("Not valid");
return ;
}
entry.SetVisible( ETrue ); // set message as visible
entry.SetInPreparation( EFalse ); // set together with the visibility flag
serverEntry.ChangeL( entry ); // commit changes
iSmsMtm->SaveMessageL(); // save message
TMsvSelectionOrdering selection;
CMsvEntry* parentEntry = CMsvEntry::NewL( iSmsMtm->Session(), KMsvDraftEntryId, selection );
CleanupStack::PushL( parentEntry );
// Move message to Outbox.
iOperation =parentEntry->MoveL( entry.Id(), KMsvGlobalOutBoxIndexEntryId, iStatus );
CleanupStack::PopAndDestroy( parentEntry );
iState = EWaitingForMoving;
SetActive();
Mostly I'm not sure about the correct values for port and class . Also some correct binary string would be nice to have for testing. Now I'm not sure if thecode is bad or the data.
Use the JSR120 specification and the wireless toolkit. they contain java example code that will work for sure.
These are implemented directly using RSocket objects in Symbian C++.
If you really want to do it in C++, the simplest way is to copy your TMsvEntry to the entry of the sms service. In your code above, that means using "iSmsMtm->ServiceId()" instead of "KMsvGlobalOutBoxIndexEntryId". also, just copy the message to the service but do move it to the outbox after it has been successfully sent.
shameless plug : http://www.quickrecipesonsymbianos.com will contain an explanation of the Symbian C++ messaging API will simple and reusable example code.
The solution that worked is to use RComm and "DATAPORT::1" to send out the binary SMS using AT commands (like using a modem).
If you want to send the SMS silently (and avoid the complexity of using the messaging APIs), you should send it via an RSocket: http://wiki.forum.nokia.com/index.php/How_to_send_an_SMS_using_sockets
Depending on your needs this might be more suitable than using the messaging APIs.