C++ CLI Serial port missing data received - visual-studio

I have a problem with missing data in serialport. When I run first time code all data is correct. But every next time data is missing.
For example :
First time : 01 00 00 00 01 0A CA - CORRECT
Second time : 0A CA - MISSING DATA
Third time : CA - MISSING DATA
private: System::Void serialPort1_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) {
numbytes = serialPort1->BytesToRead;
encodedBytes = gcnew array<Byte>(numbytes);
for (ck = 0; ck < numbytes; ck++){
encodedBytes[ck] = serialPort1->ReadByte();
}
this->Invoke(gcnew EventHandler(this,&MyForm3::SetTextCallback));
}
private: System::Void SetTextCallback(System::Object^ sender, System::EventArgs^ e){
textBox9->Text = "";
for (ck = 0; ck <numbytes; ck++){
this->textBox9->AppendText((encodedBytes[ck].ToString("X2")));
}
numbytes = 0;
ck = 0;
}

Related

How to convert a message's value from hexadecimal to decimal?

I need to write a function that converts a message's byte (this.byte(2)) from hexadecimal to decimal, from a message I receive on the CAN bus.
For example i have the following message on the CAN bus "F1 02 1A 13 00 00 00 00" The function should then returns the value 26 for this.byte(2) "1A".
I followed some examples found on the internet but I still don't get the right value.
What is then wrong with my function ?
variables
{
char hexa[2];
long decimal, place;
int val, len;
}
int HexToDec(char hexa[])
{
decimal = 0;
i=0;
place = 1;
len = strlen(hexa);
len--;
for(i=0; hexa[i]!='\0'; i++)
{
if(hexa[i]>='0' && hexa[i]<='9')
{
val = hexa[i] - 48;
}
else if(hexa[i]>='a' && hexa[i]<='f')
{
val = hexa[i] - 97 + 10;
}
else if(hexa[i]>='A' && hexa[i]<='F')
{
val = hexa[i] - 65 + 10;
}
decimal += val * _pow(16, len);
len--;
}
write("Hexadecimal number = %s\n", hexa);
write("Decimal number = %lld", decimal);
return 0;
}
on message *
{
HexToDec(this.BYTE(2)); // for example 1A in hexadecimal
}
Your requirement "convert hex to decimal" is a wrong statement. Because both Hexadecimal and Decimal are numbers. Your function HexToDec is taking string as input and not a number.
If you want to print this.BYTE(2) as a decimal value, you just have to write
write("Hex - %X", this.BYTE(2));
write("Dec - %d", this.BYTE(2));

Math calculations in arduino

I wrote a code to do a basic calculations with arduino uno. but it returns me a wrong answer for filledPercentage. It is always -1. what is the problem with this?
//include the library code:
#include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 13, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int lowLevelDistance =112;
int highLevelDistance = 47;
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
Serial.begin(9600);
}
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
int currentLevel = 101;
int filledLevel = (lowLevelDistance - currentLevel);
int fullLevel = (lowLevelDistance - highLevelDistance);
int filledPercentage = filledLevel / (fullLevel / 100);
Serial.println(lowLevelDistance);
Serial.println(highLevelDistance);
Serial.println(currentLevel);
Serial.println(filledLevel);
Serial.println(fullLevel);
Serial.println(filledPercentage);
delay(1000);
}
You shouldn't use an integer for the division, your fulllevel / 100 returns 0.65 but then is converted into an integer (truncating it into a 0).
Dividing by 0 throws an error (-1).

Issues with Arduino Timing

