Improve PWM quality, fix a crash
This commit is contained in:
parent
5a56c3b882
commit
4bf252800e
@ -5,6 +5,8 @@
|
||||
#import "JOYEmulatedButton.h"
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
#define PWM_RESOLUTION 16
|
||||
|
||||
static NSString const *JOYAxisGroups = @"JOYAxisGroups";
|
||||
static NSString const *JOYReportIDFilters = @"JOYReportIDFilters";
|
||||
static NSString const *JOYButtonUsageMapping = @"JOYButtonUsageMapping";
|
||||
@ -130,7 +132,7 @@ typedef struct __attribute__((packed)) {
|
||||
|
||||
_physicallyConnected = true;
|
||||
_logicallyConnected = true;
|
||||
_device = device;
|
||||
_device = (IOHIDDeviceRef)CFRetain(device);
|
||||
_serialSuffix = suffix;
|
||||
|
||||
IOHIDDeviceRegisterInputValueCallback(device, HIDInput, (void *)self);
|
||||
@ -603,11 +605,17 @@ typedef struct __attribute__((packed)) {
|
||||
|
||||
- (void)pwmThread
|
||||
{
|
||||
while (_rumblePWMRatio != 0) {
|
||||
[_rumbleElement setValue:1];
|
||||
[NSThread sleepForTimeInterval:_rumblePWMRatio / 10];
|
||||
[_rumbleElement setValue:0];
|
||||
[NSThread sleepForTimeInterval:(1 - _rumblePWMRatio) / 10];
|
||||
/* TODO: This does not handle correctly the case of having a multi-port controller where more than one controller
|
||||
uses rumble. */
|
||||
unsigned rumbleCounter = 0;
|
||||
while (self.connected) {
|
||||
if ([_rumbleElement setValue:rumbleCounter < round(_rumblePWMRatio * PWM_RESOLUTION)]) {
|
||||
break;
|
||||
}
|
||||
rumbleCounter += round(_rumblePWMRatio * PWM_RESOLUTION);
|
||||
if (rumbleCounter >= PWM_RESOLUTION) {
|
||||
rumbleCounter -= PWM_RESOLUTION;
|
||||
}
|
||||
}
|
||||
[_rumblePWMThreadLock lock];
|
||||
_rumblePWMThreadRunning = false;
|
||||
@ -659,6 +667,7 @@ typedef struct __attribute__((packed)) {
|
||||
else {
|
||||
if (_rumbleElement.max == 1 && _rumbleElement.min == 0) {
|
||||
[_rumblePWMThreadLock lock];
|
||||
_rumblePWMRatio = amp;
|
||||
if (!_rumblePWMThreadRunning) { // PWM thread not running, start it.
|
||||
if (amp != 0) {
|
||||
_rumblePWMRatio = amp;
|
||||
@ -666,14 +675,6 @@ typedef struct __attribute__((packed)) {
|
||||
[self performSelectorInBackground:@selector(pwmThread) withObject:nil];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (amp == 0) { // Thread is running, signal it to stop
|
||||
_rumblePWMRatio = 0;
|
||||
}
|
||||
else {
|
||||
_rumblePWMRatio = amp;
|
||||
}
|
||||
}
|
||||
[_rumblePWMThreadLock unlock];
|
||||
}
|
||||
else {
|
||||
@ -771,4 +772,12 @@ typedef struct __attribute__((packed)) {
|
||||
IOHIDManagerRegisterDeviceRemovalCallback(manager, HIDDeviceRemoved, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(manager, [runloop getCFRunLoop], kCFRunLoopDefaultMode);
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (_device) {
|
||||
CFRelease(_device);
|
||||
_device = NULL;
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
@ -5,8 +5,8 @@
|
||||
- (instancetype)initWithElement:(IOHIDElementRef)element;
|
||||
- (int32_t)value;
|
||||
- (NSData *)dataValue;
|
||||
- (void)setValue:(uint32_t)value;
|
||||
- (void)setDataValue:(NSData *)value;
|
||||
- (IOReturn)setValue:(uint32_t)value;
|
||||
- (IOReturn)setDataValue:(NSData *)value;
|
||||
@property (readonly) uint16_t usage;
|
||||
@property (readonly) uint16_t usagePage;
|
||||
@property (readonly) uint32_t uniqueID;
|
||||
|
@ -81,18 +81,20 @@
|
||||
return [NSData dataWithBytes:IOHIDValueGetBytePtr(value) length:IOHIDValueGetLength(value)];
|
||||
}
|
||||
|
||||
- (void)setValue:(uint32_t)value
|
||||
- (IOReturn)setValue:(uint32_t)value
|
||||
{
|
||||
IOHIDValueRef ivalue = IOHIDValueCreateWithIntegerValue(NULL, (__bridge IOHIDElementRef)_element, 0, value);
|
||||
IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue);
|
||||
IOReturn ret = IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue);
|
||||
CFRelease(ivalue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)setDataValue:(NSData *)value
|
||||
- (IOReturn)setDataValue:(NSData *)value
|
||||
{
|
||||
IOHIDValueRef ivalue = IOHIDValueCreateWithBytes(NULL, (__bridge IOHIDElementRef)_element, 0, value.bytes, value.length);
|
||||
IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue);
|
||||
IOReturn ret = IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue);
|
||||
CFRelease(ivalue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* For use as a dictionary key */
|
||||
|
@ -65,15 +65,15 @@
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)setValue: (uint32_t) value
|
||||
- (IOReturn)setValue: (uint32_t) value
|
||||
{
|
||||
NSMutableData *dataValue = [[_parent dataValue] mutableCopy];
|
||||
if (!dataValue) return;
|
||||
if (_size > 32) return;
|
||||
if (_size + (_offset % 8) > 32) return;
|
||||
if (!dataValue) return -1;
|
||||
if (_size > 32) return -1;
|
||||
if (_size + (_offset % 8) > 32) return -1;
|
||||
size_t parentLength = dataValue.length;
|
||||
if (_size > parentLength * 8) return;
|
||||
if (_size + _offset >= parentLength * 8) return;
|
||||
if (_size > parentLength * 8) return -1;
|
||||
if (_size + _offset >= parentLength * 8) return -1;
|
||||
uint8_t *bytes = dataValue.mutableBytes;
|
||||
|
||||
uint8_t temp[4] = {0,};
|
||||
@ -81,7 +81,7 @@
|
||||
(*(uint32_t *)temp) &= ~((1 << (_size - 1)) << (_offset % 8));
|
||||
(*(uint32_t *)temp) |= (value) << (_offset % 8);
|
||||
memcpy(bytes + _offset / 8, temp, (_offset + _size - 1) / 8 - _offset / 8 + 1);
|
||||
[_parent setDataValue:dataValue];
|
||||
return [_parent setDataValue:dataValue];
|
||||
}
|
||||
|
||||
- (NSData *)dataValue
|
||||
@ -90,9 +90,10 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setDataValue:(NSData *)data
|
||||
- (IOReturn)setDataValue:(NSData *)data
|
||||
{
|
||||
[self doesNotRecognizeSelector:_cmd];
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user