I am working with an Arduino on a project for which timing is very important. I use TimerOne to trigger timer interrupts and use micros() for delays (delayMicroseconds() was causing problems worse than the one explained below). The program is sending a manual PWM signal to an LED and it is very important that the signal is sent with an error that is less than 8 microseconds (ideally, the signal is sent at the same time in each period). My test code is shown below:
#include <TimerOne.h>
#include <SPI.h>
const int LED_PIN = 3;
const int CHIP_SELECT = 12;
const int PERIOD = 4000;
const double DUTY_CYCLE = .5;
const int HIGH_TIME = PERIOD * DUTY_CYCLE;
const int LOW_TIME = PERIOD - HIGH_TIME;
const int INITIAL_SIGNAL_DELAY = LOW_TIME / 2;
const int HIGH_TIME_TOTAL_DELAY = INITIAL_SIGNAL_DELAY + HIGH_TIME;
const int RESISTOR_VALUE = 255;
boolean triggered = false;
boolean data = false;
unsigned long triggeredTime;
unsigned long s;
unsigned long e;
boolean found;
int i = 0;
void setup()
{
s = micros();
Timer1.initialize(PERIOD);
Timer1.attachInterrupt(trigger);
pinMode(LED_PIN, 3);
pinMode(CHIP_SELECT, OUTPUT);
SPI.begin();
digitalWrite(CHIP_SELECT, LOW);
SPI.transfer(B00010001);
SPI.transfer(RESISTOR_VALUE);
digitalWrite(CHIP_SELECT, HIGH);
e = micros();
Serial.begin(115200);
Serial.print("s: ");
Serial.println(s);
Serial.print("e: ");
Serial.println(e);
}
void loop()
{
if(triggered)
{
while(micros() - triggeredTime < INITIAL_SIGNAL_DELAY)
{ }
s = micros();
digitalWrite(LED_PIN, data);
while(micros() - triggeredTime < HIGH_TIME_TOTAL_DELAY)
{ }
digitalWrite(LED_PIN, LOW);
data = !data;
triggered = false;
e = micros();
//micros();
if(s % 100 > 28 || s % 100 < 12)
{
found = true;
}
if(!found)
{
Serial.print("s: ");
Serial.println(s);
}
else
{
Serial.print("ERROR: ");
Serial.println(s);
}
//Serial.print("e: ");
//Serial.println(e);
}
}
void trigger()
{
triggeredTime = micros();
triggered = true;
}
(it should be noted that the first signal sent is always xx20, usually 5020).
So, with this code, I eventually get an error. I am not sure why, but this error occurs at the same point every single time:
.
.
.
s: 1141020
s: 1145020
s: 1149020
ERROR: 1153032
ERROR: 1157020
ERROR: 1161020
.
.
.
Now, the really weird part is if I remove the comments before micros() (the micros() right after e = micros()), there is no error (or at least there is not an error within the first 30 seconds). I was wondering if anybody could provide an explanation for why this happens. I have dedicated many hours trying to get the timing working properly and everything was working well until I encountered this error. Any help would be very much appreciated. Thank you!

Is it possible to vmap kernel module's memory?

Is there any constraint to the mapping kernel module's memory via the vmap? On my system I write a simple KMOD, that maps a kernel-function (printk) and a module-function (printx) and check if mappings are equals. The result shows me that there is a problem with mapping module's printx - the mapping and the function's code does not equals. Could someone explain me what I do wrong? And here is the code:
// vmap-test.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
int printx(void)
{
return 0;
}
void vmap_action(unsigned long address)
{
void * mapping;
struct page * page;
page = virt_to_page(address);
mapping = vmap(&page, 1, VM_MAP, PAGE_KERNEL);
if (mapping) {
int i = 0;
void * data = mapping + offset_in_page(address);
printk("VMAP: src %p -> dst %p\n", (void *)address, data);
for (i=0; i<16; i++) {
printk("%.02x %.02x\n", ((u8 *)address)[i], ((u8 *)data)[i]);
}
vunmap(mapping);
}
}
int my_module_init(void)
{
vmap_action((unsigned long)printk);
vmap_action((unsigned long)printx);
return 0;
}
module_init(my_module_init);
void my_module_exit(void)
{
}
module_exit(my_module_exit);
And the result with dmesg is:
vmap(printk)
[88107.398146] VMAP: src ffffffff813dfaef -> dst ffffc900117ddaef
[88107.398148] 55 55
[88107.398149] 48 48
[88107.398150] 89 89
[88107.398151] e5 e5
[88107.398152] 48 48
[88107.398153] 83 83
[88107.398154] ec ec
[88107.398155] 50 50
[88107.398156] 0f 0f
[88107.398156] 1f 1f
[88107.398157] 44 44
[88107.398158] 00 00
[88107.398159] 00 00
[88107.398160] 48 48
[88107.398161] 8d 8d
[88107.398162] 45 45
vmap(printx)
[88107.398164] VMAP: src ffffffffa009a010 -> dst ffffc900117fd010
[88107.398166] 55 35
[88107.398167] 48 fb
[88107.398168] 89 53
[88107.398169] e5 d5
[88107.398170] 0f f7
[88107.398171] 1f 97
[88107.398171] 44 ee
[88107.398172] 00 fd
[88107.398173] 00 d5
[88107.398174] 31 2d
[88107.398175] c0 bf
[88107.398176] 5d f6
[88107.398177] c3 2d
[88107.398178] 0f bd
[88107.398179] 1f b7
[88107.398180] 00 99
Any suggestions are welcome :) Thanks.
Well, I found that similar function is implemented in KSplice project and here is it:
/*
* map_writable creates a shadow page mapping of the range
* [addr, addr + len) so that we can write to code mapped read-only.
*
* It is similar to a generalized version of x86's text_poke. But
* because one cannot use vmalloc/vfree() inside stop_machine, we use
* map_writable to map the pages before stop_machine, then use the
* mapping inside stop_machine, and unmap the pages afterwards.
*/
static void *map_writable(void *addr, size_t len)
{
void *vaddr;
int nr_pages = DIV_ROUND_UP(offset_in_page(addr) + len, PAGE_SIZE);
struct page **pages = kmalloc(nr_pages * sizeof(*pages), GFP_KERNEL);
void *page_addr = (void *)((unsigned long)addr & PAGE_MASK);
int i;
if (pages == NULL)
return NULL;
for (i = 0; i < nr_pages; i++) {
if (__module_address((unsigned long)page_addr) == NULL) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) || !defined(CONFIG_X86_64)
pages[i] = virt_to_page(page_addr);
#else /* LINUX_VERSION_CODE < && CONFIG_X86_64 */
/* e3ebadd95cb621e2c7436f3d3646447ac9d5c16d was after 2.6.21
* This works around a broken virt_to_page() from the RHEL 5 backport
* of x86-64 relocatable kernel support.
*/
pages[i] =
pfn_to_page(__pa_symbol(page_addr) >> PAGE_SHIFT);
#endif /* LINUX_VERSION_CODE || !CONFIG_X86_64 */
WARN_ON(!PageReserved(pages[i]));
} else {
pages[i] = vmalloc_to_page(addr);
}
if (pages[i] == NULL) {
kfree(pages);
return NULL;
}
page_addr += PAGE_SIZE;
}
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
kfree(pages);
if (vaddr == NULL)
return NULL;
return vaddr + offset_in_page(addr);
}
So, as it comes there is a different handling of kernel's and module's memory. If the page is not belongs to any module then vmalloc_to_page rather then virt_to_phys used. I'll check if it helps and post the result later.

How to change default sound playback device programmatically?

How to change the default default audio device for playback and recording in vista programmatically ?
Is there any registry setting for it like sound manager in window XP?
Which API does it?
System Tray Audio Device Switcher uses "Software\Microsoft\Multimedia\Sound Mapper", "Playback" to set the index of the sound device which was obtained by enumeration the devices.
mciSendCommand from "winmm.dll" is also used
In this source code you will find the registry keys used to achieve that.
If this doesn't work you could give Process Monitor a try and monitor all registry activities of windows when you change the default device. On my Vista installation the control panel twiddles with "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\"
For Vista see
http://www.vistaaudiochanger.com/
There is no public API which allows you to change the default audio device, that is functionality that is considered to be under the users control. This has always been the case in Windows.
Having said that, if you search the web, there are a number of people who have reverse engineered the APIs that are used in Windows Vista to do this, but I'm not going to point you to them (the reverse engineered APIs are internal unsupported APIs and may change without notice from Microsoft). You use these solutions at your own peril.
I really don't know if anyone still needs this, but here is my solution.
Actually, it's for the capture device, but it can be changed easily to the render device.
It sets 3 registry values in the device's key to the current time. Magic, but that's how it works.
Note: only tested on Win7 x64
void SetDefaultRecordDevice(tstring strDeviceName){
const int BUFF_LEN = 260;
//HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture\{79434968-09f6-4dff-8086-c5e618b21473}\Role:0:
//"DE 07 08 00 06 00 10 00 15 00 38 00 1E 00 48 03"
HKEY hkCaptureDevices;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Capture") , 0, KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &hkCaptureDevices);
TCHAR lpwstrDeviceGuidKey[BUFF_LEN];
DWORD dwDeviceGuidKeySize = BUFF_LEN;
for(int i=0;RegEnumKeyEx(hkCaptureDevices, i, lpwstrDeviceGuidKey, &dwDeviceGuidKeySize, 0, 0, 0, 0) != ERROR_NO_MORE_ITEMS; ++i){
dwDeviceGuidKeySize = BUFF_LEN;
HKEY hkProps;
RegOpenKeyEx(hkCaptureDevices, (tstring(lpwstrDeviceGuidKey) + _T("\\Properties")).c_str() , 0, KEY_READ | KEY_WOW64_64KEY, &hkProps);
TCHAR data[BUFF_LEN];
DWORD dwDataSize = BUFF_LEN;
if(RegQueryValueEx(hkProps, _T("{a45c254e-df1c-4efd-8020-67d146a850e0},2"), 0, 0, (LPBYTE)data, &dwDataSize) != ERROR_SUCCESS){
continue;
} else {
tstring strCurrentDeviceName(data);
// TODO név általánosítás
if(strDeviceName == strCurrentDeviceName){
HKEY hkGuid;
RegOpenKeyEx(hkCaptureDevices, lpwstrDeviceGuidKey , 0, KEY_READ | KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_WOW64_64KEY | KEY_NOTIFY , &hkGuid);
time_t CurrentTime;
time(&CurrentTime);
time_t now = time(0);
struct tm tstruct;
gmtime_s(&tstruct, &now);
// Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
// for more information about date/time format
char CustomRegistryDateValue[16];
WORD year = tstruct.tm_year + 1900;
WORD month = tstruct.tm_mon+1;
WORD dayOfTheWeek = tstruct.tm_wday;
WORD day = tstruct.tm_mday;
WORD hour = tstruct.tm_hour;
WORD minute = tstruct.tm_min;
WORD second = tstruct.tm_sec;
WORD millisec = 0x0; // hasrautés
int k = 0;
*((WORD*)CustomRegistryDateValue + k++) = year;
*((WORD*)CustomRegistryDateValue + k++) = month;
*((WORD*)CustomRegistryDateValue + k++) = dayOfTheWeek;
*((WORD*)CustomRegistryDateValue + k++) = day;
*((WORD*)CustomRegistryDateValue + k++) = hour;
*((WORD*)CustomRegistryDateValue + k++) = minute;
*((WORD*)CustomRegistryDateValue + k++) = second;
*((WORD*)CustomRegistryDateValue + k++) = millisec;
RegSetValueExA(hkGuid, ("Role:0"), 0, REG_BINARY, (LPBYTE)CustomRegistryDateValue, 16);
RegSetValueExA(hkGuid, ("Role:1"), 0, REG_BINARY, (LPBYTE)CustomRegistryDateValue, 16);
RegSetValueExA(hkGuid, ("Role:2"), 0, REG_BINARY, (LPBYTE)CustomRegistryDateValue, 16);
RegFlushKey(hkGuid);
RegCloseKey(hkGuid);
}
}
RegCloseKey(hkProps);
}
RegCloseKey(hkCaptureDevices);
}

Resources